public int AddBytes(byte[] buffer, int offset, int length, IgnoreHelloRequestsSettings ignoreHelloRequests = IgnoreHelloRequestsSettings.IncludeHelloRequests) { var numAdded = 0; var end = offset + length; while (true) { if (_headerBufferLen == 0) { while (offset + 4 <= end) { // We can read at least the header int start = offset; offset++; var messageLen = Utils.ReadUInt24(buffer, ref offset); offset += messageLen; if (offset <= end) { // Whole message fits in buffer, this is the common case var message = new byte[4 + messageLen]; Buffer.BlockCopy(buffer, start, message, 0, 4 + messageLen); if ((!_hasHelloRequest && (ignoreHelloRequests == IgnoreHelloRequestsSettings.IncludeHelloRequests || (ignoreHelloRequests == IgnoreHelloRequestsSettings.IgnoreHelloRequestsUntilFinished && _hasFinished))) || !IsHelloRequest(message)) { _messages.Add(message); CheckType((HandshakeType)message[0]); numAdded++; } } else { // The header fits in the buffer, but not the entire message _headerBuffer = new byte[4]; _headerBufferLen = 4; Buffer.BlockCopy(buffer, start, _headerBuffer, 0, 4); _buffer = new byte[messageLen]; _bufferLen = messageLen - (offset - end); Buffer.BlockCopy(buffer, start + 4, _buffer, 0, _bufferLen); } } if (offset < end) { // Else, the whole header does not fit in the buffer _headerBuffer = new byte[4]; _headerBufferLen = end - offset; Buffer.BlockCopy(buffer, offset, _headerBuffer, 0, _headerBufferLen); } return numAdded; } else { // We have previously buffered up a part of a message that needs to be completed if (_headerBufferLen < 4) { var toCopy = Math.Min(end - offset, 4 - _headerBufferLen); Buffer.BlockCopy(buffer, offset, _headerBuffer, _headerBufferLen, toCopy); _headerBufferLen += toCopy; offset += toCopy; if (_headerBufferLen < 4) return numAdded; } // Now header buffer is complete, so we can fetch message len and fill rest of message buffer as much as possible var tmpOffset = 1; var messageLen = Utils.ReadUInt24(_headerBuffer, ref tmpOffset); var bytesToCopy = Math.Min(end - offset, messageLen - _bufferLen); if (_buffer == null) _buffer = new byte[messageLen]; Buffer.BlockCopy(buffer, offset, _buffer, _bufferLen, bytesToCopy); offset += bytesToCopy; _bufferLen += bytesToCopy; if (_bufferLen != messageLen) { return numAdded; } // Now we have a complete message to insert to the queue var message = new byte[4 + messageLen]; Buffer.BlockCopy(_headerBuffer, 0, message, 0, 4); Buffer.BlockCopy(_buffer, 0, message, 4, messageLen); if ((!_hasHelloRequest && (ignoreHelloRequests == IgnoreHelloRequestsSettings.IncludeHelloRequests || (ignoreHelloRequests == IgnoreHelloRequestsSettings.IgnoreHelloRequestsUntilFinished && _hasFinished))) || !IsHelloRequest(message)) { _messages.Add(message); CheckType((HandshakeType)message[0]); numAdded++; } _headerBuffer = null; _headerBufferLen = 0; Utils.ClearArray(_buffer); _buffer = null; _bufferLen = 0; } } }
public int AddBytes(byte[] buffer, int offset, int length, IgnoreHelloRequestsSettings ignoreHelloRequests = IgnoreHelloRequestsSettings.IncludeHelloRequests) { var numAdded = 0; var end = offset + length; while (true) { if (_headerBufferLen == 0) { while (offset + 4 <= end) { // We can read at least the header int start = offset; offset++; var messageLen = Utils.ReadUInt24(buffer, ref offset); offset += messageLen; if (offset <= end) { // Whole message fits in buffer, this is the common case var message = new byte[4 + messageLen]; Buffer.BlockCopy(buffer, start, message, 0, 4 + messageLen); if ((!_hasHelloRequest && (ignoreHelloRequests == IgnoreHelloRequestsSettings.IncludeHelloRequests || (ignoreHelloRequests == IgnoreHelloRequestsSettings.IgnoreHelloRequestsUntilFinished && _hasFinished))) || !IsHelloRequest(message)) { _messages.Add(message); CheckType((HandshakeType)message[0]); numAdded++; } } else { // The header fits in the buffer, but not the entire message _headerBuffer = new byte[4]; _headerBufferLen = 4; Buffer.BlockCopy(buffer, start, _headerBuffer, 0, 4); _buffer = new byte[messageLen]; _bufferLen = messageLen - (offset - end); Buffer.BlockCopy(buffer, start + 4, _buffer, 0, _bufferLen); } } if (offset < end) { // Else, the whole header does not fit in the buffer _headerBuffer = new byte[4]; _headerBufferLen = end - offset; Buffer.BlockCopy(buffer, offset, _headerBuffer, 0, _headerBufferLen); } return(numAdded); } else { // We have previously buffered up a part of a message that needs to be completed if (_headerBufferLen < 4) { var toCopy = Math.Min(end - offset, 4 - _headerBufferLen); Buffer.BlockCopy(buffer, offset, _headerBuffer, _headerBufferLen, toCopy); _headerBufferLen += toCopy; offset += toCopy; if (_headerBufferLen < 4) { return(numAdded); } } // Now header buffer is complete, so we can fetch message len and fill rest of message buffer as much as possible var tmpOffset = 1; var messageLen = Utils.ReadUInt24(_headerBuffer, ref tmpOffset); var bytesToCopy = Math.Min(end - offset, messageLen - _bufferLen); if (_buffer == null) { _buffer = new byte[messageLen]; } Buffer.BlockCopy(buffer, offset, _buffer, _bufferLen, bytesToCopy); offset += bytesToCopy; _bufferLen += bytesToCopy; if (_bufferLen != messageLen) { return(numAdded); } // Now we have a complete message to insert to the queue var message = new byte[4 + messageLen]; Buffer.BlockCopy(_headerBuffer, 0, message, 0, 4); Buffer.BlockCopy(_buffer, 0, message, 4, messageLen); if ((!_hasHelloRequest && (ignoreHelloRequests == IgnoreHelloRequestsSettings.IncludeHelloRequests || (ignoreHelloRequests == IgnoreHelloRequestsSettings.IgnoreHelloRequestsUntilFinished && _hasFinished))) || !IsHelloRequest(message)) { _messages.Add(message); CheckType((HandshakeType)message[0]); numAdded++; } _headerBuffer = null; _headerBufferLen = 0; Utils.ClearArray(_buffer); _buffer = null; _bufferLen = 0; } } }