/// <summary>
 /// Constructs a remote server object.
 /// </summary>
 /// <param name="connection">An established connection to the remote server.</param>
 /// <param name="doi">Remote server's DoI.</param>
 /// <param name="dor">Remote server's DoR.</param>
 /// <param name="syncID">Remote server's SyncID.</param>
 public RemoteServerImpl(Connection connection, IDomainOfInterest doi, IDomainOfResponsibility dor, Guid syncID)
 {
     this.connection = connection;
     this.doi = doi;
     this.dor = dor;
     this.syncID = syncID;
 }
        internal void HandleRemoteRegisteredComponentDefinition(Connection connection, ComponentDef componentDef)
        {
            foreach (IRemoteServer server in ServerSync.RemoteServers)
                if (server.Connection != connection)
                    server.Connection["serverSync.registerComponentDefinition"](componentDef);

            if (ComponentRegistry.Instance.FindComponentDefinition(componentDef.Name) == null)
            {
                lock (ignoredComponentRegistrations)
                    ignoredComponentRegistrations.Add(componentDef.Guid);
                ComponentRegistry.Instance.Register((ComponentDefinition)componentDef);
            }
        }
 /// <summary>
 /// Configures a JsonSerializer used in a given connection to include types names when the declared type of an
 /// object is different from the actual type.
 /// </summary>
 /// <param name="connection">A given connection.</param>
 public static void ConfigureJsonSerializer(Connection connection)
 {
     object settingsObj;
     if (connection.GetProperty("JsonSerializerSettings", out settingsObj))
     {
         JsonSerializerSettings settings = settingsObj as JsonSerializerSettings;
         if (settings != null)
         {
             settings.TypeNameHandling = TypeNameHandling.Auto;
             connection.SetProperty("JsonSerializerSettings", settings);
         }
     }
 }
        /// <summary>
        /// Updates domain-of-interest on the remote server associated with a given connection.
        /// </summary>
        /// <param name="connection">Connection to the remote server.</param>
        /// <param name="serializedDoI">New serialized domain-of-interest.</param>
        internal void HandleRemoteDoIChanged(Connection connection, string serializedDoI)
        {
            foreach (var server in ServerSync.RemoteServers)
            {
                if (server.Connection == connection)
                {
                    var newDoI = StringSerialization.DeserializeObject<IDomainOfInterest>(serializedDoI);
                    (server as RemoteServerImpl).DoI = newDoI;
                    return;
                }
            }

            throw new Exception("Received a DoR update for an unregistered server");
        }
 /// <summary>
 /// Returns login name for a given connection.
 /// </summary>
 /// <returns>The login name or null if such a connection is not registered.</returns>
 /// <param name="connection">Client connection.</param>
 public string GetLoginName(Connection connection)
 {
     if (connectionToLogin.ContainsKey(connection))
         return connectionToLogin[connection];
     return null;
 }
 /// <summary>
 /// Authenticate the user with a specified <paramref name="login"/> and <paramref name="password"/>. Returns
 /// the associated security token as GUID. If authentification fails, Guid.Empty is returned.
 /// </summary>
 /// <param name="connection">Client connection.</param>
 /// <param name="login">Login.</param>
 /// <param name="password">Password.</param>
 /// <returns>True on successful authentication, false otherwise.</returns>
 public bool Authenticate(Connection connection, string login, string password)
 {
     // Currently we just accept any login/password combinations.
     connectionToLogin[connection] = login;
     return true;
 }
        /// <summary>
        /// Handles an entity removal update from the remote sync node and removes the entity locally.
        /// </summary>
        /// <param name="guid">Guid of the removed entity.</param>
        internal void HandleRemoteRemovedEntity(Connection connection, Guid guid)
        {
            lock (syncInfo)
            {
                Entity entity = World.Instance.FindEntity(guid);
                foreach (IRemoteServer server in ServerSync.RemoteServers)
                    if (server.Connection != connection && server.DoI.IsInterestedInEntity(entity))
                        server.Connection["serverSync.removeEntity"](guid);

                if (!syncInfo.ContainsKey(guid))
                {
                    logger.Warn("Ignoring removal of entity that does not exist. Guid: " + guid);
                    return;
                }

                syncInfo.Remove(guid);
                lock (ignoredEntityRemovals)
                    ignoredEntityRemovals.Add(guid);
                World.Instance.Remove(World.Instance.FindEntity(guid));
            }
        }
        /// <summary>
        /// Relays the changes to attributes to other connected sync nodes and process them locally.
        /// </summary>
        /// <param name="guid">Guid of the entity containing affected attributes.</param>
        /// <param name="changedAttributes">A set of modified attributes with their remote sync info.</param>
        internal void HandleRemoteChangedAttributes(Connection connection, Guid guid, EntitySyncInfo changedAttributes)
        {
            Entity entity = World.Instance.FindEntity(guid);
            foreach (IRemoteServer server in ServerSync.RemoteServers)
            {
                if (server.Connection == connection)
                    continue;

                EntitySyncInfo filteredAttributes = new EntitySyncInfo();
                bool containsAttributesToSync = false;
                foreach (var component in changedAttributes.Components)
                {
                    foreach (var attribute in component.Value.Attributes)
                    {
                        if (server.DoI.IsInterestedInAttributeChange(entity, component.Key, attribute.Key))
                        {
                            filteredAttributes[component.Key][attribute.Key] = attribute.Value;
                            containsAttributesToSync = true;
                        }
                    }
                }

                if (containsAttributesToSync)
                    server.Connection["serverSync.changeAttributes"](guid, filteredAttributes);
            }

            ProcessChangedAttributes(guid, changedAttributes);
        }
        internal void HandleRemoteAddedEntity(Connection connection, Guid guid, Guid owner, EntitySyncInfo initialSyncInfo)
        {
            lock (syncInfo)
            {
                if (!syncInfo.ContainsKey(guid))
                {
                    syncInfo.Add(guid, new EntitySyncInfo());
                    lock (ignoredEntityAdditions)
                        ignoredEntityAdditions.Add(guid);
                    World.Instance.Add(new Entity(guid, owner));
                }
                else
                {
                    logger.Warn("Processing addition of already existing entity. Guid: " + guid);
                    return;
                }

                ProcessChangedAttributes(guid, initialSyncInfo);

                Entity entity = World.Instance.FindEntity(guid);
                foreach (IRemoteServer server in ServerSync.RemoteServers)
                    if (server.Connection != connection && server.DoI.IsInterestedInEntity(entity))
                        server.Connection["serverSync.addEntity"](guid, initialSyncInfo);
            }
        }
 public ClientConnectionEventArgs(Connection connection)
 {
     ClientConnection = connection;
 }
        private void WrapUpdateMethods(Connection connection)
        {
            var newObjectUpdates = connection.GenerateClientFunction("objectsync", "receiveNewObjects");
            onNewEntityHandlers[connection] = newObjectUpdates;

            var removedObjectUpdates = connection.GenerateClientFunction("objectsync", "removeObject");
            onRemovedEntityHandlers[connection] = removedObjectUpdates;

            var updatedObjectUpdates = connection.GenerateClientFunction("objectsync", "receiveObjectUpdates");
            UpdateQueue.RegisterToClientUpdates(connection, updatedObjectUpdates);
        }
        bool Authenticate(Connection connection, string login, string password)
        {
            if (!Authentication.Instance.Authenticate(connection, login, password))
                return false;

            authenticatedClients.Add(connection);
            connection.Closed += HandleAuthenticatedClientDisconnected;

            if (OnAuthenticated != null)
                OnAuthenticated(connection);

            foreach (var entry in authenticatedMethods)
                connection.RegisterFuncImplementation(entry.Key, entry.Value);

            WrapUpdateMethods(connection);
            if (NewClientConnected != null)
                NewClientConnected(this, new ClientConnectionEventArgs(connection));
            return true;
        }
        void HandleNewServerConnected(Connection connection)
        {
            IDomainOfInterest doi = null;
            IDomainOfResponsibility dor = null;
            Guid syncID = Guid.Empty;

            connection["serverSync.getDoR"]().OnSuccess<string>(delegate(string serializedDoR) {
                dor = StringSerialization.DeserializeObject<IDomainOfResponsibility>(serializedDoR);
                if (doi != null && syncID != Guid.Empty)
                    AddRemoteServer(connection, dor, doi, syncID);
            });

            connection["serverSync.getDoI"]().OnSuccess<string>(delegate(string serializedDoI)
            {
                doi = StringSerialization.DeserializeObject<IDomainOfInterest>(serializedDoI);
                if (dor != null && syncID != Guid.Empty)
                    AddRemoteServer(connection, dor, doi, syncID);
            });

            connection["serverSync.getSyncID"]().OnSuccess<Guid>(delegate(Guid remoteSyncID)
            {
                syncID = remoteSyncID;
                if (dor != null && doi != null)
                    AddRemoteServer(connection, dor, doi, remoteSyncID);
            });
        }
        void AddRemoteServer(Connection connection, IDomainOfResponsibility dor, IDomainOfInterest doi, Guid syncID)
        {
            if (syncID == ServerSync.LocalServer.SyncID)
                return;

            var newServer = new RemoteServerImpl(connection, doi, dor, syncID);

            lock (remoteServers)
                remoteServers.Add(connection, newServer);

            if (AddedServer != null)
                AddedServer(this, new ServerEventArgs(newServer));

            connection.Closed += delegate(object sender, EventArgs args)
            {
                lock (remoteServers)
                    remoteServers.Remove(connection);

                if (RemovedServer != null)
                    RemovedServer(this, new ServerEventArgs(newServer));
            };
        }