Beispiel #1
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 #2
0
        /// <summary>
        /// Create a new buffered remote function call.
        /// </summary>

        public void CreateRFC(uint inID, string funcName, Buffer buffer)
        {
            if (closed || buffer == null)
            {
                return;
            }

            Buffer b = Buffer.Create();

            b.BeginWriting(false).Write(buffer.buffer, buffer.position, buffer.size);
            b.BeginReading();

            for (int i = 0; i < rfcs.size; ++i)
            {
                RFC r = rfcs[i];

                if (r.uid == inID && r.functionName == funcName)
                {
                    if (r.buffer != null)
                    {
                        r.buffer.Recycle();
                    }
                    r.buffer = b;
                    return;
                }
            }

            RFC rfc = new RFC();

            rfc.uid          = inID;
            rfc.buffer       = b;
            rfc.functionName = funcName;
            rfcs.Add(rfc);
        }
Beispiel #3
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()?");
            }
        }
        /// <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 #5
0
        /// <summary>
        /// Verify the connection.
        /// </summary>

        public bool VerifyRequestID(Buffer buffer, bool uniqueID)
        {
            BinaryReader reader  = buffer.BeginReading();
            Packet       request = (Packet)reader.ReadByte();

            if (request == Packet.RequestID)
            {
                if (reader.ReadInt32() == version)
                {
                    lock (mLock)
                    {
                        id = uniqueID ? ++mPlayerCounter : 0;
                    }
                    name = reader.ReadString();

                    if (buffer.size > 1)
                    {
#if STANDALONE
                        data = reader.ReadBytes(buffer.size);
#else
                        data = reader.ReadObject();
#endif
                    }
                    else
                    {
                        data = null;
                    }

                    stage = TcpProtocol.Stage.Connected;

                    BinaryWriter writer = BeginSend(Packet.ResponseID);
                    writer.Write(version);
                    writer.Write(id);
                    writer.Write((Int64)(System.DateTime.UtcNow.Ticks / 10000));
                    EndSend();
                    return(true);
                }
                else
                {
                    BinaryWriter writer = BeginSend(Packet.ResponseID);
                    writer.Write(0);
                    EndSend();
                    Close(false);
                }
            }
            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Receive incoming data.
        /// </summary>

        void OnReceive(IAsyncResult result)
        {
            if (!isActive)
            {
                return;
            }
            int bytes = 0;

            try
            {
                bytes = mSocket.EndReceiveFrom(result, ref mEndPoint);
            }
            catch (System.Exception ex)
            {
                Error(new IPEndPoint(Tools.localAddress, 0), ex.Message);
            }

            if (bytes > 4)
            {
                // This datagram is now ready to be processed
                Buffer buffer = Buffer.Create();
                buffer.BeginWriting(false).Write(mTemp, 0, bytes);
                buffer.BeginReading(4);

                // The 'endPoint', gets reassigned rather than updated.
                Datagram dg = new Datagram();
                dg.buffer = buffer;
                dg.ip     = (IPEndPoint)mEndPoint;
                lock (mIn) mIn.Enqueue(dg);
            }

            // Queue up the next receive operation
            if (mSocket != null)
            {
                mEndPoint = mDefaultEndPoint;

                try
                {
                    mSocket.BeginReceiveFrom(mTemp, 0, mTemp.Length, SocketFlags.None, ref mEndPoint, OnReceive, null);
                }
                catch (System.Exception ex)
                {
                    Error(new IPEndPoint(Tools.localAddress, 0), ex.Message);
                }
            }
        }
Beispiel #7
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 #9
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 #10
0
        /// <summary>
        /// See if the received packet can be processed and split it up into different ones.
        /// </summary>

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

            for (int available = mReceiveBuffer.size - mOffset; available >= 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, available);
                                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
                        UnityEngine.Debug.LogError("Malformed data packet: " + mOffset + ", " + available + " / " + mExpected);
#else
                        Tools.LogError("Malformed data packet: " + mOffset + ", " + available + " / " + 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
                available -= 4;

                // If the entire packet is present
                if (available == 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 (available > mExpected)
                {
                    // There is more than one packet. Extract this packet fully.
                    int    realSize = mExpected + 4;
                    Buffer temp     = Buffer.Create();

                    // Extract the packet and move past its size component
                    BinaryWriter bw = temp.BeginWriting(false);
                    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
                    available -= mExpected;
                    mOffset   += realSize;
                    mExpected  = 0;
                }
                else
                {
                    break;
                }
            }
            return(true);
        }
Beispiel #11
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();
        }
