コード例 #1
0
ファイル: SmartSock.cs プロジェクト: pixonic/pixockets
        private void SendConnectionRequest()
        {
            var endPoint = SubSock.RemoteEndPoint;
            var seqState = GetSeqStateOnSend(endPoint);
            var header   = _headersPool.Get();

            header.SetSessionId(seqState.SessionId);
            header.SetConnect();
            header.Length = (ushort)header.HeaderLength;

            var buffer = _buffersPool.Get(header.HeaderLength);

            header.WriteTo(buffer, 0);

            var putBufferToPool = true;

            try
            {
                SubSock.Send(buffer, 0, header.HeaderLength, putBufferToPool);
            }
            catch (SocketException)
            {
                Close(endPoint, seqState);
            }

            _headersPool.Put(header);

            _lastConnectRequestSend = Environment.TickCount;
        }
コード例 #2
0
ファイル: SmartSockTests.cs プロジェクト: sentaniel/pixockets
        public void ReceivedPacketWithWrongLengthDropped()
        {
            var remoteEndPoint = new IPEndPoint(IPAddress.Loopback, 54321);

            _sock.Connect(remoteEndPoint.Address, remoteEndPoint.Port);
            Utils.SendConnectResponse(_bareSock, remoteEndPoint, _bufferPool);

            var header = new PacketHeader();  // Wrong Length

            header.Length = 5;
            var buffer = _bufferPool.Get(header.HeaderLength);
            var ms     = new MemoryStream(buffer);

            header.WriteTo(ms);
            ms.Write(BitConverter.GetBytes(123456789), 0, 4);  // Payload

            // Simulate send from UdpClient
            _bareSock.FakeReceive(buffer, 0, (int)ms.Length, remoteEndPoint);

            var receivedPacket = new ReceivedSmartPacket();

            Assert.IsFalse(_sock.Receive(ref receivedPacket));

            Assert.AreEqual(1, _cbs.OnConnectCalls.Count);
        }
コード例 #3
0
        public static ArraySegment <byte> ToBuffer(byte[] array, BufferPoolBase bufferPool)
        {
            var buffer = bufferPool.Get(array.Length);

            Array.Copy(array, buffer, array.Length);
            return(new ArraySegment <byte>(buffer, 0, array.Length));
        }
コード例 #4
0
        public static ArraySegment <byte> ToBuffer(MemoryStream ms, BufferPoolBase bufferPool)
        {
            var buffer = bufferPool.Get((int)ms.Length);
            var array  = ms.ToArray();

            Array.Copy(array, buffer, array.Length);
            return(new ArraySegment <byte>(buffer, 0, array.Length));
        }
コード例 #5
0
        public bool CombineIfFull(PacketHeader header, IPEndPoint endPoint, ref ReceivedSmartPacket receivedPacket)
        {
            int fullLength = 0;

            // TODO: validate that headers of all fragments match
            var frag = GetFragmentedPacket(header);

            if (frag.Buffers.Count < header.FragCount)
            {
                return(false);
            }

            var buffersCount = frag.FragCount;

            for (int i = 0; i < buffersCount; ++i)
            {
                fullLength += frag.Buffers[i].Length;
            }

            byte[] combinedBuffer = _buffersPool.Get(fullLength);
            var    targetOffset   = 0;

            for (int i = 0; i < buffersCount; ++i)
            {
                var srcBuffer = frag.Buffers[i];
                Array.Copy(srcBuffer.Buffer, srcBuffer.Offset, combinedBuffer, targetOffset, srcBuffer.Length);
                targetOffset += frag.Buffers[i].Length;
                _buffersPool.Put(srcBuffer.Buffer);
            }

            // TODO: optimize?
            _frags.Remove(frag);
            _fragPacketsPool.Put(frag);

            // TODO: calculate it?
            bool inOrder = true;

            receivedPacket.Buffer   = combinedBuffer;
            receivedPacket.Offset   = 0;
            receivedPacket.Length   = fullLength;
            receivedPacket.EndPoint = endPoint;
            receivedPacket.InOrder  = inOrder;
            return(true);
        }
コード例 #6
0
ファイル: ThreadSock.cs プロジェクト: pixonic/pixockets
        private void ReceiveLoop()
        {
            while (!_closing)
            {
                var      buffer      = _buffersPool.Get(MTUSafe);
                var      bufferInUse = false;
                EndPoint remoteEP    = _receiveEndPoint;
                try
                {
                    var bytesReceived = SysSock.ReceiveFrom(buffer, MTUSafe, SocketFlags.None, ref remoteEP);
                    //ntrf: On windows we will get EMSGSIZE error if message was truncated, but Mono on Unix will fill up the
                    //      whole buffer silently. We detect this case by allowing buffer to be slightly larger, than our typical
                    //      packet, and dropping any packet, that did fill the whole thing.
                    if (bytesReceived > 0 && bytesReceived <= MTU)
                    {
                        var packet = new ReceivedPacket();
                        packet.Buffer   = buffer;
                        packet.Offset   = 0;
                        packet.Length   = bytesReceived;
                        packet.EndPoint = (IPEndPoint)remoteEP;

                        bufferInUse = true;

                        _recvQueue.Add(packet);

                        if (_recvQueue.Count > RecvQueueLimit)
                        {
                            // Trash oldest
                            if (_recvQueue.TryTake(out packet))
                            {
                                _buffersPool.Put(packet.Buffer);
                            }
                        }
                    }
                    else
                    {
                        // If blocking call isn't actually blocking, sleep for a while
                        Thread.Sleep(10);
                    }
                }
                catch (SocketException se)
                {
                    // Ignore harmless errors
                    if (!HarmlessErrors.Contains(se.SocketErrorCode))
                    {
                        _excQueue.Add(se);
                        break;
                    }
                }

                if (!bufferInUse)
                {
                    _buffersPool.Put(buffer);
                }
            }
        }
