Beispiel #1
0
        /// <summary>
        /// Send the outgoing buffer.
        /// </summary>

        public void EndSend()
        {
            mBuffer.EndPacket();
            mTcp.SendTcpPacket(mBuffer);
            mBuffer.Recycle();
            mBuffer = null;
        }
        /// <summary>
        /// Send the outgoing buffer to the specified remote destination.
        /// </summary>

        void EndSend(IPEndPoint ip)
        {
            mBuffer.EndPacket();
            mUdp.Send(mBuffer, ip);
            mBuffer.Recycle();
            mBuffer = null;
        }
Beispiel #3
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();
            }
        }
Beispiel #4
0
        /// <summary>
        /// Cancel the send operation.
        /// </summary>

        public void CancelSend()
        {
            if (mBuffer != null)
            {
                mBuffer.EndPacket();
                mBuffer.Recycle();
                mBuffer = null;
            }
        }
Beispiel #5
0
        /// <summary>
        /// Close the connection.
        /// </summary>

        void CloseNotThreadSafe(bool notify)
        {
            Buffer.Recycle(mOut);
            stage = Stage.NotConnected;

            if (mSocket != null)
            {
                try
                {
                    if (mSocket.Connected)
                    {
                        mSocket.Shutdown(SocketShutdown.Both);
                    }
                    mSocket.Close();
                }
                catch (System.Exception) {}
                mSocket = null;

                if (notify)
                {
                    Buffer buffer = Buffer.Create();
                    buffer.BeginPacket(Packet.Disconnect);
                    buffer.EndTcpPacketWithOffset(4);

                    lock (mIn)
                    {
                        Buffer.Recycle(mIn);
                        mIn.Enqueue(buffer);
                    }
                }
                else
                {
                    lock (mIn) Buffer.Recycle(mIn);
                }
            }
            else if (notify && sendQueue != null)
            {
                sendQueue = null;
                Buffer buffer = Buffer.Create();
                buffer.BeginPacket(Packet.Disconnect);
                buffer.EndTcpPacketWithOffset(4);

                lock (mIn)
                {
                    Buffer.Recycle(mIn);
                    mIn.Enqueue(buffer);
                }
            }

            if (mReceiveBuffer != null)
            {
                mReceiveBuffer.Recycle();
                mReceiveBuffer = null;
            }
        }
Beispiel #6
0
        /// <summary>
        /// Send the outgoing buffer.
        /// </summary>

        public void EndSend()
        {
            if (mBuffer != null)
            {
                mBuffer.EndPacket();
                if (mCanSend)
                {
                    mTcp.SendTcpPacket(mBuffer);
                }
                mBuffer.Recycle();
                mBuffer = null;
            }
        }
Beispiel #7
0
        /// <summary>
        /// Send the specified packet. Marks the buffer as used.
        /// </summary>

        public void SendTcpPacket(Buffer buffer)
        {
            buffer.MarkAsUsed();

            if (mSocket != null && mSocket.Connected)
            {
                buffer.BeginReading();

                lock (mOut)
                {
                    mOut.Enqueue(buffer);

                    if (mOut.Count == 1)
                    {
                        try
                        {
                            // If it's the first packet, let's begin the send process
                            mSocket.BeginSend(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, OnSend, buffer);
                        }
                        catch (System.Exception ex)
                        {
                            Error(ex.Message);
                            Close(false);
                            Release();
                        }
                    }
                }
            }
            else
            {
                buffer.Recycle();
            }
        }