Beispiel #12
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.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 = ip;

                mList.Add(ent, mTime);
            #if STANDALONE
                Console.WriteLine(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 = ip;

                RemoveServer(internalAddress, externalAddress);
            #if STANDALONE
                Console.WriteLine(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;
        }
Beispiel #13
0
        /// <summary>
        /// Process a single incoming packet. Returns whether we should keep processing packets or not.
        /// </summary>

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

            if (buffer.size == 0)
            {
                return(true);
            }

            int    packetID = reader.ReadByte();
            Packet response = (Packet)packetID;

            // Verification step must be passed first
            if (response == Packet.ResponseID || mTcp.stage == TcpProtocol.Stage.Verifying)
            {
                if (mTcp.VerifyResponseID(response, reader))
                {
                    mTimeDifference = reader.ReadInt64() - (System.DateTime.UtcNow.Ticks / 10000);

#if !UNITY_WEBPLAYER
                    if (mUdp.isActive)
                    {
                        // If we have a UDP listener active, tell the server
                        BeginSend(Packet.RequestSetUDP).Write((ushort)mUdp.listeningPort);
                        EndSend();
                    }
#endif
                    mCanPing = true;
                    if (onConnect != null)
                    {
                        onConnect(true, null);
                    }
                }
                return(true);
            }

//#if !UNITY_EDITOR // DEBUG
//		if (response != Packet.ResponsePing) Console.WriteLine("Client: " + response + " " + buffer.position + " of " + buffer.size + ((ip == null) ? " (TCP)" : " (UDP)"));
//#else
//		if (response != Packet.ResponsePing) UnityEngine.Debug.Log("Client: " + response + " " + buffer.position + " of " + buffer.size + ((ip == null) ? " (TCP)" : " (UDP)"));
//#endif

            OnPacket callback;

            if (packetHandlers.TryGetValue((byte)response, out callback) && callback != null)
            {
                callback(response, reader, ip);
                return(true);
            }

            switch (response)
            {
            case Packet.Empty: break;

            case Packet.ForwardToAll:
            case Packet.ForwardToOthers:
            case Packet.ForwardToAllSaved:
            case Packet.ForwardToOthersSaved:
            case Packet.ForwardToHost:
            case Packet.Broadcast:
            {
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(reader);
                }
                break;
            }

            case Packet.ForwardToPlayer:
            {
                // Skip the player ID
                reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(reader);
                }
                break;
            }

            case Packet.ForwardByName:
            {
                // Skip the player name
                reader.ReadString();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(reader);
                }
                break;
            }

            case Packet.SyncPlayerData:
            {
                Player target = GetPlayer(reader.ReadInt32());

                if (target != null)
                {
                    target.data = reader.ReadObject();
                    if (onPlayerSync != null)
                    {
                        onPlayerSync(target);
                    }
                }
                break;
            }

            case Packet.ResponsePing:
            {
                int ping = (int)(mMyTime - mPingTime);

                if (ip != null)
                {
                    if (onPing != null && ip != null)
                    {
                        onPing(ip, ping);
                    }
                }
                else
                {
                    mCanPing = true;
                    mPing    = ping;
                }
                break;
            }

            case Packet.ResponseSetUDP:
            {
#if !UNITY_WEBPLAYER
                // The server has a new port for UDP traffic
                ushort port = reader.ReadUInt16();

                if (port != 0)
                {
                    IPAddress ipa = new IPAddress(mTcp.tcpEndPoint.Address.GetAddressBytes());
                    mServerUdpEndPoint = new IPEndPoint(ipa, port);

                    // Send the first UDP packet to the server
                    if (mUdp.isActive)
                    {
                        mBuffer = Buffer.Create();
                        mBuffer.BeginPacket(Packet.RequestActivateUDP).Write(playerID);
                        mBuffer.EndPacket();
                        mUdp.Send(mBuffer, mServerUdpEndPoint);
                        mBuffer.Recycle();
                        mBuffer = null;
                    }
                }
                else
                {
                    mServerUdpEndPoint = null;
                }
#endif
                break;
            }

            case Packet.ResponseJoiningChannel:
            {
                mIsInChannel = true;
                mDictionary.Clear();
                players.Clear();

                mChannelID = reader.ReadInt32();
                int count = reader.ReadInt16();

                for (int i = 0; i < count; ++i)
                {
                    Player p = new Player();
                    p.id   = reader.ReadInt32();
                    p.name = reader.ReadString();
                    p.data = reader.ReadObject();
                    mDictionary.Add(p.id, p);
                    players.Add(p);
                }
                break;
            }

            case Packet.ResponseLoadLevel:
            {
                // Purposely return after loading a level, ensuring that all future callbacks happen after loading
                if (onLoadLevel != null)
                {
                    onLoadLevel(reader.ReadString());
                }
                return(false);
            }

            case Packet.ResponsePlayerLeft:
            {
                Player p = GetPlayer(reader.ReadInt32());
                if (p != null)
                {
                    mDictionary.Remove(p.id);
                }
                players.Remove(p);
                if (onPlayerLeft != null)
                {
                    onPlayerLeft(p);
                }
                break;
            }

            case Packet.ResponsePlayerJoined:
            {
                Player p = new Player();
                p.id   = reader.ReadInt32();
                p.name = reader.ReadString();
                p.data = reader.ReadObject();
                mDictionary.Add(p.id, p);
                players.Add(p);
                if (onPlayerJoined != null)
                {
                    onPlayerJoined(p);
                }
                break;
            }

            case Packet.ResponseSetHost:
            {
                mHost = reader.ReadInt32();
                if (onSetHost != null)
                {
                    onSetHost(isHosting);
                }
                break;
            }

            case Packet.ResponseSetChannelData:
            {
                mData = reader.ReadString();
                if (onSetChannelData != null)
                {
                    onSetChannelData(mData);
                }
                break;
            }

            case Packet.ResponseJoinChannel:
            {
                mIsInChannel = reader.ReadBoolean();
                if (onJoinChannel != null)
                {
                    onJoinChannel(mIsInChannel, mIsInChannel ? null : reader.ReadString());
                }
                break;
            }

            case Packet.ResponseLeaveChannel:
            {
                mData        = "";
                mChannelID   = 0;
                mIsInChannel = false;
                mDictionary.Clear();
                players.Clear();
                if (onLeftChannel != null)
                {
                    onLeftChannel();
                }
                break;
            }

            case Packet.ResponseRenamePlayer:
            {
                Player p       = GetPlayer(reader.ReadInt32());
                string oldName = p.name;
                if (p != null)
                {
                    p.name = reader.ReadString();
                }
                if (onRenamePlayer != null)
                {
                    onRenamePlayer(p, oldName);
                }
                break;
            }

            case Packet.ResponseCreate:
            {
                if (onCreate != null)
                {
                    int    playerID = reader.ReadInt32();
                    ushort index    = reader.ReadUInt16();
                    uint   objID    = reader.ReadUInt32();
                    onCreate(playerID, index, objID, reader);
                }
                break;
            }

            case Packet.ResponseDestroy:
            {
                if (onDestroy != null)
                {
                    int count = reader.ReadUInt16();
                    for (int i = 0; i < count; ++i)
                    {
                        onDestroy(reader.ReadUInt32());
                    }
                }
                break;
            }

            case Packet.Error:
            {
                if (mTcp.stage != TcpProtocol.Stage.Connected && onConnect != null)
                {
                    onConnect(false, reader.ReadString());
                }
                else if (onError != null)
                {
                    onError(reader.ReadString());
                }
                break;
            }

            case Packet.Disconnect:
            {
                mData = "";
                if (isInChannel && onLeftChannel != null)
                {
                    onLeftChannel();
                }
                players.Clear();
                mDictionary.Clear();
                mTcp.Close(false);
                mLoadFiles.Clear();
                if (onDisconnect != null)
                {
                    onDisconnect();
                }
                break;
            }

            case Packet.ResponseLoadFile:
            {
                string     filename = reader.ReadString();
                int        size     = reader.ReadInt32();
                byte[]     data     = reader.ReadBytes(size);
                OnLoadFile lfc      = mLoadFiles.Pop();
                if (lfc != null)
                {
                    lfc(filename, data);
                }
                break;
            }
            }
            return(true);
        }
