예제 #1
0
        /// <summary>
        /// Process all incoming packets.
        /// </summary>

        public void ProcessPackets()
        {
            mMyTime = DateTime.UtcNow.Ticks / 10000;

            // Request pings every so often, letting the server know we're still here.
            if (mTcp.isConnected && mCanPing && mPingTime + 4000 < mMyTime)
            {
                mCanPing  = false;
                mPingTime = mMyTime;
                BeginSend(Packet.RequestPing);
                EndSend();
            }

            Buffer buffer    = null;
            bool   keepGoing = true;

#if !UNITY_WEBPLAYER
            IPEndPoint ip = null;

            while (keepGoing && isActive && mUdp.ReceivePacket(out buffer, out ip))
            {
                mUdpIsUsable = true;
                keepGoing    = ProcessPacket(buffer, ip);
                buffer.Recycle();
            }
#endif
            while (keepGoing && isActive && mTcp.ReceivePacket(out buffer))
            {
                keepGoing = ProcessPacket(buffer, null);
                buffer.Recycle();
            }
        }
예제 #2
0
        /// <summary>
        /// Thread that will be processing incoming data.
        /// </summary>
        void ThreadFunction()
        {
            for (; ; )
            {
            mTime = DateTime.Now.Ticks / 10000;

            // Accept incoming connections
            while (mListener != null && mListener.Pending())
            {
                TcpProtocol tc = new TcpProtocol();
                tc.data = (long)(-1);
                tc.StartReceiving(mListener.AcceptSocket());
                mTcp.Add(tc);
            }

            Buffer buffer = null;

            // Process incoming TCP packets
            for (int i = 0; i < mTcp.size; ++i)
            {
                TcpProtocol tc = mTcp[i];

                while (tc.ReceivePacket(out buffer))
                {
                    try
                    {
                        if (!ProcessPacket(buffer, tc))
                        {
                            RemoveServer(tc);
                            tc.Disconnect();
                        }
                    }
            #if STANDALONE
                    catch (System.Exception ex)
                    {
                        Console.WriteLine("ERROR: " + ex.Message);
                        RemoveServer(tc);
                        tc.Disconnect();
                    }
            #else
                    catch (System.Exception)
                    {
                        RemoveServer(tc);
                        tc.Disconnect();
                    }
            #endif
                    if (buffer != null)
                    {
                        buffer.Recycle();
                        buffer = null;
                    }
                }
            }

            // We only want to send instant updates if the number of players is under a specific threshold
            if (mTcp.size > instantUpdatesClientLimit) mInstantUpdates = false;

            // Send the server list to all connected clients
            for (int i = 0; i < mTcp.size; ++i)
            {
                TcpProtocol tc = mTcp[i];
                long customTimestamp = (long)tc.data;

                // Timestamp of -1 means we don't want updates to be sent
                if (tc.stage != TcpProtocol.Stage.Connected || customTimestamp == -1) continue;

                // If timestamp was set then the list was already sent previously
                if (customTimestamp != 0)
                {
                    // List hasn't changed -- do nothing
                    if (customTimestamp >= mLastChange) continue;

                    // Too many clients: we want the updates to be infrequent
                    if (!mInstantUpdates && customTimestamp + 4000 > mTime) continue;
                }

                // Create the server list packet
                if (buffer == null)
                {
                    buffer = Buffer.Create();
                    BinaryWriter writer = buffer.BeginPacket(Packet.ResponseServerList);
                    mList.WriteTo(writer);
                    buffer.EndPacket();
                }
                tc.SendTcpPacket(buffer);
                tc.data = mTime;
            }

            if (buffer != null)
            {
                buffer.Recycle();
                buffer = null;
            }
            Thread.Sleep(1);
            }
        }
        /// <summary>
        /// Keep receiving incoming packets.
        /// </summary>

        void Update()
        {
            Buffer buffer;
            bool   changed = false;
            long   time    = System.DateTime.UtcNow.Ticks / 10000;

            // Automatically try to connect and reconnect if not connected
            if (mRemoteAddress != null && mTcp.stage == TcpProtocol.Stage.NotConnected && mNextConnect < time)
            {
                mNextConnect = time + 5000;
                mTcp.Connect(mRemoteAddress);
            }

            // TCP-based lobby
            while (mTcp.ReceivePacket(out buffer))
            {
                if (buffer.size > 0)
                {
                    try
                    {
                        BinaryReader reader   = buffer.BeginReading();
                        Packet       response = (Packet)reader.ReadByte();

                        if (response == Packet.ResponseID)
                        {
                            if (mTcp.VerifyResponseID(response, reader))
                            {
                                isActive = true;

                                // Request the server list -- with TCP this only needs to be done once
                                mTcp.BeginSend(Packet.RequestServerList).Write(GameServer.gameID);
                                mTcp.EndSend();
                            }
                        }
                        else if (response == Packet.Disconnect)
                        {
                            knownServers.Clear();
                            isActive    = false;
                            changed     = true;
                            errorString = "";
                        }
                        else if (response == Packet.ResponseServerList)
                        {
                            lock (knownServers.list) knownServers.list.Clear();
                            knownServers.ReadFrom(reader, time);
                            changed     = true;
                            errorString = "";
                        }
                        else if (response == Packet.Error)
                        {
                            errorString = reader.ReadString();
                            Debug.LogWarning(errorString);
                            changed = true;
                        }
                    }
                    catch (System.Exception ex)
                    {
                        errorString = ex.Message;
                        Debug.LogWarning(ex.Message);
                        mTcp.Close(false);
                    }
                }
                buffer.Recycle();
            }

            // Trigger the listener callback
            if (changed && onChange != null)
            {
                onChange();
            }
        }
        /// <summary>
        /// Send periodic updates.
        /// </summary>

        void ThreadFunction()
        {
            mInternal = new IPEndPoint(Tools.localAddress, mGameServer.tcpPort);
            mExternal = new IPEndPoint(Tools.externalAddress, mGameServer.tcpPort);

            for (; ;)
            {
                long time = DateTime.UtcNow.Ticks / 10000;

                if (mShutdown)
                {
                    mTcp.Disconnect();
                    mThread = null;
#if STANDALONE
                    Tools.Print("TcpLobbyLink shut down");
#endif
                    break;
                }

#if !STANDALONE
                if (TNManager.isPaused)
                {
                    Thread.Sleep(500);
                    continue;
                }
#endif
                Buffer buffer;

                // Try to establish a connection
                if (mGameServer != null && !mTcp.isConnected && !mTcp.isTryingToConnect && mNextConnect < time)
                {
#if STANDALONE
                    Tools.Print("TcpLobbyLink is connecting to " + mRemoteAddress + "...");
#endif
                    mUpdateNeeded = true;
                    mNextConnect  = time + 15000;
                    mTcp.Connect(mRemoteAddress);
                }

                while (mTcp.ReceivePacket(out buffer))
                {
                    BinaryReader reader   = buffer.BeginReading();
                    Packet       response = (Packet)reader.ReadByte();

                    if (mTcp.stage == TcpProtocol.Stage.Verifying)
                    {
                        if (mTcp.VerifyResponseID(response, reader))
                        {
                            mTimeDifference = reader.ReadInt64() - (System.DateTime.UtcNow.Ticks / 10000);
                            mWasConnected   = true;
#if STANDALONE
                            Tools.Print("TcpLobbyLink connection established");
#endif
                        }
                        else
                        {
#if STANDALONE
                            Tools.Print("TcpLobbyLink Error: Protocol version mismatch");
#endif
                            mThread = null;
                            return;
                        }
                    }
                    else if (response == Packet.RequestPing)
                    {
                    }
#if STANDALONE
                    else if (response == Packet.Error)
                    {
                        Tools.Print("TcpLobbyLink Error: " + reader.ReadString());
                    }
                    else if (response == Packet.Disconnect)
                    {
                        Tools.Print("TcpLobbyLink disconnected");
                    }
                    else
                    {
                        Tools.Print("TcpLobbyLink can't handle this packet: " + response);
                    }
#endif
                    buffer.Recycle();
                }


                // Automatically try to re-establish a connection on disconnect
                if (mWasConnected && !mTcp.isConnected && !mTcp.isTryingToConnect)
                {
                    mNextConnect  = time + 5000;
                    mWasConnected = false;
                }
                else if (mGameServer != null && mTcp.isConnected && (mUpdateNeeded || mNextSend < time))
                {
                    mUpdateNeeded = false;
                    mNextSend     = time + 5000;

                    Buffer       buff   = Buffer.Create();
                    BinaryWriter writer = buff.BeginPacket(Packet.RequestAddServer);
                    writer.Write(GameServer.gameID);
                    writer.Write(mGameServer.name);
                    writer.Write((short)mGameServer.playerCount);
                    Tools.Serialize(writer, mInternal);
                    Tools.Serialize(writer, mExternal);
                    buff.EndPacket();
                    mTcp.SendTcpPacket(buff);
                    buff.Recycle();
                }

                try { Thread.Sleep(10); }
                catch (System.Threading.ThreadInterruptedException) { return; }
            }
        }
