private void ReceivingThreadFunction(CancellationToken cancellationToken) { //providing raw message reader with limited access to tcp stream that cancels when //token is used RawMessageReader reader = new RawMessageReader( (buffer, count, offset) => { var resTask = _tcpStream.ReadAsync(buffer, offset, count, cancellationToken); resTask.Wait(); return(resTask.Result); } ); //message reading loop while (!cancellationToken.IsCancellationRequested) { try { string nextMessageString = GetNextMessageAsString(reader); Message nextMessage = ParseMessage(nextMessageString); CallMessageCallback(nextMessage); } catch (OperationCanceledException) { break; } catch (Exception e) { if (_errorCallback != null) { _errorCallback.Invoke(e); } } } }
/// <summary> /// Reads and parses protocol message from the network stream. /// </summary> /// <returns>Parsed protocol message or null if the function fails.</returns> public async Task <Message> ReceiveMessageAsync() { log.Trace("()"); Message res = null; using (CancellationTokenSource readTimeoutTokenSource = new CancellationTokenSource(60000), timeoutShutdownTokenSource = CancellationTokenSource.CreateLinkedTokenSource(readTimeoutTokenSource.Token, shutdownCancellationToken)) { RawMessageReader messageReader = new RawMessageReader(Stream); RawMessageResult rawMessage = await messageReader.ReceiveMessageAsync(timeoutShutdownTokenSource.Token); if (rawMessage.Data != null) { res = CreateMessageFromRawData(rawMessage.Data); if (res.MessageTypeCase == Message.MessageTypeOneofCase.Response) { lastResponseStatus = res.Response.Status; lastResponseDetails = res.Response.Details; } } } ForceDisconnect = res == null; log.Trace("(-):ForceDisconnect={0}", ForceDisconnect, res != null ? "Message" : "null"); return(res); }
public void TestGetNextMessageAsStringCanReadStringOfLength8KiB() { //given StringBuilder sb = new StringBuilder(); for (int i = 0; i < 8192; i++) { sb.Append("a"); } string expected = sb.ToString(); byte[] inputBuffer = new byte[8194]; byte[] textBytes = Encoding.UTF8.GetBytes(expected); byte[] lengthBytes = BitConverter.GetBytes((ushort)textBytes.Length); if (!BitConverter.IsLittleEndian) { Array.Reverse(lengthBytes); } Array.Copy(lengthBytes, 0, inputBuffer, 0, 2); Array.Copy(textBytes, 0, inputBuffer, 2, textBytes.Length); Stream stream = new MemoryStream(inputBuffer); RawMessageReader reader = new RawMessageReader( (buffer, count, offset) => stream.Read(buffer, offset, count)); //when String actual = reader.GetNextMessageAsString(); //then Assert.AreEqual(expected, actual); stream.Dispose(); }
public void TestGetNextMessageAsStringCanReadEmptyString() { //given String expected = ""; byte[] inputBuffer = new byte[20]; byte[] textBytes = Encoding.UTF8.GetBytes(expected); byte[] lengthBytes = BitConverter.GetBytes((ushort)textBytes.Length); if (!BitConverter.IsLittleEndian) { Array.Reverse(lengthBytes); } Array.Copy(lengthBytes, 0, inputBuffer, 0, 2); Array.Copy(textBytes, 0, inputBuffer, 2, textBytes.Length); Stream stream = new MemoryStream(inputBuffer); RawMessageReader reader = new RawMessageReader( (buffer, count, offset) => stream.Read(buffer, offset, count)); //when String actual = reader.GetNextMessageAsString(); //then Assert.AreEqual(expected, actual); stream.Dispose(); }
private string GetNextMessageAsString(RawMessageReader reader) { try { return(reader.GetNextMessageAsString()); } catch (Exception e) { throw new DisconnectedException(e); } }
/// <summary> /// Reads messages from the client stream and processes them in a loop until the client disconnects /// or until an action (such as a protocol violation) that leads to disconnecting of the client occurs. /// </summary> public async Task ReceiveMessageLoop() { log.Trace("()"); try { if (UseTls) { SslStream sslStream = (SslStream)Stream; ConfigBase config = (ConfigBase)Base.ComponentDictionary[ConfigBase.ComponentName]; await sslStream.AuthenticateAsServerAsync((X509Certificate)config.Settings["TcpServerTlsCertificate"], false, SslProtocols.Tls12, false); } RawMessageReader messageReader = new RawMessageReader(Stream); while (!shutdownSignaling.IsShutdown) { RawMessageResult rawMessage = await messageReader.ReceiveMessageAsync(shutdownSignaling.ShutdownCancellationTokenSource.Token); bool disconnect = rawMessage.Data == null; bool protocolViolation = rawMessage.ProtocolViolation; if (rawMessage.Data != null) { IProtocolMessage message = CreateMessageFromRawData(rawMessage.Data); if (message != null) { disconnect = !await messageProcessor.ProcessMessageAsync(this, message); } else { protocolViolation = true; } } if (protocolViolation) { await messageProcessor.SendProtocolViolation(this); break; } if (disconnect) { break; } } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } log.Trace("(-)"); }
public void TestGetNextMessageAsStringThrowsExceptionOnInvalidRead() { //given var stream = new MemoryStream(new byte[] { 1 }); RawMessageReader reader = new RawMessageReader( (buffer, count, offset) => stream.Read(buffer, offset, count)); //when String result = reader.GetNextMessageAsString(); //then //throws exception stream.Dispose(); }
/// <summary> /// Reads messages from the client stream and processes them in a loop until the client disconnects /// or until an action (such as a protocol violation) that leads to disconnecting of the client occurs. /// </summary> /// <param name="Client">TCP client.</param> /// <param name="MessageBuilder">Client's message builder.</param> public async Task ReceiveMessageLoop(TcpClient Client, MessageBuilderLocNet MessageBuilder) { log.Trace("()"); try { NetworkStream stream = Client.GetStream(); RawMessageReader messageReader = new RawMessageReader(stream); while (!isShutdown) { RawMessageResult rawMessage = await messageReader.ReceiveMessageAsync(shutdownCancellationTokenSource.Token); bool disconnect = rawMessage.Data == null; bool protocolViolation = rawMessage.ProtocolViolation; if (rawMessage.Data != null) { Message message = CreateMessageFromRawData(rawMessage.Data); if (message != null) { disconnect = !await ProcessMessageAsync(Client, MessageBuilder, message); } else { protocolViolation = true; } } if (protocolViolation) { await SendProtocolViolation(Client); break; } if (disconnect) { break; } } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } log.Trace("(-)"); }
/// <summary> /// Attempts to connect to LOC server in a loop. /// </summary> /// <returns>true if the function succeeded, false if connection was established before the component shutdown.</returns> public override async Task <bool> ConnectAsync() { log.Trace("()"); bool res = false; // Close TCP connection if it is connected and reset client. IPEndPoint locEndPoint = (IPEndPoint)config.Settings["LocEndPoint"]; SetRemoteEndPoint(locEndPoint); while (!res && !shutdownSignaling.IsShutdown) { log.Trace("Connecting to LOC server '{0}'.", locEndPoint); if (await base.ConnectAsync()) { messageReader = new RawMessageReader(Stream); res = true; } else { log.Warn("Unable to connect to LOC server '{0}', waiting 10 seconds and then retrying.", locEndPoint); // On Ubuntu we get exception "Sockets on this platform are invalid for use after a failed connection attempt" // when we try to reconnect to the same IP:port again, after it failed for the first time. // We have to close the socket and initialize it again to be able to connect. SetRemoteEndPoint(locEndPoint); try { await Task.Delay(10000, shutdownSignaling.ShutdownCancellationTokenSource.Token); } catch { // Catch cancellation exception. } } } log.Trace("(-):{0}", res); return(res); }