Esempio n. 1
0
        /*
           =================
           CL_PacketEvent

           A packet has arrived from the main event loop
           =================
           */
        public void PacketEvent(Net.Packet packet)
        {
            clc.lastPacketTime = realtime;

            if (packet.Type == NetMessageType.OutOfBandData)
            {
                ConnectionlessPacket(packet);
                return;
            }

            if (state < ConnectState.CONNECTED)
                return; // can't be a valid sequenced packet

            //
            // packet from server
            //
            if (!IPAddress.Equals(packet.Address.Address, clc.netchan.remoteAddress.Address))
            {
                Common.Instance.WriteLine("{0}: sequence packet without connection", packet.Address.Address.ToString());
                return;
            }

            if (!NetChan_Process(clc.netchan, packet))
                return;     // out of order, duplicated, etc

            // the header is different lengths for reliable and unreliable messages
            int headerBytes = packet.Buffer.Position;

            // track the last message received so it can be returned in
            // client messages, allowing the server to detect a dropped
            // gamestate
            int oldpos = packet.Buffer.Position;
            packet.Buffer.Position = 0;
            clc.serverMessageSequence = packet.Buffer.ReadInt32();
            packet.Buffer.Position = oldpos;
            clc.lastPacketTime = realtime;
            ParseServerMessage(packet);
        }
Esempio n. 2
0
        void ConnectionlessPacket(Net.Packet packet)
        {
            string s = packet.Buffer.ReadString();
            string[] tokens = Commands.TokenizeString(s);

            Common.Instance.WriteLine("CL Packet: {0}:{1}: {2}", packet.Address.Address, packet.Address.Port, s);
            string c = tokens[0];
            if (c.Equals("challengeResponse"))
            {
                if (state != ConnectState.CONNECTING)
                {
                    Common.Instance.WriteLine("Unwanted challenge response recieved. Ignored.");
                    return;
                }

                if (!IPAddress.Equals(clc.serverAddress.Address, packet.Address.Address))
                {
                    // This challenge response is not coming from the expected address.
                    // Check whether we have a matching client challenge to prevent
                    // connection hi-jacking.

                    c = tokens[2];
                    if (!int.Parse(c).Equals(clc.challenge))
                    {
                        Common.Instance.WriteLine("Challenge response recieved from unexpected source. Ignored.");
                        return;
                    }
                }

                // start sending challenge response instead of challenge request packets
                clc.challenge = int.Parse(tokens[1]);
                state = ConnectState.CHALLENGING;
                clc.connectPacketCount = 0;
                clc.connectTime = -99999;

                // take this address as the new server address.  This allows
                // a server proxy to hand off connections to multiple servers
                clc.serverAddress = packet.Address;
                Common.Instance.WriteLine("Challenge response: {0}", clc.challenge);
                return;
            }

            // server connection
            if (c.Equals("connectResponse"))
            {
                if ((int)state >= (int)ConnectState.CONNECTED)
                {
                    Common.Instance.WriteLine("Duplicate connect recieved. Ignored");
                    return;
                }

                if (state != ConnectState.CHALLENGING)
                {
                    Common.Instance.WriteLine("connectResponse packet while not connecting. Ignored.");
                    return;
                }

                if (!IPAddress.Equals(packet.Address.Address, clc.serverAddress.Address))
                {
                    Common.Instance.WriteLine("connectResponse from wrong address. Ignored");
                }

                clc.netchan = Net.Instance.NetChan_Setup(Net.NetSource.CLIENT, packet.Address, CVars.Instance.VariableIntegerValue("net_qport"));
                Net.Instance.ClientConnect(packet.Address);
                state = ConnectState.CONNECTED;
                clc.lastPacketSentTime = -99999;   // send first packet immediately
                return;
            }

            if (c.Equals("print"))
            {
                s = tokens[1];
                clc.serverMessage = s;
                Common.Instance.WriteLine(s);
                return;
            }

            Common.Instance.WriteLine("Unknown connectionless packet: {0}" + s);
        }
