Exemple #1
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");
                }
            }
        }
Exemple #2
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);
                }
            }
        }
Exemple #3
0
        public static bool Process(netchan_t chan, sizebuf_t msg)
        {
            MSG.BeginReading(msg);
            int sequence     = MSG.ReadLong(msg);
            int sequence_ack = MSG.ReadLong(msg);

            if (chan.sock == Defines.NS_SERVER)
            {
                MSG.ReadShort(msg);
            }
            int reliable_message = sequence >> 31;
            int reliable_ack     = sequence_ack >> 31;

            sequence     &= ~(1 << 31);
            sequence_ack &= ~(1 << 31);
            if (showpackets.value != 0)
            {
                if (reliable_message != 0)
                {
                    Com.Printf("recv " + msg.cursize + " : s=" + sequence + " reliable=" + (chan.incoming_reliable_sequence ^ 1) + " ack=" + sequence_ack + " rack=" + reliable_ack + "\\n");
                }
                else
                {
                    Com.Printf("recv " + msg.cursize + " : s=" + sequence + " ack=" + sequence_ack + " rack=" + reliable_ack + "\\n");
                }
            }

            if (sequence <= chan.incoming_sequence)
            {
                if (showdrop.value != 0)
                {
                    Com.Printf(NET.AdrToString(chan.remote_address) + ":Out of order packet " + sequence + " at " + chan.incoming_sequence + "\\n");
                }
                return(false);
            }

            chan.dropped = sequence - (chan.incoming_sequence + 1);
            if (chan.dropped > 0)
            {
                if (showdrop.value != 0)
                {
                    Com.Printf(NET.AdrToString(chan.remote_address) + ":Dropped " + chan.dropped + " packets at " + sequence + "\\n");
                }
            }

            if (reliable_ack == chan.reliable_sequence)
            {
                chan.reliable_length = 0;
            }
            chan.incoming_sequence              = sequence;
            chan.incoming_acknowledged          = sequence_ack;
            chan.incoming_reliable_acknowledged = reliable_ack;
            if (reliable_message != 0)
            {
                chan.incoming_reliable_sequence ^= 1;
            }

            chan.last_received = (int)Globals.curtime;
            return(true);
        }
Exemple #4
0
        public static void SVC_RemoteCommand( )
        {
            Int32  i;
            String remaining;

            i = Rcon_Validate();
            var msg = Lib.CtoJava(Globals.net_message.data, 4, 1024);

            if (i == 0)
            {
                Com.Printf("Bad rcon from " + NET.AdrToString(Globals.net_from) + ":\\n" + msg + "\\n");
            }
            else
            {
                Com.Printf("Rcon from " + NET.AdrToString(Globals.net_from) + ":\\n" + msg + "\\n");
            }
            Com.BeginRedirect(Defines.RD_PACKET, SV_SEND.sv_outputbuf, Defines.SV_OUTPUTBUF_LENGTH, new AnonymousRD_Flusher());
            if (0 == Rcon_Validate())
            {
                Com.Printf("Bad rcon_password.\\n");
            }
            else
            {
                remaining = "";
                for (i = 2; i < Cmd.Argc(); i++)
                {
                    remaining += Cmd.Argv(i);
                    remaining += " ";
                }

                Cmd.ExecuteString(remaining);
            }

            Com.EndRedirect();
        }
