예제 #1
0
        /// <summary>
        /// Searches the first Opened connection, and tries to accept the next incoming connection request.
        /// </summary>
        /// <param name="reportsToSend">The necessary line state reports will be added to this list.</param>
        private void AcceptNextConnection(ref List <LobbyLineState[]> reportsToSend)
        {
            bool openedConnectionFound = false;

            for (int i = 0; i < this.connections.Length; i++)
            {
                if (this.connections[i].LineState == LobbyLineState.Opened)
                {
                    openedConnectionFound = true;
                    if (this.connections[i].TryAcceptNextConnection())
                    {
                        /// The state of a line has been changed so we must notify every client about this change
                        //SendLineStateReports(); /// ---> This call can cause deadlock
                        reportsToSend.Add(this.LineStates);
                    }
                    break;
                }
            }

            if (!openedConnectionFound)
            {
                /// If there is no opened communication line, we accept the connection, send a disconnect_indicator
                /// and close the connection immediately.
                LobbyConnection tmpConnection = CreateConnection_i();
                if (null != tmpConnection && tmpConnection.TryAcceptNextConnection())
                {
                    if (tmpConnection.BeginDisconnect())
                    {
                        tmpConnection.Shutdown();
                    }
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Process all incoming messages arrived from all connections.
 /// </summary>
 private void ProcessIncomingMessages()
 {
     for (int i = 0; i < this.connections.Length; i++)
     {
         if (this.connections[i].ConnectionState == LobbyConnectionState.Connected)
         {
             /// The connection is in connected state --> it's incoming messages will be processed by the server
             List <RCPackage> incomingPackages = new List <RCPackage>();
             if (this.connections[i].ReceiveIncomingPackages(ref incomingPackages))
             {
                 /// Process the incoming messages
                 foreach (RCPackage package in incomingPackages)
                 {
                     if (package.PackageType == RCPackageType.NETWORK_CUSTOM_PACKAGE)
                     {
                         /// This is a custom message, forward it to every other clients
                         package.Sender = i + 1;
                         for (int j = 0; j < this.connections.Length; j++)
                         {
                             if (i != j && this.connections[j].ConnectionState == LobbyConnectionState.Connected)
                             {
                                 if (!this.connections[j].SendPackage(package))
                                 {
                                     /// Unable to forward the message to a client --> Shutdown the connection
                                     this.connections[j].Shutdown();
                                     this.connections[j].LineState = LobbyLineState.Opened; /// Keep it opened for other clients.
                                     SendLineStateReports();
                                 }
                             }
                         }
                         /// Notify the listener object about the arrived package
                         this.listener.PackageArrived(package, i + 1);
                     }
                     else if (package.PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE &&
                              package.PackageFormat.ID == Network.FORMAT_DEDICATED_MESSAGE)
                     {
                         /// This is a dedicated message, forward only to the targets
                         byte[]    targets         = package.ReadByteArray(0); /// List of the targets
                         byte[]    theMessageBytes = package.ReadByteArray(1); /// The embedded message
                         int       parsedBytes     = 0;
                         RCPackage theMessage      = RCPackage.Parse(theMessageBytes, 0, theMessageBytes.Length, out parsedBytes);
                         if (theMessage != null && theMessage.IsCommitted && theMessage.PackageType == RCPackageType.NETWORK_CUSTOM_PACKAGE)
                         {
                             /// The embedded message is OK --> forward it to the dedicated targets
                             theMessage.Sender = i + 1;
                             for (int j = 0; j < targets.Length; j++)
                             {
                                 int target = targets[j];
                                 if (target == 0)
                                 {
                                     /// This server is the target
                                     this.listener.PackageArrived(theMessage, i + 1);
                                 }
                                 else if (target - 1 >= 0 && target - 1 < this.connections.Length && target - 1 != i)
                                 {
                                     /// Another client is the target --> forward the message to it
                                     LobbyConnection targetConn = this.connections[target - 1];
                                     if (targetConn.ConnectionState == LobbyConnectionState.Connected)
                                     {
                                         if (!targetConn.SendPackage(theMessage))
                                         {
                                             /// Unable to forward the message to a target --> Shutdown the connection
                                             targetConn.Shutdown();
                                             targetConn.LineState = LobbyLineState.Opened; /// Keep it opened for other clients.
                                             SendLineStateReports();
                                         }
                                     }
                                 }
                             }
                         }
                         else
                         {
                             /// The embedded message has unexpected format --> Shutdown the connection
                             this.connections[i].Shutdown();
                             this.connections[i].LineState = LobbyLineState.Opened; /// Keep it opened for other clients.
                             SendLineStateReports();
                             break;                                                 /// Stop processing the messages of the closed connection
                         }
                     }
                     else if (this.connections[i].ConnectionState == LobbyConnectionState.Connected &&
                              package.PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE &&
                              package.PackageFormat.ID == Network.FORMAT_DISCONNECT_INDICATOR)
                     {
                         /// The client at the other side of the connection wants to disconnect.
                         /// Acknowledge this request and shutdown the connection.
                         RCPackage disconnAck = RCPackage.CreateNetworkControlPackage(Network.FORMAT_DISCONNECT_ACK);
                         disconnAck.WriteString(0, string.Empty);
                         disconnAck.WriteByteArray(1, new byte[0] {
                         });
                         this.connections[i].SendPackage(disconnAck);
                         this.connections[i].Shutdown();
                         this.connections[i].LineState = LobbyLineState.Opened; /// Keep it opened for other clients.
                         SendLineStateReports();
                         break;                                                 /// Stop processing the messages of the closed connection
                     }
                     else if (package.PackageType == RCPackageType.NETWORK_CONTROL_PACKAGE &&
                              package.PackageFormat.ID != Network.FORMAT_DEDICATED_MESSAGE &&
                              package.PackageFormat.ID != Network.FORMAT_DISCONNECT_ACK &&
                              package.PackageFormat.ID != Network.FORMAT_DISCONNECT_INDICATOR &&
                              package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO &&
                              package.PackageFormat.ID != Network.FORMAT_LOBBY_INFO_VANISHED &&
                              package.PackageFormat.ID != Network.FORMAT_LOBBY_LINE_STATE_REPORT)
                     {
                         /// Custom internal message from a client --> notify the listener
                         this.listener.ControlPackageArrived(package, i + 1);
                     }
                     else
                     {
                         /// Unexpected message from the current connection
                         this.connections[i].Shutdown();
                         this.connections[i].LineState = LobbyLineState.Opened; /// Keep it opened for other clients.
                         SendLineStateReports();
                         break;                                                 /// Stop processing the messages of the closed connection
                     }
                 } /// end-foreach (RCPackage package in incomingPackages)
             }
             else
             {
                 /// In case of receive error, we shutdown the connection.
                 this.connections[i].Shutdown();
                 this.connections[i].LineState = LobbyLineState.Opened; /// Keep it opened for other clients.
                 SendLineStateReports();
             }
         }
         else if (this.connections[i].ConnectionState == LobbyConnectionState.Disconnecting)
         {
             /// The connection is about to disconnect --> incoming messages will be handled by the connection itself
             if (this.connections[i].ContinueDisconnect())
             {
                 /// This connection remains closed because disconnection is initiated by the server.
                 SendLineStateReports();
             }
         }
     } /// end-for (int i = 0; i < this.connections.Length; i++)
 }