DebugWriteError() private method

private DebugWriteError ( string str ) : void
str string
return void
Beispiel #1
0
        internal void AddIncomingPacket(NetPacket p)
        {
            if (p.IsFragmented)
            {
                NetUtils.DebugWrite("Fragment. Id: {0}, Part: {1}, Total: {2}", p.FragmentId, p.FragmentPart, p.FragmentsTotal);
                //Get needed array from dictionary
                ushort            packetFragId = p.FragmentId;
                IncomingFragments incomingFragments;
                if (!_holdedFragments.TryGetValue(packetFragId, out incomingFragments))
                {
                    incomingFragments = new IncomingFragments
                    {
                        Fragments = new NetPacket[p.FragmentsTotal]
                    };
                    _holdedFragments.Add(packetFragId, incomingFragments);
                }

                //Cache
                var fragments = incomingFragments.Fragments;

                //Error check
                if (p.FragmentPart >= fragments.Length || fragments[p.FragmentPart] != null)
                {
                    _packetPool.Recycle(p);
                    NetUtils.DebugWriteError("Invalid fragment packet");
                    return;
                }
                //Fill array
                fragments[p.FragmentPart] = p;

                //Increase received fragments count
                incomingFragments.ReceivedCount++;

                //Increase total size
                int dataOffset = p.GetHeaderSize() + NetConstants.FragmentHeaderSize;
                incomingFragments.TotalSize += p.Size - dataOffset;

                //Check for finish
                if (incomingFragments.ReceivedCount != fragments.Length)
                {
                    return;
                }

                NetUtils.DebugWrite("Received all fragments!");
                NetPacket resultingPacket = _packetPool.GetWithProperty(p.Property, incomingFragments.TotalSize);

                int resultingPacketOffset = resultingPacket.GetHeaderSize();
                int firstFragmentSize     = fragments[0].Size - dataOffset;
                for (int i = 0; i < incomingFragments.ReceivedCount; i++)
                {
                    //Create resulting big packet
                    int fragmentSize = fragments[i].Size - dataOffset;
                    Buffer.BlockCopy(
                        fragments[i].RawData,
                        dataOffset,
                        resultingPacket.RawData,
                        resultingPacketOffset + firstFragmentSize * i,
                        fragmentSize);

                    //Free memory
                    _packetPool.Recycle(fragments[i]);
                    fragments[i] = null;
                }

                //Send to process
                _netManager.ReceiveFromPeer(resultingPacket, _remoteEndPoint);

                //Clear memory
                _holdedFragments.Remove(packetFragId);
            }
            else //Just simple packet
            {
                _netManager.ReceiveFromPeer(p, _remoteEndPoint);
            }
        }
Beispiel #2
0
        private void DataReceived(byte[] reusableBuffer, int count, NetEndPoint remoteEndPoint)
        {
#if STATS_ENABLED
            Statistics.PacketsReceived++;
            Statistics.BytesReceived += (uint)count;
#endif

            //Try read packet
            NetPacket packet = _netPacketPool.GetAndRead(reusableBuffer, 0, count);
            if (packet == null)
            {
                NetUtils.DebugWriteError("[NM] DataReceived: bad!");
                return;
            }

            //Check unconnected
            switch (packet.Property)
            {
            case PacketProperty.DiscoveryRequest:
                if (DiscoveryEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.DiscoveryRequest);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.DiscoveryResponse:
            {
                var netEvent = CreateEvent(NetEventType.DiscoveryResponse);
                netEvent.RemoteEndPoint = remoteEndPoint;
                netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                EnqueueEvent(netEvent);
            }
                return;

            case PacketProperty.UnconnectedMessage:
                if (UnconnectedMessagesEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.ReceiveUnconnected);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.NatIntroduction:
            case PacketProperty.NatIntroductionRequest:
            case PacketProperty.NatPunchMessage:
            {
                if (NatPunchEnabled)
                {
                    NatPunchModule.ProcessMessage(remoteEndPoint, packet);
                }
                return;
            }
            }

            //Check normal packets
            NetPeer netPeer;

            //Check peers
            Monitor.Enter(_peers);
            int peersCount = _peers.Count;

            if (_peers.TryGetValue(remoteEndPoint, out netPeer))
            {
                Monitor.Exit(_peers);
                //Send
                if (packet.Property == PacketProperty.Disconnect)
                {
                    if (BitConverter.ToInt64(packet.RawData, 1) != netPeer.ConnectId)
                    {
                        //Old or incorrect disconnect
                        _netPacketPool.Recycle(packet);
                        return;
                    }

                    var netEvent = CreateEvent(NetEventType.Disconnect);
                    netEvent.Peer = netPeer;
                    netEvent.DataReader.SetSource(packet.RawData, 9, packet.Size);
                    netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose;
                    EnqueueEvent(netEvent);

                    _peers.Remove(netPeer.EndPoint);
                    //do not recycle because no sense)
                }
                else if (packet.Property == PacketProperty.ConnectAccept)
                {
                    if (netPeer.ProcessConnectAccept(packet))
                    {
                        var connectEvent = CreateEvent(NetEventType.Connect);
                        connectEvent.Peer = netPeer;
                        EnqueueEvent(connectEvent);
                    }
                    _netPacketPool.Recycle(packet);
                }
                else
                {
                    netPeer.ProcessPacket(packet);
                }
                return;
            }

            try
            {
                if (peersCount < _maxConnections && packet.Property == PacketProperty.ConnectRequest)
                {
                    int protoId = BitConverter.ToInt32(packet.RawData, 1);
                    if (protoId != NetConstants.ProtocolId)
                    {
                        NetUtils.DebugWrite(ConsoleColor.Cyan,
                                            "[NM] Peer connect reject. Invalid protocol ID: " + protoId);
                        return;
                    }

                    string peerKey = Encoding.UTF8.GetString(packet.RawData, 13, packet.Size - 13);
                    if (peerKey != ConnectKey)
                    {
                        NetUtils.DebugWrite(ConsoleColor.Cyan, "[NM] Peer connect reject. Invalid key: " + peerKey);
                        return;
                    }

                    //Getting new id for peer
                    long connectionId = BitConverter.ToInt64(packet.RawData, 5);
                    //response with id
                    netPeer = new NetPeer(this, remoteEndPoint, connectionId);
                    NetUtils.DebugWrite(ConsoleColor.Cyan, "[NM] Received peer connect request Id: {0}, EP: {1}",
                                        netPeer.ConnectId, remoteEndPoint);

                    //clean incoming packet
                    _netPacketPool.Recycle(packet);

                    _peers.Add(remoteEndPoint, netPeer);

                    var netEvent = CreateEvent(NetEventType.Connect);
                    netEvent.Peer = netPeer;
                    EnqueueEvent(netEvent);
                }
            }
            finally
            {
                Monitor.Exit(_peers);
            }
        }
