private static HandshakeResponseMessage CreateHandshakeResponseMessage(ref MessagePackReader reader, int arrayLength) { var errorMessage = ReadString(ref reader, "errorMessage"); var result = new HandshakeResponseMessage(errorMessage); if (arrayLength >= 3) { result.ReadExtensionMembers(ref reader); } return(result); }
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; } }); }
private static void WriteHandshakeResponseMessage(ref MessagePackWriter writer, HandshakeResponseMessage message) { writer.WriteArrayHeader(2); writer.Write(ServiceProtocolConstants.HandshakeResponseType); writer.Write(message.ErrorMessage); }