Example #1
0
 async Task OnCommandAsync(ArraySegment <byte> commandBuffer, WebSocket webSocket)
 {
     try
     {
         var listenerCommand = ListenerCommand.ReadObject(commandBuffer);
         if (listenerCommand.Accept != null)
         {
             // Don't block the pump waiting for the rendezvous
             this.OnAcceptCommandAsync(listenerCommand.Accept).Fork(this);
         }
         else if (listenerCommand.Request != null)
         {
             await HybridHttpConnection.CreateAsync(this, listenerCommand.Request, webSocket).ConfigureAwait(false);
         }
         else
         {
             string json = Encoding.UTF8.GetString(
                 commandBuffer.Array,
                 commandBuffer.Offset,
                 Math.Min(commandBuffer.Count, HybridConnectionConstants.MaxUnrecognizedJson));
             RelayEventSource.Log.Warning(this, $"Received an unknown command: {json}.");
         }
     }
     catch (Exception exception) when(!Fx.IsFatal(exception))
     {
         RelayEventSource.Log.HandledExceptionAsWarning(this, exception);
     }
 }
        async Task SendResponseAsync(ListenerCommand.ResponseCommand responseCommand, Stream responseBodyStream, CancellationToken cancelToken)
        {
            if (this.rendezvousWebSocket == null)
            {
                RelayEventSource.Log.HybridHttpConnectionSendResponse(this.TrackingContext, "control", responseCommand.StatusCode);
                var listenerCommand = new ListenerCommand {
                    Response = responseCommand
                };
                await this.listener.SendControlCommandAndStreamAsync(listenerCommand, responseBodyStream, cancelToken).ConfigureAwait(false);
            }
            else
            {
                RelayEventSource.Log.HybridHttpConnectionSendResponse(this.TrackingContext, "rendezvous", responseCommand.StatusCode);
                await this.EnsureRendezvousAsync(cancelToken).ConfigureAwait(false);

                using (var memoryStream = new MemoryStream(this.listener.ConnectionBufferSize))
                {
                    new ListenerCommand {
                        Response = responseCommand
                    }.WriteObject(memoryStream);
                    memoryStream.Position = 0;
                    ArraySegment <byte> buffer = memoryStream.GetArraySegment();

                    // We need to respond over the rendezvous connection
                    await this.rendezvousWebSocket.SendAsync(buffer, WebSocketMessageType.Text, true, cancelToken).ConfigureAwait(false);

                    if (responseCommand.Body && responseBodyStream != null)
                    {
                        buffer = new ArraySegment <byte>(buffer.Array, 0, buffer.Array.Length);
                        await this.rendezvousWebSocket.SendStreamAsync(responseBodyStream, WebSocketMessageType.Binary, buffer, cancelToken).ConfigureAwait(false);
                    }
                }
            }
        }
        void OnCommand(ArraySegment <byte> buffer)
        {
            try
            {
                ListenerCommand listenerCommand;
                using (var stream = new MemoryStream(buffer.Array, buffer.Offset, buffer.Count))
                {
                    listenerCommand = ListenerCommand.ReadObject(stream);
                }

                if (listenerCommand.Accept != null)
                {
                    this.OnAcceptClientCommand(listenerCommand.Accept).Fork(this);
                }
                else
                {
                    string json = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
                    RelayEventSource.Log.RelayListenerUnknownCommand(this.ToString(), json);
                }
            }
            catch (Exception exception) when(!Fx.IsFatal(exception))
            {
                RelayEventSource.Log.HandledExceptionAsWarning(this, exception);
            }
        }
        async Task OnCommandAsync(ArraySegment <byte> buffer)
        {
            try
            {
                ListenerCommand listenerCommand;
                using (var stream = new MemoryStream(buffer.Array, buffer.Offset, buffer.Count))
                {
                    listenerCommand = ListenerCommand.ReadObject(stream);
                }

                if (listenerCommand.Accept != null)
                {
                    await this.OnAcceptClientCommandAsync(listenerCommand.Accept).ConfigureAwait(false);
                }
                else
                {
                    string json = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
                    RelayEventSource.Log.RelayListenerUnknownCommand(this.ToString(), json);
                }
            }
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    throw;
                }

                RelayEventSource.Log.HandledExceptionAsWarning(this, exception);
            }
        }