Beispiel #3
0
        private void DataReceived(byte[] reusableBuffer, int count, NetEndPoint remoteEndPoint)
        {
#if STATS_ENABLED
            Statistics.PacketsReceived++;
            Statistics.BytesReceived += (uint)count;
#endif

            //Try read packet
            NetPacket packet = NetPacketPool.GetAndRead(reusableBuffer, 0, count);
            if (packet == null)
            {
                NetUtils.DebugWriteError("[NM] DataReceived: bad!");
                return;
            }

            //Check unconnected
            switch (packet.Property)
            {
            case PacketProperty.DiscoveryRequest:
                if (DiscoveryEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.DiscoveryRequest);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.DiscoveryResponse:
            {
                var netEvent = CreateEvent(NetEventType.DiscoveryResponse);
                netEvent.RemoteEndPoint = remoteEndPoint;
                netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                EnqueueEvent(netEvent);
            }
                return;

            case PacketProperty.UnconnectedMessage:
                if (UnconnectedMessagesEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.ReceiveUnconnected);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.NatIntroduction:
            case PacketProperty.NatIntroductionRequest:
            case PacketProperty.NatPunchMessage:
            {
                if (NatPunchEnabled)
                {
                    NatPunchModule.ProcessMessage(remoteEndPoint, packet);
                }
                return;
            }
            }

            //Check normal packets
            NetPeer netPeer;
            lock (_peers)
            {
                _peers.TryGetValue(remoteEndPoint, out netPeer);
            }
            if (netPeer != null &&
                netPeer.ConnectionState != ConnectionState.Disconnected)
            {
                switch (packet.Property)
                {
                case PacketProperty.Disconnect:
                    if (netPeer.ConnectionState == ConnectionState.InProgress ||
                        netPeer.ConnectionState == ConnectionState.Connected)
                    {
                        if (BitConverter.ToInt64(packet.RawData, 1) != netPeer.ConnectId)
                        {
                            //Old or incorrect disconnect
                            NetPacketPool.Recycle(packet);
                            return;
                        }

                        var netEvent = CreateEvent(NetEventType.Disconnect);
                        netEvent.Peer = netPeer;
                        netEvent.DataReader.SetSource(packet.RawData, 9, packet.Size);
                        netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose;
                        EnqueueEvent(netEvent);
                    }
                    break;

                case PacketProperty.ShutdownOk:
                    if (netPeer.ConnectionState != ConnectionState.ShutdownRequested)
                    {
                        return;
                    }
                    netPeer.ProcessPacket(packet);
                    NetUtils.DebugWriteForce(ConsoleColor.Cyan, "[NM] ShutdownOK!");
                    break;

                case PacketProperty.ConnectAccept:
                    if (netPeer.ProcessConnectAccept(packet))
                    {
                        var connectEvent = CreateEvent(NetEventType.Connect);
                        connectEvent.Peer = netPeer;
                        EnqueueEvent(connectEvent);
                    }
                    NetPacketPool.Recycle(packet);
                    return;

                default:
                    netPeer.ProcessPacket(packet);
                    return;
                }
                return;
            }

            //Unacked shutdown
            if (packet.Property == PacketProperty.Disconnect)
            {
                byte[] data = { (byte)PacketProperty.ShutdownOk };
                SendRaw(data, 0, 1, remoteEndPoint);
                return;
            }

            if (packet.Property == PacketProperty.ConnectRequest && packet.Size >= 12)
            {
                int peersCount = GetPeersCount(ConnectionState.Connected | ConnectionState.InProgress);
                lock (_connectingPeers)
                {
                    if (_connectingPeers.Contains(remoteEndPoint))
                    {
                        return;
                    }
                    if (peersCount < _maxConnections)
                    {
                        int protoId = BitConverter.ToInt32(packet.RawData, 1);
                        if (protoId != NetConstants.ProtocolId)
                        {
                            NetUtils.DebugWrite(ConsoleColor.Cyan,
                                                "[NM] Peer connect reject. Invalid protocol ID: " + protoId);
                            return;
                        }

                        //Getting new id for peer
                        long connectionId = BitConverter.ToInt64(packet.RawData, 5);

                        // Read data and create request
                        var reader = new NetDataReader(null, 0, 0);
                        if (packet.Size > 12)
                        {
                            reader.SetSource(packet.RawData, 13, packet.Size);
                        }

                        _connectingPeers.Add(remoteEndPoint);
                        var netEvent = CreateEvent(NetEventType.ConnectionRequest);
                        netEvent.ConnectionRequest =
                            new ConnectionRequest(connectionId, remoteEndPoint, reader, OnConnectionSolved);
                        EnqueueEvent(netEvent);
                    }
                }
            }
        }
        public bool Bind(int port, bool reuseAddress)
        {
            _udpSocketv4                   = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            _udpSocketv4.Blocking          = false;
            _udpSocketv4.ReceiveBufferSize = NetConstants.SocketBufferSize;
            _udpSocketv4.SendBufferSize    = NetConstants.SocketBufferSize;
            _udpSocketv4.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, NetConstants.SocketTTL);
            if (reuseAddress)
            {
                _udpSocketv4.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }
