Example #1
0
        public TcpConnection(TcpPeer parent)
        {
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }
            this.latencySimulationRecvQueue = new ConcurrentQueue <DelayedMessage>();
            this.stashed               = true;
            this.Statistics            = new TcpConnectionStatistics();
            this.sendSemaphore         = new SemaphoreSlim(1, 1);
            this.recvBuffer            = new byte[parent.Configuration.BufferSize];
            this.sendBuffer            = new byte[parent.Configuration.BufferSize];
            this.awaitingMessageHeader = new TcpRawMessageHeader();
            this.Parent = parent;
            this.logger = parent.Configuration.LogManager.GetLogger(nameof(TcpConnection));
            this.logger.Meta["kind"] = this.GetType().Name;
            this.logger.Meta["connection_endpoint"] = new RefLogLabel <TcpConnection>(this, v => v.RemoteEndpoint);
            this.logger.Meta["connected"]           = new RefLogLabel <TcpConnection>(this, s => s.Connected);
            this.logger.Meta["closed"]  = new RefLogLabel <TcpConnection>(this, s => s.closed);
            this.logger.Meta["latency"] = new RefLogLabel <TcpConnection>(this, s =>
            {
                var lat = s.Statistics.Latency;
                if (lat.HasValue)
                {
                    return(lat.Value);
                }
                else
                {
                    return("");
                }
            });

            // return $"{nameof(TcpConnection)}[id={Id}, connected={Connected}, endpoint={RemoteEndpoint}]";
        }
Example #2
0
        async Task SendMessageInternalAsync(TcpRawMessage message)
        {
            try
            {
                var socket = this.socket;
                if (!Connected)
                {
                    return; // throw new OperationCanceledException("Send operation cancelled. Connection not established");
                }
                await sendSemaphore.WaitAsync().ConfigureAwait(false);

                if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveRequest) ||
                    message.Flags.HasFlag(MessageHeaderFlags.KeepAliveResponse))
                {
                    logger.Trace($"Connection #{Id} sending {message}");
                }
                else
                {
                    logger.Debug($"Connection #{Id} sending {message}");
                }

                TcpRawMessageHeader header = new TcpRawMessageHeader(message);

                var headerBytes = header.Build();
                Buffer.BlockCopy(headerBytes.Array, headerBytes.Offset, sendBuffer, 0, headerBytes.Count);
                int  bufferPosition = headerBytes.Count;
                int  totalBytesSent = 0;
                bool messageEof     = false;

                message.Position = 0;

                do
                {
                    int bufferFreeSpace  = sendBuffer.Length - bufferPosition;
                    int messageLeftBytes = (int)(message.BaseStream.Length - message.BaseStream.Position);
                    int toCopy           = bufferFreeSpace;
                    if (messageLeftBytes <= toCopy)
                    {
                        toCopy     = messageLeftBytes;
                        messageEof = true;
                    }
                    message.BaseStream.Read(sendBuffer, bufferPosition, toCopy);
                    bufferPosition += toCopy;

                    int bufferSendPosition = 0;

                    while (bufferSendPosition < bufferPosition)
                    {
                        int sent = await Task.Factory.FromAsync(socket.BeginSend(sendBuffer, bufferSendPosition, bufferPosition - bufferSendPosition, SocketFlags.None, null, null), socket.EndSend)
                                   .ConfigureAwait(false);

                        logger.Trace($"Connection #{Id} sent {sent} bytes");
                        bufferSendPosition += sent;
                        totalBytesSent     += sent;
                    }

                    bufferPosition = 0;
                } while (!messageEof);

                Statistics.PacketOut();
                Statistics.BytesOut(totalBytesSent);
            }
            catch (SocketException)
            {
                Close();
            }
            catch (ObjectDisposedException)
            {
                Close();
            }
            catch (Exception ex)
            {
                logger.Error($"Exception in #{Id} on {message} sending: {ex}");
                Close();
            }
            finally
            {
                sendSemaphore.Release();
                message.Dispose();
            }
        }
Example #3
0
        internal void ReceiveCallback(IAsyncResult result)
        {
            try
            {
                if (socket == null || !socket.Connected)
                {
                    return;
                }

                int bytesRead = socket.EndReceive(result);

                if (bytesRead == 0)
                {
                    Close();
                    return;
                }

                Statistics.BytesIn(bytesRead);
                logger.Trace($"Connection #{Id} recv data {bytesRead} bytes");

                int recvBufferPos = 0;
                int counter       = 0;

                while (recvBufferPos <= bytesRead)
                {
                    int bytesLeft = bytesRead - recvBufferPos;
                    if (awaitingNextMessage == null)
                    {
                        if (!awaitingNextMessageHeaderValid && bytesLeft > 0)
                        {
                            awaitingNextMessageHeaderValid = awaitingMessageHeader.Write(
                                new ArraySegment <byte>(recvBuffer, recvBufferPos, bytesLeft), out int headerGotRead);
                            recvBufferPos += headerGotRead;
                        }
                        else if (awaitingNextMessageHeaderValid)
                        {
                            awaitingNextMessage      = new TcpRawMessage(Parent.Configuration.MemoryStreamPool, awaitingMessageHeader.MessageSize);
                            awaitingNextMessageWrote = 0;
                        }
                        else if (bytesLeft == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (awaitingNextMessageWrote < awaitingMessageHeader.MessageSize && bytesLeft > 0)
                        {
                            int toRead = bytesLeft;
                            if (toRead > awaitingMessageHeader.MessageSize - awaitingNextMessageWrote)
                            {
                                toRead = awaitingMessageHeader.MessageSize - awaitingNextMessageWrote;
                            }
                            if (toRead > 0)
                            {
                                awaitingNextMessage.BaseStream.Write(recvBuffer, recvBufferPos, toRead);
                                awaitingNextMessageWrote += toRead;
                                recvBufferPos            += toRead;
                            }
                        }
                        else if (awaitingNextMessageWrote == awaitingMessageHeader.MessageSize)
                        {
                            Statistics.PacketIn();
                            awaitingNextMessage.BaseStream.Position = 0;
                            var message = awaitingNextMessage;
                            awaitingNextMessage = null;
                            message.Flags       = awaitingMessageHeader.Options.Flags;
                            OnMessageReceivedInternalWithSimulation(message);
                            awaitingNextMessageWrote       = 0;
                            awaitingMessageHeader          = new TcpRawMessageHeader();
                            awaitingNextMessageHeaderValid = false;
                        }
                        else if (bytesLeft == 0)
                        {
                            break;
                        }
                    }

                    //Infinite loop protection
                    if (counter++ > recvBuffer.Length / 2 + 100)
                    {
                        logger.Critical($"Infinite loop in {this}");
                        throw new InvalidOperationException("Infinite loop");
                    }
                }

                if (socket != null)
                {
                    StartReceive();
                }
            }
            catch (ObjectDisposedException)
            { }
            catch (SocketException sex)
            {
                if (sex.SocketErrorCode != SocketError.ConnectionReset)
                {
                    logger.Error($"Connection #{Id} broken due to exception: {sex}");
                }
                else
                {
                    logger.Info($"Connection #{Id} reset");
                }
                Close();
            }
            catch (Exception ex)
            {
                logger.Error($"Connection #{Id} broken due to exception: {ex}");
                Close();
            }
        }