コード例 #7
0
ファイル: SequenceTests.cs プロジェクト: sentaniel/pixockets
        private ArraySegment <byte> CreatePacket(int n)
        {
            var header = new PacketHeader();

            header.SetSeqNum((ushort)n);
            header.Length = (ushort)(header.HeaderLength + 4);
            var buffer = _bufferPool.Get(header.Length);
            var ms     = new MemoryStream(buffer);

            header.WriteTo(ms);
            ms.Write(BitConverter.GetBytes(n), 0, 4);
            return(new ArraySegment <byte>(buffer, 0, header.Length));
        }
コード例 #8
0
        public static void SendConnectRequest(MockSock bareSock, IPEndPoint endPoint, BufferPoolBase bufferPool)
        {
            var header = new PacketHeader();

            header.SetSessionId(PacketHeader.EmptySessionId);
            header.SetConnect();

            var buffer = bufferPool.Get(header.HeaderLength);

            header.Length = (ushort)header.HeaderLength;
            header.WriteTo(buffer, 0);

            bareSock.FakeReceive(buffer, 0, header.HeaderLength, endPoint);
        }
コード例 #9
0
        public static void SendDisconnectResponse(MockSock bareSock, IPEndPoint endPoint, BufferPoolBase bufferPool)
        {
            ushort sessionId = 427;
            var    header    = new PacketHeader();

            header.SetSessionId(sessionId);
            header.SetDisconnect();

            var buffer = bufferPool.Get(header.HeaderLength);

            header.Length = (ushort)header.HeaderLength;
            header.WriteTo(buffer, 0);

            bareSock.FakeReceive(buffer, 0, header.HeaderLength, endPoint);
        }
コード例 #10
0
        private void ReceiveLoop()
        {
            while (!_closing)
            {
                var      buffer     = _buffersPool.Get(MTU);
                var      bufferUsed = false;
                EndPoint remoteEP   = _receiveEndPoint;
                try
                {
                    var bytesReceived = SysSock.ReceiveFrom(buffer, MTU, SocketFlags.None, ref remoteEP);
                    if (bytesReceived > 0)
                    {
                        var packet = new ReceivedPacket();
                        packet.Buffer   = buffer;
                        packet.Offset   = 0;
                        packet.Length   = bytesReceived;
                        packet.EndPoint = (IPEndPoint)remoteEP;

                        bufferUsed = true;

                        _recvQueue.Add(packet);

                        if (_recvQueue.Count > RecvQueueLimit)
                        {
                            // Trash oldest
                            if (_recvQueue.TryTake(out packet))
                            {
                                _buffersPool.Put(packet.Buffer);
                            }
                        }
                    }
                    else
                    {
                        // If blocking call isn't actually blocking, sleep for a while
                        Thread.Sleep(10);
                    }
                }
                catch (Exception e)
                {
                    _logger.Exception(e);
                }

                if (!bufferUsed)
                {
                    _buffersPool.Put(buffer);
                }
            }
        }
コード例 #11
0
        public override bool Receive(ref ReceivedPacket packet)
        {
            try
            {
                if (SysSock.Available == 0)
                {
                    return(false);
                }
            }
            catch (Exception e)
            {
                _logger.Exception(e);
                return(false);
            }

            var      buffer   = _buffersPool.Get(MTU);
            EndPoint remoteEP = _remoteEndPoint;

            try
            {
                int bytesReceived = 0;
                if (_connectedMode)
                {
                    bytesReceived = SysSock.Receive(buffer, MTU, SocketFlags.None);
                }
                else
                {
                    bytesReceived = SysSock.ReceiveFrom(buffer, MTU, SocketFlags.None, ref remoteEP);
                }

                if (bytesReceived > 0)
                {
                    packet.Buffer   = buffer;
                    packet.Offset   = 0;
                    packet.Length   = bytesReceived;
                    packet.EndPoint = (IPEndPoint)remoteEP;

                    return(true);
                }
            }
            catch (Exception e)
            {
                _logger.Exception(e);
            }

            _buffersPool.Put(buffer);
            return(false);
        }
