Ejemplo n.º 1
0
        public static void Master_Heartbeat( )
        {
            String string_renamed;
            Int32  i;

            if (Globals.dedicated == null || 0 == Globals.dedicated.value)
            {
                return;
            }
            if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value)
            {
                return;
            }
            if (SV_INIT.svs.last_heartbeat > SV_INIT.svs.realtime)
            {
                SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime;
            }
            if (SV_INIT.svs.realtime - SV_INIT.svs.last_heartbeat < SV_MAIN.HEARTBEAT_SECONDS * 1000)
            {
                return;
            }
            SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime;
            string_renamed             = SV_StatusString();
            for (i = 0; i < Defines.MAX_MASTERS; i++)
            {
                if (SV_MAIN.master_adr[i].port != 0)
                {
                    Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\\n");
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "heartbeat\\n" + string_renamed);
                }
            }
        }
Ejemplo n.º 2
0
        public static void SVC_Info( )
        {
            String string_renamed;
            Int32  i, count;
            Int32  version;

            if (SV_MAIN.maxclients.value == 1)
            {
                return;
            }
            version = Lib.Atoi(Cmd.Argv(1));
            if (version != Defines.PROTOCOL_VERSION)
            {
                string_renamed = SV_MAIN.hostname.string_renamed + ": wrong version\\n";
            }
            else
            {
                count = 0;
                for (i = 0; i < SV_MAIN.maxclients.value; i++)
                {
                    if (SV_INIT.svs.clients[i].state >= Defines.cs_connected)
                    {
                        count++;
                    }
                }
                string_renamed = SV_MAIN.hostname.string_renamed + " " + SV_INIT.sv.name + " " + count + "/" + ( Int32 )SV_MAIN.maxclients.value + "\\n";
            }

            Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "info\\n" + string_renamed);
        }
Ejemplo n.º 3
0
        /**
         * SVC_Info, responds with short info for broadcast scans The second parameter should
         * be the current protocol version number.
         */
        public static void SVC_Info()
        {
            string @string;
            int    i, count;
            int    version;

            if (SV_MAIN.maxclients.value == 1)
            {
                return;                 // ignore in single player
            }
            version = Lib.atoi(Cmd.Argv(1));

            if (version != Defines.PROTOCOL_VERSION)
            {
                @string = SV_MAIN.hostname.@string + ": wrong version\n";
            }
            else
            {
                count = 0;

                for (i = 0; i < SV_MAIN.maxclients.value; i++)
                {
                    if (SV_INIT.svs.clients[i].state >= Defines.cs_connected)
                    {
                        count++;
                    }
                }

                @string = SV_MAIN.hostname.@string + " " + SV_INIT.sv.name + " " + count + "/" + (int)SV_MAIN.maxclients.value + "\n";
            }

            Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "info\n" + @string);
        }
Ejemplo n.º 4
0
        public static void Gotnewcl(Int32 i, Int32 challenge, String userinfo, netadr_t adr, Int32 qport)
        {
            SV_MAIN.sv_client = SV_INIT.svs.clients[i];
            var     edictnum = i + 1;
            edict_t ent      = GameBase.g_edicts[edictnum];

            SV_INIT.svs.clients[i].edict     = ent;
            SV_INIT.svs.clients[i].challenge = challenge;
            if (!(PlayerClient.ClientConnect(ent, userinfo)))
            {
                if (Info.Info_ValueForKey(userinfo, "rejmsg") != null)
                {
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\n" + Info.Info_ValueForKey(userinfo, "rejmsg") + "\\nConnection refused.\\n");
                }
                else
                {
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nConnection refused.\\n");
                }
                Com.DPrintf("Game rejected a connection.\\n");
                return;
            }

            SV_INIT.svs.clients[i].userinfo = userinfo;
            SV_UserinfoChanged(SV_INIT.svs.clients[i]);
            Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "client_connect");
            Netchan.Setup(Defines.NS_SERVER, SV_INIT.svs.clients[i].netchan, adr, qport);
            SV_INIT.svs.clients[i].state = Defines.cs_connected;
            SZ.Init(SV_INIT.svs.clients[i].datagram, SV_INIT.svs.clients[i].datagram_buf, SV_INIT.svs.clients[i].datagram_buf.Length);
            SV_INIT.svs.clients[i].datagram.allowoverflow = true;
            SV_INIT.svs.clients[i].lastmessage            = SV_INIT.svs.realtime;
            SV_INIT.svs.clients[i].lastconnect            = SV_INIT.svs.realtime;
            Com.DPrintf("new client added.\\n");
        }
