/// <summary> /// Creates instance of identity client from snapshot. /// </summary> /// <param name="Snapshot">Identity client snapshot.</param> /// <param name="Images">Hexadecimal image data mapping to SHA256 hash.</param> /// <param name="ProfileServer">Profile server that hosts identity's profile.</param> /// <returns>New identity client instance.</returns> public static IdentityClient CreateFromSnapshot(IdentitySnapshot Snapshot, Dictionary <string, string> Images, ProfileServer ProfileServer) { IdentityClient res = new IdentityClient(); res.challenge = Crypto.FromHex(Snapshot.Challenge); res.clientChallenge = Crypto.FromHex(Snapshot.ClientChallenge); res.keys = new KeysEd25519(); res.keys.ExpandedPrivateKeyHex = Snapshot.ExpandedPrivateKeyHex; res.keys.PublicKeyHex = Snapshot.PublicKeyHex; res.keys.PrivateKeyHex = Snapshot.PrivateKeyHex; res.keys.ExpandedPrivateKey = Crypto.FromHex(res.keys.ExpandedPrivateKeyHex); res.keys.PublicKey = Crypto.FromHex(res.keys.PublicKeyHex); res.keys.PrivateKey = Crypto.FromHex(res.keys.PrivateKeyHex); res.extraData = Snapshot.ExtraData; res.hostingActive = Snapshot.HostingActive; res.identityId = Crypto.FromHex(Snapshot.IdentityId); res.imageFileName = Snapshot.ImageFileName != null?Path.Combine(CommandProcessor.ImagesDirectory, Snapshot.ImageFileName) : null; res.location = new GpsLocation(Snapshot.LocationLatitude, Snapshot.LocationLongitude); res.name = Snapshot.Name; res.profileInitialized = Snapshot.ProfileInitialized; res.profileImage = Snapshot.ProfileImageHash != null?Crypto.FromHex(Images[Snapshot.ProfileImageHash]) : null; res.thumbnailImage = Snapshot.ThumbnailImageHash != null?Crypto.FromHex(Images[Snapshot.ThumbnailImageHash]) : null; res.profileServerKey = Crypto.FromHex(Snapshot.ProfileServerKey); res.type = Snapshot.Type; res.version = Snapshot.Version; res.profileServer = ProfileServer; res.log = new PrefixLogger("ProfileServerSimulator.IdentityClient", "[" + res.Name + "] "); res.messageBuilder = new MessageBuilder(0, new List <SemVer>() { SemVer.V100 }, res.keys); res.InitializeTcpClient(); return(res); }
/// <summary> /// Executes all commands. /// </summary> /// <returns>true if the function succeeds and all the commands are executed successfully, false otherwise.</returns> public bool Execute() { log.Trace("()"); bool res = false; log.Info("Cleaning old history."); if (!ClearHistory()) { log.Error("Unable to clear history, please make sure the access to the instance folder is not blocked by other process."); log.Trace("(-):{0}", res); return(res); } log.Info(""); int index = 1; bool error = false; foreach (Command command in commands) { log.Info("Executing #{0:0000}@l{1}: {2}", index, command.LineNumber, command.OriginalCommand); switch (command.Type) { case CommandType.ProfileServer: { CommandProfileServer cmd = (CommandProfileServer)command; for (int i = 1; i <= cmd.Count; i++) { string name = GetInstanceName(cmd.GroupName, i); GpsLocation location = Helpers.GenerateRandomGpsLocation(cmd.Latitude, cmd.Longitude, cmd.Radius); int basePort = cmd.BasePort + 20 * (i - 1); ProfileServer profileServer = new ProfileServer(name, location, basePort); if (profileServer.Initialize()) { profileServers.Add(name, profileServer); } else { log.Error(" * Initialization of profile server '{0}' failed.", profileServer.Name); error = true; break; } } if (!error) { log.Info(" * {0} profile servers created.", cmd.Count); } break; } case CommandType.StartServer: { CommandStartServer cmd = (CommandStartServer)command; for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { if (!profileServer.Start()) { log.Error(" * Unable to start server instance '{0}'.", name); error = true; break; } } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { log.Info(" * {0} profile servers started.", cmd.PsCount); } break; } case CommandType.StopServer: { CommandStopServer cmd = (CommandStopServer)command; for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { if (!profileServer.Stop()) { log.Error(" * Unable to stop server instance '{0}'.", name); error = true; } } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { log.Info(" * {0} profile servers stopped.", cmd.PsCount); } break; } case CommandType.Identity: { CommandIdentity cmd = (CommandIdentity)command; List <ProfileServer> availableServers = new List <ProfileServer>(); int availableSlots = 0; for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { availableServers.Add(profileServer); availableSlots += profileServer.AvailableIdentitySlots; } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (error) { break; } if (availableSlots < cmd.Count) { log.Error(" * Total number of available identity slots in selected servers is {0}, but {1} slots are required.", availableSlots, cmd.Count); error = true; break; } for (int i = 1; i <= cmd.Count; i++) { string name = GetIdentityName(cmd.Name, i); int serverIndex = Helpers.Rng.Next(availableServers.Count); ProfileServer profileServer = availableServers[serverIndex]; GpsLocation location = Helpers.GenerateRandomGpsLocation(cmd.Latitude, cmd.Longitude, cmd.Radius); IdentityClient identityClient = null; try { identityClient = new IdentityClient(name, cmd.IdentityType, location, cmd.ImageMask, cmd.ImageChance); identityClients.Add(name, identityClient); } catch { log.Error("Unable to create identity '{0}'.", name); error = true; break; } Task <bool> initTask = identityClient.InitializeProfileHosting(profileServer); if (initTask.Result) { profileServer.AddIdentityClient(identityClient); if (profileServer.AvailableIdentitySlots == 0) { availableServers.RemoveAt(serverIndex); } } else { log.Error("Unable to register profile hosting and initialize profile of identity '{0}' on server '{1}'.", name, profileServer.Name); error = true; break; } } if (!error) { log.Info(" * {0} identities created and initialized on {1} servers.", cmd.Count, cmd.PsCount); } break; } case CommandType.CancelIdentity: { CommandCancelIdentity cmd = (CommandCancelIdentity)command; List <IdentityClient> clients = new List <IdentityClient>(); for (int i = 0; i < cmd.Count; i++) { string name = GetIdentityName(cmd.Name, cmd.Index + i); IdentityClient identityClient; if (identityClients.TryGetValue(name, out identityClient)) { clients.Add(identityClient); } else { log.Error(" * Identity name '{0}' does not exist.", name); error = true; break; } } if (error) { break; } foreach (IdentityClient client in clients) { Task <bool> cancelTask = client.CancelProfileHosting(); if (!cancelTask.Result) { log.Error("Unable to cancel profile hosting agreement of identity '{0}' on server '{1}'.", client.Name, client.ProfileServer.Name); error = true; } } if (!error) { log.Info(" * {0} identities cancelled their hosting agreement.", clients.Count); } break; } case CommandType.Neighborhood: { CommandNeighborhood cmd = (CommandNeighborhood)command; List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.PsGroups.Count; i++) { string psGroup = cmd.PsGroups[i]; int psCount = cmd.PsCounts[i]; int psIndex = cmd.PsIndexes[i]; for (int j = 0; j < psCount; j++) { string name = GetInstanceName(psGroup, psIndex + j); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { neighborhoodList.Add(profileServer); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } } if (!error) { foreach (ProfileServer ps in neighborhoodList) { if (!ps.LocServer.AddNeighborhood(neighborhoodList)) { log.Error(" * Unable to add neighbors to server '{0}'.", ps.Name); error = true; break; } } if (!error) { log.Info(" * Neighborhood of {0} profile servers has been established.", neighborhoodList.Count); } } break; } case CommandType.CancelNeighborhood: { CommandCancelNeighborhood cmd = (CommandCancelNeighborhood)command; List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.PsGroups.Count; i++) { string psGroup = cmd.PsGroups[i]; int psCount = cmd.PsCounts[i]; int psIndex = cmd.PsIndexes[i]; for (int j = 0; j < psCount; j++) { string name = GetInstanceName(psGroup, psIndex + j); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { neighborhoodList.Add(profileServer); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } } if (!error) { foreach (ProfileServer ps in neighborhoodList) { if (!ps.LocServer.CancelNeighborhood(neighborhoodList)) { log.Error(" * Unable to add neighbors to server '{0}'.", ps.Name); error = true; break; } } if (!error) { log.Info(" * Neighbor relations among {0} profile servers have been cancelled.", neighborhoodList.Count); } } break; } case CommandType.Neighbor: { CommandNeighbor cmd = (CommandNeighbor)command; ProfileServer profileServer; if (profileServers.TryGetValue(cmd.Source, out profileServer)) { List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.Targets.Count; i++) { string name = cmd.Targets[i]; ProfileServer target; if (profileServers.TryGetValue(name, out target)) { neighborhoodList.Add(target); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { if (profileServer.LocServer.AddNeighborhood(neighborhoodList)) { log.Info(" * {0} servers have been added to the neighborhood of server '{1}'.", neighborhoodList.Count, profileServer.Name); } else { log.Error(" * Unable to add neighbors to server '{0}'.", profileServer.Name); error = true; break; } } } else { log.Error(" * Profile server instance '{0}' does not exist.", cmd.Source); error = true; break; } break; } case CommandType.CancelNeighbor: { CommandCancelNeighbor cmd = (CommandCancelNeighbor)command; ProfileServer profileServer; if (profileServers.TryGetValue(cmd.Source, out profileServer)) { List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.Targets.Count; i++) { string name = cmd.Targets[i]; ProfileServer target; if (profileServers.TryGetValue(name, out target)) { neighborhoodList.Add(target); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { if (profileServer.LocServer.CancelNeighborhood(neighborhoodList)) { log.Info(" * {0} servers have been removed from the neighborhood of server '{1}'.", neighborhoodList.Count, profileServer.Name); } else { log.Error(" * Unable to remove neighbors from neighborhood of server '{0}'.", profileServer.Name); error = true; break; } } } else { log.Error(" * Profile server instance '{0}' does not exist.", cmd.Source); error = true; break; } break; } case CommandType.TestQuery: { CommandTestQuery cmd = (CommandTestQuery)command; List <ProfileServer> targetServers = new List <ProfileServer>(); for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { targetServers.Add(profileServer); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } int serversSkipped = 0; int serversQueried = 0; IdentityClient client = null; try { client = new IdentityClient("Query Client", "Query Client", new GpsLocation(0, 0), null, 0); int maxResults = cmd.IncludeImages ? 1000 : 10000; string nameFilter = cmd.NameFilter != "**" ? cmd.NameFilter : null; string typeFilter = cmd.TypeFilter != "**" ? cmd.TypeFilter : null; GpsLocation queryLocation = cmd.Latitude != GpsLocation.NoLocation.Latitude ? new GpsLocation(cmd.Latitude, cmd.Longitude) : null; foreach (ProfileServer targetServer in targetServers) { if (!targetServer.IsInitialized()) { log.Trace("Profile server '{0}' not initialized, skipping ...", targetServer.Name); serversSkipped++; continue; } byte[] targetServerId = targetServer.GetNetworkId(); client.InitializeTcpClient(); Task <IdentityClient.SearchQueryInfo> searchTask = client.SearchQueryAsync(targetServer, nameFilter, typeFilter, queryLocation, cmd.Radius, false, cmd.IncludeImages); IdentityClient.SearchQueryInfo searchResults = searchTask.Result; if (searchResults != null) { List <byte[]> expectedCoveredServers; int localServerResults; List <IdentityNetworkProfileInformation> expectedSearchResults = targetServer.GetExpectedSearchResults(nameFilter, typeFilter, queryLocation, cmd.Radius, false, cmd.IncludeImages, out expectedCoveredServers, out localServerResults); List <IdentityNetworkProfileInformation> realResults = searchResults.Results; List <byte[]> realCoveredServers = searchResults.CoveredServers; if (DebugModeEnabled) { log.Info(" * '{0}': {1} real results, {2} calculated results, {3} max. real results, {4} local server results, {5} real covered servers, {6} calculated covered servers.", targetServer.Name, realResults.Count, expectedSearchResults.Count, maxResults, localServerResults, realCoveredServers.Count, expectedCoveredServers.Count); } if (!CompareSearchResults(realResults, expectedSearchResults, maxResults)) { log.Error(" * Real search results are different from the expected results on server instance '{0}'.", targetServer.Name); error = true; break; } if (!CompareCoveredServers(targetServerId, realCoveredServers, expectedCoveredServers, localServerResults, maxResults)) { log.Error(" * Real covered servers are different from the expected covered servers on server instance '{0}'.", targetServer.Name); error = true; break; } serversQueried++; } else { log.Error(" * Unable to perform search on server instance '{0}'.", targetServer.Name); error = true; break; } } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); error = true; break; } if (!error) { log.Info(" * Results of search queries on {0} servers match expected results. {1} servers were offline and skipped.", serversQueried, serversSkipped); } break; } case CommandType.Delay: { CommandDelay cmd = (CommandDelay)command; log.Info(" * Waiting {0} seconds ...", cmd.Seconds); Thread.Sleep(TimeSpan.FromSeconds((double)cmd.Seconds)); break; } case CommandType.TakeSnapshot: { CommandTakeSnapshot cmd = (CommandTakeSnapshot)command; HashSet <string> runningServerNames = new HashSet <string>(StringComparer.Ordinal); foreach (ProfileServer ps in profileServers.Values) { if (ps.IsRunningProcess()) { if (!ps.Stop()) { log.Error(" * Failed to stop profile server '{0}'.", ps.Name); error = true; break; } runningServerNames.Add(ps.Name); } } if (error) { break; } Snapshot snapshot = new Snapshot(cmd.Name); if (snapshot.Take(runningServerNames, profileServers, identityClients)) { log.Info(" * Snapshot '{0}' has been created.", cmd.Name); } else { log.Error(" * Failed to take simulation snapshot."); error = true; } break; } case CommandType.LoadSnapshot: { CommandLoadSnapshot cmd = (CommandLoadSnapshot)command; if (index != 1) { log.Error(" * LoadSnapshot must be the very first command in the scenario."); error = true; break; } Snapshot snapshot = new Snapshot(cmd.Name); if (!snapshot.Load()) { log.Error(" * Unable to load snapshot '{0}'.", cmd.Name); error = true; break; } try { // Initialize profile servers. log.Debug("Initializing profile servers."); foreach (ProfileServerSnapshot serverSnapshot in snapshot.ProfileServers) { ProfileServer profileServer = ProfileServer.CreateFromSnapshot(serverSnapshot); profileServers.Add(profileServer.Name, profileServer); } // Initialize identities and connect them with their profile servers. log.Debug("Initializing identity clients."); foreach (IdentitySnapshot identitySnapshot in snapshot.Identities) { ProfileServer profileServer = profileServers[identitySnapshot.ProfileServerName]; IdentityClient identityClient = IdentityClient.CreateFromSnapshot(identitySnapshot, snapshot.Images, profileServer); profileServer.AddIdentityClientSnapshot(identityClient); identityClients.Add(identityClient.Name, identityClient); } // Initialize neighbor relations. log.Debug("Initializing neighborhoods."); foreach (ProfileServerSnapshot serverSnapshot in snapshot.ProfileServers) { ProfileServer profileServer = profileServers[serverSnapshot.Name]; List <ProfileServer> neighborServers = new List <ProfileServer>(); foreach (string neighborName in serverSnapshot.LocServer.NeighborsNames) { ProfileServer neighborServer = profileServers[neighborName]; neighborServers.Add(neighborServer); } profileServer.LocServer.SetNeighborhood(neighborServers); } // Start LOC servers and profile servers. log.Debug("Starting servers."); foreach (ProfileServerSnapshot serverSnapshot in snapshot.ProfileServers) { ProfileServer profileServer = profileServers[serverSnapshot.Name]; if (!profileServer.LocServer.Start()) { log.Error(" * Unable to start LOC server of profile server instance '{0}'.", profileServer.Name); error = true; break; } if (serverSnapshot.IsRunning) { if (!profileServer.Start()) { log.Error(" * Unable to start profile server instance '{0}'.", profileServer.Name); error = true; break; } } } } catch (Exception e) { log.Error(" * Snapshot is corrupted, exception occurred: {0}", e.ToString()); error = true; break; } if (!error) { log.Info(" * Simulation state loaded from snapshot '{0}'.", cmd.Name); } break; } case CommandType.DebugMode: { CommandDebugMode cmd = (CommandDebugMode)command; log.Info(" * Debug mode is now {0}.", cmd.Enable ? "ENABLED" : "DISABLED"); DebugModeEnabled = cmd.Enable; break; } default: log.Error("Invalid command type '{0}'.", command.Type); error = true; break; } index++; if (error) { break; } } res = !error; log.Trace("(-):{0}", res); return(res); }