Example #1
0
        private void SendMerged()
        {
            if (_mergeCount == 0)
            {
                return;
            }
            int bytesSent;

            if (_mergeCount > 1)
            {
                NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount);
                bytesSent = NetManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, EndPoint);
            }
            else
            {
                //Send without length information and merging
                bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, EndPoint);
            }
#if STATS_ENABLED
            Statistics.PacketsSent++;
            Statistics.BytesSent += (ulong)bytesSent;
#endif
            _mergePos   = 0;
            _mergeCount = 0;
        }
Example #2
0
        //We got punch and can connect
        private void OnNatPunch(NatPunchPacket req, IPEndPoint senderEndPoint)
        {
            //Read info
            NetDebug.Write(NetLogLevel.Trace, "[NAT] punch received from {0} - additional info: {1}",
                           senderEndPoint, req.Token);

            //Release punch success to client; enabling him to Connect() to Sender if token is ok
            if (UnsyncedEvents)
            {
                _natPunchListener.OnNatIntroductionSuccess(
                    senderEndPoint,
                    req.IsExternal ? NatAddressType.External : NatAddressType.Internal,
                    req.Token
                    );
            }
            else
            {
                _successEvents.Enqueue(new SuccessEventData
                {
                    TargetEndPoint = senderEndPoint,
                    Type           = req.IsExternal ? NatAddressType.External : NatAddressType.Internal,
                    Token          = req.Token
                });
            }
        }
        private void ReceiveLogic(object state)
        {
            var      socket         = (Socket)state;
            EndPoint bufferEndPoint =
                new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any,
                               0);
            var receiveBuffer = new byte[NetConstants.MaxPacketSize];

            while (IsActive())
            {
                int result;

                //Reading data
                try
                {
                    if (socket.Available == 0 && !socket.Poll(ReceivePollingTime, SelectMode.SelectRead))
                    {
                        continue;
                    }
                    result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None,
                                                ref bufferEndPoint);
                }
                catch (SocketException ex)
                {
                    switch (ex.SocketErrorCode)
                    {
#if UNITY_IOS && !UNITY_EDITOR
                    case SocketError.NotConnected:
#endif
                    case SocketError.Interrupted:
                    case SocketError.NotSocket:
                        return;

                    case SocketError.ConnectionReset:
                    case SocketError.MessageSize:
                    case SocketError.TimedOut:
                        NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
                                       (int)ex.SocketErrorCode, ex.ToString());
                        break;

                    default:
                        NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode,
                                            ex.ToString());
                        _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint);
                        break;
                    }

                    continue;
                }
                catch (ObjectDisposedException)
                {
                    return;
                }

                //All ok!
                NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(),
                               result);
                _listener.OnMessageReceived(receiveBuffer, result, 0, (IPEndPoint)bufferEndPoint);
            }
        }
Example #4
0
        private bool ProcessError(SocketException ex, EndPoint bufferEndPoint)
        {
            switch (ex.SocketErrorCode)
            {
#if UNITY_IOS && !UNITY_EDITOR
            case SocketError.NotConnected:
#endif
            case SocketError.Interrupted:
            case SocketError.NotSocket:
                return(true);

            case SocketError.ConnectionReset:
            case SocketError.MessageSize:
            case SocketError.TimedOut:
                NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
                               (int)ex.SocketErrorCode, ex.ToString());
                break;

            default:
                NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode,
                                    ex.ToString());
                _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint);
                break;
            }
            return(false);
        }
Example #5
0
        private bool ManualReceive(Socket socket, EndPoint bufferEndPoint, byte[] receiveBuffer)
        {
            int result;

            //Reading data
            try
            {
                int available = socket.Available;
                if (available == 0)
                {
                    return(false);
                }
                while (available > 0)
                {
                    result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None,
                                                ref bufferEndPoint);
                    NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result);
                    _listener.OnMessageReceived(receiveBuffer, result, 0, (IPEndPoint)bufferEndPoint);
                    available -= result;
                }
            }
            catch (SocketException ex)
            {
                return(ProcessError(ex, bufferEndPoint));
            }
            catch (ObjectDisposedException)
            {
                return(true);
            }
            return(false);
        }