Ejemplo n.º 5
0
        public static void SVC_GetChallenge( )
        {
            Int32 i;
            Int32 oldest;
            Int32 oldestTime;

            oldest     = 0;
            oldestTime = 0x7fffffff;
            for (i = 0; i < Defines.MAX_CHALLENGES; i++)
            {
                if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr))
                {
                    break;
                }
                if (SV_INIT.svs.challenges[i].time < oldestTime)
                {
                    oldestTime = SV_INIT.svs.challenges[i].time;
                    oldest     = i;
                }
            }

            if (i == Defines.MAX_CHALLENGES)
            {
                SV_INIT.svs.challenges[oldest].challenge = Lib.Rand() & 0x7fff;
                SV_INIT.svs.challenges[oldest].adr       = Globals.net_from;
                SV_INIT.svs.challenges[oldest].time      = ( Int32 )Globals.curtime;
                i = oldest;
            }

            Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "challenge " + SV_INIT.svs.challenges[i].challenge);
        }
Ejemplo n.º 6
0
        /**
         * Master_Shutdown, Informs all masters that this server is going down.
         */
        public static void Master_Shutdown()
        {
            int i;

            // pgm post3.19 change, cvar pointer not validated before dereferencing
            if (null == Globals.dedicated || 0 == Globals.dedicated.value)
            {
                return;                 // only dedicated servers send heartbeats
            }
            // pgm post3.19 change, cvar pointer not validated before dereferencing
            if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value)
            {
                return;                 // a private dedicated game
            }
            // send to group master
            for (i = 0; i < Defines.MAX_MASTERS; i++)
            {
                if (SV_MAIN.master_adr[i].port != 0)
                {
                    if (i > 0)
                    {
                        Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\n");
                    }

                    Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "shutdown");
                }
            }
        }
Ejemplo n.º 7
0
        /**
         * Initializes player structures after successfull connection.
         */
        public static void gotnewcl(int i, int challenge, string userinfo, netadr_t adr, int qport)
        {
            // build a new connection
            // accept the new client
            // this is the only place a client_t is ever initialized

            SV_MAIN.sv_client = SV_INIT.svs.clients[i];

            var edictnum = i + 1;

            var ent = GameBase.g_edicts[edictnum];

            SV_INIT.svs.clients[i].edict = ent;

            // save challenge for checksumming
            SV_INIT.svs.clients[i].challenge = challenge;

            // get the game a chance to reject this connection or modify the
            // userinfo
            if (!PlayerClient.ClientConnect(ent, userinfo))
            {
                if (Info.Info_ValueForKey(userinfo, "rejmsg") != null)
                {
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\n" + Info.Info_ValueForKey(userinfo, "rejmsg") + "\nConnection refused.\n");
                }
                else
                {
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nConnection refused.\n");
                }

                Com.DPrintf("Game rejected a connection.\n");

                return;
            }

            // parse some info from the info strings
            SV_INIT.svs.clients[i].userinfo = userinfo;
            SV_MAIN.SV_UserinfoChanged(SV_INIT.svs.clients[i]);

            // send the connect packet to the client
            Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "client_connect");

            Netchan.Setup(Defines.NS_SERVER, SV_INIT.svs.clients[i].netchan, adr, qport);

            SV_INIT.svs.clients[i].state = Defines.cs_connected;

            SZ.Init(SV_INIT.svs.clients[i].datagram, SV_INIT.svs.clients[i].datagram_buf, SV_INIT.svs.clients[i].datagram_buf.Length);

            SV_INIT.svs.clients[i].datagram.allowoverflow = true;
            SV_INIT.svs.clients[i].lastmessage            = SV_INIT.svs.realtime;  // don't timeout
            SV_INIT.svs.clients[i].lastconnect            = SV_INIT.svs.realtime;
            Com.DPrintf("new client added.\n");
        }