Example #5
0
 public static ListenerCommand ReadObject(ArraySegment <byte> buffer)
 {
     using (var stream = new MemoryStream(buffer.Array, buffer.Offset, buffer.Count))
     {
         return(ListenerCommand.ReadObject(stream));
     }
 }
            async void OnTokenRenewed(object sender, TokenEventArgs eventArgs)
            {
                try
                {
                    var listenerCommand = new ListenerCommand();
                    listenerCommand.RenewToken       = new ListenerCommand.RenewTokenCommand();
                    listenerCommand.RenewToken.Token = eventArgs.Token.TokenString;

                    await this.SendCommandAsync(listenerCommand, CancellationToken.None).ConfigureAwait(false);
                }
                catch (Exception exception) when(!Fx.IsFatal(exception))
                {
                    RelayEventSource.Log.HandledExceptionAsWarning(this.listener, exception);
                }
            }
            internal async Task SendCommandAsync(ListenerCommand listenerCommand, CancellationToken cancellationToken)
            {
                Task <WebSocket> connectTask = this.EnsureConnectTask(cancellationToken);
                var webSocket = await connectTask.ConfigureAwait(false);

                using (var stream = new MemoryStream())
                {
                    listenerCommand.WriteObject(stream);
                    byte[] buffer = stream.GetBuffer();
                    using (await this.sendLock.LockAsync(cancellationToken).ConfigureAwait(false))
                    {
                        await webSocket.SendAsync(
                            new ArraySegment <byte>(buffer, 0, (int)stream.Length), WebSocketMessageType.Binary, true, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
        async Task <RequestCommandAndStream> ReceiveRequestOverRendezvousAsync()
        {
            using (var cancelSource = new CancellationTokenSource(this.OperationTimeout))
            {
                // A Rendezvous is required to get full request
                await this.EnsureRendezvousAsync(cancelSource.Token).ConfigureAwait(false);
            }

            RelayEventSource.Log.HybridHttpReadRendezvousValue(this, "request command");
            ListenerCommand.RequestCommand requestCommand;
            using (var rendezvousCommandStream = new WebSocketMessageStream(this.rendezvousWebSocket, this.OperationTimeout))
            {
                // Deserializing the object from stream makes a sync-over-async call which can deadlock
                // if performed on the websocket transport's callback thread.
                requestCommand = await Task.Run(() => ListenerCommand.ReadObject(rendezvousCommandStream).Request).ConfigureAwait(false);

                if (rendezvousCommandStream.MessageType == WebSocketMessageType.Close)
                {
                    throw RelayEventSource.Log.ThrowingException(new InvalidOperationException(SR.EntityClosedOrAborted), this);
                }
                else if (rendezvousCommandStream.MessageType != WebSocketMessageType.Text)
                {
                    throw RelayEventSource.Log.ThrowingException(
                              new ProtocolViolationException(SR.GetString(SR.InvalidType, WebSocketMessageType.Text, rendezvousCommandStream.MessageType)), this);
                }
                else if (requestCommand == null)
                {
                    throw RelayEventSource.Log.ThrowingException(new ProtocolViolationException(SR.GetString(SR.InvalidType, "request", "{unknown}")), this);
                }
            }

            Stream requestStream = null;

            if (requestCommand.Body.HasValue && requestCommand.Body.Value)
            {
                RelayEventSource.Log.HybridHttpReadRendezvousValue(this, "request body");
                requestStream = new WebSocketMessageStream(this.rendezvousWebSocket, this.OperationTimeout);
            }

            return(new RequestCommandAndStream(requestCommand, requestStream));
        }
Example #9
0
            internal async Task SendCommandAndStreamAsync(ListenerCommand command, Stream stream, CancellationToken cancelToken)
            {
                Task <WebSocket> connectTask = this.EnsureConnectTask(cancelToken);
                var webSocket = await connectTask.ConfigureAwait(false);

                using (await this.sendAsyncLock.LockAsync(cancelToken).ConfigureAwait(false))
                {
                    // Since we're using the sendBuffer.Array this work needs to be inside the sendAsyncLock.
                    ArraySegment <byte> commandBuffer;
                    using (var commandStream = new MemoryStream(this.sendBuffer.Array, writable: true))
                    {
                        commandStream.SetLength(0);
                        command.WriteObject(commandStream);
                        commandBuffer = new ArraySegment <byte>(this.sendBuffer.Array, 0, (int)commandStream.Position);
                    }

                    await webSocket.SendAsync(commandBuffer, WebSocketMessageType.Text, true, cancelToken).ConfigureAwait(false);

                    if (stream != null)
                    {
                        await webSocket.SendStreamAsync(stream, WebSocketMessageType.Binary, this.sendBuffer, cancelToken).ConfigureAwait(false);
                    }
                }
            }
Example #10
0
 internal Task SendControlCommandAndStreamAsync(ListenerCommand command, Stream stream, CancellationToken cancelToken)
 {
     return(this.controlConnection.SendCommandAndStreamAsync(command, stream, cancelToken));
 }
 internal void SendControlCommand(ListenerCommand listenerCommand, CancellationToken cancellationToken)
 {
     this.controlConnection.SendCommandAsync(listenerCommand, cancellationToken).ConfigureAwait(false).GetAwaiter().GetResult();
 }