private void ProcessSendQueue(Socket handler) { while (_isConnected) { // Get the next buffer from the queue var socketAsyncEventArgs = _sendBufferQueue.Dequeue(); if (socketAsyncEventArgs == null) { continue; } _sendBufferReset.Reset(); // Do the send TryUnsafeSocketOperation(_socket, SocketAsyncOperation.Send, socketAsyncEventArgs); if (!_sendBufferReset.WaitOne(_communicationTimeout)) { HandleCommunicationError(_socket, new TimeoutException("The connection timed out before the send acknowledgement was received")); return; } } }
private void ProcessReceivedMessage(Socket handler) { int bytesToRead = -1; int threadId = -1; int controlBytesOffset = 0; byte[] protocolBuffer = new byte[ProtocolHelper.ControlBytesPlaceholder.Length]; byte[] 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]; } var bytesAvailable = bytesRead - currentOffset; var bytesToCopy = Math.Min(bytesToRead, bytesAvailable); // Copy bytes to buffer Buffer.BlockCopy(buffer, currentOffset, resultBuffer, 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); } }
private void ProcessReceivedMessage(ConnectedClient connectedClient) { int bytesToRead = -1; int threadId = -1; int availableTest = 0; int controlBytesOffset = 0; byte[] protocolBuffer = new byte[_controlBytesPlaceholder.Length]; byte[] resultBuffer = null; var handler = connectedClient.Socket; BlockingQueue <SocketAsyncEventArgs> receiveBufferQueue = null; _currentlyConnectedClientsReceiveQueuesLock.EnterReadLock(); try { if (!_currentlyConnectedClientsReceiveQueues.TryGetValue(handler, out receiveBufferQueue)) { // Peace out! return; } } finally { _currentlyConnectedClientsReceiveQueuesLock.ExitReadLock(); } // Loop until socket is done while (_isListening) { // If the socket is disposed, we're done try { availableTest = handler.Available; } catch (ObjectDisposedException) { // Peace out! return; } // 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 = _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 == _controlBytesPlaceholder.Length) { // Parse out control bytes 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]; } var bytesAvailable = bytesRead - currentOffset; var bytesToCopy = Math.Min(bytesToRead, bytesAvailable); // Copy bytes to buffer Buffer.BlockCopy(buffer, currentOffset, resultBuffer, 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; connectedClient.LastResponse = DateTime.UtcNow; } } // Push the buffer back onto the pool _socketAsyncEventArgsReceivePool.Push(socketAsyncEventArgs); } }
private void ProcessReceivedMessage(MessageState messageState) { int currentOffset = 0; int bytesRead = 0; while (_isDoingSomething) { // Check if we need a buffer if (messageState.Buffer == null) { // Get the next buffer BlockingQueue <KeyValuePair <byte[], int> > queue = null; _receiveBufferQueueLock.EnterReadLock(); try { if (!_receiveBufferQueue.TryGetValue(messageState.Handler.GetHashCode(), out queue)) { throw new Exception("FATAL: No receive queue created for current socket"); } } finally { _receiveBufferQueueLock.ExitReadLock(); } var receiveBufferEntry = queue.Dequeue(); messageState.Buffer = receiveBufferEntry.Key; currentOffset = 0; bytesRead = receiveBufferEntry.Value; } // Check if we need to get our control byte values if (messageState.TotalBytesToRead == -1) { // We do, see if we have enough bytes received to get them if (currentOffset + _controlBytesPlaceholder.Length > currentOffset + bytesRead) { // We don't yet have enough bytes to read the control bytes, so get more bytes // Loop until we have enough data to proceed int bytesNeeded = _controlBytesPlaceholder.Length - bytesRead; while (bytesNeeded > 0) { // Combine the buffers BlockingQueue <KeyValuePair <byte[], int> > queue = null; _receiveBufferQueueLock.EnterReadLock(); try { if (!_receiveBufferQueue.TryGetValue(messageState.Handler.GetHashCode(), out queue)) { throw new Exception("FATAL: No receive queue created for current socket"); } } finally { _receiveBufferQueueLock.ExitReadLock(); } var nextBufferEntry = queue.Dequeue(); var combinedBuffer = new byte[bytesRead + nextBufferEntry.Value]; Buffer.BlockCopy(messageState.Buffer, currentOffset, combinedBuffer, 0, bytesRead); Buffer.BlockCopy(nextBufferEntry.Key, 0, combinedBuffer, bytesRead, nextBufferEntry.Value); // Set the new combined buffer and appropriate bytes read messageState.Buffer = combinedBuffer; // Reset bytes read and current offset currentOffset = 0; bytesRead = combinedBuffer.Length; // Subtract from bytes needed bytesNeeded -= nextBufferEntry.Value; } } // Parse out control bytes ExtractControlBytes(messageState.Buffer, currentOffset, out messageState.TotalBytesToRead, out messageState.ThreadId); // Offset the index by the control bytes currentOffset += _controlBytesPlaceholder.Length; // Take control bytes off of bytes read bytesRead -= _controlBytesPlaceholder.Length; } int numberOfBytesToRead = Math.Min(bytesRead, messageState.TotalBytesToRead); messageState.Data.Write(messageState.Buffer, currentOffset, numberOfBytesToRead); // Set total bytes read int originalTotalBytesToRead = messageState.TotalBytesToRead; messageState.TotalBytesToRead -= numberOfBytesToRead; // Check if we're done if (messageState.TotalBytesToRead == 0) { // Done, add to complete received messages CompleteMessage(messageState.Handler, messageState.ThreadId, messageState.Data.ToArray()); } // Check if we have an overlapping message frame in our message AKA if the bytesRead was larger than the total bytes to read if (bytesRead > originalTotalBytesToRead) { // Get the number of bytes remaining to be read int bytesRemaining = bytesRead - numberOfBytesToRead; // Set total bytes to read to default messageState.TotalBytesToRead = -1; // Dispose and reinitialize data stream messageState.Data.Dispose(); messageState.Data = new MemoryStream(); // Now we have the next message, so recursively process it currentOffset += numberOfBytesToRead; bytesRead = bytesRemaining; continue; } // Only create a new message state if we are done with this message if (!(bytesRead < originalTotalBytesToRead)) { // Get new state for the next message but transfer over handler Socket handler = messageState.Handler; messageState.Data.Dispose(); messageState.Data = new MemoryStream(); messageState.Handler = handler; messageState.TotalBytesToRead = -1; messageState.ThreadId = -1; } // Reset buffer for next message _bufferPool.Push(messageState.Buffer); messageState.Buffer = null; } }