Ejemplo n.º 8
0
        /*
         * ===============================================================================
         *
         * OPERATOR CONSOLE ONLY COMMANDS
         *
         * These commands can only be entered from stdin or by a remote operator datagram
         * ===============================================================================
         */

        /*
         * ====================
         * SV_SetMaster_f
         *
         * Specify a list of master servers
         * ====================
         */
        public static void SV_SetMaster_f()
        {
            int i, slot;

            // only dedicated servers send heartbeats
            if (Globals.dedicated.value == 0)
            {
                Com.Printf("Only dedicated servers use masters.\n");

                return;
            }

            // make sure the server is listed public
            Cvar.Set("public", "1");

            for (i = 1; i < Defines.MAX_MASTERS; i++)
            {
                SV_MAIN.master_adr[i] = new();
            }

            slot = 1;             // slot 0 will always contain the id master

            for (i = 1; i < Cmd.Argc(); i++)
            {
                if (slot == Defines.MAX_MASTERS)
                {
                    break;
                }

                if (!NET.StringToAdr(Cmd.Argv(i), SV_MAIN.master_adr[i]))
                {
                    Com.Printf("Bad address: " + Cmd.Argv(i) + "\n");

                    continue;
                }

                if (SV_MAIN.master_adr[slot].port == 0)
                {
                    SV_MAIN.master_adr[slot].port = Defines.PORT_MASTER;
                }

                Com.Printf("Master server at " + NET.AdrToString(SV_MAIN.master_adr[slot]) + "\n");
                Com.Printf("Sending a ping.\n");

                Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[slot], "ping");

                slot++;
            }

            SV_INIT.svs.last_heartbeat = -9999999;
        }
Ejemplo n.º 9
0
        public static void Master_Heartbeat()
        {
            string @string;
            int    i;

            // pgm post3.19 change, cvar pointer not validated before dereferencing
            if (Globals.dedicated == null || 0 == Globals.dedicated.value)
            {
                return;                 // only dedicated servers send heartbeats
            }
            // pgm post3.19 change, cvar pointer not validated before dereferencing
            if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value)
            {
                return;                 // a private dedicated game
            }
            // check for time wraparound
            if (SV_INIT.svs.last_heartbeat > SV_INIT.svs.realtime)
            {
                SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime;
            }

            if (SV_INIT.svs.realtime - SV_INIT.svs.last_heartbeat < SV_MAIN.HEARTBEAT_SECONDS * 1000)
            {
                return;                 // not time to send yet
            }
            SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime;

            // send the same string that we would give for a status OOB command
            @string = SV_MAIN.SV_StatusString();

            // send to group master
            for (i = 0; i < Defines.MAX_MASTERS; i++)
            {
                if (SV_MAIN.master_adr[i].port != 0)
                {
                    Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\n");
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "heartbeat\n" + @string);
                }
            }
        }
Ejemplo n.º 10
0
        public static void Master_Shutdown( )
        {
            Int32 i;

            if (null == Globals.dedicated || 0 == Globals.dedicated.value)
            {
                return;
            }
            if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value)
            {
                return;
            }
            for (i = 0; i < Defines.MAX_MASTERS; i++)
            {
                if (SV_MAIN.master_adr[i].port != 0)
                {
                    if (i > 0)
                    {
                        Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\\n");
                    }
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "shutdown");
                }
            }
        }