Example #6
0
        private void SendMerged()
        {
            if (_mergeCount == 0)
            {
                return;
            }
            int bytesSent;

            if (_mergeCount > 1)
            {
                NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount);
                bytesSent = NetManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, EndPoint);
            }
            else
            {
                //Send without length information and merging
                bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, EndPoint);
            }

            if (NetManager.EnableStatistics)
            {
                Statistics.IncrementPacketsSent();
                Statistics.AddBytesSent(bytesSent);
            }

            _mergePos   = 0;
            _mergeCount = 0;
        }
Example #7
0
        private bool ManualReceive(Socket socket, EndPoint bufferEndPoint, byte[] receiveBuffer)
        {
            int result;

            //Reading data
            try
            {
                int available = socket.Available;
                if (available == 0)
                {
                    return(false);
                }
                while (available > 0)
                {
                    var packet = _listener.NetPacketPool.GetPacket(NetConstants.MaxPacketSize);
                    packet.Size = socket.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None,
                                                     ref bufferEndPoint);
                    NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result);
                    _listener.OnMessageReceived(packet, 0, (IPEndPoint)bufferEndPoint);
                    available -= packet.Size;
                }
            }
            catch (SocketException ex)
            {
                return(ProcessError(ex, bufferEndPoint));
            }
            catch (ObjectDisposedException)
            {
                return(true);
            }
            return(false);
        }
Example #8
0
        internal void SendUserData(NetPacket packet)
        {
            packet.ConnectionNumber = _connectNum;
            int       mergedPacketSize = NetConstants.HeaderSize + packet.Size + 2;
            const int sizeTreshold     = 20;

            if (mergedPacketSize + sizeTreshold >= _mtu)
            {
                NetDebug.Write(NetLogLevel.Trace, "[P]SendingPacket: " + packet.Property);
                int bytesSent = NetManager.SendRaw(packet, EndPoint);
#if STATS_ENABLED
                Statistics.PacketsSent++;
                Statistics.BytesSent += (ulong)bytesSent;
#endif
                return;
            }
            if (_mergePos + mergedPacketSize > _mtu)
            {
                SendMerged();
            }

            FastBitConverter.GetBytes(_mergeData.RawData, _mergePos + NetConstants.HeaderSize, (ushort)packet.Size);
            Buffer.BlockCopy(packet.RawData, 0, _mergeData.RawData, _mergePos + NetConstants.HeaderSize + 2, packet.Size);
            _mergePos += packet.Size + 2;
            _mergeCount++;
            //DebugWriteForce("Merged: " + _mergePos + "/" + (_mtu - 2) + ", count: " + _mergeCount);
        }
Example #9
0
        private void ReceiveLogic(object state)
        {
            Socket   socket         = (Socket)state;
            EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);

            byte[] receiveBuffer = new byte[NetConstants.MaxPacketSize];

            //Console.WriteLine("Socket family: " + socket.AddressFamily);
            //Console.WriteLine("IPEndpoint: " + bufferEndPoint);

            // Create socket event args
            var e = new SocketAsyncEventArgs();

            e.Completed     += (sender, args) => OnReceive(socket, args, receiveBuffer, bufferEndPoint);
            e.RemoteEndPoint = bufferEndPoint;
            e.SetBuffer(receiveBuffer, 0, NetConstants.MaxPacketSize);

            // Read initial data
            bool willRaiseEvent = false;

            try
            {
                willRaiseEvent = _udpSocketv4.ReceiveFromAsync(e);
            }
            // According to msdn this call CAN raise an exception, so let's catch it just in case
            catch (SocketException ex)
            {
                switch (ex.SocketErrorCode)
                {
                case SocketError.Interrupted:
                    return;

                case SocketError.ConnectionReset:
                case SocketError.MessageSize:
                case SocketError.TimedOut:
                    NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
                                   (int)ex.SocketErrorCode, ex.ToString());
                    break;

                default:
                    NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode,
                                        ex.ToString());
                    _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)e.RemoteEndPoint);
                    break;
                }
            }

            // If error, call OnReceive
            if (!willRaiseEvent)
            {
                OnReceive(socket, e, receiveBuffer, bufferEndPoint);
            }
        }