예제 #5
0
        /// <summary>
        /// Send periodic updates.
        /// </summary>

        void ThreadFunction()
        {
            mInternal = new IPEndPoint(Tools.localAddress, mGameServer.tcpPort);
            mExternal = new IPEndPoint(Tools.externalAddress, mGameServer.tcpPort);

            for (; ;)
            {
                long time = DateTime.UtcNow.Ticks / 10000;

                if (mShutdown)
                {
                    mTcp.Disconnect();
                    mThread = null;
                    break;
                }

                Buffer buffer;

                // Try to establish a connection
                if (mGameServer != null && !mTcp.isConnected && mNextConnect < time)
                {
                    mNextConnect = time + 15000;
                    mTcp.Connect(mRemoteAddress);
                }

                while (mTcp.ReceivePacket(out buffer))
                {
                    BinaryReader reader   = buffer.BeginReading();
                    Packet       response = (Packet)reader.ReadByte();

                    if (mTcp.stage == TcpProtocol.Stage.Verifying)
                    {
                        if (mTcp.VerifyResponseID(response, reader))
                        {
                            mTimeDifference = reader.ReadInt64() - (System.DateTime.UtcNow.Ticks / 10000);
                            mWasConnected   = true;
                        }
                        else
                        {
#if STANDALONE
                            Console.WriteLine("TcpLobbyLink: Protocol version mismatch");
#endif
                            mThread = null;
                            return;
                        }
                    }
                    else if (response == Packet.Error)
                    {
                        // Automatically try to re-establish a connection on disconnect
                        mNextConnect = mWasConnected ? 0 : time + 30000;
#if STANDALONE
                        Console.WriteLine("TcpLobbyLink: " + reader.ReadString());
#endif
                    }
#if STANDALONE
                    else
                    {
                        Console.WriteLine("TcpLobbyLink can't handle this packet: " + response);
                    }
#endif
                    buffer.Recycle();
                }

                if (mGameServer != null && mTcp.isConnected)
                {
                    BinaryWriter writer = mTcp.BeginSend(Packet.RequestAddServer);
                    writer.Write(GameServer.gameID);
                    writer.Write(mGameServer.name);
                    writer.Write((short)mGameServer.playerCount);
                    Tools.Serialize(writer, mInternal);
                    Tools.Serialize(writer, mExternal);
                    mTcp.EndSend();
                    mGameServer = null;
                }
                Thread.Sleep(10);
            }
        }