Beispiel #8
0
        /// <summary>
        /// Try to establish a connection with the specified remote destination.
        /// </summary>

        public void Connect(IPEndPoint externalIP, IPEndPoint internalIP = null)
        {
#if !MODDING
            Disconnect();

            lock (mIn) Buffer.Recycle(mIn);
            lock (mOut) Buffer.Recycle(mOut);

#if W2 && !STANDALONE
            if (externalIP != null && externalIP.Port != 5181 && Game.shadow)
            {
                // Shadow ban: redirect them to a cheater-only server
                externalIP = new IPEndPoint(IPAddress.Parse("54.158.239.111"), 5146);
                internalIP = null;
            }
#endif
            if (externalIP != null)
            {
                // Some routers, like Asus RT-N66U don't support NAT Loopback, and connecting to an external IP
                // will connect to the router instead. So if it's a local IP, connect to it first.
                if (internalIP != null && Tools.GetSubnet(Tools.localAddress) == Tools.GetSubnet(internalIP.Address))
                {
                    tcpEndPoint = internalIP;
                    mFallback   = externalIP;
                }
                else
                {
                    tcpEndPoint = externalIP;
                    mFallback   = internalIP;
                }
                ConnectToTcpEndPoint();
            }
#endif
        }
Beispiel #9
0
        /// <summary>
        /// Send the specified datagram.
        /// </summary>

        public void Send(Buffer buffer, IPEndPoint ip)
        {
            if (ip.Address.Equals(IPAddress.Broadcast))
            {
                Broadcast(buffer, ip.Port);
                return;
            }

            buffer.MarkAsUsed();

            if (mSocket != null)
            {
                buffer.BeginReading();

                lock (mOut)
                {
                    Datagram dg = new Datagram();
                    dg.buffer = buffer;
                    dg.ip     = ip;
                    mOut.Enqueue(dg);

                    if (mOut.Count == 1)
                    {
                        // If it's the first datagram, begin the sending process
                        mSocket.BeginSendTo(buffer.buffer, buffer.position, buffer.size,
                                            SocketFlags.None, ip, OnSend, null);
                    }
                }
            }
            else
            {
                buffer.Recycle();
                throw new InvalidOperationException("The socket is null. Did you forget to call UdpProtocol.Start()?");
            }
        }
