예제 #1
0
        //public void SendMessage(RawMessage message)
        //{
        //    SendMessageAsync(message);
        //}

        public virtual async Task SendMessageAsync(TcpRawMessage message)
        {
            if (!Connected)
            {
                message.Dispose();
                throw new InvalidOperationException($"Connection is not established");
            }

            if (Parent.Configuration.ConnectionSimulation != null)
            {
                int delay = Parent.Configuration.ConnectionSimulation.GetHalfDelay();
                if (delay > 0)
                {
                    await Task.Delay(delay).ConfigureAwait(false);
                }
            }

            Task newSendTask = null;

            lock (sendMutex)
            {
                sendTask = sendTask.ContinueWith(
                    (task, msg) =>
                {
                    return(SendMessageInternalAsync(msg as TcpRawMessage));
                }, message)
                           .Unwrap();

                newSendTask = sendTask;
            }

            await newSendTask.ConfigureAwait(false);
        }
예제 #2
0
        void OnMessageReceivedInternal(TcpRawMessage message)
        {
            if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveRequest) ||
                message.Flags.HasFlag(MessageHeaderFlags.KeepAliveResponse))
            {
                logger.Trace($"Connection #{Id} recv message {message}");
            }
            else
            {
                logger.Debug($"Connection #{Id} recv message {message}");
            }

            if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveRequest))
            {
                LastKeepAliveRequestReceived = DateTime.UtcNow;
                _ = SendMessageAsync(TcpRawMessage.GetEmpty(Parent.Configuration.MemoryStreamPool, MessageHeaderFlags.KeepAliveResponse));
                message.Dispose();
                return;
            }

            if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveResponse))
            {
                Statistics.UpdateLatency((float)(DateTime.UtcNow - this.lastKeepAliveSent).TotalMilliseconds);
                keepAliveResponseGot = true;
                message.Dispose();
                return;
            }

            Parent.Configuration.SynchronizeSafe(() =>
            {
                try
                {
                    OnMessageReceived(new MessageEventArgs(this, message));
                }
                catch (Exception ex)
                {
                    logger.Error($"Unhandled exception in #{Id} -> {this.GetType().Name}.OnMessageReceived: {ex}");
                }
            }, logger);
        }
예제 #3
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();
            }
        }