public virtual async Task WriteAsync(ServiceMessage serviceMessage) { // We have to lock around outgoing sends since the pipe is single writer. // The lock is per serviceConnection await _serviceConnectionLock.WaitAsync(); var errorMessage = ErrorMessage; if (!string.IsNullOrEmpty(errorMessage)) { _serviceConnectionLock.Release(); throw new InvalidOperationException(errorMessage); } if (ConnectionContext == null) { _serviceConnectionLock.Release(); throw new InvalidOperationException(); } try { // Write the service protocol message ServiceProtocol.WriteMessage(serviceMessage, ConnectionContext.Transport.Output); await ConnectionContext.Transport.Output.FlushAsync(); } catch (Exception ex) { Log.FailedToWrite(Logger, ConnectionId, ex); } finally { _serviceConnectionLock.Release(); } }
public async Task SendMessage(string target, object[] args) { var callHubRequest = new InvocationMessage(invocationId: _invId++.ToString(), target: target, arguments: args); var callHubServiceMessage = new ConnectionDataMessage(ConnectionId, _signalRPro.GetMessageBytes(callHubRequest)); _servicePro.WriteMessage(callHubServiceMessage, ServiceSideConnection.MockServicePipe.Output); var flushResult = await ServiceSideConnection.MockServicePipe.Output.FlushAsync(); if (flushResult.IsCanceled || flushResult.IsCompleted) { throw new InvalidOperationException($"Sending InvocationMessage {_invId} for client connection id {ConnectionId} resulted in FlushResult with IsCanceled {flushResult.IsCanceled} IsCompleted {flushResult.IsCompleted}"); } }
private async Task MockServiceAsyncWithException(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(); await Task.Delay(TimeSpan.FromSeconds(1)); proto.WriteMessage(BuildPingMessage("_exception", "1"), conn.Application.Output); await conn.Application.Output.FlushAsync(); }
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 (message is PingMessage ping && ping.TryGetValue(Constants.ServicePingMessageKey.ShutdownKey, out string val)) { if (val == Constants.ServicePingMessageValue.ShutdownFin) { PingMessage pong = new PingMessage { Messages = new string[2] { Constants.ServicePingMessageKey.ShutdownKey, Constants.ServicePingMessageValue.ShutdownFinAck } }; proto.WriteMessage(pong, conn.Application.Output); await conn.Application.Output.FlushAsync(); break; } } } } finally { conn.Application.Input.AdvanceTo(buffer.Start, buffer.End); } } }
public async Task <MockServiceSideClientConnection> ConnectClientAsync() { if (!await _completedHandshake.Task) { throw new InvalidOperationException("Service connection has failed service connection handshake"); } var clientConnId = SDKSideServiceConnection.ConnectionId + "_client_" + Interlocked.Increment(ref s_clientConnNum); MockServiceSideClientConnection clientConn = new MockServiceSideClientConnection(clientConnId, this); ClientConnections.Add(clientConn); var openClientConnMsg = new OpenConnectionMessage(clientConnId, new System.Security.Claims.Claim[] { }); _servicePro.WriteMessage(openClientConnMsg, MockServicePipe.Output); var flushResult = _lastFlushResult = await MockServicePipe.Output.FlushAsync(); if (flushResult.IsCanceled || flushResult.IsCompleted) { // any better way? throw new InvalidOperationException($"Sending OpenConnectionMessage for clientConnId {clientConnId} returned flush result: IsCanceled {flushResult.IsCanceled} IsCompleted {flushResult.IsCompleted}"); } var clientHandshakeRequest = new AspNetCore.SignalR.Protocol.HandshakeRequestMessage("json", 1); var clientHandshake = new ConnectionDataMessage(clientConnId, GetMessageBytes(clientHandshakeRequest)); _servicePro.WriteMessage(clientHandshake, MockServicePipe.Output); flushResult = _lastFlushResult = await MockServicePipe.Output.FlushAsync(); if (flushResult.IsCanceled || flushResult.IsCompleted) { throw new InvalidOperationException($"Sending HandshakeRequestMessage for clientConnId {clientConnId} returned flush result: IsCanceled {flushResult.IsCanceled} IsCompleted {flushResult.IsCompleted}"); } string hsErr = await clientConn.HandshakeCompleted.Task; if (!string.IsNullOrEmpty(hsErr)) { throw new InvalidOperationException($"client connection {clientConnId} handshake returned {hsErr}"); } return(clientConn); }
public async Task WriteMessageAsync(ServiceMessage message) { if (_connectionContext == null) { throw new InvalidOperationException("Server connection is not yet established."); } ServiceProtocol.WriteMessage(message, _connectionContext.Application.Output); await _connectionContext.Application.Output.FlushAsync(); }
private async Task SendHandshakeRequestAsync(PipeWriter output) { Log.SendingHandshakeRequest(_logger); ServiceProtocol.WriteMessage(_handshakeRequest, output); var sendHandshakeResult = await output.FlushAsync(); if (sendHandshakeResult.IsCompleted) { throw new InvalidOperationException("Service disconnected before handshake complete."); } }
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 Task StartAsync() { _processIncoming = Task.Run(async() => { while (true) { var result = 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)) { if (message is HandshakeRequestMessage) { var handshakeResponse = new HandshakeResponseMessage(""); _servicePro.WriteMessage(handshakeResponse, MockServicePipe.Output); var flushResult = await MockServicePipe.Output.FlushAsync(); if (flushResult.IsCanceled || flushResult.IsCompleted) { CompletedServiceConnectionHandshake.TrySetResult(false); } else { CompletedServiceConnectionHandshake.TrySetResult(true); } break; } } } } finally { MockServicePipe.Input.AdvanceTo(buffer.Start, buffer.End); } } }); return(Task.CompletedTask); }