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();
            }
        }
Exemplo n.º 2
0
        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}");
            }
        }
Exemplo n.º 3
0
        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();
        }
Exemplo n.º 4
0
        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);
                }
            }
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        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();
        }
Exemplo n.º 7
0
        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.");
            }
        }
Exemplo n.º 8
0
        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);
                }
            }
        }
Exemplo n.º 9
0
        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);
        }