Beispiel #10
0
        /// <summary>
        /// Close the connection.
        /// </summary>

        public void Close(bool notify)
        {
            stage = Stage.NotConnected;
            name  = "Guest";
            data  = null;

            if (mReceiveBuffer != null)
            {
                mReceiveBuffer.Recycle();
                mReceiveBuffer = null;
            }

            if (mSocket != null)
            {
                try
                {
                    if (mSocket.Connected)
                    {
                        mSocket.Shutdown(SocketShutdown.Both);
                    }
                    mSocket.Close();
                }
                catch (System.Exception) {}
                mSocket = null;

                if (notify)
                {
                    Buffer buffer = Buffer.Create();
                    buffer.BeginPacket(Packet.Disconnect);
                    buffer.EndTcpPacketWithOffset(4);
                    lock (mIn) mIn.Enqueue(buffer);
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Send the specified buffer to the entire LAN.
        /// </summary>

        public void Broadcast(Buffer buffer, int port)
        {
            if (buffer != null)
            {
                buffer.MarkAsUsed();
#if UNITY_WEBPLAYER || UNITY_FLASH
#if UNITY_EDITOR
                UnityEngine.Debug.LogError("[TNet] Sending broadcasts doesn't work in the Unity Web Player or Flash");
#endif
#else
                IPEndPoint endPoint = mMulticast ? mMulticastEndPoint : mBroadcastEndPoint;
                endPoint.Port = port;

                try
                {
                    mSocket.SendTo(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, endPoint);
                }
                catch (System.Exception ex)
                {
                    Error(null, ex.Message);
                }
#endif
                buffer.Recycle();
            }
        }
Beispiel #12
0
        /// <summary>
        /// Send an empty packet to the target destination.
        /// Can be used for NAT punch-through, or just to keep a UDP connection alive.
        /// Empty packets are simply ignored.
        /// </summary>

        public void SendEmptyPacket(IPEndPoint ip)
        {
            Buffer buffer = Buffer.Create();

            buffer.BeginPacket(Packet.Empty);
            buffer.EndPacket();
            Send(buffer, ip);
            buffer.Recycle();
        }
Beispiel #13
0
        /// <summary>
        /// Send the outgoing buffer.
        /// </summary>

        public void EndSend()
        {
            if (mBuffer != null)
            {
                mBuffer.EndPacket();
                SendTcpPacket(mBuffer);
                mBuffer.Recycle();
                mBuffer = null;
            }
        }
Beispiel #14
0
        /// <summary>
        /// Send the specified datagram.
        /// </summary>

        public void Send(Buffer buffer, IPEndPoint ip)
        {
#if !MODDING
            if (ip.Address.Equals(IPAddress.Broadcast))
            {
                Broadcast(buffer, ip.Port);
            }
            else if (mSocket != null)
            {
                if (mSocket.AddressFamily != ip.AddressFamily)
                {
#if UNITY_EDITOR
                    UnityEngine.Debug.LogError("UDP socket " + name + " (" + mSocket.AddressFamily + ") and the desired address " + ip.Address +
                                               " (" + ip.AddressFamily + ") were started with different address families");
#else
                    Tools.LogError("UDP socket " + name + " (" + mSocket.AddressFamily + ") and the desired address " + ip.Address +
                                   " (" + ip.AddressFamily + ") were started with different address families");
#endif
                    return;
                }

                buffer.MarkAsUsed();
                buffer.BeginReading();

                lock (mOut)
                {
                    Datagram dg = new Datagram();
                    dg.buffer = buffer;
                    dg.ip     = ip;
                    mOut.Enqueue(dg);

                    if (mOut.Count == 1)
                    {
                        try
                        {
                            // If it's the first datagram, begin the sending process
                            mSocket.BeginSendTo(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, ip, OnSend, null);
                        }
                        catch (Exception ex)
                        {
                            Tools.LogError(ex.Message + "\n" + ex.StackTrace);
                            buffer.Recycle();
                        }
                    }
                }
            }
            else
            {
                Tools.LogError("The socket is null. Did you forget to call UdpProtocol.Start()?");
            }
#endif
        }
Beispiel #15
0
        /// <summary>
        /// Stop listening for incoming packets.
        /// </summary>

        public void Stop()
        {
            mPort = -1;

            if (mSocket != null)
            {
                mSocket.Close();
                mSocket = null;
            }

            Buffer.Recycle(mIn);
            Buffer.Recycle(mOut);
        }
        /// <summary>
        /// Send periodic updates.
        /// </summary>

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

            for (; ;)
            {
#if !STANDALONE
                if (TNManager.isPaused)
                {
                    Thread.Sleep(500);
                    continue;
                }
#endif
                long time = DateTime.UtcNow.Ticks / 10000;

                if (mShutdown)
                {
                    Buffer       buffer = Buffer.Create();
                    BinaryWriter writer = buffer.BeginPacket(Packet.RequestRemoveServer);
                    writer.Write(GameServer.gameID);
                    Tools.Serialize(writer, mInternal);
                    Tools.Serialize(writer, mExternal);
                    buffer.EndPacket();
                    mUdp.Send(buffer, mRemoteAddress);
                    buffer.Recycle();
                    mThread = null;
                    break;
                }

                if (mNextSend < time && mGameServer != null)
                {
                    mNextSend = time + 3000;
                    Buffer buffer = Buffer.Create();
                    var    writer = buffer.BeginPacket(Packet.RequestAddServer);
                    writer.Write(GameServer.gameID);
                    writer.Write(mGameServer.name);
                    writer.Write((short)mGameServer.playerCount);
                    Tools.Serialize(writer, mInternal);
                    Tools.Serialize(writer, mExternal);
                    buffer.EndPacket();
                    mUdp.Send(buffer, mRemoteAddress);
                    buffer.Recycle();
                }

                try { Thread.Sleep(10); }
                catch (System.Threading.ThreadInterruptedException) { return; }
            }
        }
Beispiel #17
0
        /// <summary>
        /// Stop listening for incoming packets.
        /// </summary>

        public void Stop()
        {
#if !MODDING
            mPort = -1;

            if (mSocket != null)
            {
                mSocket.Close();
                mSocket = null;
            }

            Buffer.Recycle(mIn);
            Buffer.Recycle(mOut);
#endif
        }
        /// <summary>
        /// Recycle an entire queue of buffers.
        /// </summary>

        static public void Recycle(Queue <Buffer> list)
        {
#if RECYCLE_BUFFERS
            lock (mPool)
            {
                while (list.Count != 0)
                {
                    Buffer b = list.Dequeue();
                    b.Recycle();
                }
            }
#else
            list.Clear();
#endif
        }
Beispiel #19
0
		/// <summary>
		/// Recycle an entire list of buffers.
		/// </summary>

		static public void Recycle (List<Buffer> list)
		{
#if RECYCLE_BUFFERS
			lock (mPool)
			{
				for (int i = 0; i < list.size; ++i)
				{
					Buffer b = list[i];
					b.Recycle(false);
				}
				list.Clear();
			}
#else
			list.Clear();
#endif
		}
Beispiel #20
0
        /// <summary>
        /// Try to establish a connection with the specified remote destination.
        /// </summary>

        public void Connect(IPEndPoint externalIP, IPEndPoint internalIP)
        {
            Disconnect();

            Buffer.Recycle(mIn);
            Buffer.Recycle(mOut);

            // Some routers, like Asus RT-N66U don't support NAT Loopback, and connecting to an external IP
            // will connect to the router instead. So if it's a local IP, connect to it first.
            if (internalIP != null && Tools.GetSubnet(Tools.localAddress) == Tools.GetSubnet(internalIP.Address))
            {
                tcpEndPoint = internalIP;
                mFallback   = externalIP;
            }
            else
            {
                tcpEndPoint = externalIP;
                mFallback   = internalIP;
            }
            ConnectToTcpEndPoint();
        }
        /// <summary>
        /// Release the buffers.
        /// </summary>

        public void Release()
        {
            stage = Stage.NotConnected;

            if (mSocket != null)
            {
                try
                {
                    if (mSocket.Connected)
                    {
                        mSocket.Shutdown(SocketShutdown.Both);
                    }
                    mSocket.Close();
                }
                catch (System.Exception) {}
                mSocket = null;
            }

            Buffer.Recycle(mIn);
            Buffer.Recycle(mOut);
        }
        protected override void OnDisable()
        {
            isActive = false;
            base.OnDisable();

            try
            {
                mUdp.Stop();

                if (mRequest != null)
                {
                    mRequest.Recycle();
                    mRequest = null;
                }
                if (onChange != null)
                {
                    onChange();
                }
            }
            catch (System.Exception) { }
        }
        /// <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.Now.Ticks / 10000;

                if (mShutdown)
                {
                    Buffer       buffer = Buffer.Create();
                    BinaryWriter writer = buffer.BeginPacket(Packet.RequestRemoveServer);
                    writer.Write(GameServer.gameID);
                    Tools.Serialize(writer, mInternal);
                    Tools.Serialize(writer, mExternal);
                    buffer.EndPacket();
                    mUdp.Send(buffer, mRemoteAddress);
                    buffer.Recycle();
                    mThread = null;
                    break;
                }

                if (mNextSend < time && mGameServer != null)
                {
                    mNextSend = time + 3000;
                    Buffer       buffer = Buffer.Create();
                    BinaryWriter writer = buffer.BeginPacket(Packet.RequestAddServer);
                    writer.Write(GameServer.gameID);
                    writer.Write(mGameServer.name);
                    writer.Write((short)mGameServer.playerCount);
                    Tools.Serialize(writer, mInternal);
                    Tools.Serialize(writer, mExternal);
                    buffer.EndPacket();
                    mUdp.Send(buffer, mRemoteAddress);
                    buffer.Recycle();
                }
                Thread.Sleep(10);
            }
        }