Exemple #5
0
        public static void Transmit(netchan_t chan, int length, byte[] data)
        {
            int send_reliable;
            int w1, w2;

            if (chan.message.overflowed)
            {
                chan.fatal_error = true;
                Com.Printf(NET.AdrToString(chan.remote_address) + ":Outgoing message overflow\\n");
                return;
            }

            send_reliable = Netchan_NeedReliable(chan) ? 1 : 0;
            if (chan.reliable_length == 0 && chan.message.cursize != 0)
            {
                System.Array.Copy(chan.message_buf, 0, chan.reliable_buf, 0, chan.message.cursize);
                chan.reliable_length    = chan.message.cursize;
                chan.message.cursize    = 0;
                chan.reliable_sequence ^= 1;
            }

            SZ.Init(send, send_buf, send_buf.Length);
            w1 = (chan.outgoing_sequence & ~(1 << 31)) | (send_reliable << 31);
            w2 = (chan.incoming_sequence & ~(1 << 31)) | (chan.incoming_reliable_sequence << 31);
            chan.outgoing_sequence++;
            chan.last_sent = (int)Globals.curtime;
            MSG.WriteInt(send, w1);
            MSG.WriteInt(send, w2);
            if (chan.sock == Defines.NS_CLIENT)
            {
                MSG.WriteShort(send, (int)qport.value);
            }
            if (send_reliable != 0)
            {
                SZ.Write(send, chan.reliable_buf, chan.reliable_length);
                chan.last_reliable_sequence = chan.outgoing_sequence;
            }

            if (send.maxsize - send.cursize >= length)
            {
                SZ.Write(send, data, length);
            }
            else
            {
                Com.Printf("Netchan_Transmit: dumped unreliable\\n");
            }
            NET.SendPacket(chan.sock, send.cursize, send.data, chan.remote_address);
            if (showpackets.value != 0)
            {
                if (send_reliable != 0)
                {
                    Com.Printf("send " + send.cursize + " : s=" + (chan.outgoing_sequence - 1) + " reliable=" + chan.reliable_sequence + " ack=" + chan.incoming_sequence + " rack=" + chan.incoming_reliable_sequence + "\\n");
                }
                else
                {
                    Com.Printf("send " + send.cursize + " : s=" + (chan.outgoing_sequence - 1) + " ack=" + chan.incoming_sequence + " rack=" + chan.incoming_reliable_sequence + "\\n");
                }
            }
        }
Exemple #6
0
        public static void SV_Status_f( )
        {
            Int32    i, j, l;
            client_t cl;
            String   s;
            Int32    ping;

            if (SV_INIT.svs.clients == null)
            {
                Com.Printf("No server running.\\n");
                return;
            }

            Com.Printf("map              : " + SV_INIT.sv.name + "\\n");
            Com.Printf("num score ping name            lastmsg address               qport \\n");
            Com.Printf("--- ----- ---- --------------- ------- --------------------- ------\\n");
            for (i = 0; i < SV_MAIN.maxclients.value; i++)
            {
                cl = SV_INIT.svs.clients[i];
                if (0 == cl.state)
                {
                    continue;
                }
                Com.Printf("%3i ", i);
                Com.Printf("%5i ", cl.edict.client.ps.stats[Defines.STAT_FRAGS]);
                if (cl.state == Defines.cs_connected)
                {
                    Com.Printf("CNCT ");
                }
                else if (cl.state == Defines.cs_zombie)
                {
                    Com.Printf("ZMBI ");
                }
                else
                {
                    ping = cl.ping < 9999 ? cl.ping : 9999;
                    Com.Printf("%4i ", ping);
                }

                Com.Printf("%s", cl.name);
                l = 16 - cl.name.Length;
                for (j = 0; j < l; j++)
                {
                    Com.Printf(" ");
                }
                Com.Printf("%7i ", SV_INIT.svs.realtime - cl.lastmessage);
                s = NET.AdrToString(cl.netchan.remote_address);
                Com.Printf(s);
                l = 22 - s.Length;
                for (j = 0; j < l; j++)
                {
                    Com.Printf(" ");
                }
                Com.Printf("%5i", cl.netchan.qport);
                Com.Printf("\\n");
            }

            Com.Printf("\\n");
        }
Exemple #7
0
        /**
         * A connectionless packet has four leading 0xff characters to distinguish
         * it from a game channel. Clients that are in the game can still send
         * connectionless packets. It is used also by rcon commands.
         */
        public static void SV_ConnectionlessPacket()
        {
            string s;
            string c;

            MSG.BeginReading(Globals.net_message);
            MSG.ReadLong(Globals.net_message);             // skip the -1 marker

            s = MSG.ReadStringLine(Globals.net_message);

            Cmd.TokenizeString(s.ToCharArray(), false);

            c = Cmd.Argv(0);

            //for debugging purposes
            //Com.Printf("Packet " + NET.AdrToString(Netchan.net_from) + " : " + c + "\n");
            //Com.Printf(Lib.hexDump(net_message.data, 64, false) + "\n");

            if (0 == Lib.strcmp(c, "ping"))
            {
                SV_MAIN.SVC_Ping();
            }
            else if (0 == Lib.strcmp(c, "ack"))
            {
                SV_MAIN.SVC_Ack();
            }
            else if (0 == Lib.strcmp(c, "status"))
            {
                SV_MAIN.SVC_Status();
            }
            else if (0 == Lib.strcmp(c, "info"))
            {
                SV_MAIN.SVC_Info();
            }
            else if (0 == Lib.strcmp(c, "getchallenge"))
            {
                SV_MAIN.SVC_GetChallenge();
            }
            else if (0 == Lib.strcmp(c, "connect"))
            {
                SV_MAIN.SVC_DirectConnect();
            }
            else if (0 == Lib.strcmp(c, "rcon"))
            {
                SV_MAIN.SVC_RemoteCommand();
            }
            else
            {
                Com.Printf("bad connectionless packet from " + NET.AdrToString(Globals.net_from) + "\n");
                Com.Printf("[" + s + "]\n");
                Com.Printf("" + Lib.hexDump(Globals.net_message.data, 128, false));
            }
        }