Beispiel #14
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 #15
0
        /// <summary>
        /// Receive and process a single incoming packet.
        /// Returns 'true' if a packet was received, 'false' otherwise.
        /// </summary>
        bool ProcessPlayerPacket(Buffer buffer, TcpPlayer player, bool reliable)
        {
            BinaryReader reader = buffer.BeginReading();
            Packet request = (Packet)reader.ReadByte();

            //#if UNITY_EDITOR // DEBUG
            //		if (request != Packet.RequestPing) UnityEngine.Debug.Log("Server: " + request + " " + buffer.position + " " + buffer.size);
            //#else
            //		if (request != Packet.RequestPing) Console.WriteLine("Server: " + request + " " + buffer.position + " " + buffer.size);
            //#endif

            // If the player has not yet been verified, the first packet must be an ID request
            if (player.stage == TcpProtocol.Stage.Verifying)
            {
            if (player.VerifyRequestID(request, reader, true))
            {
                mDictionaryID.Add(player.id, player);
                if (lobbyLink != null) lobbyLink.SendUpdate(this);
                if (onPlayerConnect != null) onPlayerConnect(player);
                return true;
            }
            #if STANDALONE
            Console.WriteLine(player.address + " has failed the verification step");
            #endif
            RemovePlayer(player);
            return false;
            }

            switch (request)
            {
            case Packet.Empty:
            {
                break;
            }
            case Packet.Error:
            {
                Error(player, reader.ReadString());
                break;
            }
            case Packet.Disconnect:
            {
                RemovePlayer(player);
                break;
            }
            case Packet.RequestPing:
            {
                // Respond with a ping back
                BeginSend(Packet.ResponsePing);
                EndSend(true, player);
                break;
            }
            case Packet.RequestSetUDP:
            {
                int port = reader.ReadUInt16();

                if (port != 0)
                {
                    IPAddress ip = new IPAddress(player.tcpEndPoint.Address.GetAddressBytes());
                    SetPlayerUdpEndPoint(player, new IPEndPoint(ip, port));
                }
                else SetPlayerUdpEndPoint(player, null);

                // Let the player know if we are hosting an active UDP connection
                ushort udp = mUdp.isActive ? (ushort)mUdp.listeningPort : (ushort)0;
                BeginSend(Packet.ResponseSetUDP).Write(udp);
                EndSend(true, player);

                // Send an empty packet to the target player to open up UDP for communication
                if (player.udpEndPoint != null) mUdp.SendEmptyPacket(player.udpEndPoint);
                break;
            }
            case Packet.RequestJoinChannel:
            {
                // Join the specified channel
                int		channelID	= reader.ReadInt32();
                string	pass		= reader.ReadString();
                string	levelName	= reader.ReadString();
                bool	persist		= reader.ReadBoolean();
                ushort	playerLimit = reader.ReadUInt16();

                // Join a random existing channel or create a new one
                if (channelID == -2)
                {
                    bool randomLevel = string.IsNullOrEmpty(levelName);
                    channelID = -1;

                    for (int i = 0; i < mChannels.size; ++i)
                    {
                        Channel ch = mChannels[i];

                        if (ch.isOpen && (randomLevel || levelName.Equals(ch.level)) &&
                            (string.IsNullOrEmpty(ch.password) || (ch.password == pass)))
                        {
                            channelID = ch.id;
                            break;
                        }
                    }

                    // If no level name has been specified and no channels were found, we're done
                    if (randomLevel && channelID == -1)
                    {
                        BinaryWriter writer = BeginSend(Packet.ResponseJoinChannel);
                        writer.Write(false);
                        writer.Write("No suitable channels found");
                        EndSend(true, player);
                        break;
                    }
                }

                // Join a random new channel
                if (channelID == -1)
                {
                    channelID = mRandom.Next(100000000);

                    for (int i = 0; i < 1000; ++i)
                    {
                        if (!ChannelExists(channelID)) break;
                        channelID = mRandom.Next(100000000);
                    }
                }

                if (player.channel == null || player.channel.id != channelID)
                {
                    bool isNew;
                    Channel channel = CreateChannel(channelID, out isNew);

                    if (channel == null || !channel.isOpen)
                    {
                        BinaryWriter writer = BeginSend(Packet.ResponseJoinChannel);
                        writer.Write(false);
                        writer.Write("The requested channel is closed");
                        EndSend(true, player);
                    }
                    else if (isNew)
                    {
                        channel.password = pass;
                        channel.persistent = persist;
                        channel.level = levelName;
                        channel.playerLimit = playerLimit;

                        SendLeaveChannel(player, false);
                        SendJoinChannel(player, channel);
                    }
                    else if (string.IsNullOrEmpty(channel.password) || (channel.password == pass))
                    {
                        SendLeaveChannel(player, false);
                        SendJoinChannel(player, channel);
                    }
                    else
                    {
                        BinaryWriter writer = BeginSend(Packet.ResponseJoinChannel);
                        writer.Write(false);
                        writer.Write("Wrong password");
                        EndSend(true, player);
                    }
                }
                break;
            }
            case Packet.RequestSetName:
            {
                // Change the player's name
                player.name = reader.ReadString();

                BinaryWriter writer = BeginSend(Packet.ResponseRenamePlayer);
                writer.Write(player.id);
                writer.Write(player.name);

                if (player.channel != null)
                {
                    EndSend(true, player.channel, null);
                }
                else
                {
                    EndSend(true, player);
                }
                break;
            }
            case Packet.RequestSaveFile:
            {
                string fileName = reader.ReadString();
                byte[] data = reader.ReadBytes(reader.ReadInt32());
                SaveFile(fileName, data);
                break;
            }
            case Packet.RequestLoadFile:
            {
                string fn = reader.ReadString();
                byte[] data = LoadFile(fn);

                BinaryWriter writer = BeginSend(Packet.ResponseLoadFile);
                writer.Write(fn);

                if (data != null)
                {
                    writer.Write(data.Length);
                    writer.Write(data);
                }
                else
                {
                    writer.Write(0);
                }
                EndSend(true, player);
                break;
            }
            case Packet.RequestDeleteFile:
            {
                DeleteFile(reader.ReadString());
                break;
            }
            case Packet.RequestNoDelay:
            {
                player.noDelay = reader.ReadBoolean();
                break;
            }
            case Packet.RequestChannelList:
            {
                BinaryWriter writer = BeginSend(Packet.ResponseChannelList);

                int count = 0;
                for (int i = 0; i < mChannels.size; ++i)
                    if (!mChannels[i].closed) ++count;

                writer.Write(count);

                for (int i = 0; i < mChannels.size; ++i)
                {
                    Channel ch = mChannels[i];

                    if (!ch.closed)
                    {
                        writer.Write(ch.id);
                        writer.Write((ushort)ch.players.size);
                        writer.Write(ch.playerLimit);
                        writer.Write(!string.IsNullOrEmpty(ch.password));
                        writer.Write(ch.persistent);
                        writer.Write(ch.level);
                        writer.Write(ch.data);
                    }
                }
                EndSend(true, player);
                break;
            }
            case Packet.RequestSetTimeout:
            {
                // The passed value is in seconds, but the stored value is in milliseconds (to avoid a math operation)
                player.timeoutTime = reader.ReadInt32() * 1000;
                break;
            }
            case Packet.ForwardToPlayer:
            {
                // Forward this packet to the specified player
                TcpPlayer target = GetPlayer(reader.ReadInt32());

                if (target != null && target.isConnected)
                {
                    // Reset the position back to the beginning (4 bytes for size, 1 byte for ID, 4 bytes for player)
                    buffer.position = buffer.position - 9;
                    target.SendTcpPacket(buffer);
                }
                break;
            }
            case Packet.Broadcast:
            {
                // 4 bytes for size, 1 byte for ID
                buffer.position = buffer.position - 5;

                // Forward the packet to everyone connected to the server
                for (int i = 0; i < mPlayers.size; ++i)
                {
                    TcpPlayer tp = mPlayers[i];

                    if (reliable || tp.udpEndPoint == null || !mAllowUdp)
                    {
                        tp.SendTcpPacket(buffer);
                    }
                    else mUdp.Send(buffer, tp.udpEndPoint);
                }
                break;
            }
            default:
            {
                if (player.channel != null && (int)request <= (int)Packet.ForwardToPlayerBuffered)
                {
                    // Other packets can only be processed while in a channel
                    if ((int)request >= (int)Packet.ForwardToAll)
                    {
                        ProcessForwardPacket(player, buffer, reader, request, reliable);
                    }
                    else
                    {
                        ProcessChannelPacket(player, buffer, reader, request);
                    }
                }
                else if (onCustomPacket != null)
                {
                    onCustomPacket(player, buffer, reader, request, reliable);
                }
                break;
            }
            }
            return true;
        }
        /// <summary>
        /// Process an incoming packet.
        /// </summary>

        bool ProcessPacket(Buffer buffer, IPEndPoint ip)
        {
            if (mBan.Count != 0 && mBan.Contains(ip.Address.ToString()))
            {
                return(false);
            }

            var reader  = buffer.BeginReading();
            var request = (Packet)reader.ReadByte();

            switch (request)
            {
            case Packet.RequestPing:
            {
                var writer = BeginSend(Packet.ResponsePing);
                writer.Write(mTime);
                writer.Write((ushort)mList.list.size);
                EndSend(ip);
                break;
            }

            case Packet.RequestAddServer:
            {
                if (reader.ReadUInt16() != GameServer.gameID)
                {
                    return(false);
                }

                var ent = new ServerList.Entry();
                ent.ReadFrom(reader);

                if (mBan.Count != 0 && (mBan.Contains(ent.externalAddress.Address.ToString()) || IsBanned(ent.name)))
                {
                    return(false);
                }

                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);
        }
Beispiel #17
0
        /// <summary>
        /// Process a single incoming packet. Returns whether we should keep processing packets or not.
        /// </summary>

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

            if (buffer.size == 0)
            {
                return(true);
            }

            int    packetID = reader.ReadByte();
            Packet response = (Packet)packetID;

            // Verification step must be passed first
            if (mTcp.stage == TcpProtocol.Stage.Verifying)
            {
                if (mTcp.VerifyResponseID(response, reader))
                {
#if !UNITY_WEBPLAYER
                    if (mUdp.isActive)
                    {
                        // If we have a UDP listener active, tell the server
                        BeginSend(Packet.RequestSetUDP).Write(mUdp.isActive ? (ushort)mUdp.listeningPort : (ushort)0);
                        EndSend();
                    }
#endif
                    mCanPing = true;
                    if (onConnect != null)
                    {
                        onConnect(true, null);
                    }
                }
                else if (onConnect != null)
                {
                    onConnect(false, "Protocol version mismatch!");
                }
                return(true);
            }

//#if !UNITY_EDITOR // DEBUG
//        if (response != Packet.ResponsePing) Console.WriteLine("Client: " + response + " " + buffer.position + " of " + buffer.size + ((ip == null) ? " (TCP)" : " (UDP)"));
//#else
//        if (response != Packet.ResponsePing) UnityEngine.Debug.Log("Client: " + response + " " + buffer.position + " of " + buffer.size + ((ip == null) ? " (TCP)" : " (UDP)"));
//#endif

            switch (response)
            {
            case Packet.Empty: break;

            case Packet.ForwardToAll:
            case Packet.ForwardToOthers:
            case Packet.ForwardToAllSaved:
            case Packet.ForwardToOthersSaved:
            case Packet.ForwardToHost:
            {
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(reader);
                }
                break;
            }

            case Packet.ForwardToPlayer:
            {
                // Skip the player ID
                reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(reader);
                }
                break;
            }

            case Packet.ResponsePing:
            {
                mPing    = (int)(mTime - mPingTime);
                mCanPing = true;
                break;
            }

            case Packet.ResponseSetUDP:
            {
#if !UNITY_WEBPLAYER
                // The server has a new port for UDP traffic
                ushort port = reader.ReadUInt16();

                if (port != 0)
                {
                    IPAddress ipa = new IPAddress(mTcp.tcpEndPoint.Address.GetAddressBytes());
                    mServerUdpEndPoint = new IPEndPoint(ipa, port);
                    // Send an empty packet to the server, opening up the communication channel
                    if (mUdp.isActive)
                    {
                        mUdp.SendEmptyPacket(mServerUdpEndPoint);
                    }
                }
                else
                {
                    mServerUdpEndPoint = null;
                }
#endif
                break;
            }

            case Packet.ResponseJoiningChannel:
            {
                mIsInChannel = true;
                mDictionary.Clear();
                players.Clear();

                mChannelID = reader.ReadInt32();
                int count = reader.ReadInt16();

                for (int i = 0; i < count; ++i)
                {
                    Player p = new Player();
                    p.id   = reader.ReadInt32();
                    p.name = reader.ReadString();
                    mDictionary.Add(p.id, p);
                    players.Add(p);
                }
                break;
            }

            case Packet.ResponseLoadLevel:
            {
                // Purposely return after loading a level, ensuring that all future callbacks happen after loading
                if (onLoadLevel != null)
                {
                    onLoadLevel(reader.ReadString());
                }
                return(false);
            }

            case Packet.ResponsePlayerLeft:
            {
                Player p = GetPlayer(reader.ReadInt32());
                if (p != null)
                {
                    mDictionary.Remove(p.id);
                }
                players.Remove(p);
                if (onPlayerLeft != null)
                {
                    onPlayerLeft(p);
                }
                break;
            }

            case Packet.ResponsePlayerJoined:
            {
                Player p = new Player();
                p.id   = reader.ReadInt32();
                p.name = reader.ReadString();
                mDictionary.Add(p.id, p);
                players.Add(p);
                if (onPlayerJoined != null)
                {
                    onPlayerJoined(p);
                }
                break;
            }

            case Packet.ResponseSetHost:
            {
                mHost = reader.ReadInt32();
                if (onSetHost != null)
                {
                    onSetHost(isHosting);
                }
                break;
            }

            case Packet.ResponseSetChannelData:
            {
                mData = reader.ReadString();
                if (onSetChannelData != null)
                {
                    onSetChannelData(mData);
                }
                break;
            }

            case Packet.ResponseJoinChannel:
            {
                mIsInChannel = reader.ReadBoolean();
                if (onJoinChannel != null)
                {
                    onJoinChannel(mIsInChannel, mIsInChannel ? null : reader.ReadString());
                }
                break;
            }

            case Packet.ResponseLeaveChannel:
            {
                mData        = "";
                mChannelID   = 0;
                mIsInChannel = false;
                mDictionary.Clear();
                players.Clear();
                if (onLeftChannel != null)
                {
                    onLeftChannel();
                }
                break;
            }

            case Packet.ResponseRenamePlayer:
            {
                Player p       = GetPlayer(reader.ReadInt32());
                string oldName = p.name;
                if (p != null)
                {
                    p.name = reader.ReadString();
                }
                if (onRenamePlayer != null)
                {
                    onRenamePlayer(p, oldName);
                }
                break;
            }

            case Packet.ResponseCreate:
            {
                if (onCreate != null)
                {
                    int   playerID = reader.ReadInt32();
                    short index    = reader.ReadInt16();
                    uint  objID    = reader.ReadUInt32();
                    onCreate(playerID, index, objID, reader);
                }
                break;
            }

            case Packet.ResponseDestroy:
            {
                if (onDestroy != null)
                {
                    int count = reader.ReadUInt16();
                    for (int i = 0; i < count; ++i)
                    {
                        onDestroy(reader.ReadUInt32());
                    }
                }
                break;
            }

            case Packet.Error:
            {
                if (mTcp.stage != TcpProtocol.Stage.Connected && onConnect != null)
                {
                    onConnect(false, reader.ReadString());
                }
                else if (onError != null)
                {
                    onError(reader.ReadString());
                }
                break;
            }

            case Packet.Disconnect:
            {
                mData = "";
                if (isInChannel && onLeftChannel != null)
                {
                    onLeftChannel();
                }
                players.Clear();
                mDictionary.Clear();
                mTcp.Close(false);
                if (onDisconnect != null)
                {
                    onDisconnect();
                }
                break;
            }

            default:
            {
                OnPacket callback;

                if (packetHandlers.TryGetValue((byte)response, out callback))
                {
                    if (callback != null)
                    {
                        callback(response, reader, ip);
                    }
                }
                break;
            }
            }
            return(true);
        }
        /// <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();
        }
