/// <summary> /// Handles the player connection, the connection is closed once the request is completed /// </summary> protected override void Handle() { try { InboundPacket clientRequest = Receive(); ClientToMaster clientRequestType = (ClientToMaster)clientRequest.PopByte(); ConnectionLog("REQUEST TYPE={0}", clientRequestType); switch (clientRequestType) { case ClientToMaster.Query: HandleQuery(clientRequest); break; case ClientToMaster.GetMOTD: HandleMOTDRequest(clientRequest); break; case ClientToMaster.QueryUpgrade: HandleQueryUpgrade(clientRequest); break; default: HandleUnknownRequest(clientRequest); break; } } catch (ThreadAbortException) { aborted = true; } catch (Exception) // ex) { //if (!aborted) // MasterServer.Log("Client connection error: {0}", ex.Message); } }
/// <summary> /// Client has made an unrecognised request /// </summary> /// <param name="clientRequest"></param> private void HandleUnknownRequest(InboundPacket clientRequest) { clientRequest.Rewind(); ConnectionLog("UNKNOWN REQUEST CODE={0}", clientRequest.PopByte()); //MasterServer.Log("Client at {0} sent unrecognised query ", socket.RemoteEndPoint.ToString()); }
private bool PopByte(string name) { try { byte b = packet.PopByte(); return(Log("byte {0} = 0x{1:x2}", name, b)); } catch { return(Error("No byte available")); } }
/// <summary> /// Handles a connection from a CLIENT /// </summary> /// <param name="login">Login response packet</param> protected virtual void HandleClientConnection(InboundPacket login) { ConnectionLog(Protocol.LOGIN_RESPONSE_APPROVED); Send(Protocol.LOGIN_RESPONSE_APPROVED); byte osByte = login.PopByte(); // Host's detected operating system locale = login.PopString(); // Host's locale, eg. int, est // Map the OS value to the relevant enum value if it's valid operatingSystem = Enum.IsDefined(typeof(OperatingSystem), osByte) ? (OperatingSystem)osByte : OperatingSystem.UnknownOS; ConnectionLog("{0} OS={1} LOCALE={2}", type, operatingSystem, locale); innerConnection = new ClientConnection(this, socket, logWriter, serverList, geoIP, operatingSystem, locale); innerConnection.Handle(); // Handle the connection in this thread }
/// <summary> /// Handles a connection from a SERVER /// </summary> /// <param name="login">Login response packet</param> protected virtual void HandleServerConnection(InboundPacket login) { ConnectionLog(Protocol.LOGIN_RESPONSE_APPROVED); Send(Protocol.LOGIN_RESPONSE_APPROVED); bool bStatLogging = (login.PopInt() == 0); // Seems to be -1 if disabled, 0 if enabled byte osByte = login.PopByte(); // Host's detected operating system locale = login.PopString(); // Host's locale, eg. int // Map the OS value to the relevant enum value if it's valid operatingSystem = Enum.IsDefined(typeof(OperatingSystem), osByte) ? (OperatingSystem)osByte : OperatingSystem.UnknownOS; ConnectionLog("{0} BSTATLOGGING={1} OS={2} LOCALE={3}", type, bStatLogging, operatingSystem, locale); innerConnection = new ServerConnection(this, socket, logWriter, serverList, geoIP, operatingSystem, locale, bStatLogging, md5Manager, cdKeyValidator, gameStats); innerConnection.Handle(); // Handle the connection in this thread }
/// <summary> /// Handle the server connection /// </summary> protected override void Handle() { // Loop until connection is closed or forcibly aborted while (socket.Connected && !aborted) { try { // Read data from the socket InboundPacket packet = Receive(); if (!packet.Empty && packet.Valid) { ServerInfoPacket serverInfo = (ServerInfoPacket)packet; // Connection is considered "established" once the heartbeat has been established switch (State) { // Waiting for initial greeting from the server case ConnectionState.WaitingHello: HandleHello(serverInfo); break; // Waiting to receive heartbeat from the server case ConnectionState.WaitingHeartbeat: if ((DateTime.Now - waitingHeartbeatTime).TotalSeconds > waitForHeartbeatSeconds) { ConnectionLog("TIMEOUT WAITING HEARTBEAT IN STATE {0}", State); MasterServer.Log("[{0}] Timeout waiting for heartbeat response."); outerConnection.Abort(); } else { ConnectionLog("UNSOLICITED MESSAGE IN STATE {0}", State); } break; // Connection is established, process inbound packets as normal server conversation case ConnectionState.Established: switch (serverInfo.PacketCode) { case ServerToMaster.ClientResponse: HandleClientChallengeResponse(serverInfo); break; case ServerToMaster.GameState: HandleGameState(serverInfo); break; case ServerToMaster.Stats: HandleStats(serverInfo); break; case ServerToMaster.ClientDisconnectFailed: HandleClientDisconnectFailed(serverInfo); break; case ServerToMaster.MD5Version: HandleMD5Version(serverInfo); break; case ServerToMaster.CheckOptionReply: HandleCheckOptionReply(serverInfo); break; default: packet.Rewind(); ConnectionLog("INVALID MESSAGE STATE={0} CODE={1}", State, packet.PopByte()); break; } break; } } else if (socket.Connected) { ConnectionLog("INVALID PACKET STATE={0} DATA={1}", State, packet.PrintBytes(true)); Debug.WriteLine(String.Format("Invalid packet from server at {0} in state {1}", server.Address, State)); Debug.WriteLine(packet.Print()); if (State == ConnectionState.WaitingHeartbeat && (DateTime.Now - waitingHeartbeatTime).TotalSeconds > waitForHeartbeatSeconds) { MasterServer.Log("[{0}] Timeout waiting for heartbeat response.", server); ConnectionLog("TIMEOUT WAITING HEARTBEAT IN STATE {0}", State); outerConnection.Abort(); } } } catch (ThreadAbortException) { aborted = true; } catch (Exception ex) { if (!aborted) { ConnectionLog("ERROR: {0}", ex.Message); } break; } } if (!socket.Connected) { MasterServer.Log("[{0}] Connection closed", server); } serverList.Remove(server); server = null; }