Example #10
0
        //"Accept" incoming constructor
        internal void Accept(long connectId, byte connectNum)
        {
            _connectTime     = connectId;
            _connectionState = ConnectionState.Connected;
            ConnectionNum    = connectNum;

            //Make initial packet
            _connectAcceptPacket = NetConnectAcceptPacket.Make(_connectTime, connectNum, false);
            //Send
            NetManager.SendRaw(_connectAcceptPacket, EndPoint);

            NetDebug.Write(NetLogLevel.Trace, "[CC] ConnectId: {0}", _connectTime);
        }
Example #11
0
        //"Accept" incoming constructor
        internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, long connectId, byte connectNum)
            : this(netManager, remoteEndPoint, id)
        {
            _connectTime     = connectId;
            _connectionState = ConnectionState.Connected;
            ConnectionNum    = connectNum;

            //Make initial packet
            _connectAcceptPacket = NetConnectAcceptPacket.Make(_connectTime, connectNum, false);
            //Send
            NetManager.SendRaw(_connectAcceptPacket, EndPoint);

            NetDebug.Write(NetLogLevel.Trace, "[CC] ConnectId: {0}", _connectTime);
        }
Example #12
0
        protected override bool SendNextPackets()
        {
            if (_mustSendAcks)
            {
                _mustSendAcks = false;
                NetDebug.Write("[RR]SendAcks");
                lock (_outgoingAcks)
                    Peer.SendUserData(_outgoingAcks);
            }

            long currentTime       = DateTime.UtcNow.Ticks;
            bool hasPendingPackets = false;

            lock (_pendingPackets)
            {
                //get packets from queue
                while (!OutgoingQueue.IsEmpty)
                {
                    int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
                    if (relate >= _windowSize)
                    {
                        break;
                    }

                    if (!OutgoingQueue.TryDequeue(out var netPacket))
                    {
                        break;
                    }

                    netPacket.Sequence  = (ushort)_localSeqence;
                    netPacket.ChannelId = _id;
                    _pendingPackets[_localSeqence % _windowSize].Init(netPacket);
                    _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
                }

                //send
                for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
                {
                    // Please note: TrySend is invoked on a mutable struct, it's important to not extract it into a variable here
                    bool hasPacket;
                    _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer, out hasPacket);
                    if (hasPacket)
                    {
                        hasPendingPackets = true;
                    }
                }
            }

            return(hasPendingPackets || _mustSendAcks || OutgoingQueue.Count > 0);
        }
Example #13
0
        //"Connect to" constructor
        internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, byte connectNum, NetDataWriter connectData)
            : this(netManager, remoteEndPoint, id)
        {
            _connectTime     = DateTime.UtcNow.Ticks;
            _connectionState = ConnectionState.Outgoing;
            ConnectionNum    = connectNum;

            //Make initial packet
            _connectRequestPacket = NetConnectRequestPacket.Make(connectData, _connectTime);
            _connectRequestPacket.ConnectionNumber = connectNum;

            //Send request
            NetManager.SendRaw(_connectRequestPacket, EndPoint);

            NetDebug.Write(NetLogLevel.Trace, "[CC] ConnectId: {0}, ConnectNum: {1}", _connectTime, connectNum);
        }
