/// <inheritdoc /> protected override Task <bool> SendInternalAsync(IByteStreamHandler byteStreamHandler, ReadOnlySpan <char> rawMessage) { byteStreamHandler.MustNotBeNull(nameof(byteStreamHandler)); // Check for start- and endsymbols inside the message TcpCommunicatorUtil.EnsureNoEndsymbolsInMessage(rawMessage, _endSymbols); // Perform message formatting var sendBuffer = StringBuffer.Acquire(rawMessage.Length + _endSymbols.Length); byte[]? bytes = null; try { sendBuffer.Append(_startSymbols, 0, _startSymbols.Length); if (rawMessage.Length > 0) { sendBuffer.Append(rawMessage); } sendBuffer.Append(_endSymbols, 0, _endSymbols.Length); sendBuffer.GetInternalData(out var buffer, out var currentCount); var sendMessageByteLength = _encoding.GetByteCount(buffer, 0, currentCount); bytes = ByteArrayPool.Take(sendMessageByteLength); _encoding.GetBytes(buffer, 0, currentCount, bytes, 0); StringBuffer.Release(sendBuffer); sendBuffer = null; return(byteStreamHandler.SendAsync( new ArraySegment <byte>(bytes, 0, sendMessageByteLength))); } finally { if (bytes != null) { ByteArrayPool.Return(bytes); } if (sendBuffer != null) { StringBuffer.Release(sendBuffer); } } }
/// <inheritdoc /> protected override Task <bool> SendInternalAsync(IByteStreamHandler byteStreamHandler, ReadOnlySpan <char> rawMessage) { byteStreamHandler.MustNotBeNull(nameof(byteStreamHandler)); var rawMessageLength = rawMessage.Length; var lengthDigitCount = TcpCommunicatorUtil.GetCountOfDigits(rawMessageLength); var sendBuffer = StringBuffer.Acquire(rawMessageLength + 3 + lengthDigitCount); byte[]? bytes = null; try { sendBuffer.Append(SYMBOL_START); sendBuffer.Append(rawMessageLength, StringView.Empty); sendBuffer.Append(SYMBOL_DELIMITER); if (rawMessage.Length > 0) { sendBuffer.Append(rawMessage); } sendBuffer.Append(SYMBOL_END); sendBuffer.GetInternalData(out var buffer, out var currentCount); var sendMessageByteLength = _encoding.GetByteCount(buffer, 0, currentCount); bytes = ByteArrayPool.Take(sendMessageByteLength); _encoding.GetBytes(buffer, 0, currentCount, bytes, 0); StringBuffer.Release(sendBuffer); sendBuffer = null; return(byteStreamHandler.SendAsync( new ArraySegment <byte>(bytes, 0, sendMessageByteLength))); } finally { if (bytes != null) { ByteArrayPool.Return(bytes); } if (sendBuffer != null) { StringBuffer.Release(sendBuffer); } } }
/// <inheritdoc /> public override void OnReceivedBytes(bool isNewConnection, ArraySegment <byte> receivedBytes) { receivedBytes.MustNotBeDefault(nameof(receivedBytes)); // Clear receive buffer on new connections if (isNewConnection) { _receiveStringBuffer.Clear(); _decoder.Reset(); } // Parse characters if (receivedBytes.Count == 0) { return; } var addedChars = _receiveStringBuffer.Append(receivedBytes, _decoder); if (addedChars == 0) { return; } while (_receiveStringBuffer.Count > 0) { // Check for start symbol if (_receiveStringBuffer[0] != SYMBOL_START) { throw new MessageRecognitionException($"Error during message recognition. Expected '{SYMBOL_START}' at the start of a message, got '{_receiveStringBuffer[0]}'!"); } // Search delimiter var delimiterIndex = -1; for (var loop = 1; loop < _receiveStringBuffer.Count; loop++) { if (_receiveStringBuffer[loop] == SYMBOL_DELIMITER) { delimiterIndex = loop; break; } if (!TcpCommunicatorUtil.IsNumeric(_receiveStringBuffer[loop])) { throw new MessageRecognitionException($"Error during message recognition. Symbol in length field is not numeric (current index: {loop})!"); } if (loop > 11) { throw new MessageRecognitionException($"Error during message recognition. Length field too long (current index: {loop})!"); } } if (delimiterIndex == -1) { break; } // Parse message count int rawMessageLength; try { rawMessageLength = TcpCommunicatorUtil.ParseInt32FromStringPart( _receiveStringBuffer, 1, delimiterIndex - 1); } catch (Exception ex) { throw new MessageRecognitionException($"Unable to parse message length: {ex.Message}"); } // Look whether we've received the full message var fullMessageLength = delimiterIndex + rawMessageLength + 2; if (_receiveStringBuffer.Count < fullMessageLength) { break; } // Check endsymbol if (_receiveStringBuffer[fullMessageLength - 1] != SYMBOL_END) { throw new MessageRecognitionException($"Error during message recognition. Expected '{SYMBOL_END}' at the end of a message, got '{_receiveStringBuffer[fullMessageLength - 1]}'!"); } // Raise found message base.NotifyRecognizedMessage(_receiveStringBuffer.GetPartReadOnly( delimiterIndex + 1, rawMessageLength)); // Remove the message with endsymbols from receive buffer _receiveStringBuffer.RemoveFromStart(fullMessageLength); } }
public void Check_ParseIntFromStringPart() { Assert.IsTrue(1 == TcpCommunicatorUtil.ParseInt32FromStringPart(new StringBuffer("<1|...>"), 1, 1)); Assert.IsTrue(12 == TcpCommunicatorUtil.ParseInt32FromStringPart(new StringBuffer("<12|...>"), 1, 2)); Assert.IsTrue(123 == TcpCommunicatorUtil.ParseInt32FromStringPart(new StringBuffer("<123|...>"), 1, 3)); }