示例#1
0
        private bool ProcessControlMessage(ENetCommand cmd, BufferRead buf)
        {
            if (cmd == ENetCommand.NetNop)
            {
                return(true);
            }

            if (cmd == ENetCommand.NetDisconnect)
            {
                var reason = buf.ReadString();
                _messageHandler.ConnectionClosing(reason);
                return(false);
            }

            if (cmd == ENetCommand.NetFile)
            {
                var transferId = buf.ReadUInt();
                var fileName   = buf.ReadString();

                if (buf.ReadByte() != 0 && IsSafeFileToDownload(fileName))
                {
                    _messageHandler.FileRequested(fileName, transferId);
                }
                else
                {
                    _messageHandler.FileDenied(fileName, transferId);
                }

                return(true);
            }

            Console.WriteLine("NetChannel: Received bad control command type {0} from {1}.", (ushort)cmd, _remoteAddress);
            return(false);
        }
示例#2
0
        //Must be marked unsafe as the JIT is usually in charge of organizing struct layout
        public static unsafe int Size(this ENetCommand command)
        {
            switch (command)
            {
            case ENetCommand.ACKNOWLEDGE:
                return(sizeof(ENetProtocolAcknowledge));

            case ENetCommand.CONNECT:
                return(sizeof(ENetProtocolConnect));

            case ENetCommand.VERIFY_CONNECT:
                return(sizeof(ENetProtocolVerifyConnect));

            case ENetCommand.DISCONNECT:
                return(sizeof(ENetProtocolDisconnect));

            case ENetCommand.PING:
                return(sizeof(ENetProtocolPing));

            case ENetCommand.SEND_RELIABLE:
                return(sizeof(ENetProtocolSendReliable));

            case ENetCommand.SEND_UNRELIABLE:
                return(sizeof(ENetProtocolSendUnreliable));

            case ENetCommand.SEND_FRAGMENT:
                return(sizeof(ENetProtocolSendFragment));

            case ENetCommand.SEND_UNSEQUENCED:
                return(sizeof(ENetProtocolSendUnsequenced));

            case ENetCommand.BANDWIDTH_LIMIT:
                return(sizeof(ENetProtocolBandwidthLimit));

            case ENetCommand.THROTTLE_CONFIGURE:
                return(sizeof(ENetProtocolThrottleConfigure));

            case ENetCommand.PROTOCOL_HEADER:
                return(sizeof(ENetProtocolHeader));

            default:
                return(0);
            }
        }