Ejemplo n.º 11
0
        /**
         * Returns a challenge number that can be used in a subsequent
         * client_connect command. We do this to prevent denial of service attacks
         * that flood the server with invalid connection IPs. With a challenge, they
         * must give a valid IP address.
         */
        public static void SVC_GetChallenge()
        {
            int i;
            int oldest;
            int oldestTime;

            oldest     = 0;
            oldestTime = 0x7fffffff;

            // see if we already have a challenge for this ip
            for (i = 0; i < Defines.MAX_CHALLENGES; i++)
            {
                if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr))
                {
                    break;
                }

                if (SV_INIT.svs.challenges[i].time < oldestTime)
                {
                    oldestTime = SV_INIT.svs.challenges[i].time;
                    oldest     = i;
                }
            }

            if (i == Defines.MAX_CHALLENGES)
            {
                // overwrite the oldest
                SV_INIT.svs.challenges[oldest].challenge = Lib.rand() & 0x7fff;
                SV_INIT.svs.challenges[oldest].adr       = Globals.net_from;
                SV_INIT.svs.challenges[oldest].time      = (int)Globals.curtime;
                i = oldest;
            }

            // send it back
            Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "challenge " + SV_INIT.svs.challenges[i].challenge);
        }
Ejemplo n.º 12
0
 public static void SVC_Status( )
 {
     Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "print\\n" + SV_StatusString());
 }
Ejemplo n.º 13
0
        public static void SVC_DirectConnect( )
        {
            String   userinfo;
            netadr_t adr;
            Int32    i;
            client_t cl;
            Int32    version;
            Int32    qport;

            adr = Globals.net_from;
            Com.DPrintf("SVC_DirectConnect ()\\n");
            version = Lib.Atoi(Cmd.Argv(1));
            if (version != Defines.PROTOCOL_VERSION)
            {
                Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nServer is version " + Globals.VERSION + "\\n");
                Com.DPrintf("    rejected connect from version " + version + "\\n");
                return;
            }

            qport = Lib.Atoi(Cmd.Argv(2));
            var challenge = Lib.Atoi(Cmd.Argv(3));

            userinfo = Cmd.Argv(4);
            userinfo = Info.Info_SetValueForKey(userinfo, "ip", NET.AdrToString(Globals.net_from));
            if (SV_INIT.sv.attractloop)
            {
                if (!NET.IsLocalAddress(adr))
                {
                    Com.Printf("Remote connect in attract loop.  Ignored.\\n");
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nConnection refused.\\n");
                    return;
                }
            }

            if (!NET.IsLocalAddress(adr))
            {
                for (i = 0; i < Defines.MAX_CHALLENGES; i++)
                {
                    if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr))
                    {
                        if (challenge == SV_INIT.svs.challenges[i].challenge)
                        {
                            break;
                        }
                        Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nBad challenge.\\n");
                        return;
                    }
                }

                if (i == Defines.MAX_CHALLENGES)
                {
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nNo challenge for address.\\n");
                    return;
                }
            }

            for (i = 0; i < SV_MAIN.maxclients.value; i++)
            {
                cl = SV_INIT.svs.clients[i];
                if (cl.state == Defines.cs_free)
                {
                    continue;
                }
                if (NET.CompareBaseAdr(adr, cl.netchan.remote_address) && (cl.netchan.qport == qport || adr.port == cl.netchan.remote_address.port))
                {
                    if (!NET.IsLocalAddress(adr) && (SV_INIT.svs.realtime - cl.lastconnect) < (( Int32 )SV_MAIN.sv_reconnect_limit.value * 1000))
                    {
                        Com.DPrintf(NET.AdrToString(adr) + ":reconnect rejected : too soon\\n");
                        return;
                    }

                    Com.Printf(NET.AdrToString(adr) + ":reconnect\\n");
                    Gotnewcl(i, challenge, userinfo, adr, qport);
                    return;
                }
            }

            var index = -1;

            for (i = 0; i < SV_MAIN.maxclients.value; i++)
            {
                cl = SV_INIT.svs.clients[i];
                if (cl.state == Defines.cs_free)
                {
                    index = i;
                    break;
                }
            }

            if (index == -1)
            {
                Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nServer is full.\\n");
                Com.DPrintf("Rejected a connection.\\n");
                return;
            }

            Gotnewcl(index, challenge, userinfo, adr, qport);
        }