Example #14
0
        private void ReceiveLogicAsync(IAsyncResult ar)
        {
            Socket   _udpSocket     = (Socket)ar.AsyncState;
            EndPoint bufferEndPoint = new IPEndPoint(_udpSocket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);

            try
            {
                int result = _udpSocket.EndReceiveFrom(ar, ref bufferEndPoint);
                //clone receive array
                byte[] buffer = new byte[result];
                Array.Copy(_receiveBufferv4, buffer, result);
                //call BeginReceiveFrom before _listener.OnMessageReceived
                _udpSocket.BeginReceiveFrom(_receiveBufferv4, 0, _receiveBufferv4.Length, SocketFlags.None, ref bufferEndPoint, ReceiveLogicAsync, _udpSocket);
                _listener.OnMessageReceived(buffer, result, 0, (IPEndPoint)bufferEndPoint);
            }
            catch (SocketException ex)
            {
                switch (ex.SocketErrorCode)
                {
                case SocketError.Interrupted:
                    return;

                case SocketError.ConnectionReset:
                case SocketError.MessageSize:
                case SocketError.TimedOut:
                    NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
                                   (int)ex.SocketErrorCode, ex.ToString());
                    break;

                case SocketError.NotConnected:
                    NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
                                   (int)ex.SocketErrorCode, ex.ToString());
                    break;

                default:
                    NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode,
                                        ex.ToString());

                    _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint);
                    break;
                }
            }
            catch (ObjectDisposedException)
            {
                return;
            }
        }
Example #15
0
        private void ProcessMtuPacket(NetPacket packet)
        {
            //header + int
            if (packet.Size < NetConstants.PossibleMtu[0])
            {
                return;
            }

            //first stage check (mtu check and mtu ok)
            int receivedMtu = BitConverter.ToInt32(packet.RawData, 1);
            int endMtuCheck = BitConverter.ToInt32(packet.RawData, packet.Size - 4);

            if (receivedMtu != packet.Size || receivedMtu != endMtuCheck || receivedMtu > NetConstants.MaxPacketSize)
            {
                NetDebug.WriteError("[MTU] Broken packet. RMTU {0}, EMTU {1}, PSIZE {2}", receivedMtu, endMtuCheck, packet.Size);
                return;
            }

            if (packet.Property == PacketProperty.MtuCheck)
            {
                _mtuCheckAttempts = 0;
                NetDebug.Write("[MTU] check. send back: " + receivedMtu);
                packet.Property = PacketProperty.MtuOk;
                NetManager.SendRawAndRecycle(packet, EndPoint);
            }
            else if (receivedMtu > _mtu && !_finishMtu) //MtuOk
            {
                //invalid packet
                if (receivedMtu != NetConstants.PossibleMtu[_mtuIdx + 1])
                {
                    return;
                }

                lock (_mtuMutex)
                {
                    _mtuIdx++;
                    _mtu = receivedMtu;
                }
                //if maxed - finish.
                if (_mtuIdx == NetConstants.PossibleMtu.Length - 1)
                {
                    _finishMtu = true;
                }

                NetDebug.Write("[MTU] ok. Increase to: " + _mtu);
            }
        }
Example #16
0
        internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force)
        {
            lock (_shutdownLock)
            {
                //trying to shutdown already disconnected
                if (_connectionState == ConnectionState.Disconnected ||
                    _connectionState == ConnectionState.ShutdownRequested)
                {
                    return(ShutdownResult.None);
                }

                var result = _connectionState == ConnectionState.Connected
                    ? ShutdownResult.WasConnected
                    : ShutdownResult.Success;

                //don't send anything
                if (force)
                {
                    _connectionState = ConnectionState.Disconnected;
                    return(result);
                }

                //reset time for reconnect protection
                Interlocked.Exchange(ref _timeSinceLastPacket, 0);

                //send shutdown packet
                _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length)
                {
                    ConnectionNumber = _connectNum
                };
                FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime);
                if (_shutdownPacket.Size >= _mtu)
                {
                    //Drop additional data
                    NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!");
                }
                else if (data != null && length > 0)
                {
                    Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length);
                }
                _connectionState = ConnectionState.ShutdownRequested;
                NetDebug.Write("[Peer] Send disconnect");
                NetManager.SendRaw(_shutdownPacket, EndPoint);
                return(result);
            }
        }
