public async Task <IClientConnection> ConnectAsync(ClientOptions options, CancellationToken cancellationToken) { Log.Trace("Establishing new connection with broker"); ITransportConnection transportConnection = null; try { transportConnection = await options.Transport.ConnectAsync(cancellationToken).ConfigureAwait(false); using (cancellationToken.Register(() => transportConnection.TryTerminate())) { Log.Debug("Connection {0} established. Performing handshake: {1}", transportConnection.Id, options); var channel = await transportConnection.CreateChannelAsync().ConfigureAwait(false); var protocolSerializer = options.Protocol.Serializer; using (var connectRequest = options.Protocol.MessageFactory.CreateConnectRequest( options.ApplicationId, options.ApplicationInstanceId)) { var serializedRequest = protocolSerializer.Serialize(connectRequest); try { await channel.Out .WriteAsync(new TransportMessageFrame(serializedRequest), cancellationToken) .ConfigureAwait(false); channel.Out.TryComplete(); } catch { serializedRequest.Dispose(); throw; } } Log.Trace("Connection {0} receiving connection response.", transportConnection.Id); using (var serializedResponse = await channel.In.ReadAsync(cancellationToken).ConfigureAwait(false)) using (var connectResponse = protocolSerializer.DeserializeConnectResponse(serializedResponse.Payload)) { await channel.Completion.ConfigureAwait(false); Log.Debug("Successfully authenticated: {0}", connectResponse); return(new ClientConnection(connectResponse.ConnectionId, transportConnection)); } } } catch (Exception ex) { if (transportConnection != null) { Log.Error("Connection failed {0}", transportConnection); } else { Log.Warn(ex, "Connection failed"); } throw; } }
public async Task <IReadOnlyCollection <DiscoveredMethod> > DiscoverAsync(MethodDiscoveryQuery query, ContextLinkageOptions contextLinkageDiscoveryOptions = null, bool online = false) { var channel = await _transportConnection.CreateChannelAsync().ConfigureAwait(false); try { using (var msg = _protocol.MessageFactory .CreateMethodDiscoveryRequest( query.InputMessageId, query.OutputMessageId, Convert(query.MethodReference), online ? DiscoveryMode.Online : DiscoveryMode.Offline, contextLinkageDiscoveryOptions.Convert(_protocol.MessageFactory))) { var serializedRequest = _protocol.Serializer.Serialize(msg); try { await channel.Out.WriteAsync(new TransportMessageFrame(serializedRequest)).ConfigureAwait(false); channel.Out.TryComplete(); } catch { serializedRequest.Dispose(); throw; } using (var serializedResponse = (await channel.In.ReadAsync().ConfigureAwait(false)).Payload) { var discoveryResponse = _protocol.Serializer.DeserializeMethodDiscoveryResponse(serializedResponse); return(Convert(discoveryResponse)); } } } catch (Exception ex) { channel.Out.TryTerminate(ex); throw; } finally { await channel.Completion.ConfigureAwait(false); } }
public async ValueTask <IOutcomingInvocation <TRequest, TResponse> > CreateAsync <TRequest, TResponse>( MethodCallDescriptor methodCall, Maybe <TRequest> request = default, Maybe <ContextLinkageOptions> contextLinkageOptions = default) { var channel = await _connection.CreateChannelAsync().ConfigureAwait(false); InvocationMethodDescriptor methodDescriptor = null; InvocationTargetDescriptor targetDescriptor = null; if (methodCall.Method.HasValue) { var method = methodCall.Method.Value; methodDescriptor = new InvocationMethodDescriptor(method.Service.Id, method.Name, method.Service.Alias); } if (methodCall.ProvidedMethod.HasValue) { var method = methodCall.ProvidedMethod.Value; methodDescriptor = new InvocationMethodDescriptor(method.ProvidedService.ServiceId, method.Name, method.ProvidedService.ServiceId); targetDescriptor = new InvocationTargetDescriptor(method.ProvidedService.ApplicationId, method.ProvidedService.ConnectionId, method.ProvidedService.ServiceAlias); } var descriptor = new OutcomingInvocationDescriptor(methodDescriptor, targetDescriptor, contextLinkageOptions); var invocation = new OutcomingInvocation <TRequest, TResponse>( descriptor, channel, _protocol, GetMarshaller <TRequest>(), GetMarshaller <TResponse>()); invocation.Start(); if (request.HasValue) { await invocation.Out.WriteAsync(request.Value).ConfigureAwait(false); invocation.Out.TryComplete(); } return(invocation); }
#pragma warning disable xUnit1026 // Theory methods should use all of their parameters public void SendMessagesInBothDirections(ChannelExchange[] cases) #pragma warning restore xUnit1026 // Theory methods should use all of their parameters { var serverSentMessageHashes = new List <List <byte[]> >(); var serverReceivedMessageHashes = new List <List <byte[]> >(); var clientSentMessageHashes = new List <List <byte[]> >(); var clientReceivedMessageHashes = new List <List <byte[]> >(); async Task HandleChannelAsync(ITransportChannel c, int[] send, List <byte[]> received, List <byte[]> sent) { Log.Info("Handling channel {0}", c.Id); var receiveTask = TaskRunner.RunInBackground( async() => { while (true) { var receivedMsg = await c.TryReceiveMessageAsync().ConfigureAwait(false); if (!receivedMsg.HasValue) { break; } lock (Md5) { received.Add(Md5.ComputeHash(receivedMsg.Value)); } } }); foreach (var length in send) { var msg = TestsSuite.Random.GetRandomBytes(length); await c.SendMessageAsync(msg).ConfigureAwait(false); lock (Md5) { sent.Add(Md5.ComputeHash(msg)); } } c.Out.TryComplete(); await receiveTask.ConfigureAwait(false); Log.Info("Channel handling completed {0}. Received {1} messages.", c.Id, received.Count); } ITransportConnection clientConnection = null; ITransportConnection serverConnection = null; var serverTask = TaskRunner.RunInBackground( async() => { await Server.StartAsync().ConfigureAwait(false); serverConnection = await Server.In.ReadAsync().ConfigureAwait(false); Log.Info("Server connection created"); var channelTasks = new List <Task>(); foreach (var channelExchange in cases) { var channel = await serverConnection.CreateChannelAsync().ConfigureAwait(false); Log.Info("Server channel created"); var rec = new List <byte[]>(); var sent = new List <byte[]>(); clientReceivedMessageHashes.Add(rec); clientSentMessageHashes.Add(sent); channelTasks.Add(TaskRunner.RunInBackground(() => HandleChannelAsync(channel, channelExchange.ClientMessageLengths, rec, sent))); } await Task.WhenAll(channelTasks).ConfigureAwait(false); }); var clientTask = TaskRunner.RunInBackground( async() => { clientConnection = await Client.ConnectAsync(BrokerWorkingDir).ConfigureAwait(false); Log.Info("Client connection created"); var channelTasks = new List <Task>(); foreach (var channelExchange in cases) { var channel = await clientConnection.IncomingChannels.ReadAsync().ConfigureAwait(false); Log.Info("Client channel received"); var rec = new List <byte[]>(); var sent = new List <byte[]>(); serverReceivedMessageHashes.Add(rec); serverSentMessageHashes.Add(sent); channelTasks.Add(TaskRunner.RunInBackground(() => HandleChannelAsync(channel, channelExchange.ServerMessageLengths, rec, sent))); } await Task.WhenAll(channelTasks).ConfigureAwait(false); }); Should.CompleteIn(Task.WhenAll(serverTask, clientTask), Timeout30Sec); Should.CompleteIn(clientConnection.CompleteAsync(), Timeout1Sec); Should.CompleteIn(serverConnection.CompleteAsync(), Timeout1Sec); Log.Debug("Tasks completed"); serverReceivedMessageHashes.Count.ShouldBe(cases.Length); serverSentMessageHashes.Count.ShouldBe(cases.Length); clientReceivedMessageHashes.Count.ShouldBe(cases.Length); clientSentMessageHashes.Count.ShouldBe(cases.Length); for (int i = 0; i < serverReceivedMessageHashes.Count; i++) { serverReceivedMessageHashes[i].Count.ShouldBe(clientSentMessageHashes[i].Count); for (int j = 0; j < serverReceivedMessageHashes[i].Count; j++) { serverReceivedMessageHashes[i][j].ShouldBe(clientSentMessageHashes[i][j]); } } for (int i = 0; i < clientReceivedMessageHashes.Count; i++) { clientReceivedMessageHashes[i].Count.ShouldBe(serverSentMessageHashes[i].Count); for (int j = 0; j < clientReceivedMessageHashes[i].Count; j++) { clientReceivedMessageHashes[i][j].ShouldBe(serverSentMessageHashes[i][j]); } } }
public async ValueTask <ITransportChannel> CreateChannelAsync() { return(await _connection.CreateChannelAsync().ConfigureAwait(false)); }