Beispiel #19
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.uniqueID = reader.ReadUInt32();
                co.objectID = 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 #20
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 = 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 = 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);
        }
        /// <summary>
        /// Receive and process a single incoming packet.
        /// Returns 'true' if a packet was received, 'false' otherwise.
        /// </summary>

        bool ProcessPlayerPacket(Buffer buffer, TcpPlayer player, bool reliable)
        {
            BinaryReader reader  = buffer.BeginReading();
            Packet       request = (Packet)reader.ReadByte();

//#if UNITY_EDITOR // DEBUG
//		if (request != Packet.RequestPing) UnityEngine.Debug.Log("Server: " + request + " " + buffer.position + " " + buffer.size);
//#else
//		if (request != Packet.RequestPing) Console.WriteLine("Server: " + request + " " + buffer.position + " " + buffer.size);
//#endif

            // If the player has not yet been verified, the first packet must be an ID request
            if (player.stage == TcpProtocol.Stage.Verifying)
            {
                if (player.VerifyRequestID(request, reader, true))
                {
                    mDictionaryID.Add(player.id, player);
                    if (lobbyLink != null)
                    {
                        lobbyLink.SendUpdate(this);
                    }
                    if (onPlayerConnect != null)
                    {
                        onPlayerConnect(player);
                    }
                    return(true);
                }
#if STANDALONE
                Console.WriteLine(player.address + " has failed the verification step");
#endif
                RemovePlayer(player);
                return(false);
            }

            switch (request)
            {
            case Packet.Empty:
            {
                break;
            }

            case Packet.Error:
            {
                Error(player, reader.ReadString());
                break;
            }

            case Packet.Disconnect:
            {
                RemovePlayer(player);
                break;
            }

            case Packet.RequestPing:
            {
                // Respond with a ping back
                BeginSend(Packet.ResponsePing);
                EndSend(true, player);
                break;
            }

            case Packet.RequestSetUDP:
            {
                int port = reader.ReadUInt16();

                if (port != 0)
                {
                    IPAddress ip = new IPAddress(player.tcpEndPoint.Address.GetAddressBytes());
                    SetPlayerUdpEndPoint(player, new IPEndPoint(ip, port));
                }
                else
                {
                    SetPlayerUdpEndPoint(player, null);
                }

                // Let the player know if we are hosting an active UDP connection
                ushort udp = mUdp.isActive ? (ushort)mUdp.listeningPort : (ushort)0;
                BeginSend(Packet.ResponseSetUDP).Write(udp);
                EndSend(true, player);

                // Send an empty packet to the target player to open up UDP for communication
                if (player.udpEndPoint != null)
                {
                    mUdp.SendEmptyPacket(player.udpEndPoint);
                }
                break;
            }

            case Packet.RequestJoinChannel:
            {
                // Join the specified channel
                int    channelID   = reader.ReadInt32();
                string pass        = reader.ReadString();
                string levelName   = reader.ReadString();
                bool   persist     = reader.ReadBoolean();
                ushort playerLimit = reader.ReadUInt16();

                // Join a random existing channel or create a new one
                if (channelID == -2)
                {
                    bool randomLevel = string.IsNullOrEmpty(levelName);
                    channelID = -1;

                    for (int i = 0; i < mChannels.size; ++i)
                    {
                        Channel ch = mChannels[i];

                        if (ch.isOpen && (randomLevel || levelName.Equals(ch.level)) &&
                            (string.IsNullOrEmpty(ch.password) || (ch.password == pass)))
                        {
                            channelID = ch.id;
                            break;
                        }
                    }

                    // If no level name has been specified and no channels were found, we're done
                    if (randomLevel && channelID == -1)
                    {
                        BinaryWriter writer = BeginSend(Packet.ResponseJoinChannel);
                        writer.Write(false);
                        writer.Write("No suitable channels found");
                        EndSend(true, player);
                        break;
                    }
                }

                // Join a random new channel
                if (channelID == -1)
                {
                    channelID = mRandom.Next(100000000);

                    for (int i = 0; i < 1000; ++i)
                    {
                        if (!ChannelExists(channelID))
                        {
                            break;
                        }
                        channelID = mRandom.Next(100000000);
                    }
                }

                if (player.channel == null || player.channel.id != channelID)
                {
                    bool    isNew;
                    Channel channel = CreateChannel(channelID, out isNew);

                    if (channel == null || !channel.isOpen)
                    {
                        BinaryWriter writer = BeginSend(Packet.ResponseJoinChannel);
                        writer.Write(false);
                        writer.Write("The requested channel is closed");
                        EndSend(true, player);
                    }
                    else if (isNew)
                    {
                        channel.password    = pass;
                        channel.persistent  = persist;
                        channel.level       = levelName;
                        channel.playerLimit = playerLimit;

                        SendLeaveChannel(player, false);
                        SendJoinChannel(player, channel);
                    }
                    else if (string.IsNullOrEmpty(channel.password) || (channel.password == pass))
                    {
                        SendLeaveChannel(player, false);
                        SendJoinChannel(player, channel);
                    }
                    else
                    {
                        BinaryWriter writer = BeginSend(Packet.ResponseJoinChannel);
                        writer.Write(false);
                        writer.Write("Wrong password");
                        EndSend(true, player);
                    }
                }
                break;
            }

            case Packet.RequestSetName:
            {
                // Change the player's name
                player.name = reader.ReadString();

                BinaryWriter writer = BeginSend(Packet.ResponseRenamePlayer);
                writer.Write(player.id);
                writer.Write(player.name);

                if (player.channel != null)
                {
                    EndSend(true, player.channel, null);
                }
                else
                {
                    EndSend(true, player);
                }
                break;
            }

            case Packet.RequestSaveFile:
            {
                string fileName = reader.ReadString();
                byte[] data     = reader.ReadBytes(reader.ReadInt32());
                SaveFile(fileName, data);
                break;
            }

            case Packet.RequestLoadFile:
            {
                string fn   = reader.ReadString();
                byte[] data = LoadFile(fn);

                BinaryWriter writer = BeginSend(Packet.ResponseLoadFile);
                writer.Write(fn);

                if (data != null)
                {
                    writer.Write(data.Length);
                    writer.Write(data);
                }
                else
                {
                    writer.Write(0);
                }
                EndSend(true, player);
                break;
            }

            case Packet.RequestDeleteFile:
            {
                DeleteFile(reader.ReadString());
                break;
            }

            case Packet.RequestNoDelay:
            {
                player.noDelay = reader.ReadBoolean();
                break;
            }

            case Packet.RequestChannelList:
            {
                BinaryWriter writer = BeginSend(Packet.ResponseChannelList);

                int count = 0;
                for (int i = 0; i < mChannels.size; ++i)
                {
                    if (!mChannels[i].closed)
                    {
                        ++count;
                    }
                }

                writer.Write(count);

                for (int i = 0; i < mChannels.size; ++i)
                {
                    Channel ch = mChannels[i];

                    if (!ch.closed)
                    {
                        writer.Write(ch.id);
                        writer.Write((ushort)ch.players.size);
                        writer.Write(ch.playerLimit);
                        writer.Write(!string.IsNullOrEmpty(ch.password));
                        writer.Write(ch.persistent);
                        writer.Write(ch.level);
                        writer.Write(ch.data);
                    }
                }
                EndSend(true, player);
                break;
            }

            case Packet.ForwardToPlayer:
            {
                // Forward this packet to the specified player
                TcpPlayer target = GetPlayer(reader.ReadInt32());

                if (target != null && target.isConnected)
                {
                    // Reset the position back to the beginning (4 bytes for size, 1 byte for ID, 4 bytes for player)
                    buffer.position = buffer.position - 9;
                    target.SendTcpPacket(buffer);
                }
                break;
            }

            default:
            {
                if (player.channel != null && (int)request <= (int)Packet.ForwardToPlayerBuffered)
                {
                    // Other packets can only be processed while in a channel
                    if ((int)request >= (int)Packet.ForwardToAll)
                    {
                        ProcessForwardPacket(player, buffer, reader, request, reliable);
                    }
                    else
                    {
                        ProcessChannelPacket(player, buffer, reader, request);
                    }
                }
                else if (onCustomPacket != null)
                {
                    onCustomPacket(player, buffer, reader, request, reliable);
                }
                break;
            }
            }
            return(true);
        }
