/// <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(); } } } }
/// <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++) }