Example #17
0
        public override void SendNextPackets()
        {
            if (_mustSendAcks)
            {
                _mustSendAcks = false;
                NetDebug.Write("[RR]SendAcks");
                lock (_outgoingAcks)
                {
                    Peer.SendUserData(_outgoingAcks);
                }
            }

            var currentTime = DateTime.UtcNow.Ticks;

            lock (_pendingPackets)
            {
                //get packets from queue
                lock (OutgoingQueue)
                {
                    while (OutgoingQueue.Count > 0)
                    {
                        var relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
                        if (relate >= _windowSize)
                        {
                            break;
                        }

                        var netPacket = OutgoingQueue.Dequeue();
                        netPacket.Sequence  = (ushort)_localSeqence;
                        netPacket.ChannelId = _id;
                        _pendingPackets[_localSeqence % _windowSize].Init(netPacket);
                        _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
                    }
                }

                //send
                for (var pendingSeq = _localWindowStart;
                     pendingSeq != _localSeqence;
                     pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
                {
                    _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer);
                }
            }
        }
Example #18
0
        public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint, ref SocketError errorCode)
        {
            if (!IsActive())
            {
                return(0);
            }
            try
            {
                var socket = _udpSocketv4;
                if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support)
                {
                    socket = _udpSocketv6;
                }

                //Console.WriteLine("{0}, {1}, {2}, {3}, {4}", data, offset, size, SocketFlags.None, remoteEndPoint);
                int result = socket.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint);
                NetDebug.Write(NetLogLevel.Trace, "[S]Send packet to {0}, result: {1}", remoteEndPoint, result);
                return(result);
            }
            catch (SocketException ex)
            {
                switch (ex.SocketErrorCode)
                {
                case SocketError.NoBufferSpaceAvailable:
                case SocketError.Interrupted:
                    return(0);

                case SocketError.MessageSize:     //do nothing
                    break;

                default:
                    NetDebug.WriteError("[S]" + ex);
                    break;
                }
                errorCode = ex.SocketErrorCode;
                return(-1);
            }
            catch (Exception ex)
            {
                NetDebug.WriteError("[S]" + ex);
                return(-1);
            }
        }
 public void TrySend(long currentTime, NetPeer peer)
 {
     if (_packet == null)
     {
         return;
     }
     if (_isSent) //check send time
     {
         double resendDelay    = peer.ResendDelay * TimeSpan.TicksPerMillisecond;
         double packetHoldTime = currentTime - _timeStamp;
         if (packetHoldTime < resendDelay)
         {
             return;
         }
         NetDebug.Write("[RC]Resend: {0} > {1}", (int)packetHoldTime, resendDelay);
     }
     _timeStamp = currentTime;
     _isSent    = true;
     peer.SendUserData(_packet);
 }
Example #20
0
        public override void SendNextPackets()
        {
            //check sending acks
            if (_mustSendAcks)
            {
                _mustSendAcks = false;
                NetDebug.Write("[RR]SendAcks");
                Monitor.Enter(_outgoingAcks);
                Peer.SendUserData(_outgoingAcks);
                Monitor.Exit(_outgoingAcks);
            }

            long currentTime = DateTime.UtcNow.Ticks;

            Monitor.Enter(_pendingPackets);
            //get packets from queue
            Monitor.Enter(OutgoingQueue);
            while (OutgoingQueue.Count > 0)
            {
                int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
                if (relate < _windowSize)
                {
                    var netPacket = OutgoingQueue.Dequeue();
                    netPacket.Sequence  = (ushort)_localSeqence;
                    netPacket.ChannelId = _id;
                    _pendingPackets[_localSeqence % _windowSize].Init(netPacket);
                    _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
                }
                else //Queue filled
                {
                    break;
                }
            }
            Monitor.Exit(OutgoingQueue);
            //send
            for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
            {
                _pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer);
            }
            Monitor.Exit(_pendingPackets);
        }