Beispiel #24
0
        /// <summary>
        /// Send the specified datagram.
        /// </summary>

        public void Send(Buffer buffer, IPEndPoint ip)
        {
            if (ip.Address.Equals(IPAddress.Broadcast))
            {
                Broadcast(buffer, ip.Port);
            }
            else if (mSocket != null)
            {
                buffer.MarkAsUsed();
                buffer.BeginReading();

                lock (mOut)
                {
                    Datagram dg = new Datagram();
                    dg.buffer = buffer;
                    dg.ip     = ip;
                    mOut.Enqueue(dg);

                    if (mOut.Count == 1)
                    {
                        try
                        {
                            // If it's the first datagram, begin the sending process
                            mSocket.BeginSendTo(buffer.buffer, buffer.position, buffer.size,
                                                SocketFlags.None, ip, OnSend, null);
                        }
                        catch (Exception ex)
                        {
                            Tools.LogError(ex.Message + "\n" + ex.StackTrace);
                            buffer.Recycle();
                        }
                    }
                }
            }
            else
            {
                Tools.LogError("The socket is null. Did you forget to call UdpProtocol.Start()?");
            }
        }
        /// <summary>
        /// Send the specified packet. Marks the buffer as used.
        /// </summary>

        public void SendTcpPacket(Buffer buffer)
        {
            buffer.MarkAsUsed();

            if (mSocket != null && mSocket.Connected)
            {
                buffer.BeginReading();

                lock (mOut)
                {
                    mOut.Enqueue(buffer);

                    if (mOut.Count == 1)
                    {
                        // If it's the first packet, let's begin the send process
                        mSocket.BeginSend(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, OnSend, buffer);
                    }
                }
            }
            else
            {
                buffer.Recycle();
            }
        }
