Example #1
0
 private bool PopString(string name)
 {
     try
     {
         string s = packet.PopString();
         return(Log("string {0} = \"{1}\"", name, s));
     }
     catch
     {
         return(Error("No string available"));
     }
 }
Example #2
0
        /// <summary>
        /// Try to login with the specified details and get the response
        /// </summary>
        /// <param name="cdKey">CD key hash for login</param>
        /// <param name="saltedKey">Salted key hash for login</param>
        /// <param name="type">Remote client type (eg. CLIENT or SERVER)</param>
        /// <param name="version">Remote client version</param>
        /// <param name="locale">Remote client locale</param>
        /// <returns>Login response from the server</returns>
        public string Login(string cdKey, string saltedKey, string type, int version, string locale)
        {
            string response = Protocol.LOGIN_RESPONSE_DENIED;

            if (!connectionError)
            {
                try
                {
                    OutboundPacket login = new OutboundPacket();
                    login.Append(cdKey).Append(saltedKey).Append(type).Append(version);
                    if (type == Protocol.HOST_SERVER)
                    {
                        login.Append(-1);                               // stats enabled flag for server
                    }
                    login.Append((byte)0x04).Append(locale);
                    Send(login);

                    InboundPacket loginResponse = Receive();
                    response = loginResponse.PopString();
                }
                catch
                {
                    connectionError = true;
                }
            }

            Close();

            return(response);
        }
Example #3
0
        /// <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
        }
Example #4
0
        /// <summary>
        /// Establish the connection to the remote master server and get the challenge salt
        /// </summary>
        /// <returns>Master server challenge salt (or 0 on failure)</returns>
        public int Connect()
        {
            int salt = 0;

            try
            {
                socket.Connect(host, port);
                InboundPacket challenge = Receive();
                salt = int.Parse(challenge.PopString());
            }
            catch
            {
                connectionError = true;
            }

            return(salt);
        }
Example #5
0
        /// <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
        }
Example #6
0
        /// <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>();
            }
        }
Example #7
0
        /// <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);
        }