#if !NETCORE
            _udpSocketv4.DontFragment = true;
#endif

            try
            {
                _udpSocketv4.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            }
            catch (SocketException e)
            {
                NetUtils.DebugWriteError("Broadcast error: {0}", e.ToString());
            }

            if (!BindSocket(_udpSocketv4, new IPEndPoint(IPAddress.Any, port)))
            {
                return(false);
            }
            _port                  = ((IPEndPoint)_udpSocketv4.LocalEndPoint).Port;
            _running               = true;
            _threadv4              = new Thread(ReceiveLogic);
            _threadv4.Name         = "SocketThreadv4(" + _port + ")";
            _threadv4.IsBackground = true;
            _threadv4.Start(_udpSocketv4);

            //Check IPv6 support
            if (!IPv6Support)
            {
                return(true);
            }

            _udpSocketv6                   = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
            _udpSocketv6.Blocking          = false;
            _udpSocketv6.ReceiveBufferSize = NetConstants.SocketBufferSize;
            _udpSocketv6.SendBufferSize    = NetConstants.SocketBufferSize;
            if (reuseAddress)
            {
                _udpSocketv6.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }

            //Use one port for two sockets
            if (BindSocket(_udpSocketv6, new IPEndPoint(IPAddress.IPv6Any, _port)))
            {
                try
                {
#if !ENABLE_IL2CPP
                    _udpSocketv6.SetSocketOption(
                        SocketOptionLevel.IPv6,
                        SocketOptionName.AddMembership,
                        new IPv6MulticastOption(MulticastAddressV6));
#endif
                }
                catch (Exception)
                {
                    // Unity3d throws exception - ignored
                }

                _threadv6              = new Thread(ReceiveLogic);
                _threadv6.Name         = "SocketThreadv6(" + _port + ")";
                _threadv6.IsBackground = true;
                _threadv6.Start(_udpSocketv6);
            }

            return(true);
        }