Beispiel #26
0
        /// <summary>
        /// Send completion callback. Recycles the buffer.
        /// </summary>

        void OnSend(IAsyncResult result)
        {
            if (stage == Stage.NotConnected)
            {
                return;
            }
            int bytes;

            try
            {
#if !UNITY_WINRT
                bytes = mSocket.EndSend(result);
                Buffer buff = (Buffer)result.AsyncState;

                // If not everything was sent...
                if (bytes < buff.size)
                {
                    try
                    {
                        // Advance the position and send the rest
                        buff.position += bytes;
                        mSocket.BeginSend(buff.buffer, buff.position, buff.size, SocketFlags.None, OnSend, buff);
                        return;
                    }
                    catch (Exception ex)
                    {
                        RespondWithError(ex);
                        CloseNotThreadSafe(false);
                    }
                }
#endif
                lock (mOut)
                {
                    // The buffer has been sent and can now be safely recycled
                    Buffer b = (mOut.Count != 0) ? mOut.Dequeue() : null;
                    if (b != null)
                    {
                        b.Recycle();
                    }

#if !UNITY_WINRT
                    if (bytes > 0 && mSocket != null && mSocket.Connected)
                    {
                        // Nothing else left -- just exit
                        if (mOut.Count == 0)
                        {
                            return;
                        }

                        try
                        {
                            Buffer next = mOut.Peek();
                            mSocket.BeginSend(next.buffer, next.position, next.size, SocketFlags.None, OnSend, next);
                        }
                        catch (Exception ex)
                        {
                            RespondWithError(ex);
                            CloseNotThreadSafe(false);
                        }
                    }
                    else
                    {
                        CloseNotThreadSafe(true);
                    }
#endif
                }
            }
            catch (System.Exception ex)
            {
                bytes = 0;
                Close(true);
                RespondWithError(ex);
            }
        }
Beispiel #27
0
        /// <summary>
        /// Release the buffers.
        /// </summary>

        public void Release()
        {
            Close(false);
            Buffer.Recycle(mIn);
            Buffer.Recycle(mOut);
        }