Exemple #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;
        }
Exemple #9
0
        public static void SV_ConnectionlessPacket( )
        {
            String s;
            String c;

            MSG.BeginReading(Globals.net_message);
            MSG.ReadLong(Globals.net_message);
            s = MSG.ReadStringLine(Globals.net_message);
            Cmd.TokenizeString(s.ToCharArray(), false);
            c = Cmd.Argv(0);
            if (0 == Lib.Strcmp(c, "ping"))
            {
                SVC_Ping();
            }
            else if (0 == Lib.Strcmp(c, "ack"))
            {
                SVC_Ack();
            }
            else if (0 == Lib.Strcmp(c, "status"))
            {
                SVC_Status();
            }
            else if (0 == Lib.Strcmp(c, "info"))
            {
                SVC_Info();
            }
            else if (0 == Lib.Strcmp(c, "getchallenge"))
            {
                SVC_GetChallenge();
            }
            else if (0 == Lib.Strcmp(c, "connect"))
            {
                SVC_DirectConnect();
            }
            else if (0 == Lib.Strcmp(c, "rcon"))
            {
                SVC_RemoteCommand();
            }
            else
            {
                Com.Printf("bad connectionless packet from " + NET.AdrToString(Globals.net_from) + "\\n");
                Com.Printf("[" + s + "]\\n");
                Com.Printf("" + Lib.HexDump(Globals.net_message.data, 128, false));
            }
        }
Exemple #10
0
        /**
         * A client issued an rcon command. Shift down the remaining args Redirect
         * all printfs fromt hte server to the client.
         */
        public static void SVC_RemoteCommand()
        {
            int    i;
            string remaining;

            i = SV_MAIN.Rcon_Validate();

            var msg = Lib.CtoJava(Globals.net_message.data, 4, 1024);

            if (i == 0)
            {
                Com.Printf("Bad rcon from " + NET.AdrToString(Globals.net_from) + ":\n" + msg + "\n");
            }
            else
            {
                Com.Printf("Rcon from " + NET.AdrToString(Globals.net_from) + ":\n" + msg + "\n");
            }

            Com.BeginRedirect(
                Defines.RD_PACKET,
                SV_SEND.sv_outputbuf,
                Defines.SV_OUTPUTBUF_LENGTH,
                (target, buffer) => { SV_SEND.SV_FlushRedirect(target, Lib.stringToBytes(buffer.ToString())); }
                );

            if (0 == SV_MAIN.Rcon_Validate())
            {
                Com.Printf("Bad rcon_password.\n");
            }
            else
            {
                remaining = "";

                for (i = 2; i < Cmd.Argc(); i++)
                {
                    remaining += Cmd.Argv(i);
                    remaining += " ";
                }

                Cmd.ExecuteString(remaining);
            }

            Com.EndRedirect();
        }
Exemple #11
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);
                }
            }
        }
Exemple #12
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");
                }
            }
        }
Exemple #13
0
 public string toString()
 {
     return(this.type == Defines.NA_LOOPBACK ? "loopback" : NET.AdrToString(this));
 }
Exemple #14
0
 public override String ToString( )
 {
     return((type == Defines.NA_LOOPBACK) ? "loopback" : NET.AdrToString(this));
 }
Exemple #15
0
 public static void SVC_Ack( )
 {
     Com.Printf("Ping acknowledge from " + NET.AdrToString(Globals.net_from) + "\\n");
 }
Exemple #16
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);
        }
Exemple #17
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);
        }