/// <summary>
 /// Adds a neighbor profile server to the list of neighbors when loading simulation from snapshot.
 /// </summary>
 public void AddNeighborSnapshot(ProfileServer Neighbor)
 {
     lock (neighborsLock)
     {
         neighbors.Add(Neighbor.Name, Neighbor);
     }
 }
Example #2
0
        /// <summary>
        /// Creates instance of profile server from snapshot.
        /// </summary>
        /// <param name="Snapshot">Profile server snapshot.</param>
        /// <returns>New profile server instance.</returns>
        public static ProfileServer CreateFromSnapshot(ProfileServerSnapshot Snapshot)
        {
            ProfileServer res = new ProfileServer(Snapshot.Name, new GpsLocation(Snapshot.LocationLatitude, Snapshot.LocationLongitude), Snapshot.BasePort);

            res.availableIdentitySlots         = Snapshot.AvailableIdentitySlots;
            res.clientAppServiceInterfacePort  = Snapshot.ClientAppServiceInterfacePort;
            res.clientCustomerInterfacePort    = Snapshot.ClientCustomerInterfacePort;
            res.clientNonCustomerInterfacePort = Snapshot.ClientNonCustomerInterfacePort;
            res.ipAddress                   = IPAddress.Parse(Snapshot.IpAddress);
            res.locPort                     = Snapshot.LocPort;
            res.networkId                   = Snapshot.NetworkId.FromHex();
            res.primaryInterfacePort        = Snapshot.PrimaryInterfacePort;
            res.serverNeighborInterfacePort = Snapshot.ServerNeighborInterfacePort;
            res.instanceDirectory           = res.GetInstanceDirectoryName();
            res.locServer                   = new LocServer(res);

            byte[] ipBytes = res.ipAddress.GetAddressBytes();
            Iop.Locnet.NodeContact contact = new Iop.Locnet.NodeContact()
            {
                IpAddress  = ProtocolHelper.ByteArrayToByteString(ipBytes),
                ClientPort = (uint)res.locPort,
                NodePort   = (uint)res.locPort
            };

            return(res);
        }
        /// <summary>
        /// Loads snapshot from snapshot folder.
        /// </summary>
        /// <returns>true if the function succeeds, false otherwise.</returns>
        public bool Load()
        {
            log.Trace("()");

            bool error = false;

            try
            {
                log.Debug("Loading profile servers information.");
                string serializedProfileServers = File.ReadAllText(profileServersFile);

                log.Debug("Deserializing profile servers information.");
                ProfileServers = JsonConvert.DeserializeObject <List <ProfileServerSnapshot> >(serializedProfileServers);


                log.Debug("Loading identities information.");
                string serializedIdentities = File.ReadAllText(identitiesFile);

                log.Debug("Deserializing identities information.");
                Identities = JsonConvert.DeserializeObject <List <IdentitySnapshot> >(serializedIdentities);

                log.Debug("Loading images information.");
                string serializedImages = File.ReadAllText(imagesFile);

                log.Debug("Deserializing images information.");
                Images = JsonConvert.DeserializeObject <Dictionary <string, string> >(serializedImages);


                log.Debug("Loading profile servers instance folders.");
                foreach (ProfileServerSnapshot server in ProfileServers)
                {
                    string serverInstanceDirectory   = ProfileServer.GetInstanceDirectoryName(server.Name);
                    string snapshotInstanceDirectory = Path.Combine(new string[] { snapshotDirectory, "bin", server.Name });
                    log.Debug("Copying '{0}' to '{1}'.", snapshotInstanceDirectory, serverInstanceDirectory);
                    if (!Helpers.DirectoryCopy(snapshotInstanceDirectory, serverInstanceDirectory))
                    {
                        log.Error("Unable to copy files from directory '{0}' to '{1}'.", snapshotInstanceDirectory, serverInstanceDirectory);
                        error = true;
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                log.Error("Exception occurred while trying to load serialized simulation files: {0}", e.ToString());
                error = true;
            }

            bool res = !error;

            log.Trace("(-):{0}", res);
            return(res);
        }
        /// <summary>
        /// Initializes the LOC server instance.
        /// </summary>
        /// <param name="ProfileServer">Associated profile server.</param>
        public LocServer(ProfileServer ProfileServer)
        {
            log = new Logger("NetworkSimulator.LocServer", "[" + ProfileServer.Name + "] ");
            log.Trace("()");

            this.profileServer = ProfileServer;
            ipAddress          = ProfileServer.IpAddress;
            port = ProfileServer.LocPort;

            nodeLocation = ProfileServer.NodeLocation;

            listener = new TcpListener(ipAddress, port);
            listener.Server.LingerState = new LingerOption(true, 0);
            listener.Server.NoDelay     = true;

            log.Trace("(-)");
        }
Example #5
0
        /// <summary>
        /// Uninstalls a neighborhood notification.
        /// </summary>
        /// <param name="ServerToInform">Profile server that was about to be informed, but will not be anymore.</param>
        public void UninstallInitializationNeighborhoodNotification(ProfileServer ServerToInform)
        {
            log.Trace("(ServerToInform.Name:'{0}')", ServerToInform.Name);

            lock (internalLock)
            {
                if (initializationNeighborhoodNotificationList.Remove(ServerToInform))
                {
                    log.Debug("Server '{0}' removed from neighborhood notification list of server '{1}'.", ServerToInform.Name, Name);
                }
                else
                {
                    log.Debug("Server '{0}' not found on the neighborhood notification list of server '{1}' and can't be removed.", ServerToInform.Name, Name);
                }
            }

            log.Trace("(-)");
        }
Example #6
0
        /// <summary>
        /// Installs a notification to sent to the profile server, for which this profile server acts as a neighbor.
        /// The notification will be sent as soon as this profile server starts and performs its profile initialization.
        /// </summary>
        /// <param name="ServerToInform">Profile server to inform.</param>
        public void InstallInitializationNeighborhoodNotification(ProfileServer ServerToInform)
        {
            log.Trace("(ServerToInform.Name:'{0}')", ServerToInform.Name);

            lock (internalLock)
            {
                if (initializationNeighborhoodNotificationList.Add(ServerToInform))
                {
                    log.Debug("Server '{0}' added to neighborhood notification list of server '{1}'.", ServerToInform.Name, Name);
                }
                else
                {
                    log.Debug("Server '{0}' is already on neighborhood notification list of server '{1}'.", ServerToInform.Name, Name);
                }
            }

            log.Trace("(-)");
        }
Example #7
0
        /// <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       = Snapshot.Challenge.FromHex();
            res.clientChallenge = Snapshot.ClientChallenge.FromHex();

            res.keys = new KeysEd25519();
            res.keys.ExpandedPrivateKeyHex = Snapshot.ExpandedPrivateKeyHex;
            res.keys.PublicKeyHex          = Snapshot.PublicKeyHex;
            res.keys.PrivateKeyHex         = Snapshot.PrivateKeyHex;
            res.keys.ExpandedPrivateKey    = res.keys.ExpandedPrivateKeyHex.FromHex();
            res.keys.PublicKey             = res.keys.PublicKeyHex.FromHex();
            res.keys.PrivateKey            = res.keys.PrivateKeyHex.FromHex();

            res.extraData     = Snapshot.ExtraData;
            res.hostingActive = Snapshot.HostingActive;
            res.identityId    = Snapshot.IdentityId.FromHex();
            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 ? Images[Snapshot.ProfileImageHash].FromHex() : null;
            res.thumbnailImage = Snapshot.ThumbnailImageHash != null ? Images[Snapshot.ThumbnailImageHash].FromHex() : null;

            res.profileServerKey = Snapshot.ProfileServerKey.FromHex();
            res.type             = Snapshot.Type;
            res.version          = Snapshot.Version;

            res.profileServer  = ProfileServer;
            res.log            = new Logger("NetworkSimulator.IdentityClient", "[" + res.Name + "] ");
            res.messageBuilder = new PsMessageBuilder(0, new List <SemVer>()
            {
                SemVer.V100
            }, res.keys);
            res.InitializeTcpClient();

            return(res);
        }
Example #8
0
        /// <summary>
        /// Connects to a profile server and performs a search query on it and downloads all possible results.
        /// </summary>
        /// <param name="Server">Profile server to query.</param>
        /// <param name="NameFilter">Name filter of the search query, or null if name filtering is not required.</param>
        /// <param name="TypeFilter">Type filter of the search query, or null if type filtering is not required.</param>
        /// <param name="LocationFilter">Location filter of the search query, or null if location filtering is not required.</param>
        /// <param name="Radius">If <paramref name="LocationFilter"/> is not null, this is the radius of the target area.</param>
        /// <param name="IncludeHostedOnly">If set to true, the search results should only include profiles hosted on the queried profile server.</param>
        /// <param name="IncludeImages">If set to true, the search results should include images.</param>
        /// <returns>List of results or null if the function fails.</returns>
        public async Task <SearchQueryInfo> SearchQueryAsync(ProfileServer Server, string NameFilter, string TypeFilter, GpsLocation LocationFilter, int Radius, bool IncludeHostedOnly, bool IncludeImages)
        {
            log.Trace("()");

            SearchQueryInfo res       = null;
            bool            connected = false;

            try
            {
                await ConnectAsync(Server.IpAddress, Server.ClientNonCustomerInterfacePort, true);

                connected = true;
                if (await StartConversationAsync())
                {
                    uint maxResults                  = (uint)(IncludeImages ? 1000 : 10000);
                    uint maxResponseResults          = (uint)(IncludeImages ? 100 : 1000);
                    PsProtocolMessage requestMessage = messageBuilder.CreateProfileSearchRequest(TypeFilter, NameFilter, null, LocationFilter, (uint)Radius, maxResponseResults, maxResults, IncludeHostedOnly, IncludeImages);
                    await SendMessageAsync(requestMessage);

                    PsProtocolMessage responseMessage = await ReceiveMessageAsync();

                    bool idOk     = responseMessage.Id == requestMessage.Id;
                    bool statusOk = responseMessage.Response.Status == Status.Ok;

                    bool searchRequestOk = idOk && statusOk;
                    if (searchRequestOk)
                    {
                        int           totalResultCount = (int)responseMessage.Response.ConversationResponse.ProfileSearch.TotalRecordCount;
                        List <byte[]> coveredServers   = new List <byte[]>();
                        foreach (ByteString coveredServerId in responseMessage.Response.ConversationResponse.ProfileSearch.CoveredServers)
                        {
                            coveredServers.Add(coveredServerId.ToByteArray());
                        }

                        List <IdentityNetworkProfileInformation> results = responseMessage.Response.ConversationResponse.ProfileSearch.Profiles.ToList();
                        while (results.Count < totalResultCount)
                        {
                            int remaining = Math.Min((int)maxResponseResults, totalResultCount - results.Count);
                            requestMessage = messageBuilder.CreateProfileSearchPartRequest((uint)results.Count, (uint)remaining);
                            await SendMessageAsync(requestMessage);

                            responseMessage = await ReceiveMessageAsync();

                            idOk     = responseMessage.Id == requestMessage.Id;
                            statusOk = responseMessage.Response.Status == Status.Ok;

                            searchRequestOk = idOk && statusOk;
                            if (!searchRequestOk)
                            {
                                break;
                            }

                            results.AddRange(responseMessage.Response.ConversationResponse.ProfileSearchPart.Profiles.ToList());
                        }

                        res = new SearchQueryInfo();
                        res.CoveredServers = coveredServers;
                        res.Results        = results;
                    }
                }
            }
            catch (Exception e)
            {
                log.Error("Exception occurred: {0}", e.ToString());
            }

            if (connected)
            {
                CloseTcpClient();
            }

            if (res != null)
            {
                log.Trace("(-):*.Results.Count={0},*.CoveredServers.Count={1}", res.Results.Count, res.CoveredServers.Count);
            }
            else
            {
                log.Trace("(-):null");
            }
            return(res);
        }
Example #9
0
        /// <summary>
        /// Establishes a hosting agreement with a profile server and initializes a profile.
        /// </summary>
        /// <param name="Server">Profile server to host the identity.</param>
        /// <returns>true if the function succeeded, false otherwise.</returns>
        public async Task <bool> InitializeProfileHosting(ProfileServer Server)
        {
            log.Trace("(Server.Name:'{0}')", Server.Name);
            bool res = false;

            profileServer = Server;
            InitializeTcpClient();

            try
            {
                await ConnectAsync(Server.IpAddress, Server.ClientNonCustomerInterfacePort, true);

                if (await EstablishProfileHostingAsync(type))
                {
                    hostingActive = true;
                    CloseTcpClient();

                    InitializeTcpClient();
                    await ConnectAsync(Server.IpAddress, Server.ClientCustomerInterfacePort, true);

                    if (await CheckInAsync())
                    {
                        if (await InitializeProfileAsync(name, profileImage, location, null))
                        {
                            profileInitialized = true;
                            if (profileImage != null)
                            {
                                if (await GetProfileThumbnailImage())
                                {
                                    res = true;
                                }
                                else
                                {
                                    log.Error("Unable to obtain identity's thumbnail image from profile server '{0}'.", Server.Name);
                                }
                            }
                            else
                            {
                                res = true;
                            }
                        }
                        else
                        {
                            log.Error("Unable to initialize profile on profile server '{0}'.", Server.Name);
                        }
                    }
                    else
                    {
                        log.Error("Unable to check-in to profile server '{0}'.", Server.Name);
                    }
                }
                else
                {
                    log.Error("Unable to establish profile hosting with server '{0}'.", Server.Name);
                }
            }
            catch (Exception e)
            {
                log.Error("Exception occurred: {0}", e.ToString());
            }

            CloseTcpClient();

            log.Trace("(-):{0}", res);
            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);
        }