/// <summary> /// Starts authenticating the user /// </summary> /// <param name="connection"></param> /// <param name="username"></param> /// <param name="password"></param> public void Authenticate(NetConnection connection, String username, String password) { // Hey we can't yet, connect first if (!IsConnected) { Connect(_serverEP); return; } SetStep(AuthenticationStatus.ServerConnection); NetLobby.Authenticate(connection, username, password); _handshake = connection.Tag as Handshake; SetStep(AuthenticationStatus.HandshakeData); }
/// <summary> /// /// </summary> public void Loop() { try { // This is checked each cycle while (this.IsRunning) { _client.MessageReceivedEvent.WaitOne(1000); NetIncomingMessage msg = _client.ReadMessage(); // No message received, please relieve CPU if (msg == null) { continue; } switch (msg.MessageType) { case NetIncomingMessageType.Data: if (msg.SenderConnection.Tag is Connection) { ((Connection)msg.SenderConnection.Tag).IncomingMessage(msg); } else { NetLobby.IncomingMessage(msg); } break; case NetIncomingMessageType.StatusChanged: NetConnectionStatus statusByte = (NetConnectionStatus)msg.ReadByte(); switch (statusByte) { case NetConnectionStatus.Disconnecting: break; // When disconnect is called and processed case NetConnectionStatus.Disconnected: // If already connection established, destroy resources if (msg.SenderConnection.Tag is Connection && !((Connection)msg.SenderConnection.Tag).IsDisposed) { ((Connection)msg.SenderConnection.Tag).Dispose(); } // Received a reason for disconnecting? (e.a. Handshake Fail) String finalReason = Encoding.UTF8.GetString(msg.ReadBytes((Int32)msg.ReadVariableUInt32())); // Some exceptions that should be catched but even so if (finalReason.StartsWith("Handshake data validation failed")) { SetStep(AuthenticationStatus.NoServerConnection); OnAuthenticationFailed.Invoke("Could not connect"); } else if (finalReason.StartsWith("Failed to establish")) { SetStep(AuthenticationStatus.NoServerConnection); OnAuthenticationTimeout.Invoke("Could not connect"); } Disconnect(""); break; case NetConnectionStatus.Connected: SetStep(AuthenticationStatus.ServerConnection); var username = _username; var password = _password; // Connected so lets start authenticating Authenticate(_client.ServerConnection, _username, _password); break; } break; } } Disconnect(""); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
/// <summary> /// Client message loop /// </summary> private void ClientLoop() { NetIncomingMessage msg; while (this.IsRunning) { _server.MessageReceivedEvent.WaitOne(1000); msg = _server.ReadMessage(); // If this second no messages accepted, releave CPU if (msg == null) { continue; } try { switch (msg.MessageType) { // MESSAGETYPE: DATA // The main message type in networking is the data type. When the connection is not linked, the // data is the verification data of the handshake and will be processed accordingly. If not, // the message is passed onto the Connection and processed by their respective protocol. case NetIncomingMessageType.Data: var connection = msg.SenderConnection.Tag as Connection; if (connection != null) { // Client was authenticated so just process the message connection.IncomingMessage(msg); } else { // Client is not yet authenticate so handle that. In my case we directly expect // authentication, but you can write your own handling code. The following code // handles just that. var handshake = NetLobby.IncomingMessage(msg); switch (handshake) { case Handshake.Contents.Succes: Connection new_connection = new Connection(_server, msg.SenderConnection, (msg.SenderConnection.Tag as Handshake).CreateEncryption()); OnConnected.Invoke(new_connection.NodeId, new_connection.Username); break; case Handshake.Contents.Error: case Handshake.Contents.Denied: msg.SenderConnection.Disconnect("Error occured during handshake."); break; case Handshake.Contents.Expired: msg.SenderConnection.Disconnect("Handshake expired."); break; } } break; // MESSAGETYPE: CONNECTION APPROVAL // The ConnectionApproval message type is seen when a node yields the peer#connect function. When // the RemoteEndpoint specified is reached, a loose connection is made. It's up to the other end, // the one that is connected too, to deny or approve the connection. case NetIncomingMessageType.ConnectionApproval: // Here you can add approval code to the public section of the server msg.SenderConnection.Approve(); break; // MESSAGETYPE: STATUS CHANGED // Internal type that is triggered when a connection is initiated, responded too, connecting, // disconnecting, connected or disconnected. Upon a connection, we might have received some // RemoteHailData. This is part of the SRPP protocol and is proccesed accordingly. When // disconnecting, the Connection is disposed, internal connection is disconnected and all is // logged. case NetIncomingMessageType.StatusChanged: NetConnectionStatus statusByte = (NetConnectionStatus)msg.ReadByte(); switch (statusByte) { case NetConnectionStatus.Disconnecting: break; case NetConnectionStatus.Disconnected: // If already connection established, destroy resources var disconnected_connection = msg.SenderConnection.Tag as Connection; if (disconnected_connection != null) { OnDisconnected.Invoke(disconnected_connection.NodeId, disconnected_connection.Username); if (!disconnected_connection.IsDisposed) { disconnected_connection.Dispose(); } } String finalReason = Encoding.UTF8.GetString(msg.ReadBytes((Int32)msg.ReadVariableUInt32())); // Do something with the message if you want like logging: Received a reason for disconnecting... break; case NetConnectionStatus.Connected: break; default: String statusChange = Encoding.UTF8.GetString(msg.ReadBytes((Int32)msg.ReadVariableUInt32())); // You can log/debug status messages here break; } break; #if DEBUG case NetIncomingMessageType.DebugMessage: String debugMessage = Encoding.UTF8.GetString(msg.ReadBytes((Int32)msg.ReadVariableUInt32())); // log break; #endif case NetIncomingMessageType.WarningMessage: String warningMessage = Encoding.UTF8.GetString(msg.ReadBytes((Int32)msg.ReadVariableUInt32())); // log; break; case NetIncomingMessageType.ErrorMessage: String errorMessage = Encoding.UTF8.GetString(msg.ReadBytes((Int32)msg.ReadVariableUInt32())); // log break; default: throw new NetException("MessageType: " + msg.MessageType + " is not supported."); } // Recycle please _server.Recycle(msg); } catch (Exception e) { try { // Disconnect client on error msg.SenderConnection.Disconnect("No tolerance: exception " + e.Message); } catch (Exception) { } } } // Early shutdown _server.Shutdown("Server shutting down"); Console.WriteLine("Client Service is Stopping at " + NetTime.ToReadable(NetTime.Now)); _server.Shutdown("Final shutdown"); }