Beispiel #1
0
        /// <summary>
        /// Begin sending a new packet to the server.
        /// </summary>

        public BinaryWriter BeginSend(byte packetID)
        {
            mBuffer = Buffer.Create();
            return(mBuffer.BeginPacket(packetID));
        }
Beispiel #2
0
        /// <summary>
        /// Send the specified packet. Marks the buffer as used.
        /// </summary>

        public void SendTcpPacket(Buffer buffer, bool instant = false)
        {
#if !MODDING
            buffer.MarkAsUsed();

            var reader = buffer.BeginReading();

            if (buffer.size == 0)
            {
#if UNITY_EDITOR
                Debug.LogError("Trying to send a zero packet! " + buffer.position + " " + buffer.isWriting + " " + id);
#endif
                buffer.Recycle();
                return;
            }

#if DEBUG_PACKETS && !STANDALONE
            var 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 (custom != null)
            {
                if (!custom.SendPacket(buffer))
                {
                    buffer.Recycle();
                    Disconnect();
                }
                else
                {
                    buffer.Recycle();
                }
                return;
            }

            if (mSocket != null && mSocket.Connected)
            {
                lock (mOut)
                {
#if UNITY_WINRT
                    mSocket.Send(buffer.buffer, buffer.size, SocketFlags.None);
#else
                    if (instant)
                    {
                        try
                        {
                            var before = mSocket.NoDelay;
                            if (!before)
                            {
                                mSocket.NoDelay = true;
                            }
                            mSocket.Send(buffer.buffer, buffer.position, buffer.size, SocketFlags.None);
                            if (!before)
                            {
                                mSocket.NoDelay = false;
                            }
                            buffer.Recycle();
                            return;
                        }
                        catch { }
                    }

                    if (mSending)
                    {
                        // Simply add this packet to the outgoing queue
                        mOut.Enqueue(buffer);
                    }
                    else
                    {
                        // If it's the first packet, let's begin the send process
                        mSending = true;

                        try
                        {
                            mSocket.BeginSend(buffer.buffer, buffer.position, buffer.size, SocketFlags.None, OnSend, buffer);
                        }
                        catch (System.Exception ex)
                        {
                            mOut.Clear();
                            buffer.Recycle();
                            AddError(ex);
                            CloseNotThreadSafe(false);
                            mSending = false;
                        }
                    }
#endif
                }
                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)
                {
                    lock (sendQueue) sendQueue.Enqueue(buffer);
                    return;
                }

                // Multi-part packet -- split it up into separate ones
                lock (sendQueue)
                {
                    for (;;)
                    {
                        var bytes  = reader.ReadBytes(size);
                        var temp   = Buffer.Create();
                        var writer = temp.BeginWriting();
                        writer.Write(size);
                        writer.Write(bytes);
                        temp.BeginReading(4);
                        sendQueue.Enqueue(temp);

                        if (buffer.size > 0)
                        {
                            size = reader.ReadInt32();
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
#endif
            buffer.Recycle();
        }
Beispiel #3
0
        /// <summary>
        /// Close the connection.
        /// </summary>

        void CloseNotThreadSafe(bool notify)
        {
#if !MODDING
#if STANDALONE || UNITY_EDITOR
            if (id != 0)
            {
                Tools.Log(name + " (" + address + "): Disconnected [" + id + "]");
            }
#endif
            Buffer.Recycle(mOut);
            stage    = Stage.NotConnected;
            mSending = false;

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

                if (custom != null)
                {
                    custom.OnDisconnect();
                }

                if (notify)
                {
                    var 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;
            }

            if (onClose != null)
            {
                onClose(this);
            }

            id = 0;
#endif
        }
Beispiel #4
0
        /// <summary>
        /// Begin sending a new packet to the server.
        /// </summary>

        public BinaryWriter BeginSend(Packet type)
        {
            mBuffer = Buffer.Create();
            return(mBuffer.BeginPacket(type));
        }
Beispiel #5
0
        /// <summary>
        /// Add an error packet to the incoming queue.
        /// </summary>

        public void AddError(string error)
        {
            AddError(Buffer.Create(), error);
        }
Beispiel #6
0
        /// <summary>
        /// Add this packet to the incoming queue.
        /// </summary>

        public void AddPacket(Buffer buff)
        {
            lock (mIn) mIn.Enqueue(buff);
            lastReceivedTime = DateTime.UtcNow.Ticks / 10000;
        }
Beispiel #7
0
        /// <summary>
        /// See if the received packet can be processed and split it up into different ones.
        /// </summary>

        bool ProcessBuffer(byte[] bytes, int offset, int byteCount)
        {
            if (offset + byteCount > bytes.Length)
            {
                LogError("ProcessBuffer(" + bytes.Length + " bytes, offset " + offset + ", count " + byteCount);
                return(false);
            }

            if (mReceiveBuffer == null)
            {
                // Create a new packet buffer
                mReceiveBuffer = Buffer.Create();
                mReceiveBuffer.BeginWriting(false).Write(bytes, offset, byteCount);
                mExpected = 0;
                mOffset   = 0;
            }
            else
            {
                // Append this data to the end of the last used buffer
                mReceiveBuffer.BeginWriting(true).Write(bytes, offset, byteCount);
            }

            for (mAvailable = mReceiveBuffer.size - mOffset; mAvailable > 4;)
            {
                // Figure out the expected size of the packet
                if (mExpected == 0)
                {
                    mExpected = mReceiveBuffer.PeekInt(mOffset);

                    // "GET " -- HTTP GET request sent by a web browser
                    if (mExpected == 542393671)
                    {
                        if (httpGetSupport)
                        {
                            if (stage == Stage.Verifying || stage == Stage.WebBrowser)
                            {
                                stage = Stage.WebBrowser;
                                string request = Encoding.ASCII.GetString(mReceiveBuffer.buffer, mOffset, mAvailable);
                                mReceiveBuffer.BeginPacket(Packet.RequestHTTPGet).Write(request);
                                mReceiveBuffer.EndPacket();
                                mReceiveBuffer.BeginReading(4);

                                lock (mIn)
                                {
                                    mIn.Enqueue(mReceiveBuffer);
                                    mReceiveBuffer = null;
                                    mExpected      = 0;
                                    mOffset        = 0;
                                }
                            }
                            return(true);
                        }

                        mReceiveBuffer.Recycle();
                        mReceiveBuffer = null;
                        mExpected      = 0;
                        mOffset        = 0;
                        Disconnect();
                        return(false);
                    }
                    else if (mExpected < 0 || mExpected > 16777216)
                    {
#if UNITY_EDITOR
                        LogError("Malformed data packet: " + mOffset + ", " + mAvailable + " / " + mExpected);

                        var temp = new byte[mReceiveBuffer.size];
                        for (int i = 0; i < byteCount; ++i)
                        {
                            temp[i] = mReceiveBuffer.buffer[i];
                        }

                        var fn = "error_" + lastReceivedTime + ".full";
                        Tools.WriteFile(fn, temp);
                        Debug.Log("Packet saved as " + fn);
#else
                        LogError("Malformed data packet: " + mOffset + ", " + mAvailable + " / " + mExpected);
#endif
                        mReceiveBuffer.Recycle();
                        mReceiveBuffer = null;
                        mExpected      = 0;
                        mOffset        = 0;
                        Disconnect();
                        return(false);
                    }
                }

                // The first 4 bytes of any packet always contain the number of bytes in that packet
                mAvailable -= 4;

                // If the entire packet is present
                if (mAvailable == mExpected)
                {
                    // Reset the position to the beginning of the packet
                    mReceiveBuffer.BeginReading(mOffset + 4);

                    // This packet is now ready to be processed
                    lock (mIn)
                    {
                        mIn.Enqueue(mReceiveBuffer);
                        mReceiveBuffer = null;
                        mExpected      = 0;
                        mOffset        = 0;
                    }
                    break;
                }
                else if (mAvailable > mExpected)
                {
                    // There is more than one packet. Extract this packet fully.
                    int realSize = mExpected + 4;
                    var temp     = Buffer.Create();

                    // Extract the packet and move past its size component
                    var bw = temp.BeginWriting();
                    bw.Write(mReceiveBuffer.buffer, mOffset, realSize);
                    temp.BeginReading(4);

                    // This packet is now ready to be processed
                    lock (mIn)
                    {
                        mIn.Enqueue(temp);

                        // Skip this packet
                        mAvailable -= mExpected;
                        mOffset    += realSize;
                        mExpected   = 0;
                    }
                }
                else
                {
                    break;
                }
            }
            return(true);
        }
Beispiel #8
0
        /// <summary>
        /// Load the channel's data from the specified file.
        /// </summary>

        public bool LoadFrom(BinaryReader reader)
        {
            int version = reader.ReadInt32();

            if (version != Player.version)
            {
                return(false);
            }

            // Clear all RFCs, just in case
            for (int i = 0; i < rfcs.size; ++i)
            {
                RFC r = rfcs[i];
                if (r.buffer != null)
                {
                    r.buffer.Recycle();
                }
            }
            rfcs.Clear();
            created.Clear();
            destroyed.Clear();

            level         = reader.ReadString();
            data          = reader.ReadString();
            objectCounter = reader.ReadUInt32();
            password      = reader.ReadString();
            persistent    = reader.ReadBoolean();
            playerLimit   = reader.ReadUInt16();

            int size = reader.ReadInt32();

            for (int i = 0; i < size; ++i)
            {
                RFC rfc = new RFC();
                rfc.uid = reader.ReadUInt32();
                if (rfc.functionID == 0)
                {
                    rfc.functionName = reader.ReadString();
                }
                Buffer b = Buffer.Create();
                b.BeginWriting(false).Write(reader.ReadBytes(reader.ReadInt32()));
                rfc.buffer = b;
                rfcs.Add(rfc);
            }

            size = reader.ReadInt32();

            for (int i = 0; i < size; ++i)
            {
                CreatedObject co = new CreatedObject();
                co.playerID    = reader.ReadInt32();
                co.objectID    = reader.ReadUInt32();
                co.objectIndex = reader.ReadUInt16();
                co.type        = 1;
                Buffer b = Buffer.Create();
                b.BeginWriting(false).Write(reader.ReadBytes(reader.ReadInt32()));
                b.BeginReading();
                co.buffer = b;
                created.Add(co);
            }

            size = reader.ReadInt32();
            for (int i = 0; i < size; ++i)
            {
                destroyed.Add(reader.ReadUInt32());
            }
            return(true);
        }
Beispiel #9
0
        /// <summary>
        /// Process an incoming packet.
        /// </summary>

        bool ProcessPacket(Buffer buffer, IPEndPoint ip)
        {
            BinaryReader reader  = buffer.BeginReading();
            Packet       request = (Packet)reader.ReadByte();

            switch (request)
            {
            case Packet.RequestPing:
            {
                BeginSend(Packet.ResponsePing);
                EndSend(ip);
                break;
            }

            case Packet.RequestAddServer:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                ServerList.Entry ent = new ServerList.Entry();
                ent.ReadFrom(reader);

                if (ent.externalAddress.Address.Equals(IPAddress.None) ||
                    ent.externalAddress.Address.Equals(IPAddress.IPv6None))
                {
                    ent.externalAddress = ip;
                }

                mList.Add(ent, mTime);
#if STANDALONE
                Tools.Print(ip + " added a server (" + ent.internalAddress + ", " + ent.externalAddress + ")");
#endif
                return(true);
            }

            case Packet.RequestRemoveServer:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                IPEndPoint internalAddress, externalAddress;
                Tools.Serialize(reader, out internalAddress);
                Tools.Serialize(reader, out externalAddress);

                if (externalAddress.Address.Equals(IPAddress.None) ||
                    externalAddress.Address.Equals(IPAddress.IPv6None))
                {
                    externalAddress = ip;
                }

                RemoveServer(internalAddress, externalAddress);
#if STANDALONE
                Tools.Print(ip + " removed a server (" + internalAddress + ", " + externalAddress + ")");
#endif
                return(true);
            }

            case Packet.RequestServerList:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }
                mList.WriteTo(BeginSend(Packet.ResponseServerList));
                EndSend(ip);
                return(true);
            }
            }
            return(false);
        }