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; }
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); }
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)); }
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)); }
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); }
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); } } }
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)); }
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); }
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); }
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); } } }
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); }
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); }
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); }
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); }