private bool PopInt(string name) { try { int i = packet.PopInt(); return(Log("int {0} = {1}", name, i)); } catch { return(Error("No int available")); } }
/// <summary> /// Creates a new player object from information in a received server data packet /// </summary> /// <param name="packet">Packet containing player information at the current pointer position</param> /// <param name="address">Player address, from the server info header</param> public Player(Server server, InboundPacket packet, string address) { Address = address; PlayerNumber = packet.PopInt(); OnPropertyChanged("PlayerNumber"); if (server.Version > 2225) { PlayerID = packet.PopInt(); OnPropertyChanged("PlayerID"); } Name = packet.PopString(); OnPropertyChanged("Name"); Ping = packet.PopInt(); OnPropertyChanged("Ping"); Score = packet.PopInt(); OnPropertyChanged("Score"); StatsID = packet.PopInt(); OnPropertyChanged("StatsID"); if (server.Version > 2225) { Info = packet.PopKeyValueArray(); OnPropertyChanged("Info"); } else { Info = new Dictionary <string, string>(); } }
/// <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 connection /// </summary> protected virtual void Handle() { try { // Initialise validation context for this session validationContext = cdKeyValidator.BeginValidation("login"); // Log the new connection to the connection log ConnectionLog("ACCEPT LOCALPORT={0} SALT={1}", LocalPort, cdKeyValidator.GetSalt(validationContext)); // Send the challenge salt Send(cdKeyValidator.GetSalt(validationContext).ToString()); // Read back the authentication from the player InboundPacket login = Receive(); cdKey = login.PopString(); // Get the first MD5 which should be the CD key hash saltedCDKey = login.PopString(); // Get the second MD5 which should be the CD key plus salt hash type = login.PopString(); // Type of client eg. CLIENT or SERVER version = login.PopInt(); // Client's engine version // Write the login info to the connection log ConnectionLog("CONNECT MD5={0} SALTED={1} TYPE={2} VERSION={3}", cdKey, saltedCDKey, type, version); // Set values into the validation context validationContext.SetClientInfo(cdKey, saltedCDKey, type, version); // Check the CD key if (Validate(validationContext)) { if (version < Protocol.MIN_SUPPORTED_CLIENT_VERSION) { ConnectionLog(Protocol.LOGIN_RESPONSE_UPGRADE); MasterServer.Log("{0} at {1} rejected, outdated version: got {2}", type, (socket.RemoteEndPoint as IPEndPoint).Address.ToString(), version); // This is my best guess for how an UPGRADE packet should be structured, if it's wrong it seems to crash the client OutboundPacket UpgradePacket = new OutboundPacket(Protocol.LOGIN_RESPONSE_UPGRADE); UpgradePacket.Append(Protocol.MIN_SUPPORTED_CLIENT_VERSION); UpgradePacket.Append(0x00); // Send the UPGRADE response Send(UpgradePacket); } else { // Send MSLIST packet if enabled, if the MSLIST is sent successfully then close the // connection (SendMSList() returns true if the MSLIST was sent) if (!SendMSList()) { switch (type) { case Protocol.HOST_CLIENT: HandleClientConnection(login); break; case Protocol.HOST_SERVER: HandleServerConnection(login); break; default: HandleUnknownConnection(login); break; } } } } } catch (ThreadAbortException) { aborted = true; } catch (Exception ex) { ConnectionLog("EXCEPTION: {0}", ex.Message); } try { socket.Close(); } catch { } ConnectionLog("CLOSED"); ConnectionThreadManager.Remove(Thread.CurrentThread); ConnectionManager.DeRegister(this); }