Beispiel #5
0
        //Process incoming packet
        internal void ProcessPacket(NetPacket packet)
        {
            _timeSinceLastPacket = 0;

            NetUtils.DebugWrite("[RR]PacketProperty: {0}", packet.Property);
            switch (packet.Property)
            {
            case PacketProperty.ConnectRequest:
                //response with connect
                long newId = BitConverter.ToInt64(packet.RawData, NetConstants.RequestConnectIdIndex);

                NetUtils.DebugWrite("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}", _connectId, newId, _remoteEndPoint);
                if (newId > _connectId)
                {
                    _connectId = newId;
                }

                SendConnectAccept();
                _packetPool.Recycle(packet);
                break;

            case PacketProperty.Merged:
                int pos = NetConstants.HeaderSize;
                while (pos < packet.Size)
                {
                    ushort size = BitConverter.ToUInt16(packet.RawData, pos);
                    pos += 2;
                    NetPacket mergedPacket = _packetPool.GetAndRead(packet.RawData, pos, size);
                    if (mergedPacket == null)
                    {
                        _packetPool.Recycle(packet);
                        break;
                    }
                    pos += size;
                    ProcessPacket(mergedPacket);
                }
                break;

            //If we get ping, send pong
            case PacketProperty.Ping:
                if (NetUtils.RelativeSequenceNumber(packet.Sequence, _remotePingSequence) < 0)
                {
                    _packetPool.Recycle(packet);
                    break;
                }
                NetUtils.DebugWrite("[PP]Ping receive, send pong");
                _remotePingSequence = packet.Sequence;
                _packetPool.Recycle(packet);

                //send
                CreateAndSend(PacketProperty.Pong, _remotePingSequence);
                break;

            //If we get pong, calculate ping time and rtt
            case PacketProperty.Pong:
                if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pingSequence) < 0)
                {
                    _packetPool.Recycle(packet);
                    break;
                }
                _pingSequence = packet.Sequence;
                int rtt = (int)(DateTime.UtcNow - _pingTimeStart).TotalMilliseconds;
                UpdateRoundTripTime(rtt);
                NetUtils.DebugWrite("[PP]Ping: {0}", rtt);
                _packetPool.Recycle(packet);
                break;

            //Process ack
            case PacketProperty.AckReliable:
                _reliableUnorderedChannel.ProcessAck(packet);
                _packetPool.Recycle(packet);
                break;

            case PacketProperty.AckReliableOrdered:
                _reliableOrderedChannel.ProcessAck(packet);
                _packetPool.Recycle(packet);
                break;

            //Process in order packets
            case PacketProperty.Sequenced:
                _sequencedChannel.ProcessPacket(packet);
                break;

            case PacketProperty.ReliableUnordered:
                _reliableUnorderedChannel.ProcessPacket(packet);
                break;

            case PacketProperty.ReliableOrdered:
                _reliableOrderedChannel.ProcessPacket(packet);
                break;

            case PacketProperty.ReliableSequenced:
                _reliableSequencedChannel.ProcessPacket(packet);
                break;

            //Simple packet without acks
            case PacketProperty.Unreliable:
                AddIncomingPacket(packet);
                return;

            case PacketProperty.MtuCheck:
            case PacketProperty.MtuOk:
                ProcessMtuPacket(packet);
                break;

            case PacketProperty.ShutdownOk:
                _connectionState = ConnectionState.Disconnected;
                break;

            default:
                NetUtils.DebugWriteError("Error! Unexpected packet type: " + packet.Property);
                break;
            }
        }
        private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEndPoint)
        {
#if STATS_ENABLED
            Statistics.PacketsReceived++;
            Statistics.BytesReceived += (uint)count;
#endif
            //Try read packet
            NetPacket packet = NetPacketPool.GetPacket(count, false);
            if (!packet.FromBytes(reusableBuffer, 0, count))
            {
                NetPacketPool.Recycle(packet);
                NetUtils.DebugWriteError("[NM] DataReceived: bad!");
                return;
            }

            //get peer
            //Check normal packets
            NetPeer netPeer;
            //old packets protection
            bool peerFound = _peers.TryGetValue(remoteEndPoint, out netPeer);

            //Check unconnected
            switch (packet.Property)
            {
            case PacketProperty.DiscoveryRequest:
                if (!DiscoveryEnabled)
                {
                    break;
                }
                CreateEvent(NetEvent.EType.DiscoveryRequest, remoteEndPoint: remoteEndPoint, readerSource: packet);
                break;

            case PacketProperty.DiscoveryResponse:
                CreateEvent(NetEvent.EType.DiscoveryResponse, remoteEndPoint: remoteEndPoint, readerSource: packet);
                break;

            case PacketProperty.UnconnectedMessage:
                if (!UnconnectedMessagesEnabled)
                {
                    break;
                }
                CreateEvent(NetEvent.EType.ReceiveUnconnected, remoteEndPoint: remoteEndPoint, readerSource: packet);
                break;

            case PacketProperty.NatIntroduction:
            case PacketProperty.NatIntroductionRequest:
            case PacketProperty.NatPunchMessage:
                if (NatPunchEnabled)
                {
                    NatPunchModule.ProcessMessage(remoteEndPoint, packet);
                }
                break;

            case PacketProperty.Disconnect:
                if (peerFound)
                {
                    var disconnectResult = netPeer.ProcessDisconnect(packet);
                    if (disconnectResult == DisconnectResult.None)
                    {
                        NetPacketPool.Recycle(packet);
                        return;
                    }
                    if (disconnectResult == DisconnectResult.Disconnect)
                    {
                        _connectedPeersCount--;
                    }
                    CreateEvent(
                        NetEvent.EType.Disconnect,
                        netPeer,
                        disconnectReason: disconnectResult == DisconnectResult.Disconnect
                                ? DisconnectReason.RemoteConnectionClose
                                : DisconnectReason.ConnectionRejected,
                        readerSource: packet
                        );
                }
                else
                {
                    NetPacketPool.Recycle(packet);
                }
                //Send shutdown
                SendRaw(new[] { (byte)PacketProperty.ShutdownOk }, 0, 1, remoteEndPoint);
                break;

            case PacketProperty.ConnectAccept:
                var connAccept = NetConnectAcceptPacket.FromData(packet);
                if (connAccept != null && peerFound && netPeer.ProcessConnectAccept(connAccept))
                {
                    CreateEvent(NetEvent.EType.Connect, netPeer);
                }
                break;

            case PacketProperty.ConnectRequest:
                var connRequest = NetConnectRequestPacket.FromData(packet);
                if (connRequest != null)
                {
                    ProcessConnectRequest(remoteEndPoint, netPeer, connRequest);
                }
                break;

            default:
                if (peerFound)
                {
                    netPeer.ProcessPacket(packet);
                }
                break;
            }
        }