Example #21
0
        internal bool ProcessConnectAccept(NetConnectAcceptPacket packet)
        {
            if (_connectionState != ConnectionState.Outgoing)
            {
                return(false);
            }

            //check connection id
            if (packet.ConnectionId != _connectTime)
            {
                NetDebug.Write(NetLogLevel.Trace, "[NC] Invalid connectId: {0}", _connectTime);
                return(false);
            }
            //check connect num
            ConnectionNum = packet.ConnectionNumber;

            NetDebug.Write(NetLogLevel.Trace, "[NC] Received connection accept");
            _timeSinceLastPacket = 0;
            _connectionState     = ConnectionState.Connected;
            return(true);
        }
Example #22
0
        /// <summary>
        /// Flush all queued packets
        /// </summary>
        public void Flush()
        {
            if (_connectionState != ConnectionState.Connected)
            {
                return;
            }
            lock (_flushLock)
            {
                _reliableOrderedChannel.SendNextPackets();
                _reliableUnorderedChannel.SendNextPackets();
                _reliableSequencedChannel.SendNextPackets();
                _sequencedChannel.SendNextPackets();
                _unreliableChannel.SendNextPackets();

                //If merging enabled
                if (_mergePos > 0)
                {
                    if (_mergeCount > 1)
                    {
                        NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount);
                        _netManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, _remoteEndPoint);
#if STATS_ENABLED
                        Statistics.PacketsSent++;
                        Statistics.BytesSent += (ulong)(NetConstants.HeaderSize + _mergePos);
#endif
                    }
                    else
                    {
                        //Send without length information and merging
                        _netManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, _remoteEndPoint);
#if STATS_ENABLED
                        Statistics.PacketsSent++;
                        Statistics.BytesSent += (ulong)(_mergePos - 2);
#endif
                    }
                    _mergePos   = 0;
                    _mergeCount = 0;
                }
            }
        }
        internal bool Shutdown(byte[] data, int start, int length, bool force)
        {
            lock (this)
            {
                //trying to shutdown already disconnected
                if (_connectionState == ConnectionState.Disconnected ||
                    _connectionState == ConnectionState.ShutdownRequested)
                {
                    return(false);
                }

                //don't send anything
                if (force)
                {
                    _connectionState = ConnectionState.Disconnected;
                    return(true);
                }

                //reset time for reconnect protection
                _timeSinceLastPacket = 0;

                //send shutdown packet
                _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length);
                _shutdownPacket.ConnectionNumber = _connectNum;
                FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime);
                if (_shutdownPacket.Size >= _mtu)
                {
                    //Drop additional data
                    NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!");
                }
                else if (data != null && length > 0)
                {
                    Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length);
                }
                _connectionState = ConnectionState.ShutdownRequested;
                NetDebug.Write("[Peer] Send disconnect");
                _netManager.SendRaw(_shutdownPacket, _remoteEndPoint);
                return(true);
            }
        }
Example #24
0
        private void ReceiveLogic(object state)
        {
            Socket   socket         = (Socket)state;
            EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);

            byte[] receiveBuffer = new byte[NetConstants.MaxPacketSize];

            while (IsActive())
            {
                int result;

                //Reading data
                try
                {
                    if (socket.Available == 0 && !socket.Poll(ReceivePollingTime, SelectMode.SelectRead))
                    {
                        continue;
                    }
                    result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None,
                                                ref bufferEndPoint);
                }
                catch (SocketException ex)
                {
                    if (ProcessError(ex, bufferEndPoint))
                    {
                        return;
                    }
                    continue;
                }
                catch (ObjectDisposedException)
                {
                    return;
                }

                //All ok!
                NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result);
                _listener.OnMessageReceived(receiveBuffer, result, 0, (IPEndPoint)bufferEndPoint);
            }
        }
