private void Analyse() { result.Clear(); unknownCounter = 0; tail = packet.PrintBytes(); packet.Rewind(); MatchCollection variables = structureRegex.Matches(structure.Replace("\r", "")); bool continueParsing = true; foreach (Match variable in variables) { string name = (variable.Groups["name"].Value != "") ? variable.Groups["name"].Value : String.Format("Unknown{0}", ++unknownCounter); switch (variable.Groups["pop"].Value.ToLower()) { case "b": continueParsing = PopByte(name); break; case "u": continueParsing = PopUShort(name); break; case "i": continueParsing = PopInt(name); break; case "c": continueParsing = PopCompactIndex(name); break; case "s": continueParsing = PopString(name); break; case "k": continueParsing = PopKeyValueArray(name); break; } if (!continueParsing) { break; } } tail = packet.Print(packet.Pointer); }
/// <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; }