Beispiel #7
0
        //Process incoming packet
        internal void ProcessPacket(NetPacket packet)
        {
            _timeSinceLastPacket = 0;
            if (packet.ConnectionNumber != _connectNum &&
                packet.Property != PacketProperty.ShutdownOk) //withou connectionNum
            {
                NetUtils.DebugWrite(ConsoleColor.Red, "[RR]Old packet");
                _packetPool.Recycle(packet);
                return;
            }

            NetUtils.DebugWrite("[RR]PacketProperty: {0}", packet.Property);
            switch (packet.Property)
            {
            case PacketProperty.Merged:
                int pos = NetConstants.HeaderSize;
                while (pos < packet.Size)
                {
                    ushort size = BitConverter.ToUInt16(packet.RawData, pos);
                    pos += 2;
                    NetPacket mergedPacket = _packetPool.GetPacket(size, false);
                    if (!mergedPacket.FromBytes(packet.RawData, pos, size))
                    {
                        _packetPool.Recycle(packet);
                        break;
                    }
                    pos += size;
                    ProcessPacket(mergedPacket);
                }
                break;

            //If we get ping, send pong
            case PacketProperty.Ping:
                if (NetUtils.RelativeSequenceNumber(packet.Sequence, _remotePingSequence) < 0)
                {
                    _packetPool.Recycle(packet);
                    break;
                }
                NetUtils.DebugWrite("[PP]Ping receive, send pong");
                _remotePingSequence = packet.Sequence;
                _packetPool.Recycle(packet);

                //send
                _pongPacket.Sequence = _remotePingSequence;
                _netManager.SendRaw(_pongPacket, _remoteEndPoint);
                break;

            //If we get pong, calculate ping time and rtt
            case PacketProperty.Pong:
                if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pingSequence) < 0)
                {
                    _packetPool.Recycle(packet);
                    break;
                }
                _pingSequence = packet.Sequence;
                int rtt = (int)(DateTime.UtcNow - _pingTimeStart).TotalMilliseconds;
                UpdateRoundTripTime(rtt);
                NetUtils.DebugWrite("[PP]Ping: {0}", rtt);
                _packetPool.Recycle(packet);
                break;

            //Process ack
            case PacketProperty.AckReliable:
                _reliableUnorderedChannel.ProcessAck(packet);
                _packetPool.Recycle(packet);
                break;

            case PacketProperty.AckReliableOrdered:
                _reliableOrderedChannel.ProcessAck(packet);
                _packetPool.Recycle(packet);
                break;

            //Process in order packets
            case PacketProperty.Sequenced:
                _sequencedChannel.ProcessPacket(packet);
                break;

            case PacketProperty.ReliableUnordered:
                _reliableUnorderedChannel.ProcessPacket(packet);
                break;

            case PacketProperty.ReliableOrdered:
                _reliableOrderedChannel.ProcessPacket(packet);
                break;

            case PacketProperty.ReliableSequenced:
                _reliableSequencedChannel.ProcessPacket(packet);
                break;

            case PacketProperty.AckReliableSequenced:
                _reliableSequencedChannel.ProcessAck(packet);
                _packetPool.Recycle(packet);
                break;

            //Simple packet without acks
            case PacketProperty.Unreliable:
                AddIncomingPacket(packet);
                return;

            case PacketProperty.MtuCheck:
            case PacketProperty.MtuOk:
                ProcessMtuPacket(packet);
                break;

            case PacketProperty.ShutdownOk:
                if (_connectionState == ConnectionState.ShutdownRequested)
                {
                    _connectionState = ConnectionState.Disconnected;
                }
                _packetPool.Recycle(packet);
                break;

            default:
                NetUtils.DebugWriteError("Error! Unexpected packet type: " + packet.Property);
                break;
            }
        }
Beispiel #8
0
        public void Receive(bool ipV6, byte[] receiveBuffer)
        {
            Socket      socket;
            EndPoint    bufferEndPoint;
            NetEndPoint bufferNetEndPoint;
            int         result;

            if (ipV6 == true)
            {
                socket            = _udpSocketv6;
                bufferEndPoint    = _bufferEndPointv6;
                bufferNetEndPoint = _bufferNetEndPointv6;
            }
            else
            {
                socket            = _udpSocketv4;
                bufferEndPoint    = _bufferEndPointv4;
                bufferNetEndPoint = _bufferNetEndPointv4;
            }

            while (true)
            {
                if (socket == null || socket.Available < 1)
                {
                    return;
                }

                //Reading data
                try
                {
                    result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref bufferEndPoint);
                    if (!bufferNetEndPoint.EndPoint.Equals(bufferEndPoint))
                    {
                        bufferNetEndPoint = new NetEndPoint((IPEndPoint)bufferEndPoint);
                    }
                }
                catch (SocketException ex)
                {
                    if (ex.SocketErrorCode == SocketError.WouldBlock)
                    {
                        // Hiii! Increase buffer size
                        return;
                    }
                    if (ex.SocketErrorCode == SocketError.ConnectionReset ||
                        ex.SocketErrorCode == SocketError.MessageSize ||
                        ex.SocketErrorCode == SocketError.Interrupted)
                    {
                        //10040 - message too long
                        //10054 - remote close (not error)
                        //Just UDP
                        NetUtils.DebugWrite(ConsoleColor.DarkRed, "[R] Ingored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString());
                        return;
                    }
                    NetUtils.DebugWriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString());
                    _onMessageReceived(null, 0, (int)ex.SocketErrorCode, bufferNetEndPoint);

                    return;
                }

                //All ok!
                NetUtils.DebugWrite(ConsoleColor.Blue, "[R]Received data from {0}, result: {1}", bufferNetEndPoint.ToString(), result);
                _onMessageReceived(receiveBuffer, result, 0, bufferNetEndPoint);
            }
        }
