public static PooledMessage AppendControlBytesToMessage(IMessage message, int threadId) { // Create room for the control bytes var messageWithControlBytes = PooledMessage.Rent(ControlBytesPlaceholder.Length + message.Length); // Tell messageWithControlBytes that it can be returned to the pool after it has been send messageWithControlBytes.ReturnAfterSend(); // Copy data to message with control bytes Buffer.BlockCopy(message.Content, 0, messageWithControlBytes.Content, ControlBytesPlaceholder.Length, message.Length); // Set the control bytes on the message SetControlBytes(messageWithControlBytes.Content, message.Length, threadId); // Tell message it has been sent. It may decide to return to pool message.Sent(); return(messageWithControlBytes); }
private void ProcessReceivedMessage(Socket handler) { int bytesToRead = -1; int threadId = -1; int controlBytesOffset = 0; byte[] protocolBuffer = new byte[ProtocolHelper.ControlBytesPlaceholder.Length]; PooledMessage resultBuffer = null; // Loop until socket is done while (_isConnected) { // Get the next buffer from the queue var socketAsyncEventArgs = _receiveBufferQueue.Dequeue(); if (socketAsyncEventArgs == null) { continue; } var buffer = socketAsyncEventArgs.Buffer; int bytesRead = socketAsyncEventArgs.BytesTransferred; int currentOffset = 0; while (currentOffset < bytesRead) { // Check if we need to get our control byte values if (bytesToRead == -1) { var controlBytesNeeded = ProtocolHelper.ControlBytesPlaceholder.Length - controlBytesOffset; var controlBytesAvailable = bytesRead - currentOffset; var controlBytesToCopy = Math.Min(controlBytesNeeded, controlBytesAvailable); // Copy bytes to control buffer Buffer.BlockCopy(buffer, currentOffset, protocolBuffer, controlBytesOffset, controlBytesToCopy); controlBytesOffset += controlBytesToCopy; currentOffset += controlBytesToCopy; // Check if done if (controlBytesOffset == ProtocolHelper.ControlBytesPlaceholder.Length) { // Parse out control bytes ProtocolHelper.ExtractControlBytes(protocolBuffer, out bytesToRead, out threadId); // Reset control bytes offset controlBytesOffset = 0; // Ensure message is not larger than maximum message size if (bytesToRead > _maxMessageSize) { HandleCommunicationError(handler, new InvalidOperationException(string.Format("message of length {0} exceeds maximum message length of {1}", bytesToRead, _maxMessageSize))); return; } } // Continue the loop continue; } // Have control bytes, get message bytes // SPECIAL CASE: if empty message, skip a bunch of stuff if (bytesToRead != 0) { // Initialize buffer if needed if (resultBuffer == null) { //resultBuffer = new byte[bytesToRead] resultBuffer = PooledMessage.Rent(bytesToRead); } var bytesAvailable = bytesRead - currentOffset; var bytesToCopy = Math.Min(bytesToRead, bytesAvailable); // Copy bytes to buffer Buffer.BlockCopy(buffer, currentOffset, resultBuffer.Content, resultBuffer.Length - bytesToRead, bytesToCopy); currentOffset += bytesToCopy; bytesToRead -= bytesToCopy; } // Check if we're done if (bytesToRead == 0) { if (resultBuffer != null) { // Done, add to complete received messages CompleteMessage(handler, threadId, resultBuffer); // Reset message state resultBuffer = null; } bytesToRead = -1; threadId = -1; _lastResponse = DateTime.UtcNow; } } _socketAsyncEventArgsReceivePool.Push(socketAsyncEventArgs); } }