Beispiel #22
0
        /// <summary>
        /// Process an incoming packet.
        /// </summary>
        bool ProcessPacket(Buffer buffer, TcpProtocol tc)
        {
            BinaryReader reader = buffer.BeginReading();
            Packet request = (Packet)reader.ReadByte();

            // TCP connections must be verified first to ensure that they are using the correct protocol
            if (tc.stage == TcpProtocol.Stage.Verifying)
            {
            if (tc.VerifyRequestID(request, reader, false)) return true;
            #if STANDALONE
            Console.WriteLine(tc.address + " has failed the verification step");
            #endif
            return false;
            }

            switch (request)
            {
            case Packet.RequestServerList:
            {
                if (reader.ReadUInt16() != GameServer.gameID) return false;
                tc.data = (long)0;
                return true;
            }
            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 = tc.tcpEndPoint;

                mList.Add(ent, mTime).data = tc;
                mLastChange = mTime;
            #if STANDALONE
                Console.WriteLine(tc.address + " 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 = tc.tcpEndPoint;

                RemoveServer(internalAddress, externalAddress);
            #if STANDALONE
                Console.WriteLine(tc.address + " removed a server (" + internalAddress + ", " + externalAddress + ")");
            #endif
                return true;
            }
            case Packet.Disconnect:
            {
            #if STANDALONE
                if (RemoveServer(tc)) Console.WriteLine(tc.address + " has disconnected");
            #else
                RemoveServer(tc);
            #endif
                mTcp.Remove(tc);
                return true;
            }
            case Packet.RequestSaveFile:
            {
                string fileName = reader.ReadString();
                byte[] data = reader.ReadBytes(reader.ReadInt32());
                SaveFile(fileName, data);
                break;
            }
            case Packet.RequestLoadFile:
            {
                string fn = reader.ReadString();
                byte[] data = LoadFile(fn);

                BinaryWriter writer = BeginSend(Packet.ResponseLoadFile);
                writer.Write(fn);

                if (data != null)
                {
                    writer.Write(data.Length);
                    writer.Write(data);
                }
                else writer.Write(0);
                EndSend(tc);
                break;
            }
            case Packet.RequestDeleteFile:
            {
                DeleteFile(reader.ReadString());
                break;
            }
            case Packet.Error:
            {
            #if STANDALONE
                Console.WriteLine(tc.address + " error: " + reader.ReadString());
            #endif
                return false;
            }
            }
            #if STANDALONE
            Console.WriteLine(tc.address + " sent a packet not handled by the lobby server: " + request);
            #endif
            return false;
        }