Example #25
0
        //We got introduce and must punch
        private void OnNatIntroductionResponse(NatIntroduceResponsePacket req)
        {
            NetDebug.Write(NetLogLevel.Trace, "[NAT] introduction received");

            // send internal punch
            var punchPacket = new NatPunchPacket {
                Token = req.Token
            };

            Send(punchPacket, req.Internal);
            NetDebug.Write(NetLogLevel.Trace, "[NAT] internal punch sent to " + req.Internal);

            // hack for some routers
            _socket.Ttl = 2;
            _socket.SendRaw(new[] { (byte)PacketProperty.Empty }, 0, 1, req.External);

            // send external punch
            _socket.Ttl            = NetConstants.SocketTTL;
            punchPacket.IsExternal = true;
            Send(punchPacket, req.External);
            NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + req.External);
        }
Example #26
0
        internal void SendUserData(NetPacket packet)
        {
            packet.ConnectionNumber = _connectNum;
            //2 - merge byte + minimal packet size + datalen(ushort)
            if (_netManager.MergeEnabled && _mergePos + packet.Size + NetConstants.HeaderSize * 2 + 2 < _mtu)
            {
                FastBitConverter.GetBytes(_mergeData.RawData, _mergePos + NetConstants.HeaderSize, (ushort)packet.Size);
                Buffer.BlockCopy(packet.RawData, 0, _mergeData.RawData, _mergePos + NetConstants.HeaderSize + 2, packet.Size);
                _mergePos += packet.Size + 2;
                _mergeCount++;

                //DebugWriteForce("Merged: " + _mergePos + "/" + (_mtu - 2) + ", count: " + _mergeCount);
                return;
            }

            NetDebug.Write(NetLogLevel.Trace, "[P]SendingPacket: " + packet.Property);
            _netManager.SendRaw(packet, _remoteEndPoint);
#if STATS_ENABLED
            Statistics.PacketsSent++;
            Statistics.BytesSent += (ulong)packet.Size;
#endif
        }
Example #27
0
        private void HandleNatIntroduction(NetDataReader dr)
        {
            // read intro
            byte       hostByte       = dr.GetByte();
            IPEndPoint remoteInternal = dr.GetNetEndPoint();
            IPEndPoint remoteExternal = dr.GetNetEndPoint();
            string     token          = dr.GetString(MaxTokenLength);

            NetDebug.Write(NetLogLevel.Trace, "[NAT] introduction received; we are designated " + (hostByte == HostByte ? "host" : "client"));
            NetDataWriter writer = new NetDataWriter();

            // send internal punch
            writer.Put((byte)PacketProperty.NatPunchMessage);
            writer.Put(hostByte);
            writer.Put(token);
            SocketError errorCode = 0;

            _socket.SendTo(writer.Data, 0, writer.Length, remoteInternal, ref errorCode);
            NetDebug.Write(NetLogLevel.Trace, "[NAT] internal punch sent to " + remoteInternal);

            // send external punch
            writer.Reset();
            writer.Put((byte)PacketProperty.NatPunchMessage);
            writer.Put(hostByte);
            writer.Put(token);
            if (hostByte == HostByte)
            {
                _socket.Ttl = 2;
                _socket.SendTo(writer.Data, 0, writer.Length, remoteExternal, ref errorCode);
                _socket.Ttl = NetConstants.SocketTTL;
            }
            else
            {
                _socket.SendTo(writer.Data, 0, writer.Length, remoteExternal, ref errorCode);
            }

            NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + remoteExternal);
        }
Example #28
0
        private void HandleNatPunch(IPEndPoint senderEndPoint, NetDataReader dr)
        {
            byte fromHostByte = dr.GetByte();

            if (fromHostByte != HostByte && fromHostByte != ClientByte)
            {
                //garbage
                return;
            }

            //Read info
            string additionalInfo = dr.GetString(MaxTokenLength);

            NetDebug.Write(NetLogLevel.Trace, "[NAT] punch received from {0} - additional info: {1}", senderEndPoint, additionalInfo);

            //Release punch success to client; enabling him to Connect() to msg.Sender if token is ok
            lock (_successEvents)
            {
                _successEvents.Enqueue(new SuccessEventData {
                    TargetEndPoint = senderEndPoint, Token = additionalInfo
                });
            }
        }
