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