Beispiel #9
0
        public bool Bind(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool reuseAddress, bool enableIPv4, bool enableIPv6)
        {
            if (enableIPv4)
            {
                _udpSocketv4                   = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                _udpSocketv4.Blocking          = false;
                _udpSocketv4.ReceiveBufferSize = NetConstants.SocketBufferSize;
                _udpSocketv4.SendBufferSize    = NetConstants.SocketBufferSize;
                _udpSocketv4.Ttl               = NetConstants.SocketTTL;
                if (reuseAddress)
                {
                    _udpSocketv4.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                }
#if !NETCORE
                _udpSocketv4.DontFragment = true;
#endif
                try
                {
                    _udpSocketv4.EnableBroadcast = true;
                }
                catch (SocketException e)
                {
                    NetUtils.DebugWriteError("Broadcast error: {0}", e.ToString());
                }

                if (!BindSocket(_udpSocketv4, new IPEndPoint(addressIPv4, port)))
                {
                    return(false);
                }
                LocalPort = ((IPEndPoint)_udpSocketv4.LocalEndPoint).Port;

                _bufferEndPointv4    = new IPEndPoint(_udpSocketv4.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
                _bufferNetEndPointv4 = new NetEndPoint((IPEndPoint)_bufferEndPointv4);
            }

            //Check IPv6 support
            if (!IPv6Support || enableIPv6 == false)
            {
                return(true);
            }

            _udpSocketv6                   = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
            _udpSocketv6.Blocking          = false;
            _udpSocketv6.ReceiveBufferSize = NetConstants.SocketBufferSize;
            _udpSocketv6.SendBufferSize    = NetConstants.SocketBufferSize;
            //_udpSocketv6.Ttl = NetConstants.SocketTTL;
            if (reuseAddress)
            {
                _udpSocketv6.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }

            //Use one port for two sockets
            if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort)))
            {
                try
                {
#if !ENABLE_IL2CPP
                    _udpSocketv6.SetSocketOption(
                        SocketOptionLevel.IPv6,
                        SocketOptionName.AddMembership,
                        new IPv6MulticastOption(MulticastAddressV6));
#endif
                }
                catch (Exception)
                {
                    // Unity3d throws exception - ignored
                }
            }

            _bufferEndPointv6    = new IPEndPoint(_udpSocketv4.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
            _bufferNetEndPointv6 = new NetEndPoint((IPEndPoint)_bufferEndPointv6);

            return(true);
        }