Beispiel #28
0
        /// <summary>
        /// Send the specified datagram.
        /// </summary>
        public void Send(Buffer buffer, IPEndPoint ip)
        {
            if (ip.Address.Equals(IPAddress.Broadcast))
            {
            Broadcast(buffer, ip.Port);
            return;
            }

            buffer.MarkAsUsed();

            if (mSocket != null)
            {
            buffer.BeginReading();

            lock (mOut)
            {
                Datagram dg = new Datagram();
                dg.buffer = buffer;
                dg.ip = ip;
                mOut.Enqueue(dg);

                if (mOut.Count == 1)
                {
                    // If it's the first datagram, begin the sending process
                    mSocket.BeginSendTo(buffer.buffer, buffer.position, buffer.size,
                        SocketFlags.None, ip, OnSend, null);
                }
            }
            }
            else
            {
            buffer.Recycle();
            throw new InvalidOperationException("The socket is null. Did you forget to call UdpProtocol.Start()?");
            }
        }
Beispiel #29
0
        /// <summary>
        /// Send the specified buffer to the entire LAN.
        /// </summary>
        public void Broadcast(Buffer buffer, int port)
        {
            if (buffer != null)
            {
            buffer.MarkAsUsed();
            #if UNITY_WEBPLAYER || UNITY_FLASH
            #if UNITY_EDITOR
            UnityEngine.Debug.LogError("[TNet] Sending broadcasts doesn't work in the Unity Web Player or Flash");
            #endif
            #else
            IPEndPoint endPoint = mMulticast ? mMulticastEndPoint : mBroadcastEndPoint;
            endPoint.Port = port;

            try
            {
                mSocket.SendTo(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, endPoint);
            }
            catch (System.Exception ex)
            {
                Error(null, ex.Message);
            }
            #endif
            buffer.Recycle();
            }
        }
        /// <summary>
        /// Channel joining process involves multiple steps. It's faster to perform them all at once.
        /// </summary>

        public void FinishJoiningChannel()
        {
            Buffer buffer = Buffer.Create();

            // Step 2: Tell the player who else is in the channel
            BinaryWriter writer = buffer.BeginPacket(Packet.ResponseJoiningChannel);
            {
                writer.Write(channel.id);
                writer.Write((short)channel.players.size);

                for (int i = 0; i < channel.players.size; ++i)
                {
                    TcpPlayer tp = channel.players[i];
                    writer.Write(tp.id);
                    writer.Write(string.IsNullOrEmpty(tp.name) ? "Guest" : tp.name);
                }
            }

            // End the first packet, but remember where it ended
            int offset = buffer.EndPacket();

            // Step 3: Inform the player of who is hosting
            if (channel.host == null)
            {
                channel.host = this;
            }
            buffer.BeginPacket(Packet.ResponseSetHost, offset);
            writer.Write(channel.host.id);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Step 4: Send the channel's data
            if (!string.IsNullOrEmpty(channel.data))
            {
                buffer.BeginPacket(Packet.ResponseSetChannelData, offset);
                writer.Write(channel.data);
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 5: Inform the player of what level we're on
            buffer.BeginPacket(Packet.ResponseLoadLevel, offset);
            writer.Write(string.IsNullOrEmpty(channel.level) ? "" : channel.level);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Step 6: Send the list of objects that have been created
            for (int i = 0; i < channel.created.size; ++i)
            {
                Channel.CreatedObject obj = channel.created.buffer[i];
                buffer.BeginPacket(Packet.ResponseCreate, offset);
                writer.Write(obj.playerID);
                writer.Write(obj.objectID);
                writer.Write(obj.uniqueID);
                writer.Write(obj.buffer.buffer, obj.buffer.position, obj.buffer.size);
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 7: Send the list of objects that have been destroyed
            if (channel.destroyed.size != 0)
            {
                buffer.BeginPacket(Packet.ResponseDestroy, offset);
                writer.Write((ushort)channel.destroyed.size);
                for (int i = 0; i < channel.destroyed.size; ++i)
                {
                    writer.Write(channel.destroyed.buffer[i]);
                }
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 8: Send all buffered RFCs to the new player
            for (int i = 0; i < channel.rfcs.size; ++i)
            {
                Buffer rfcBuff = channel.rfcs[i].buffer;
                rfcBuff.BeginReading();
                buffer.BeginWriting(offset);
                writer.Write(rfcBuff.buffer, rfcBuff.position, rfcBuff.size);
                offset = buffer.EndWriting();
            }

            // Step 9: The join process is now complete
            buffer.BeginPacket(Packet.ResponseJoinChannel, offset);
            writer.Write(true);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Send the entire buffer
            SendTcpPacket(buffer);
            buffer.Recycle();
        }
        /// <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; }
            }
        }
Beispiel #32
0
        /// <summary>
        /// Send the specified packet. Marks the buffer as used.
        /// </summary>
        public void SendTcpPacket(Buffer buffer)
        {
            buffer.MarkAsUsed();

            if (mSocket != null && mSocket.Connected)
            {
            buffer.BeginReading();

            lock (mOut)
            {
                mOut.Enqueue(buffer);

                if (mOut.Count == 1)
                {
                    try
                    {
                        // If it's the first packet, let's begin the send process
                        mSocket.BeginSend(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, OnSend, buffer);
                    }
                    catch (System.Exception ex)
                    {
                        Error(ex.Message);
                        Close(false);
                        Release();
                    }
                }
            }
            }
            else buffer.Recycle();
        }
Beispiel #33
0
        /// <summary>
        /// Send the specified packet. Marks the buffer as used.
        /// </summary>

        public void SendTcpPacket(Buffer buffer)
        {
            buffer.MarkAsUsed();
            BinaryReader reader = buffer.BeginReading();

#if DEBUG_PACKETS && !STANDALONE
            Packet packet = (Packet)buffer.PeekByte(4);
            if (packet != Packet.RequestPing && packet != Packet.ResponsePing)
            {
                UnityEngine.Debug.Log("Sending: " + packet + " to " + name + " (" + (buffer.size - 5).ToString("N0") + " bytes)");
            }
#endif

            if (mSocket != null && mSocket.Connected)
            {
                lock (mOut)
                {
                    mOut.Enqueue(buffer);

                    // If it's the first packet, let's begin the send process
                    if (mOut.Count == 1)
                    {
                        try
                        {
#if !UNITY_WINRT
                            mSocket.BeginSend(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, OnSend, buffer);
#endif
                        }
                        catch (System.Exception ex)
                        {
                            mOut.Clear();
                            buffer.Recycle();
                            RespondWithError(ex);
                            CloseNotThreadSafe(false);
                        }
                    }
                }
                return;
            }

            if (sendQueue != null)
            {
                if (buffer.position != 0)
                {
                    // Offline mode sends packets individually and they should not be reused
#if UNITY_EDITOR
                    Debug.LogWarning("Packet's position is " + buffer.position + " instead of 0. Potentially sending the same packet more than once. Ignoring...");
#endif
                    return;
                }

                // Skip the packet's size
                int size = reader.ReadInt32();

                if (size == buffer.size)
                {
                    // Note that after this the buffer can no longer be used again as its offset is +4
                    lock (sendQueue) sendQueue.Enqueue(buffer);
                    return;
                }

                // Multi-part packet -- split it up into separate ones
                lock (sendQueue)
                {
                    for (;;)
                    {
                        byte[] bytes = reader.ReadBytes(size);

                        Buffer       temp   = Buffer.Create();
                        BinaryWriter writer = temp.BeginWriting();
                        writer.Write(size);
                        writer.Write(bytes);
                        temp.BeginReading(4);
                        temp.EndWriting();
                        sendQueue.Enqueue(temp);

                        if (buffer.size > 0)
                        {
                            size = reader.ReadInt32();
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            buffer.Recycle();
        }