Beispiel #23
0
        /// <summary>
        /// Process a single incoming packet. Returns whether we should keep processing packets or not.
        /// </summary>

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

            if (buffer.size == 0)
            {
                return(true);
            }

            int    packetID = reader.ReadByte();
            Packet response = (Packet)packetID;

#if DEBUG_PACKETS && !STANDALONE
            if (response != Packet.ResponsePing && response != Packet.Broadcast)
            {
                UnityEngine.Debug.Log("Client: " + response + " (" + buffer.size + " bytes) " + ((ip == null) ? "(TCP)" : "(UDP)"));
            }
#endif
            // Verification step must be passed first
            if (response == Packet.ResponseID || mTcp.stage == TcpProtocol.Stage.Verifying)
            {
                if (mTcp.VerifyResponseID(response, reader))
                {
                    mTimeDifference = reader.ReadInt64() - (System.DateTime.UtcNow.Ticks / 10000);

#if !UNITY_WEBPLAYER
                    if (mUdp.isActive)
                    {
                        // If we have a UDP listener active, tell the server
                        BeginSend(Packet.RequestSetUDP).Write((ushort)mUdp.listeningPort);
                        EndSend();
                    }
#endif
                    mCanPing = true;
                    if (onConnect != null)
                    {
                        onConnect(true, null);
                    }
                }
                return(true);
            }

            OnPacket callback;

            if (packetHandlers.TryGetValue((byte)response, out callback) && callback != null)
            {
                callback(response, reader, ip);
                return(true);
            }

            switch (response)
            {
            case Packet.Empty: break;

            case Packet.ForwardToAll:
            case Packet.ForwardToOthers:
            case Packet.ForwardToAllSaved:
            case Packet.ForwardToOthersSaved:
            case Packet.ForwardToHost:
            case Packet.BroadcastAdmin:
            case Packet.Broadcast:
            {
                packetSourceID = reader.ReadInt32();
                int channelID = reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(channelID, reader);
                }
                break;
            }

            case Packet.ForwardToPlayer:
            {
                packetSourceID = reader.ReadInt32();
                reader.ReadInt32();                 // Skip the target player ID
                int channelID = reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(channelID, reader);
                }
                break;
            }

            case Packet.ForwardByName:
            {
                packetSourceID = reader.ReadInt32();
                reader.ReadString();                 // Skip the player name
                int channelID = reader.ReadInt32();
                if (onForwardedPacket != null)
                {
                    onForwardedPacket(channelID, reader);
                }
                break;
            }

            case Packet.ResponseSetPlayerData:
            {
                int    pid    = reader.ReadInt32();
                Player target = GetPlayer(pid);

                if (target != null)
                {
                    string   path = reader.ReadString();
                    DataNode node = target.Set(path, reader.ReadObject());
                    if (onSetPlayerData != null)
                    {
                        onSetPlayerData(target, path, node);
                    }
                }
                else
                {
                    UnityEngine.Debug.LogError("Not found: " + pid);
                }
                break;
            }

            case Packet.ResponsePing:
            {
                int ping = (int)(mMyTime - mPingTime);

                if (ip != null)
                {
                    if (onPing != null && ip != null)
                    {
                        onPing(ip, ping);
                    }
                }
                else
                {
                    mCanPing = true;
                    mPing    = ping;
                }
                break;
            }

            case Packet.ResponseSetUDP:
            {
#if !UNITY_WEBPLAYER
                // The server has a new port for UDP traffic
                ushort port = reader.ReadUInt16();

                if (port != 0 && mTcp.tcpEndPoint != null)
                {
                    IPAddress ipa = new IPAddress(mTcp.tcpEndPoint.Address.GetAddressBytes());
                    mServerUdpEndPoint = new IPEndPoint(ipa, port);

                    // Send the first UDP packet to the server
                    if (mUdp.isActive)
                    {
                        mBuffer = Buffer.Create();
                        mBuffer.BeginPacket(Packet.RequestActivateUDP).Write(playerID);
                        mBuffer.EndPacket();
                        mUdp.Send(mBuffer, mServerUdpEndPoint);
                        mBuffer.Recycle();
                        mBuffer = null;
                    }
                }
                else
                {
                    mServerUdpEndPoint = null;
                }
#endif
                break;
            }

            case Packet.ResponseJoiningChannel:
            {
                int     channelID = reader.ReadInt32();
                int     count     = reader.ReadInt16();
                Channel ch        = GetChannel(channelID, true);

                for (int i = 0; i < count; ++i)
                {
                    int    pid = reader.ReadInt32();
                    Player p   = GetPlayer(pid, true);

                    if (reader.ReadBoolean())
                    {
                        p.name     = reader.ReadString();
                        p.dataNode = reader.ReadDataNode();
                    }
                    ch.players.Add(p);
                }
                break;
            }

            case Packet.ResponseLoadLevel:
            {
                // Purposely return after loading a level, ensuring that all future callbacks happen after loading
                int    channelID = reader.ReadInt32();
                string scene     = reader.ReadString();
                if (onLoadLevel != null)
                {
                    onLoadLevel(channelID, scene);
                }
                return(false);
            }

            case Packet.ResponsePlayerJoined:
            {
                int channelID = reader.ReadInt32();

                Channel ch = GetChannel(channelID);

                if (ch != null)
                {
                    Player p = GetPlayer(reader.ReadInt32(), true);

                    if (reader.ReadBoolean())
                    {
                        p.name     = reader.ReadString();
                        p.dataNode = reader.ReadDataNode();
                    }

                    ch.players.Add(p);
                    if (onPlayerJoin != null)
                    {
                        onPlayerJoin(channelID, p);
                    }
                }
                break;
            }

            case Packet.ResponsePlayerLeft:
            {
                int channelID = reader.ReadInt32();
                int playerID  = reader.ReadInt32();

                Channel ch = GetChannel(channelID);

                if (ch != null)
                {
                    Player p = ch.GetPlayer(playerID);
                    ch.players.Remove(p);
                    RebuildPlayerDictionary();
                    if (onPlayerLeave != null)
                    {
                        onPlayerLeave(channelID, p);
                    }
                }
                break;
            }

            case Packet.ResponseSetHost:
            {
                int channelID = reader.ReadInt32();
                int hostID    = reader.ReadInt32();

                for (int i = 0; i < mChannels.size; ++i)
                {
                    Channel ch = mChannels[i];

                    if (ch.id == channelID)
                    {
                        ch.host = GetPlayer(hostID);
                        if (onHostChanged != null)
                        {
                            onHostChanged(ch);
                        }
                        break;
                    }
                }
                break;
            }

            case Packet.ResponseSetChannelData:
            {
                int     channelID = reader.ReadInt32();
                Channel ch        = GetChannel(channelID);

                if (ch != null)
                {
                    string   path = reader.ReadString();
                    DataNode node = ch.Set(path, reader.ReadObject());
                    if (onSetChannelData != null)
                    {
                        onSetChannelData(ch, path, node);
                    }
                }
                break;
            }

            case Packet.ResponseJoinChannel:
            {
                int    channelID = reader.ReadInt32();
                bool   success   = reader.ReadBoolean();
                string msg       = success ? null : reader.ReadString();

                // mJoining can contain -2 and -1 when joining random channels
                if (!mJoining.Remove(channelID))
                {
                    for (int i = 0; i < mJoining.size; ++i)
                    {
                        int id = mJoining[i];

                        if (id < 0)
                        {
                            mJoining.RemoveAt(i);
                            break;
                        }
                    }
                }
#if UNITY_EDITOR
                if (!success)
                {
                    UnityEngine.Debug.LogError("ResponseJoinChannel: " + success + ", " + msg);
                }
#endif
                if (onJoinChannel != null)
                {
                    onJoinChannel(channelID, success, msg);
                }
                break;
            }

            case Packet.ResponseLeaveChannel:
            {
                int channelID = reader.ReadInt32();

                for (int i = 0; i < mChannels.size; ++i)
                {
                    Channel ch = mChannels[i];

                    if (ch.id == channelID)
                    {
                        mChannels.RemoveAt(i);
                        break;
                    }
                }

                RebuildPlayerDictionary();
                if (onLeaveChannel != null)
                {
                    onLeaveChannel(channelID);
                }

                // Purposely exit after receiving a "left channel" notification so that other packets get handled in the next frame.
                return(false);
            }

            case Packet.ResponseRenamePlayer:
            {
                Player p       = GetPlayer(reader.ReadInt32());
                string oldName = p.name;
                if (p != null)
                {
                    p.name = reader.ReadString();
                }
                if (onRenamePlayer != null)
                {
                    onRenamePlayer(p, oldName);
                }
                break;
            }

            case Packet.ResponseCreateObject:
            {
                if (onCreate != null)
                {
                    int  playerID  = reader.ReadInt32();
                    int  channelID = reader.ReadInt32();
                    uint objID     = reader.ReadUInt32();
                    onCreate(channelID, playerID, objID, reader);
                }
                break;
            }

            case Packet.ResponseDestroyObject:
            {
                if (onDestroy != null)
                {
                    int channelID = reader.ReadInt32();
                    int count     = reader.ReadUInt16();

                    for (int i = 0; i < count; ++i)
                    {
                        uint val = reader.ReadUInt32();
                        onDestroy(channelID, val);
                    }
                }
                break;
            }

            case Packet.ResponseTransferObject:
            {
                if (onTransfer != null)
                {
                    int  from = reader.ReadInt32();
                    int  to   = reader.ReadInt32();
                    uint id0  = reader.ReadUInt32();
                    uint id1  = reader.ReadUInt32();
                    onTransfer(from, to, id0, id1);
                }
                break;
            }

            case Packet.Error:
            {
                string err = reader.ReadString();
                if (onError != null)
                {
                    onError(err);
                }
                if (mTcp.stage != TcpProtocol.Stage.Connected && onConnect != null)
                {
                    onConnect(false, err);
                }
                break;
            }

            case Packet.Disconnect:
            {
                if (onLeaveChannel != null)
                {
                    while (mChannels.size > 0)
                    {
                        int     index = mChannels.size - 1;
                        Channel ch    = mChannels[index];
                        mChannels.RemoveAt(index);
                        onLeaveChannel(ch.id);
                    }
                }

                mChannels.Clear();
                mGetChannelsCallbacks.Clear();
                mDictionary.Clear();
                mTcp.Close(false);
                mLoadFiles.Clear();
                mGetFiles.Clear();
                mJoining.Clear();
                mIsAdmin = false;

                if (mLocalServer != null)
                {
                    mLocalServer.localClient = null;
                    mLocalServer             = null;
                }

                if (onDisconnect != null)
                {
                    onDisconnect();
                }
                mConfig = new DataNode("Version", Player.version);
                break;
            }

            case Packet.ResponseGetFileList:
            {
                string   filename = reader.ReadString();
                int      size     = reader.ReadInt32();
                string[] files    = null;

                if (size > 0)
                {
                    files = new string[size];
                    for (int i = 0; i < size; ++i)
                    {
                        files[i] = reader.ReadString();
                    }
                }

                OnGetFiles cb = null;
                if (mGetFiles.TryGetValue(filename, out cb))
                {
                    mGetFiles.Remove(filename);
                }

                if (cb != null)
                {
                    try
                    {
                        cb(filename, files);
                    }
#if UNITY_EDITOR
                    catch (System.Exception ex)
                    {
                        Debug.LogError(ex.Message + ex.StackTrace);
                    }
#else
                    catch (System.Exception) {}
#endif
                }
                break;
            }

            case Packet.ResponseLoadFile:
            {
                string     filename = reader.ReadString();
                int        size     = reader.ReadInt32();
                byte[]     data     = reader.ReadBytes(size);
                OnLoadFile cb       = null;

                if (mLoadFiles.TryGetValue(filename, out cb))
                {
                    mLoadFiles.Remove(filename);
                }

                if (cb != null)
                {
                    try
                    {
                        cb(filename, data);
                    }
#if UNITY_EDITOR
                    catch (System.Exception ex)
                    {
                        Debug.LogError(ex.Message + ex.StackTrace);
                    }
#else
                    catch (System.Exception) {}
#endif
                }
                break;
            }

            case Packet.ResponseVerifyAdmin:
            {
                int    pid = reader.ReadInt32();
                Player p   = GetPlayer(pid);
                if (p == player)
                {
                    mIsAdmin = true;
                }
                if (onSetAdmin != null)
                {
                    onSetAdmin(p);
                }
                break;
            }

            case Packet.ResponseSetServerData:
            {
                string path = reader.ReadString();
                object obj  = reader.ReadObject();

                if (obj != null)
                {
                    DataNode node = mConfig.SetHierarchy(path, obj);
                    if (onSetServerData != null)
                    {
                        onSetServerData(path, node);
                    }
                }
                else
                {
                    DataNode node = mConfig.RemoveHierarchy(path);
                    if (onSetServerData != null)
                    {
                        onSetServerData(path, node);
                    }
                }
                break;
            }

            case Packet.ResponseChannelList:
            {
                if (mGetChannelsCallbacks.Count != 0)
                {
                    OnGetChannels       cb       = mGetChannelsCallbacks.Dequeue();
                    List <Channel.Info> channels = new List <Channel.Info>();
                    int count = reader.ReadInt32();

                    for (int i = 0; i < count; ++i)
                    {
                        Channel.Info info = new Channel.Info();
                        info.id           = reader.ReadInt32();
                        info.players      = reader.ReadUInt16();
                        info.limit        = reader.ReadUInt16();
                        info.hasPassword  = reader.ReadBoolean();
                        info.isPersistent = reader.ReadBoolean();
                        info.level        = reader.ReadString();
                        info.data         = reader.ReadDataNode();
                        channels.Add(info);
                    }

                    if (cb != null)
                    {
                        cb(channels);
                    }
                }
                break;
            }

            case Packet.ResponseLockChannel:
            {
                int     channelID = reader.ReadInt32();
                bool    isLocked  = reader.ReadBoolean();
                Channel ch        = GetChannel(channelID);
                if (ch != null)
                {
                    ch.isLocked = isLocked;
                }
                if (onLockChannel != null)
                {
                    onLockChannel(channelID, isLocked);
                }
                break;
            }
            }
            return(true);
        }