コード例 #12
0
        public void NotReSendAfterAckAndTimeout()
        {
            _sock.AckTimeout = 1;

            var remoteEndPoint = new IPEndPoint(IPAddress.Loopback, 23452);

            Utils.SendConnectRequest(_bareSock, remoteEndPoint, _bufferPool);
            var receivedPacket = new ReceivedSmartPacket();

            Assert.IsFalse(_sock.Receive(ref receivedPacket));

            var buffer = BitConverter.GetBytes(123456789);

            _sock.Send(remoteEndPoint, buffer, 0, buffer.Length, true);

            var sent       = _bareSock.Sends[1];
            var headerSent = new PacketHeader();

            headerSent.Init(sent.Buffer, sent.Offset);

            var ackHeader = new PacketHeader();

            ackHeader.AddAck(headerSent.SeqNum);
            ackHeader.Length = (ushort)ackHeader.HeaderLength;
            buffer           = _bufferPool.Get(ackHeader.Length);
            ackHeader.WriteTo(buffer, 0);
            _bareSock.FakeReceive(buffer, 0, ackHeader.Length, new IPEndPoint(IPAddress.Loopback, 23452));

            receivedPacket = new ReceivedSmartPacket();
            // Just ack in the packet, no payload
            Assert.IsFalse(_sock.Receive(ref receivedPacket));

            Thread.Sleep(20);
            _sock.Tick();

            Assert.AreEqual(2, _bareSock.Sends.Count);
        }
コード例 #13
0
        public override bool Receive(ref ReceivedPacket packet)
        {
            try
            {
                if (SysSock.Available == 0)
                {
                    return(false);
                }
            }
            catch (SocketException se)
            {
                // Ignore harmless errors
                if (!HarmlessErrors.Contains(se.SocketErrorCode))
                {
                    _logger.Exception(se);
                    throw;
                }
            }

            var      buffer      = _buffersPool.Get(MTUSafe);
            var      bufferInUse = false;
            EndPoint remoteEP    = _remoteEndPoint;

            try
            {
                int bytesReceived = 0;
                if (_connectedMode)
                {
                    bytesReceived = SysSock.Receive(buffer, MTUSafe, SocketFlags.None);
                }
                else
                {
                    bytesReceived = SysSock.ReceiveFrom(buffer, MTUSafe, SocketFlags.None, ref remoteEP);
                }

                //ntrf: On windows we will get EMSGSIZE error if message was truncated, but Mono on Unix will fill up the
                //      whole buffer silently. We detect this case by allowing buffer to be slightly larger, than our typical
                //      packet, and dropping any packet, that did fill the whole thing.
                if (bytesReceived > 0 && bytesReceived <= MTU)
                {
                    packet.Buffer   = buffer;
                    bufferInUse     = true;
                    packet.Offset   = 0;
                    packet.Length   = bytesReceived;
                    packet.EndPoint = (IPEndPoint)remoteEP;

                    return(true);
                }
            }
            catch (SocketException se)
            {
                // Ignore harmless errors
                if (!HarmlessErrors.Contains(se.SocketErrorCode))
                {
                    _logger.Exception(se);
                    throw;
                }
            }
            finally
            {
                // We don't return buffer here if it is to be processed by client
                if (!bufferInUse)
                {
                    _buffersPool.Put(buffer);
                }
            }

            return(false);
        }
コード例 #14
0
        public override bool Receive(ref ReceivedPacket packet)
        {
            byte[] buffer      = null;
            var    bufferInUse = false;

            try
            {
                if (!Begin())
                {
                    return(false);
                }

                if (!SysSock.Poll(0, SelectMode.SelectRead))
                {
                    return(false);
                }

                buffer = _buffersPool.Get(MTUSafe);
                EndPoint remoteEP = _receiveEndPoint;

                var bytesReceived = SysSock.ReceiveFrom(buffer, MTUSafe, SocketFlags.None, ref remoteEP);
                //ntrf: On windows we will get EMSGSIZE error if message was truncated, but Mono on Unix will fill up the
                //      whole buffer silently. We detect this case by allowing buffer to be slightly larger, than our typical
                //      packet, and dropping any packet, that did fill the whole thing.
                if (bytesReceived > 0 && bytesReceived <= MTU)
                {
                    packet.Buffer   = buffer;
                    bufferInUse     = true;
                    packet.Offset   = 0;
                    packet.Length   = bytesReceived;
                    packet.EndPoint = (IPEndPoint)remoteEP;

                    return(true);
                }
            }
            catch (SocketException sx)
            {
                var err = sx.SocketErrorCode;

                // Ignore harmless errors
                // On Windows machines we might have a case of ICMP Port Unreachable being delivered,
                // which causes ECONNRESET on next receive call
                if (!HarmlessErrors.Contains(err))
                {
                    End();

                    // Our socket might be killed by iOS. Recreate the socket.
                    if (err != SocketError.NotConnected)
                    {
                        _logger.Exception(sx);
                        throw;
                    }
                }
            }
            finally
            {
                // We don't return buffer here if it is to be processed by client
                if (buffer != null && !bufferInUse)
                {
                    _buffersPool.Put(buffer);
                }
            }

            return(false);
        }