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]);
                }
            }
        }
示例#5
0
 public async ValueTask <ITransportChannel> CreateChannelAsync()
 {
     return(await _connection.CreateChannelAsync().ConfigureAwait(false));
 }