Beispiel #10
0
        private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEndPoint)
        {
#if STATS_ENABLED
            Statistics.PacketsReceived++;
            Statistics.BytesReceived += (uint)count;
#endif

            //Try read packet
            NetPacket packet = NetPacketPool.GetPacket(count, false);
            if (!packet.FromBytes(reusableBuffer, 0, count))
            {
                NetPacketPool.Recycle(packet);
                NetUtils.DebugWriteError("[NM] DataReceived: bad!");
                return;
            }

            //Check unconnected
            switch (packet.Property)
            {
            case PacketProperty.DiscoveryRequest:
                if (DiscoveryEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.DiscoveryRequest);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.DiscoveryResponse:
            {
                var netEvent = CreateEvent(NetEventType.DiscoveryResponse);
                netEvent.RemoteEndPoint = remoteEndPoint;
                netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                EnqueueEvent(netEvent);
            }
                return;

            case PacketProperty.UnconnectedMessage:
                if (UnconnectedMessagesEnabled)
                {
                    var netEvent = CreateEvent(NetEventType.ReceiveUnconnected);
                    netEvent.RemoteEndPoint = remoteEndPoint;
                    netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count);
                    EnqueueEvent(netEvent);
                }
                return;

            case PacketProperty.NatIntroduction:
            case PacketProperty.NatIntroductionRequest:
            case PacketProperty.NatPunchMessage:
            {
                if (NatPunchEnabled)
                {
                    NatPunchModule.ProcessMessage(remoteEndPoint, packet);
                }
                return;
            }
            }

            //Check normal packets
            NetPeer netPeer;
            bool    isPeerConnecting;
            lock (_connectingPeers)
            {
                isPeerConnecting = _connectingPeers.Contains(remoteEndPoint);
                _peers.TryGetValue(remoteEndPoint, out netPeer);
            }

            if (netPeer != null)
            {
                if (netPeer.ConnectionState == ConnectionState.Disconnected)
                {
                    return;
                }
                NetEvent netEvent;
                switch (packet.Property)
                {
                case PacketProperty.Disconnect:
                    if (netPeer.ConnectionState == ConnectionState.InProgress ||
                        netPeer.ConnectionState == ConnectionState.Connected)
                    {
                        if (BitConverter.ToInt64(packet.RawData, 1) != netPeer.ConnectId)
                        {
                            //Old or incorrect disconnect
                            NetPacketPool.Recycle(packet);
                            return;
                        }
                        netEvent      = CreateEvent(NetEventType.Disconnect);
                        netEvent.Peer = netPeer;
                        netEvent.DataReader.SetSource(packet.RawData, 9, packet.Size);
                        netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose;
                        EnqueueEvent(netEvent);
                        netPeer.ProcessPacket(packet);
                        SendRaw(new[] { (byte)PacketProperty.ShutdownOk }, 0, 1, remoteEndPoint);
                    }
                    return;

                case PacketProperty.ConnectAccept:
                    if (netPeer.ProcessConnectAccept(packet))
                    {
                        var connectEvent = CreateEvent(NetEventType.Connect);
                        connectEvent.Peer = netPeer;
                        EnqueueEvent(connectEvent);
                    }
                    return;

                case PacketProperty.ConnectRequest:
                    long newId = BitConverter.ToInt64(packet.RawData, NetConstants.RequestConnectIdIndex);
                    NetUtils.DebugWrite("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}", netPeer.ConnectId, newId, remoteEndPoint);

                    //Remove old peer and connect new
                    if (newId > netPeer.ConnectId)
                    {
                        netEvent      = CreateEvent(NetEventType.Disconnect);
                        netEvent.Peer = netPeer;
                        netEvent.DataReader.SetSource(packet.RawData, 9, packet.Size);
                        netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose;
                        _peers.RemovePeer(netPeer);
                        break;
                        //To reconnect peer
                    }
                    else
                    {
                        //Just answer accept
                        netPeer.ProcessPacket(packet);
                        return;
                    }

                default:
                    netPeer.ProcessPacket(packet);
                    return;
                }
            }

            //Unacked shutdown
            if (packet.Property == PacketProperty.Disconnect)
            {
                SendRaw(new[] { (byte)PacketProperty.ShutdownOk }, 0, 1, remoteEndPoint);
                return;
            }

            if (packet.Property == PacketProperty.ConnectRequest && packet.Size >= 12)
            {
                NetUtils.DebugWrite("[NM] Received ConnectionRequest");
                if (isPeerConnecting)
                {
                    NetUtils.DebugWrite("[NM] Peer already connecting");
                    return;
                }
                if (GetPeersCount(ConnectionState.Connected | ConnectionState.InProgress) < _maxConnections)
                {
                    int protoId = BitConverter.ToInt32(packet.RawData, 1);
                    if (protoId != NetConstants.ProtocolId)
                    {
                        NetUtils.DebugWrite(ConsoleColor.Cyan,
                                            "[NM] Peer connect reject. Invalid protocol ID: " + protoId);
                        return;
                    }

                    //Getting new id for peer
                    long connectionId = BitConverter.ToInt64(packet.RawData, 5);

                    // Read data and create request
                    var reader = new NetDataReader(null, 0, 0);
                    if (packet.Size > 12)
                    {
                        reader.SetSource(packet.RawData, 13, packet.Size);
                    }

                    NetUtils.DebugWrite("[NM] Creating request event: " + connectionId);
                    lock (_connectingPeers)
                    {
                        _connectingPeers.Add(remoteEndPoint);
                    }
                    var netEvent = CreateEvent(NetEventType.ConnectionRequest);
                    netEvent.ConnectionRequest =
                        new ConnectionRequest(connectionId, remoteEndPoint, reader, OnConnectionSolved);
                    EnqueueEvent(netEvent);
                }
            }
        }