Beispiel #24
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 #25
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 #26
0
        /// <summary>
        /// See if the received packet can be processed and split it up into different ones.
        /// </summary>

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

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

                    if (mExpected < 0 || mExpected > 16777216)
                    {
                        Close(true);
                        return(false);
                    }
                }

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

                // If the entire packet is present
                if (available == 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 (available > mExpected)
                {
                    // There is more than one packet. Extract this packet fully.
                    int    realSize = mExpected + 4;
                    Buffer temp     = Buffer.Create();

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

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

                    // Skip this packet
                    available -= mExpected;
                    mOffset   += realSize;
                    mExpected  = 0;
                }
                else
                {
                    break;
                }
            }
            return(true);
        }
Beispiel #27
0
        /// <summary>
        /// Process a single incoming packet. Returns whether we should keep processing packets or not.
        /// </summary>
        bool ProcessPacket(Buffer buffer, IPEndPoint ip)
        {
            mPacketSource = ip;
            BinaryReader reader = buffer.BeginReading();
            if (buffer.size == 0) return true;

            int packetID = reader.ReadByte();
            Packet response = (Packet)packetID;

            // Verification step must be passed first
            if (mTcp.stage == TcpProtocol.Stage.Verifying)
            {
            if (mTcp.VerifyResponseID(response, reader))
            {
            #if !UNITY_WEBPLAYER
                if (mUdp.isActive)
                {
                    // If we have a UDP listener active, tell the server
                    BeginSend(Packet.RequestSetUDP).Write(mUdp.isActive ? (ushort)mUdp.listeningPort : (ushort)0);
                    EndSend();
                }
            #endif
                mCanPing = true;
                if (onConnect != null) onConnect(true, null);
            }
            else if (onConnect != null)
            {
                onConnect(false, "Protocol version mismatch!");
            }
            return true;
            }

            //#if !UNITY_EDITOR // DEBUG
            //        if (response != Packet.ResponsePing) Console.WriteLine("Client: " + response + " " + buffer.position + " of " + buffer.size + ((ip == null) ? " (TCP)" : " (UDP)"));
            //#else
            //        if (response != Packet.ResponsePing) UnityEngine.Debug.Log("Client: " + response + " " + buffer.position + " of " + buffer.size + ((ip == null) ? " (TCP)" : " (UDP)"));
            //#endif

            switch (response)
            {
            case Packet.Empty: break;
            case Packet.ForwardToAll:
            case Packet.ForwardToOthers:
            case Packet.ForwardToAllSaved:
            case Packet.ForwardToOthersSaved:
            case Packet.ForwardToHost:
            case Packet.Broadcast:
            {
                if (onForwardedPacket != null) onForwardedPacket(reader);
                break;
            }
            case Packet.ForwardToPlayer:
            {
                // Skip the player ID
                reader.ReadInt32();
                if (onForwardedPacket != null) onForwardedPacket(reader);
                break;
            }
            case Packet.ResponsePing:
            {
                mPing = (int)(mTime - mPingTime);
                mCanPing = true;
                break;
            }
            case Packet.ResponseSetUDP:
            {
            #if !UNITY_WEBPLAYER
                // The server has a new port for UDP traffic
                ushort port = reader.ReadUInt16();

                if (port != 0)
                {
                    IPAddress ipa = new IPAddress(mTcp.tcpEndPoint.Address.GetAddressBytes());
                    mServerUdpEndPoint = new IPEndPoint(ipa, port);
                    // Send an empty packet to the server, opening up the communication channel
                    if (mUdp.isActive) mUdp.SendEmptyPacket(mServerUdpEndPoint);
                }
                else mServerUdpEndPoint = null;
            #endif
                break;
            }
            case Packet.ResponseJoiningChannel:
            {
                mIsInChannel = true;
                mDictionary.Clear();
                players.Clear();

                mChannelID = reader.ReadInt32();
                int count = reader.ReadInt16();

                for (int i = 0; i < count; ++i)
                {
                    Player p = new Player();
                    p.id = reader.ReadInt32();
                    p.name = reader.ReadString();
                    mDictionary.Add(p.id, p);
                    players.Add(p);
                }
                break;
            }
            case Packet.ResponseLoadLevel:
            {
                // Purposely return after loading a level, ensuring that all future callbacks happen after loading
                if (onLoadLevel != null) onLoadLevel(reader.ReadString());
                return false;
            }
            case Packet.ResponsePlayerLeft:
            {
                Player p = GetPlayer(reader.ReadInt32());
                if (p != null) mDictionary.Remove(p.id);
                players.Remove(p);
                if (onPlayerLeft != null) onPlayerLeft(p);
                break;
            }
            case Packet.ResponsePlayerJoined:
            {
                Player p = new Player();
                p.id = reader.ReadInt32();
                p.name = reader.ReadString();
                mDictionary.Add(p.id, p);
                players.Add(p);
                if (onPlayerJoined != null) onPlayerJoined(p);
                break;
            }
            case Packet.ResponseSetHost:
            {
                mHost = reader.ReadInt32();
                if (onSetHost != null) onSetHost(isHosting);
                break;
            }
            case Packet.ResponseSetChannelData:
            {
                mData = reader.ReadString();
                if (onSetChannelData != null) onSetChannelData(mData);
                break;
            }
            case Packet.ResponseJoinChannel:
            {
                mIsInChannel = reader.ReadBoolean();
                if (onJoinChannel != null) onJoinChannel(mIsInChannel, mIsInChannel ? null : reader.ReadString());
                break;
            }
            case Packet.ResponseLeaveChannel:
            {
                mData = "";
                mChannelID = 0;
                mIsInChannel = false;
                mDictionary.Clear();
                players.Clear();
                if (onLeftChannel != null) onLeftChannel();
                break;
            }
            case Packet.ResponseRenamePlayer:
            {
                Player p = GetPlayer(reader.ReadInt32());
                string oldName = p.name;
                if (p != null) p.name = reader.ReadString();
                if (onRenamePlayer != null) onRenamePlayer(p, oldName);
                break;
            }
            case Packet.ResponseCreate:
            {
                if (onCreate != null)
                {
                    int playerID = reader.ReadInt32();
                    ushort index = reader.ReadUInt16();
                    uint objID = reader.ReadUInt32();
                    onCreate(playerID, index, objID, reader);
                }
                break;
            }
            case Packet.ResponseDestroy:
            {
                if (onDestroy != null)
                {
                    int count = reader.ReadUInt16();
                    for (int i = 0; i < count; ++i) onDestroy(reader.ReadUInt32());
                }
                break;
            }
            case Packet.Error:
            {
                if (mTcp.stage != TcpProtocol.Stage.Connected && onConnect != null)
                {
                    onConnect(false, reader.ReadString());
                }
                else if (onError != null)
                {
                    onError(reader.ReadString());
                }
                break;
            }
            case Packet.Disconnect:
            {
                mData = "";
                if (isInChannel && onLeftChannel != null) onLeftChannel();
                players.Clear();
                mDictionary.Clear();
                mTcp.Close(false);
                if (onDisconnect != null) onDisconnect();
                break;
            }
            default:
            {
                OnPacket callback;

                if (packetHandlers.TryGetValue((byte)response, out callback))
                {
                    if (callback != null)
                    {
                        callback(response, reader, ip);
                    }
                }
                break;
            }
            }
            return true;
        }