/// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="port">The port for the server of the bus. Leave null for default port.</param>
        /// <param name="accessControl">Control requirements for user and password for connecting clients, pass null for no control (everyone can connect).</param>
        public ServerMessageBus(string name, int? port, ServerAccessControl accessControl)
            : base(name)
        {
            AccessControl = accessControl;
            if (port.HasValue == false)
            {
                port = DefaultPort;
            }

            _server = new SocketMessageServer(base.Serializer);
            _server.Start(new IPEndPoint(IPAddress.Any, port.Value));

            _server.ClientAsyncMessageSendEvent += new SocketMessageServer.AsyncMessageSendUpdateDelegate(_server_ClientAsyncMessageSendEvent);
            _server.ClientConnectedEvent += new SocketMessageServer.ServerClientUpdateDelegate(_server_ClientConnectedEvent);
            _server.ClientDisconnectedEvent += new SocketMessageServer.ServerClientUpdateDelegate(_server_ClientDisconnectedEvent);
            _server.ClientMessageReceivedEvent += new SocketMessageServer.MessageUpdateDelegate(_server_ClientMessageReceivedEvent);

            ApplicationLifetimeHelper.ApplicationClosingEvent += new CommonHelper.DefaultDelegate(ApplicationLifetimeHelper_ApplicationClosingEvent);
        }
        void _server_ClientMessageReceivedEvent(SocketMessageServer server, SocketCommunicatorEx client, object message)
        {
            ServerAccessControl accessControl = AccessControl;
            // Check security first.
            if (accessControl != null && message is AccessMessage == false)
            {
                if (accessControl.IsAllowed(ObtainClientAccessControl(client.Id)) == false)
                {
            #if Matrix_Diagnostics
                    InstanceMonitor.Info("Message [" + message.ToString()  +"] from client [" + client.ToString() + "] not allowed due to access control.", TracerItem.PriorityEnum.Medium);
            #endif
                    return;
                }
            }

            if (message is EnvelopeMessage)
            {// Envelope user message.

                EnvelopeMessage envelopeMessage = (EnvelopeMessage)message;

                // Remove the remote message bus index association.
                envelopeMessage.Sender.LocalMessageBusIndex = ClientId.InvalidMessageBusClientIndex;

                foreach (ClientId id in envelopeMessage.Receivers)
                {
                    // Assign the id as local id, if it is, otherwise skip it.
                    id.LocalMessageBusIndex = base.GetClientIndexByGuid(id.Guid);
                    if (id.IsMessageBusIndexValid)
                    {
                        id.MessageBus = this;
                        if (DoSendToClient(envelopeMessage.Sender, id, envelopeMessage.Envelope, null) != SendToClientResultEnum.Success)
                        {
            #if Matrix_Diagnostics
                            InstanceMonitor.OperationError(string.Format("Failed to accept envelope message [{0}].", envelopeMessage.ToString()));
            #endif
                        }
                    }
                    else
                    {
            #if Matrix_Diagnostics
                        InstanceMonitor.OperationError(string.Format("Failed to accept envelope message [{0}] due unrecognized receiver id.", envelopeMessage.ToString()));
            #endif
                    }

                }
            }
            else if (message is ClientsListMessage)
            {// Message bus system message.

                ClientsListMessage updateMessage = (ClientsListMessage)message;
                for (int i = 0; i < updateMessage.Ids.Count; i++)
                {
                    RegisterClientId(client.Id, updateMessage.Ids[i], updateMessage.Types[i], updateMessage.SourcesTypes[i]);
                }

            }
            else if (message is RequestClientListUpdateMessage)
            {
                SendClientsUpdate(client.Id);
            }
            else if (message is ClientUpdateMessage)
            {
                ClientUpdateMessage updateMessage = (ClientUpdateMessage)message;

                bool validClient;
                lock (_syncRoot)
                {
                    validClient = _remoteClientNetId.ContainsKey(updateMessage.ClientId);
                }

                if (validClient)
                {
                    RaiseClientAddedEvent(updateMessage.ClientId);
                }
                else
                {
            #if Matrix_Diagnostics
                    InstanceMonitor.OperationError(string.Format("Failed to raise update event for client [{0}], since client not found.", updateMessage.ClientId.ToString()));
            #endif
                }
            }
            else if (message is AccessMessage)
            {
                ClientAccessControl control = ObtainClientAccessControl(client.Id);
                if (control != null)
                {
                    control.Update(message as AccessMessage);
                }
            }
            else if (message is StateUpdateMessage)
            {
                RaiseCounterPartyUpdateEvent("Client:" + client.Id.ToString(), ((StateUpdateMessage)message).State.ToString());
            }
            else
            {
            #if Matrix_Diagnostics
                InstanceMonitor.Warning(string.Format("Message [{0}] not recognized.", message.GetType().Name));
            #endif
            }
        }
        void _server_ClientDisconnectedEvent(SocketMessageServer server, SocketCommunicatorEx client)
        {
            // Clear all clients hooked on this connection.
            ListUnique<ClientId> clientsIds = null;
            lock (_syncRoot)
            {
                if (_remoteClientsNetIds.TryGetByKey(client.Id, ref clientsIds) == false)
                {
                    return;
                }

                _clientsAccessControl.Remove(client.Id);

                _remoteClientsNetIds.RemoveByKey(client.Id);
                foreach (ClientId id in clientsIds)
                {
                    _remoteClientNetId.Remove(id);
                    _remoteClientsTypes.Remove(id);
                    _remoteClientsSourcesTypesNames.Remove(id);
                }
            }

            // Raise event to notify of the disconnection of all these Ids.
            foreach (ClientId id in clientsIds)
            {
                // Notify of clients removal, with non permanent remove, since they may later be restored.
                RaiseClientRemovedEvent(id, false);
            }
        }
        void _server_ClientConnectedEvent(SocketMessageServer server, SocketCommunicatorEx client)
        {
            // The client expects is, so activate keep alive.
            client.KeepAlive = true;

            // Send local bus clients info to connected element.
            // Important - this will also be sent even to clients that do not have verified access control.
            if (SendClientsUpdate(client.Id) == false)
            {
            #if Matrix_Diagnostics
                InstanceMonitor.OperationError("Failed to send clients update to client [" + client.ToString() + ", " + client.Id + "].");
            #endif
            }
        }
 void _server_ClientAsyncMessageSendEvent(SocketMessageServer server, SocketCommunicatorEx client, SocketCommunicator.AsyncMessageSendInfo info)
 {
     // A message has been successfully sent to client.
 }
        public override void Dispose()
        {
            ApplicationLifetimeHelper.ApplicationClosingEvent -= new CommonHelper.DefaultDelegate(ApplicationLifetimeHelper_ApplicationClosingEvent);

            SocketMessageServer server = _server;
            _server = null;

            if (server != null)
            {
                server.ClientAsyncMessageSendEvent -= new SocketMessageServer.AsyncMessageSendUpdateDelegate(_server_ClientAsyncMessageSendEvent);
                server.ClientConnectedEvent -= new SocketMessageServer.ServerClientUpdateDelegate(_server_ClientConnectedEvent);
                server.ClientDisconnectedEvent -= new SocketMessageServer.ServerClientUpdateDelegate(_server_ClientDisconnectedEvent);
                server.ClientMessageReceivedEvent -= new SocketMessageServer.MessageUpdateDelegate(_server_ClientMessageReceivedEvent);

                server.Stop(TimeSpan.FromSeconds(2));
                server.Dispose();
            }

            base.Dispose();
        }