示例#3
0
        private unsafe void ReceiveDatagram(IAsyncResult ar)
        {
            IPEndPoint fromAddr = new IPEndPoint(IPAddress.Any, 0);
            byte[] data = connection.EndReceive(ar, ref fromAddr);
            if (!shuttingDown) connection.BeginReceive(ReceiveDatagram, null);

            #region "ENet Structure Handling"
            var handle = GCHandle.Alloc(data, GCHandleType.Pinned);
            IntPtr dataStart = handle.AddrOfPinnedObject();
            ENetProtocolHeader header = (ENetProtocolHeader)Marshal.PtrToStructure(dataStart, typeof(ENetProtocolHeader));
            Util.ToHostOrder(ref header.PeerID);
            ushort flag = (ushort)(header.PeerID & PROTOCOL_HEADER_FLAG_MASK);
            header.PeerID &= unchecked((ushort)~(uint)PROTOCOL_HEADER_FLAG_MASK);

            ENetPeer? peer = null;
            if (header.PeerID != PROTOCOL_MAXIMUM_PEER_ID) //peer remains null if the first command is expected to be a connect
            {
                try
                {
                    peer = Peers[header.PeerID];
                    if (peer.Value.State == ENetPeerState.Disconnected || 
                        peer.Value.State == ENetPeerState.Zombie ||
                        //Don't include ENET_HOST_BROADCAST, it's meant for clients broadcasting the connect packet and communicating with any server that responds
                        !peer.Value.Address.Equals(fromAddr) /* && peer.Value.Address != ENET_HOST_BROADCAST */)
                    {
                        goto finalPacket; //The peer is disconnected, dead or the packets origin doesn't match the peer - Ignore them
                    }
                }
                catch (System.Collections.Generic.KeyNotFoundException)
                {
                    goto finalPacket; //The client doesn't exist and this doesn't follow connection protocol - Ignore them
                }
            }
            int currentDataOffset = ((flag & PROTOCOL_HEADER_FLAG_SENT_TIME) != 0) ? sizeof(ENetProtocolHeader) : sizeof(ENetProtocolHeader) - 2; //sentTime is 2 bytes
            while (currentDataOffset < data.Length)
            {
                ENetProtocol packet = (ENetProtocol)Marshal.PtrToStructure(dataStart + currentDataOffset, typeof(ENetProtocol));
                Util.ToHostOrder(ref packet.Header.ReliableSequenceNumber);
                if (packet.Header.ChannelID >= ChannelLayout.ChannelCount()) continue;
                ENetCommand command = (ENetCommand)(packet.Header.Command & (byte)ENetCommand.COMMAND_MASK);
                if(command >= ENetCommand.COUNT) continue;
                if (peer == null && command != ENetCommand.CONNECT) return; //Peer was following connection protocol but didn't send the connect first
                currentDataOffset += command.Size();
                if (currentDataOffset > data.Length) return; //The ENetCommand is larger than the remaining data
                switch (command)
                {
                    case ENetCommand.ACKNOWLEDGE:
                        Util.ToHostOrder(ref packet.Acknowledge.ReceivedReliableSequenceNumber);
                        Util.ToHostOrder(ref packet.Acknowledge.ReceivedSentTime);
                        //TODO: Handle Acknowledge
                        break;
                    case ENetCommand.BANDWIDTH_LIMIT:
                        Util.ToHostOrder(ref packet.BandwidthLimit.IncomingBandwidth);
                        Util.ToHostOrder(ref packet.BandwidthLimit.OutgoingBandwidth);
                        //TODO: Handle Bandwidth Limit
                        break;
                    case ENetCommand.CONNECT:
                        Console.WriteLine("A connected peer sent a connect packet. WTF are they doing?");
                        Util.ToHostOrder(ref packet.Connect.MTU);
                        Util.ToHostOrder(ref packet.Connect.WindowSize);
                        Util.ToHostOrder(ref packet.Connect.ChannelCount);
                        Util.ToHostOrder(ref packet.Connect.IncomingBandwidth);
                        Util.ToHostOrder(ref packet.Connect.OutgoingBandwidth);
                        Util.ToHostOrder(ref packet.Connect.PacketThrottleInterval);
                        Util.ToHostOrder(ref packet.Connect.PacketThrottleAcceleration);
                        Util.ToHostOrder(ref packet.Connect.PacketThrottleDeceleration);
                        Util.ToHostOrder(ref packet.Connect.SessionID);
                        peer = HandleConnect(fromAddr, packet.Connect);
                        break;
                    case ENetCommand.DISCONNECT:
                        Util.ToHostOrder(ref packet.Disconnect.Data);
                        //TODO: Handle Disconnect
                        break;
                    case ENetCommand.PING:
                        //Ping has no handling in the real ENet
                        break;
                    case ENetCommand.SEND_FRAGMENT:
                        Util.ToHostOrder(ref packet.SendFragment.DataLength); //We have to assume the fragment is the right type for the channel until I figure out how it indicates it
                        Util.ToHostOrder(ref packet.SendFragment.StartSequenceNumber);
                        Util.ToHostOrder(ref packet.SendFragment.FragmentCount);
                        Util.ToHostOrder(ref packet.SendFragment.FragmentNumber);
                        Util.ToHostOrder(ref packet.SendFragment.TotalLength);
                        Util.ToHostOrder(ref packet.SendFragment.FragmentOffset);
                        byte[] fragmentData = new byte[packet.SendFragment.DataLength];
                        Marshal.Copy(dataStart + currentDataOffset, fragmentData, 0, packet.SendFragment.DataLength);
                        currentDataOffset += packet.SendFragment.DataLength;
                        HandleReliable(peer.Value, packet, true, fragmentData);
                        break;
                    case ENetCommand.SEND_RELIABLE:
                        Util.ToHostOrder(ref packet.SendReliable.DataLength);
                        if ((ChannelLayout[packet.Header.ChannelID] & ENetSendType.RELIABLE) == 0) //Each of the data handlers uses this to quickly discard any data not matching the channels send type
                        {
                            currentDataOffset += packet.SendReliable.DataLength;
                            break;
                        }
                        byte[] reliableData = new byte[packet.SendReliable.DataLength];
                        Marshal.Copy(dataStart + currentDataOffset, reliableData, 0, packet.SendReliable.DataLength);
                        currentDataOffset += packet.SendReliable.DataLength;
                        HandleReliable(peer.Value, packet, false, reliableData);
                        break;
                    case ENetCommand.SEND_UNRELIABLE:
                        Util.ToHostOrder(ref packet.SendUnreliable.DataLength);
                        if ((ChannelLayout[packet.Header.ChannelID] & ENetSendType.UNRELIABLE) == 0)
                        {
                            currentDataOffset += packet.SendUnreliable.DataLength;
                            break;
                        }
                        Util.ToHostOrder(ref packet.SendUnreliable.UnreliableSequenceNumber);
                        byte[] unreliableData = new byte[packet.SendUnreliable.DataLength];
                        Marshal.Copy(dataStart + currentDataOffset, unreliableData, 0, packet.SendUnreliable.DataLength);
                        currentDataOffset += packet.SendUnreliable.DataLength;
                        HandleUnreliable(peer.Value, packet.SendUnreliable, unreliableData);
                        break;
                    case ENetCommand.SEND_UNSEQUENCED:
                        Util.ToHostOrder(ref packet.SendUnsequenced.DataLength);
                        if ((ChannelLayout[packet.Header.ChannelID] & ENetSendType.UNSEQUENCED) == 0)
                        {
                            currentDataOffset += packet.SendUnsequenced.DataLength;
                            break;
                        }
                        Util.ToHostOrder(ref packet.SendUnsequenced.UnsequencedGroup);
                        byte[] unsequencedData = new byte[packet.SendUnsequenced.DataLength];
                        Marshal.Copy(dataStart + currentDataOffset, unsequencedData, 0, packet.SendUnsequenced.DataLength);
                        currentDataOffset += packet.SendUnsequenced.DataLength;
                        HandleUnsequenced(peer.Value, packet.SendUnsequenced, unsequencedData);
                        break;
                    case ENetCommand.THROTTLE_CONFIGURE:
                        Util.ToHostOrder(ref packet.ThrottleConfigure.PacketThrottleInterval);
                        Util.ToHostOrder(ref packet.ThrottleConfigure.PacketThrottleAcceleration);
                        Util.ToHostOrder(ref packet.ThrottleConfigure.PacketThrottleDeceleration);
                        //TODO: Handle Throttle Configure
                        break;
                    case ENetCommand.VERIFY_CONNECT:
                        Util.ToHostOrder(ref packet.VerifyConnect.MTU);
                        Util.ToHostOrder(ref packet.VerifyConnect.WindowSize);
                        Util.ToHostOrder(ref packet.VerifyConnect.ChannelCount);
                        Util.ToHostOrder(ref packet.VerifyConnect.IncomingBandwidth);
                        Util.ToHostOrder(ref packet.VerifyConnect.OutgoingBandwidth);
                        Util.ToHostOrder(ref packet.VerifyConnect.PacketThrottleInterval);
                        Util.ToHostOrder(ref packet.VerifyConnect.PacketThrottleAcceleration);
                        Util.ToHostOrder(ref packet.VerifyConnect.PacketThrottleDeceleration);
                        //TODO: Handle Verify Connect
                        break;
                    default:
                        goto finalPacket;
                }
            }
            finalPacket:
            handle.Free();
            #endregion

            if (shuttingDown) shutdownComplete.Set();
        }