Example #29
0
            //Returns true if there is a pending packet inside
            public bool TrySend(DateTime currentTime, NetPeer peer)
            {
                if (_packet == null)
                {
                    return(false);
                }

                if (_isSent) //check send time
                {
                    TimeSpan resendDelay    = peer.ResendDelay;
                    TimeSpan packetHoldTime = currentTime - _timeStamp;
                    if (packetHoldTime < resendDelay)
                    {
                        return(true);
                    }

                    NetDebug.Write("[RC]Resend: {0} > {1}", packetHoldTime, resendDelay);
                }
                _timeStamp = currentTime;
                _isSent    = true;
                peer.SendUserData(_packet);
                return(true);
            }
Example #30
0
        private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress, IPv6Mode ipv6Mode)
        {
            //Setup socket
            socket.ReceiveTimeout    = 500;
            socket.SendTimeout       = 500;
            socket.ReceiveBufferSize = NetConstants.SocketBufferSize;
            socket.SendBufferSize    = NetConstants.SocketBufferSize;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                try
                {
                    socket.IOControl(SioUdpConnreset, new byte[] { 0 }, null);
                }
                catch
                {
                    //ignored
                }
            }

            try
            {
                socket.ExclusiveAddressUse = !reuseAddress;
                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress);
            }
            catch
            {
                //Unity with IL2CPP throws an exception here, it doesn't matter in most cases so just ignore it
            }
            if (ep.AddressFamily == AddressFamily.InterNetwork || ipv6Mode == IPv6Mode.DualMode)
            {
                Ttl = NetConstants.SocketTTL;

                try { socket.EnableBroadcast = true; }
                catch (SocketException e)
                {
                    NetDebug.WriteError($"[B]Broadcast error: {e.SocketErrorCode}");
                }

                if (ipv6Mode == IPv6Mode.DualMode)
                {
                    try { socket.DualMode = true; }
                    catch (Exception e)
                    {
                        NetDebug.WriteError($"[B]Bind exception (dualmode setting): {e}");
                    }
                }
                else if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    try { socket.DontFragment = true; }
                    catch (SocketException e)
                    {
                        NetDebug.WriteError($"[B]DontFragment error: {e.SocketErrorCode}");
                    }
                }
            }
            //Bind
            try
            {
                socket.Bind(ep);
                NetDebug.Write(NetLogLevel.Trace, $"[B]Successfully binded to port: {((IPEndPoint)socket.LocalEndPoint).Port}, AF: {socket.AddressFamily}");

                //join multicast
                if (ep.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    try
                    {
#if !UNITY_2018_3_OR_NEWER
                        socket.SetSocketOption(
                            SocketOptionLevel.IPv6,
                            SocketOptionName.AddMembership,
                            new IPv6MulticastOption(MulticastAddressV6));
#endif
                    }
                    catch (Exception)
                    {
                        // Unity3d throws exception - ignored
                    }
                }
            }
            catch (SocketException bindException)
            {
                switch (bindException.SocketErrorCode)
                {
                //IPv6 bind fix
                case SocketError.AddressAlreadyInUse:
                    if (socket.AddressFamily == AddressFamily.InterNetworkV6 && ipv6Mode != IPv6Mode.DualMode)
                    {
                        try
                        {
                            //Set IPv6Only
                            socket.DualMode = false;
                            socket.Bind(ep);
                        }
                        catch (SocketException ex)
                        {
                            //because its fixed in 2018_3
                            NetDebug.WriteError($"[B]Bind exception: {ex}, errorCode: {ex.SocketErrorCode}");
                            return(false);
                        }
                        return(true);
                    }
                    break;

                //hack for iOS (Unity3D)
                case SocketError.AddressFamilyNotSupported:
                    return(true);
                }
                NetDebug.WriteError($"[B]Bind exception: {bindException}, errorCode: {bindException.SocketErrorCode}");
                return(false);
            }
            return(true);
        }