Ejemplo n.º 14
0
 public static void SVC_Ping( )
 {
     Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "ack");
 }
Ejemplo n.º 15
0
        /**
         * A connection request that did not come from the master.
         */
        public static void SVC_DirectConnect()
        {
            string   userinfo;
            netadr_t adr;
            int      i;
            client_t cl;

            int version;
            int qport;

            adr = Globals.net_from;

            Com.DPrintf("SVC_DirectConnect ()\n");

            version = Lib.atoi(Cmd.Argv(1));

            if (version != Defines.PROTOCOL_VERSION)
            {
                Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nServer is version " + Globals.VERSION + "\n");
                Com.DPrintf("    rejected connect from version " + version + "\n");

                return;
            }

            qport = Lib.atoi(Cmd.Argv(2));
            var challenge = Lib.atoi(Cmd.Argv(3));

            userinfo = Cmd.Argv(4);

            // force the IP key/value pair so the game can filter based on ip
            userinfo = Info.Info_SetValueForKey(userinfo, "ip", NET.AdrToString(Globals.net_from));

            // attractloop servers are ONLY for local clients
            if (SV_INIT.sv.attractloop)
            {
                if (!NET.IsLocalAddress(adr))
                {
                    Com.Printf("Remote connect in attract loop.  Ignored.\n");
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nConnection refused.\n");

                    return;
                }
            }

            // see if the challenge is valid
            if (!NET.IsLocalAddress(adr))
            {
                for (i = 0; i < Defines.MAX_CHALLENGES; i++)
                {
                    if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr))
                    {
                        if (challenge == SV_INIT.svs.challenges[i].challenge)
                        {
                            break;                             // good
                        }
                        Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nBad challenge.\n");

                        return;
                    }
                }

                if (i == Defines.MAX_CHALLENGES)
                {
                    Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nNo challenge for address.\n");

                    return;
                }
            }

            // if there is already a slot for this ip, reuse it
            for (i = 0; i < SV_MAIN.maxclients.value; i++)
            {
                cl = SV_INIT.svs.clients[i];

                if (cl.state == Defines.cs_free)
                {
                    continue;
                }

                if (NET.CompareBaseAdr(adr, cl.netchan.remote_address) && (cl.netchan.qport == qport || adr.port == cl.netchan.remote_address.port))
                {
                    if (!NET.IsLocalAddress(adr) && SV_INIT.svs.realtime - cl.lastconnect < (int)SV_MAIN.sv_reconnect_limit.value * 1000)
                    {
                        Com.DPrintf(NET.AdrToString(adr) + ":reconnect rejected : too soon\n");

                        return;
                    }

                    Com.Printf(NET.AdrToString(adr) + ":reconnect\n");

                    SV_MAIN.gotnewcl(i, challenge, userinfo, adr, qport);

                    return;
                }
            }

            // find a client slot
            //newcl = null;
            var index = -1;

            for (i = 0; i < SV_MAIN.maxclients.value; i++)
            {
                cl = SV_INIT.svs.clients[i];

                if (cl.state == Defines.cs_free)
                {
                    index = i;

                    break;
                }
            }

            if (index == -1)
            {
                Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nServer is full.\n");
                Com.DPrintf("Rejected a connection.\n");

                return;
            }

            SV_MAIN.gotnewcl(index, challenge, userinfo, adr, qport);
        }