Beispiel #11
0
        private void ReceiveLogic(object state)
        {
            Socket      socket            = (Socket)state;
            EndPoint    bufferEndPoint    = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
            NetEndPoint bufferNetEndPoint = new NetEndPoint((IPEndPoint)bufferEndPoint);

#if WIN32 && UNSAFE
            int       saddrSize         = 32;
            byte[]    prevAddress       = new byte[saddrSize];
            byte[]    socketAddress     = new byte[saddrSize];
            byte[]    addrBuffer        = new byte[16]; //IPAddress.IPv6AddressBytes
            var       sockeHandle       = socket.Handle;
            IntPtr[]  fileDescriptorSet = { (IntPtr)1, sockeHandle };
            TimeValue time = new TimeValue {
                Microseconds = SocketReceivePollTime
            };
#endif
            byte[] receiveBuffer = new byte[NetConstants.PacketSizeLimit];

            while (_running)
            {
                int result;

                //Reading data
                try
                {
#if WIN32 && UNSAFE
                    fileDescriptorSet[0] = (IntPtr)1;
                    fileDescriptorSet[1] = sockeHandle;
                    int socketCount = select(0, fileDescriptorSet, null, null, ref time);
                    if ((SocketError)socketCount == SocketError.SocketError)
                    {
                        throw new SocketException(Marshal.GetLastWin32Error());
                    }
                    if ((int)fileDescriptorSet[0] == 0 || fileDescriptorSet[1] != sockeHandle)
                    {
                        continue;
                    }

                    result = recvfrom(
                        sockeHandle,
                        receiveBuffer,
                        receiveBuffer.Length,
                        SocketFlags.None,
                        socketAddress,
                        ref saddrSize);
                    if ((SocketError)result == SocketError.SocketError)
                    {
                        throw new SocketException(Marshal.GetLastWin32Error());
                    }

                    bool recreate = false;
                    for (int i = 0; i < saddrSize; i++)
                    {
                        if (socketAddress[i] != prevAddress[i])
                        {
                            prevAddress[i] = socketAddress[i];
                            recreate       = true;
                        }
                    }
                    if (recreate)
                    {
                        if (socket.AddressFamily == AddressFamily.InterNetwork)
                        {
                            int  port    = (socketAddress[2] << 8 & 0xFF00) | socketAddress[3];
                            long address = (
                                (socketAddress[4] & 0x000000FF) |
                                (socketAddress[5] << 8 & 0x0000FF00) |
                                (socketAddress[6] << 16 & 0x00FF0000) |
                                (socketAddress[7] << 24)
                                ) & 0x00000000FFFFFFFF;
                            bufferNetEndPoint = new NetEndPoint(new IPEndPoint(address, port));
                        }
                        else
                        {
                            for (int i = 0; i < addrBuffer.Length; i++)
                            {
                                addrBuffer[i] = socketAddress[i + 8];
                            }
                            int  port  = (socketAddress[2] << 8 & 0xFF00) | (socketAddress[3]);
                            long scope = (socketAddress[27] << 24) +
                                         (socketAddress[26] << 16) +
                                         (socketAddress[25] << 8) +
                                         (socketAddress[24]);
                            bufferNetEndPoint = new NetEndPoint(new IPEndPoint(new IPAddress(addrBuffer, scope), port));
                        }
                    }
#else
                    if (!socket.Poll(SocketReceivePollTime, SelectMode.SelectRead))
                    {
                        continue;
                    }
                    result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref bufferEndPoint);
                    if (!bufferNetEndPoint.EndPoint.Equals(bufferEndPoint))
                    {
                        bufferNetEndPoint = new NetEndPoint((IPEndPoint)bufferEndPoint);
                    }
#endif
                }
                catch (SocketException ex)
                {
                    if (ex.SocketErrorCode == SocketError.ConnectionReset ||
                        ex.SocketErrorCode == SocketError.MessageSize)
                    {
                        //10040 - message too long
                        //10054 - remote close (not error)
                        //Just UDP
                        NetUtils.DebugWrite(ConsoleColor.DarkRed, "[R] Ingored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString());
                        continue;
                    }
                    NetUtils.DebugWriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString());
                    _onMessageReceived(null, 0, (int)ex.SocketErrorCode, bufferNetEndPoint);

                    continue;
                }

                //All ok!
                NetUtils.DebugWrite(ConsoleColor.Blue, "[R]Received data from {0}, result: {1}", bufferNetEndPoint.ToString(), result);
                _onMessageReceived(receiveBuffer, result, 0, bufferNetEndPoint);
            }
        }
Beispiel #12
0
        public int SendTo(byte[] data, int offset, int size, NetEndPoint remoteEndPoint, ref int errorCode)
        {
            try
            {
                var socket = _udpSocketv4;
                if (remoteEndPoint.EndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support)
                {
                    socket = _udpSocketv6;
                }

                int result;
#if WIN32 && UNSAFE
                var      handle            = socket.Handle;
                IntPtr[] fileDescriptorSet = { (IntPtr)1, handle };
                int      socketCount       = select(0, null, fileDescriptorSet, null, ref SendPollTime);
                if ((SocketError)socketCount == SocketError.SocketError)
                {
                    throw new SocketException(Marshal.GetLastWin32Error());
                }
                if ((int)fileDescriptorSet[0] == 0 || fileDescriptorSet[1] != handle)
                {
                    return(0);
                }
                unsafe
                {
                    fixed(byte *pinnedBuffer = data)
                    {
                        result = sendto(
                            handle,
                            pinnedBuffer + offset,
                            size,
                            SocketFlags.None,
                            remoteEndPoint.SocketAddr,
                            remoteEndPoint.SocketAddr.Length);
                    }
                }

                if ((SocketError)result == SocketError.SocketError)
                {
                    throw new SocketException(Marshal.GetLastWin32Error());
                }
#else
                if (!socket.Poll(SocketSendPollTime, SelectMode.SelectWrite))
                {
                    return(-1);
                }
                result = socket.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint.EndPoint);
#endif

                NetUtils.DebugWrite(ConsoleColor.Blue, "[S]Send packet to {0}, result: {1}", remoteEndPoint.EndPoint, result);
                return(result);
            }
            catch (SocketException ex)
            {
                if (ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
                {
                    return(0);
                }
                if (ex.SocketErrorCode != SocketError.MessageSize)
                {
                    NetUtils.DebugWriteError("[S]" + ex);
                }

                errorCode = (int)ex.SocketErrorCode;
                return(-1);
            }
            catch (Exception ex)
            {
                NetUtils.DebugWriteError("[S]" + ex);
                return(-1);
            }
        }