Esempio n. 3
0
        void ParseServerMessage(Net.Packet packet)
        {
            // get the reliable sequence acknowledge number
            clc.reliableAcknowledge = packet.Buffer.ReadInt32();

            if (clc.reliableAcknowledge < clc.reliableSequence - 64)
            {
                clc.reliableAcknowledge = clc.reliableSequence;
            }
            //
            // parse the message
            //
            NetBuffer buf = packet.Buffer;
            while (true)
            {
                int cmd = buf.ReadByte();

                // See if this is an extension command after the EOF, which means we
                //  got data that a legacy client should ignore.
                if ((cmd == (int)svc_ops_e.svc_EOF) && (buf.PeekByte() == (int)clc_ops_e.clc_extension))
                {
                    //Common.Instance.WriteLine("NET: EXTENSION");
                    buf.ReadByte(); // throw the svc_extension byte away.
                    cmd = buf.ReadByte();   // something legacy clients can't do!
                    // sometimes you get a svc_extension at end of stream...dangling
                    //  bits in the huffman decoder giving a bogus value?
                    if (cmd == -1)
                        cmd = (int)svc_ops_e.svc_EOF;
                }

                if (cmd == (int)svc_ops_e.svc_EOF)
                {
                    // END OF MESSAGE
                    break;
                }

                switch (cmd)
                {
                    case (int)svc_ops_e.svc_serverCommand:
                        ParseCommandString(buf);
                        break;
                    case (int)svc_ops_e.svc_gamestate:
                        ParseGameState(buf);
                        break;
                    case (int)svc_ops_e.svc_snapshot:
                        ParseSnapshot(buf);
                        break;
                    case (int)svc_ops_e.svc_download:
                        //ParseDownload(buf);
                        break;
                    case (int)svc_ops_e.svc_nop:
                        break;
                    default:
                        Common.Instance.Error("Illegible server message");
                        break;
                }
            }
        }
Esempio n. 4
0
 bool NetChan_Process(Net.netchan_t chan, Net.Packet packet)
 {
     bool ret = Net.Instance.NetChan_Process(chan, packet);
     return ret;
 }
Esempio n. 5
0
 public void NetChan_Transmit(Net.netchan_t chan, NetBuffer msg)
 {
     msg.Write((byte)clc_ops_e.clc_EOF);
     Net.Instance.NetChan_Transmit(chan, msg);
 }
Esempio n. 6
0
        /*
        =================
        SV_ConnectionlessPacket

        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.
        =================
        */
        void ConnectionLessPacket(Net.Packet packet)
        {
            NetBuffer buf = packet.Buffer;

            string data = buf.ReadString();
            Common.Instance.WriteLine("SV_ConnLessPacket: {0}=>{1}", packet.Address, data);
            string[] tokens = Commands.TokenizeString(data);

            string c = tokens[0];
            if (c.Equals("getchallenge"))
            {
                GetChallenge(packet.Address, tokens[1]);
            }
            else if (c.Equals("connect"))
            {
                DirectConnect(packet.Address, tokens);
            }
        }
Esempio n. 7
0
        /*
           =================
           SV_PacketEvent

           A packet has arrived from the main event loop
           =================
           */
        public void PacketEvent(Net.Packet packet)
        {
            // check for connectionless packet (0xffffffff) first
            if (packet.Type == Lidgren.Network.NetMessageType.OutOfBandData)
            {
                ConnectionLessPacket(packet);
                return;
            }

            // read the qport out of the message so we can fix up
            // stupid address translating routers
            NetBuffer buf = packet.Buffer;
            buf.ReadInt32();
            int qport = buf.ReadInt16() & 0xffff;

            // find which client the message is from
            for (int i = 0; i < clients.Count; i++)
            {
                client_t client = clients[i];
                if (client.state == clientState_t.CS_FREE)
                    continue;

                if (!packet.Address.Address.Equals(client.netchan.remoteAddress.Address))
                    continue;

                // it is possible to have multiple clients from a single IP
                // address, so they are differentiated by the qport variable
                if (client.netchan.qport != qport)
                {
                    continue;
                }

                // the IP port can't be used to differentiate them, because
                // some address translating routers periodically change UDP
                // port assignments
                if (client.netchan.remoteAddress.Port != packet.Address.Port)
                {
                    Common.Instance.WriteLine("PacketEvent: fixing up translation port");
                    client.netchan.remoteAddress.Port = packet.Address.Port;
                }

                // make sure it is a valid, in sequence packet
                //??
                // zombie clients still need to do the Netchan_Process
                // to make sure they don't need to retransmit the final
                // reliable message, but they don't do any other processing
                if (client.state != clientState_t.CS_ZOMBIE)
                {
                    client.lastPacketTime = time; // don't timeout
                    ExecuteClientMessage(client, buf);
                }
                return;
            }

            // if we received a sequenced packet from an address we don't recognize,
            // send an out of band disconnect packet to it
            Net.Instance.OutOfBandMessage(Net.NetSource.SERVER, packet.Address, "disconnect");
        }