private async Task ServiceStatusPingAsync(TimerAwaitable timer) { using (timer) { timer.Start(); while (await timer) { try { // Check if last send time is longer than default keep-alive ticks and then send ping if (Stopwatch.GetTimestamp() - Interlocked.Read(ref _lastSendTimestamp) > DefaultGetServiceStatusTicks) { await WriteAsync(RuntimeServicePingMessage.GetStatusPingMessage(true)); Interlocked.Exchange(ref _lastSendTimestamp, Stopwatch.GetTimestamp()); Log.SentServiceStatusPing(Logger); } } catch (Exception e) { Log.FailedSendingServiceStatusPing(Logger, e); } } } }
public Task WriteAsync(ServiceMessage serviceMessage) { if (RuntimeServicePingMessage.IsFin(serviceMessage)) { _offline.SetResult(true); } return(Task.CompletedTask); }
public override Task HandlePingAsync(PingMessage pingMessage) { if (RuntimeServicePingMessage.TryGetStatus(pingMessage, out var status)) { _active = GetServiceStatus(status, CheckWindow, CheckTimeSpan); Log.ReceivedServiceStatusPing(Logger, status, Endpoint); } return(Task.CompletedTask); }
private async Task MockServiceAsync(TestServiceConnectionForCloseAsync conn) { IServiceProtocol proto = new ServiceProtocol(); await conn.ConnectionCreated; // open 2 new connections (to create 2 new outgoing tasks proto.WriteMessage(new OpenConnectionMessage(Guid.NewGuid().ToString(), new Claim[0]), conn.Application.Output); proto.WriteMessage(new OpenConnectionMessage(Guid.NewGuid().ToString(), new Claim[0]), conn.Application.Output); await conn.Application.Output.FlushAsync(); while (true) { var result = await conn.Application.Input.ReadAsync(); var buffer = result.Buffer; try { // write back a FinAck after receiving a Fin if (proto.TryParseMessage(ref buffer, out ServiceMessage message)) { if (RuntimeServicePingMessage.IsFin(message)) { var pong = RuntimeServicePingMessage.GetFinAckPingMessage(); proto.WriteMessage(pong, conn.Application.Output); await conn.Application.Output.FlushAsync(); break; } } } finally { conn.Application.Input.AdvanceTo(buffer.Start, buffer.End); } } }
public void Start() { _processIncoming = Task.Run(async() => { try { while (true) { var result = _lastReadResult = await MockServicePipe.Input.ReadAsync(); if (result.IsCanceled || result.IsCompleted) { break; } var buffer = result.Buffer; try { if (!buffer.IsEmpty) { while (_servicePro.TryParseMessage(ref buffer, out var message)) { // always enqueue so tests can peek and analyze any of these messages EnqueueMessage(message); // now react to some of the connection related stuff if (message is HandshakeRequestMessage) { var handshakeResponse = new HandshakeResponseMessage(""); _servicePro.WriteMessage(handshakeResponse, MockServicePipe.Output); var flushResult = _lastFlushResult = await MockServicePipe.Output.FlushAsync(); if (flushResult.IsCanceled || flushResult.IsCompleted) { _completedHandshake.TrySetResult(false); } else { // sending ack merely allows SDK side to proceed with establishing the connection // for this service connection to become available for hubs to send messages // we'd need to wait for SDK side service connection to change its status _completedHandshake.TrySetResult(true); } continue; } else if (message is ConnectionDataMessage cdm) { var payload = cdm.Payload; // do we know this client? var clientConnection = ClientConnections.Where(c => c.ConnectionId == cdm.ConnectionId).FirstOrDefault(); if (clientConnection != null) { // is this client expecting handshake response? if (clientConnection.ExpectsClientHandshake) { // todo: maybe try parse first and then check if handshake is expected? if (HandshakeProtocol.TryParseResponseMessage(ref payload, out var response)) { clientConnection.ExpectsClientHandshake = false; clientConnection.HandshakeCompleted.TrySetResult(response.Error); } } // There is no such goal to provide full message parsing capabilities here // But it is useful to know the hub invocation return result in some tests so there we have it. while (_signalRPro.TryParseMessage(ref payload, MockSvc.CurrentInvocationBinder, out HubMessage hubMessage)) { clientConnection.EnqueueMessage(hubMessage); if (hubMessage is CloseMessage closeMsg) { clientConnection.CloseMessageReceivedFromSdk = true; } } } } else if (message is ServicePingMessage ping && ping.IsFin()) { var pong = RuntimeServicePingMessage.GetFinAckPingMessage(); _servicePro.WriteMessage(pong, MockServicePipe.Output); var flushResult = _lastFlushResult = await MockServicePipe.Output.FlushAsync(); //todo: do we care about this flush result? } } } } finally { MockServicePipe.Input.AdvanceTo(buffer.Start, buffer.End); } } } catch (Exception e) { _processIncomingException = e; } }); }