Exemplo n.º 1
0
            async Task <int> CreateTransportAsync(HttpListenerContext context, IHandler handler)
            {
                X509Certificate2 clientCertificate = null;

                if (this.Listener.sslSettings != null && this.Listener.sslSettings.ClientCertificateRequired)
                {
                    clientCertificate = await context.Request.GetClientCertificateAsync().ConfigureAwait(false);

                    if (clientCertificate == null)
                    {
                        return(40300);
                    }

                    if (this.Listener.sslSettings.RemoteCertificateValidationCallback != null)
                    {
                        SslPolicyErrors sslError = SslPolicyErrors.None;
                        X509Chain       chain    = new X509Chain();
                        chain.ChainPolicy.RevocationMode = this.Listener.sslSettings.CheckCertificateRevocation ?
                                                           X509RevocationMode.Online : X509RevocationMode.NoCheck;
                        chain.Build(clientCertificate);
                        if (chain.ChainStatus.Length > 0)
                        {
                            sslError = SslPolicyErrors.RemoteCertificateChainErrors;
                        }

                        bool success = this.Listener.sslSettings.RemoteCertificateValidationCallback(
                            this, clientCertificate, chain, sslError);
                        if (!success)
                        {
                            return(40301);
                        }
                    }
                    else if (context.Request.ClientCertificateError != 0)
                    {
                        return(40302);
                    }
                }

                IPrincipal principal = context.User;

                if (principal == null && clientCertificate != null)
                {
                    principal = new GenericPrincipal(new X509Identity(clientCertificate), new string[0]);
                }

                string subProtocol = null;

                string[] subProtocols = context.Request.Headers.GetValues("Sec-WebSocket-Protocol");
                for (int i = 0; i < subProtocols.Length; i++)
                {
                    if (subProtocols[i].Equals(WebSocketTransport.WebSocketSubProtocol) ||
                        subProtocols[i].Equals("AMQPWSB10")     // defined by the previous draft
                        )
                    {
                        subProtocol = subProtocols[i];
                        break;
                    }
                }

                if (subProtocol == null)
                {
                    return(40003);
                }

                var wsContext = await context.AcceptWebSocketAsync(subProtocol).ConfigureAwait(false);

                if (handler != null && handler.CanHandle(EventId.WebSocketAccept))
                {
                    handler.Handle(Event.Create(EventId.WebSocketAccept, null, context: wsContext));
                }

                var wsTransport = new ListenerWebSocketTransport(wsContext.WebSocket, principal);

                await this.Listener.HandleTransportAsync(wsTransport, handler, wsContext.WebSocket).ConfigureAwait(false);

                return(0);
            }
Exemplo n.º 2
0
        private async Task <bool> ProcessConnectionAsync(
            CancellationToken cancellationToken,
            HttpListenerContext httpContext)
        {
            Logger.Debug("ProcessConnectionAsync");

            WebSocketContext webSocketContext = null;

            try
            {
                webSocketContext = await httpContext.AcceptWebSocketAsync(null);
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "AcceptWebSocketAsync");

                // The upgrade process failed somehow. For simplicity lets assume it was a failure on the part of the server and indicate this using 500.
                httpContext.Response.StatusCode = 500;
                httpContext.Response.Close();
                return(false);
            }

            WebSocket    webSocket = webSocketContext.WebSocket;
            MemoryStream ms        = new MemoryStream();

            try
            {
                IWebSocketConnectionHandler handler = this.createConnectionHandler();

                byte[] receiveBuffer = null;

                // While the WebSocket connection remains open run a simple loop that receives data and sends it back.
                while (webSocket.State == WebSocketState.Open)
                {
                    try
                    {
                        if (receiveBuffer == null)
                        {
                            receiveBuffer = new byte[MaxBufferSize];
                        }

                        WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), cancellationToken);

                        if (receiveResult.MessageType == WebSocketMessageType.Close)
                        {
                            Logger.Debug("ProcessConnectionAsync: closing websocket");
                            await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", cancellationToken);

                            continue;
                        }

                        if (receiveResult.EndOfMessage)
                        {
                            await ms.WriteAsync(receiveBuffer, 0, receiveResult.Count, cancellationToken);

                            receiveBuffer = ms.ToArray();
                            ms.Dispose();
                            ms = new MemoryStream();
                        }
                        else
                        {
                            await ms.WriteAsync(receiveBuffer, 0, receiveResult.Count, cancellationToken);

                            continue;
                        }

                        byte[] wsresponse = null;
                        try
                        {
                            // dispatch to App provided function with requested payload
                            wsresponse = await handler.ProcessWsMessageAsync(receiveBuffer, cancellationToken);
                        }
                        catch (Exception ex)
                        {
                            // catch any error in the appAction and notify the client
                            wsresponse = await new ProtobufWsSerializer().SerializeAsync(
                                new WsResponseMessage
                            {
                                Result = WsResult.Error,
                                Value  = Encoding.UTF8.GetBytes(ex.Message)
                            });
                        }

                        // Send Result back to client
                        await webSocket.SendAsync(
                            new ArraySegment <byte>(wsresponse),
                            WebSocketMessageType.Binary,
                            true,
                            cancellationToken);
                    }
                    catch (WebSocketException ex)
                    {
                        Logger.Error(ex, "ProcessConnectionAsync: WebSocketException={0}", webSocket.State);
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "ProcessConnectionAsync");
                throw;
            }
        }
Exemplo n.º 3
0
 /// <inheritdoc />
 public async Task <IWebSocketContext> AcceptWebSocketAsync(int receiveBufferSize)
 => new WebSocketContext(await _context.AcceptWebSocketAsync(subProtocol: null,
                                                             receiveBufferSize: receiveBufferSize,
                                                             keepAliveInterval: TimeSpan.FromSeconds(30))
                         .ConfigureAwait(false));
Exemplo n.º 4
0
        public async Task AcceptWebSocket(HttpListenerContext context, CancellationToken ct)
#endif
        {
            _ct = ct;

            // first, accept the websocket
            $"{ServerName} - Accepting WebSocket . . .".Debug(nameof(WebSocketsServer));

#if NET47
            const int receiveBufferSize = 2048;
#endif

            var webSocketContext =
#if NET47
                await context.AcceptWebSocketAsync(
                    subProtocol : null,
                    receiveBufferSize : receiveBufferSize,
                    keepAliveInterval : TimeSpan.FromSeconds(30));
#else
                await context.AcceptWebSocketAsync();
#endif

            // remove the disconnected clients
            CollectDisconnected();
            lock (_syncRoot)
            {
                // add the newly-connected client
                _mWebSockets.Add(webSocketContext);
            }

            $"{ServerName} - WebSocket Accepted - There are {WebSockets.Count} sockets connected.".Debug(
                nameof(WebSocketsServer));

            // call the abstract member
#if NET47
            OnClientConnected(webSocketContext, context.Request.LocalEndPoint, context.Request.RemoteEndPoint);
#else
            OnClientConnected(webSocketContext);
#endif

            try
            {
#if NET47
                // define a receive buffer
                var receiveBuffer = new byte[receiveBufferSize];

                // define a dynamic buffer that holds multi-part receptions
                var receivedMessage = new List <byte>(receiveBuffer.Length * 2);

                // poll the WebSockets connections for reception
                while (webSocketContext.WebSocket.State == WebSocketState.Open)
                {
                    // retrieve the result (blocking)
                    var receiveResult =
                        await webSocketContext.WebSocket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), ct);

                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        // close the connection if requested by the client
                        await webSocketContext.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, ct);

                        return;
                    }

                    var frameBytes = new byte[receiveResult.Count];
                    Array.Copy(receiveBuffer, frameBytes, frameBytes.Length);
                    this.OnFrameReceived(webSocketContext, frameBytes, receiveResult);

                    // add the response to the multi-part response
                    receivedMessage.AddRange(frameBytes);

                    if (receivedMessage.Count > _maximumMessageSize && _maximumMessageSize > 0)
                    {
                        // close the connection if message exceeds max length
                        await webSocketContext.WebSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig,
                                                                    $"Message too big. Maximum is {_maximumMessageSize} bytes.",
                                                                    ct);

                        // exit the loop; we're done
                        return;
                    }

                    // if we're at the end of the message, process the message
                    if (receiveResult.EndOfMessage)
                    {
                        this.OnMessageReceived(webSocketContext, receivedMessage.ToArray(), receiveResult);
                        receivedMessage.Clear();
                    }
                }
#else
                webSocketContext.WebSocket.OnMessage += (s, e) =>
                {
                    var isText = e.IsText ? WebSocketMessageType.Text : WebSocketMessageType.Binary;

                    OnMessageReceived(webSocketContext,
                                      e.RawData,
                                      new WebSocketReceiveResult(e.RawData.Length, isText, e.Opcode == Opcode.Close));
                };

                while (webSocketContext.WebSocket.IsConnected)
                {
                    await Task.Delay(500, ct);
                }
#endif
            }
            catch (Exception ex)
            {
                ex.Log(nameof(WebSocketsServer));
            }
            finally
            {
                // once the loop is completed or connection aborted, remove the WebSocket
                RemoveWebSocket(webSocketContext);
            }
        }
Exemplo n.º 5
0
        public async Task AcceptWebSocketAsync_InvalidKeepAlive_ThrowsWebSocketException()
        {
            HttpListenerContext context = await GetWebSocketContext();

            TimeSpan keepAlive = TimeSpan.FromMilliseconds(-2);
            await Assert.ThrowsAsync <ArgumentOutOfRangeException>("keepAliveInterval", () => context.AcceptWebSocketAsync(null, keepAlive));
        }
Exemplo n.º 6
0
        public async Task AcceptWebSocketAsync_NullArrayInArraySegment_ThrowsArgumentNullException()
        {
            HttpListenerContext context = await GetWebSocketContext();

            ArraySegment <byte> internalBuffer = new FakeArraySegment()
            {
                Array = null
            }.ToActual();
            await AssertExtensions.ThrowsAsync <ArgumentNullException>("internalBuffer.Array", () => context.AcceptWebSocketAsync(null, 1024, TimeSpan.MaxValue, internalBuffer));
        }
        private static async Task ListenerProcessingLoopAsync()
        {
            var cancellationToken = ListenerLoopTokenSource.Token;

            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    HttpListenerContext context = await Listener.GetContextAsync();

                    if (ServerIsRunning)
                    {
                        if (context.Request.IsWebSocketRequest)
                        {
                            // HTTP is only the initial connection; upgrade to a client-specific websocket
                            HttpListenerWebSocketContext wsContext = null;
                            try
                            {
                                wsContext = await context.AcceptWebSocketAsync(subProtocol : null);

                                int socketId = Interlocked.Increment(ref SocketCounter);
                                var client   = new ConnectedClient(socketId, wsContext.WebSocket);
                                Clients.TryAdd(socketId, client);
                                Console.WriteLine($"Socket {socketId}: New connection.");
                                _ = Task.Run(() => SocketProcessingLoopAsync(client).ConfigureAwait(false));
                            }
                            catch (Exception)
                            {
                                // server error if upgrade from HTTP to WebSocket fails
                                context.Response.StatusCode        = 500;
                                context.Response.StatusDescription = "WebSocket upgrade failed";
                                context.Response.Close();
                                return;
                            }
                        }
                        else
                        {
                            if (context.Request.AcceptTypes.Contains("text/html"))
                            {
                                Console.WriteLine("Sending HTML to client.");
                                ReadOnlyMemory <byte> HtmlPage = new ReadOnlyMemory <byte>(Encoding.UTF8.GetBytes(SimpleHtmlClient.HTML));
                                context.Response.ContentType       = "text/html; charset=utf-8";
                                context.Response.StatusCode        = 200;
                                context.Response.StatusDescription = "OK";
                                context.Response.ContentLength64   = HtmlPage.Length;
                                await context.Response.OutputStream.WriteAsync(HtmlPage, CancellationToken.None);

                                await context.Response.OutputStream.FlushAsync(CancellationToken.None);
                            }
                            else
                            {
                                context.Response.StatusCode = 400;
                            }
                            context.Response.Close();
                        }
                    }
                    else
                    {
                        // HTTP 409 Conflict (with server's current state)
                        context.Response.StatusCode        = 409;
                        context.Response.StatusDescription = "Server is shutting down";
                        context.Response.Close();
                        return;
                    }
                }
            }
            catch (HttpListenerException ex) when(ServerIsRunning)
            {
                Program.ReportException(ex);
            }
        }
Exemplo n.º 8
0
        public async Task AcceptWebSocketAsync_InvalidSubProtocol_ThrowsArgumentException(string subProtocol)
        {
            HttpListenerContext context = await GetWebSocketContext();

            await AssertExtensions.ThrowsAsync <ArgumentException>("subProtocol", () => context.AcceptWebSocketAsync(subProtocol));
        }
Exemplo n.º 9
0
        // a web socket is attaching
        private async void ProcessWebSocket(HttpListenerContext ctx, string protocol, Tuple <WebSocketsResponderFunc, Object> responder, CancellationToken canceltk)
        {
            WebSocketContext wsctx;

            try
            {
                System.Diagnostics.Debug.WriteLine("WEBSOCKET Accepting on " + prefixesString + " protocol " + protocol);
                wsctx = await ctx.AcceptWebSocketAsync(protocol);
            }
            catch (Exception e)
            {
                // The upgrade process failed somehow. For simplicity lets assume it was a failure on the part of the server and indicate this using 500.
                ctx.Response.StatusCode = 500;
                ctx.Response.Close();
                System.Diagnostics.Debug.WriteLine("Exception: {0}", e);
                return;
            }

            ServerLog?.Invoke("WEBSOCKET accepted " + prefixesString);
            System.Diagnostics.Debug.WriteLine("WEBSOCKET accepted " + prefixesString);

            WebSocket webSocket = wsctx.WebSocket;

            lock (webSockets)
                webSockets.Add(webSocket);       // add to the pool of web sockets to throw data at.


            try
            {
                byte[] receiveBuffer = new byte[WebSocketMsgBufferSize];

                while (webSocket.State == WebSocketState.Open)
                {
                    WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), canceltk);

                    ServerLog?.Invoke("WEBSOCKET request " + prefixesString + ": " + receiveResult.MessageType);
                    System.Diagnostics.Debug.WriteLine("WEBSOCKET request " + prefixesString + " type " + receiveResult.MessageType + " len " + receiveResult.Count);

                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        System.Diagnostics.Debug.WriteLine("WEBSOCKET close req " + prefixesString);
                        webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None).Wait();        // here we block until complete
                    }
                    else
                    {
                        responder.Item1(ctx.Request, webSocket, receiveResult, receiveBuffer, responder.Item2);
                    }
                }

                System.Diagnostics.Debug.WriteLine("WEBSOCKET closed on " + prefixesString);
            }
            catch (System.Threading.Tasks.TaskCanceledException)
            {
                // normal task canceled exception
            }
            catch (Exception e)
            {
                // Just log any exceptions to the console. Pretty much any exception that occurs when calling `SendAsync`/`ReceiveAsync`/`CloseAsync` is unrecoverable in that it will abort the connection and leave the `WebSocket` instance in an unusable state.
                System.Diagnostics.Debug.WriteLine("Exception: {0}", e);
            }
            finally
            {
                if (webSocket != null)      // Clean up by disposing the WebSocket once it is closed/aborted.
                {
                    lock (webSockets)
                        webSockets.Remove(webSocket);
                    webSocket.Dispose();
                }
            }

            System.Diagnostics.Debug.WriteLine("WEBSOCKET terminate " + prefixesString);
        }
        public virtual async void ProcessWebSocketRequest(HttpListenerContext context)
        {
            WebSocketContext webSocketContext = null;

            try
            {
                // When calling `AcceptWebSocketAsync` the negotiated subprotocol must be specified. For simplicity now we assumes that no subprotocol
                // was requested.
                webSocketContext = await context.AcceptWebSocketAsync(null);

                if (_websocketConnectionCount == int.MaxValue)
                {
                    Log("[VERBOSE] Websocket reset connection count");
                    _websocketConnectionCount = 0;
                }
                Interlocked.Increment(ref _websocketConnectionCount);
                Log(string.Format("[VERBOSE] Websocket #{0}", _websocketConnectionCount));
            }
            catch (Exception ex)
            {
                // The upgrade process failed somehow. For simplicity lets assume it was a failure on the part of the server and indicate this using 500.
                context.Response.StatusCode = 500;
                context.Response.Close();
                Log(string.Format("[ERROR] {0}", ex.Message));
                return;
            }

            WebSocket webSocket = webSocketContext.WebSocket;
            string    clientId  = WebSocketClients.AddSocket(webSocket);

            try
            {
                Log("[VERBOSE] Websocket is receiving");

                //### Receiving
                // Define a receive buffer to hold data received on the WebSocket connection. The buffer will be reused as we only need to hold on to the data
                // long enough to send it back to the sender.
                ArraySegment <byte> receiveBuffer = new ArraySegment <byte>(new byte[1024]);  // 8192;
                MemoryStream        msText        = null;
                MemoryStream        msBin         = null;

                // While the WebSocket connection remains open run a simple loop that receives data and sends it back.
                while (webSocket.State == WebSocketState.Open)
                {
                    // The first step is to begin a receive operation on the WebSocket. `ReceiveAsync` takes two parameters:
                    //
                    // * An `ArraySegment` to write the received data to.
                    // * A cancellation token. In this example we are not using any timeouts so we use `CancellationToken.None`.
                    //
                    // `ReceiveAsync` returns a `Task<WebSocketReceiveResult>`. The `WebSocketReceiveResult` provides information on the receive operation that was just
                    // completed, such as:
                    //
                    // * `WebSocketReceiveResult.MessageType` - What type of data was received and written to the provided buffer. Was it binary, utf8, or a close message?
                    // * `WebSocketReceiveResult.Count` - How many bytes were read?
                    // * `WebSocketReceiveResult.EndOfMessage` - Have we finished reading the data for this message or is there more coming?
                    WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(receiveBuffer, CancellationToken.None);

                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        // The WebSocket protocol defines a close handshake that allows a party to send a close frame when they wish to gracefully shut down the connection.
                        // The party on the other end can complete the close handshake by sending back a close frame.
                        //
                        // If we received a close frame then lets participate in the handshake by sending a close frame back. This is achieved by calling `CloseAsync`.
                        // `CloseAsync` will also terminate the underlying TCP connection once the close handshake is complete.
                        //
                        // The WebSocket protocol defines different status codes that can be sent as part of a close frame and also allows a close message to be sent.
                        // If we are just responding to the client's request to close we can just use `WebSocketCloseStatus.NormalClosure` and omit the close message.

                        Log(string.Format("[VERBOSE] Websocket for client {0} graceful close", clientId));
                        await WebSocketClients.RemoveSocket(clientId);
                    }
                    else if (receiveResult.MessageType == WebSocketMessageType.Text)
                    {
                        // We received text!

                        if (msText == null)
                        {
                            Log("[VERBOSE] Websocket text frame");
                            msText = new MemoryStream();
                        }
                        else
                        {
                            Log("[VERBOSE] Websocket text frame (append)");
                        }

                        msText.Write(receiveBuffer.Array, receiveBuffer.Offset, receiveResult.Count);

                        if (receiveResult.EndOfMessage)
                        {
                            msText.Seek(0, SeekOrigin.Begin);
                            using (var reader = new StreamReader(msText, Encoding.UTF8))
                            {
                                string receiveText = reader.ReadToEnd();
                                string sendText    = ProcessWebSocketTextRequest(clientId, receiveText);
                                byte[] encoded     = Encoding.UTF8.GetBytes(sendText);
                                var    sendBuffer  = new ArraySegment <byte>(encoded, 0, encoded.Length);
                                await webSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
                            }

                            msText.Close();
                            msText.Dispose();
                            msText = null;
                        }
                    }
                    else
                    {
                        // We received binary data!

                        if (msBin == null)
                        {
                            Log("[VERBOSE] Websocket bin frame");
                            msBin = new MemoryStream();
                        }
                        else
                        {
                            Log("[VERBOSE] Websocket bin frame (append)");
                        }

                        msBin.Write(receiveBuffer.Array, receiveBuffer.Offset, receiveResult.Count);

                        if (receiveResult.EndOfMessage)
                        {
                            msBin.Seek(0, SeekOrigin.Begin);
                            Stream sendStream = ProcessWebSocketBinaryRequest(clientId, msBin);
                            sendStream.Seek(0, SeekOrigin.Begin);
                            byte[] sendBytes = new byte[sendStream.Length];
                            sendStream.Read(sendBytes, 0, (int)sendStream.Length);
                            var sendBuffer = new ArraySegment <byte>(sendBytes, 0, sendBytes.Length);
                            await webSocket.SendAsync(sendBuffer, WebSocketMessageType.Binary, true, CancellationToken.None);

                            msBin.Close();
                            msBin.Dispose();
                            msBin = null;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log(string.Format("[ERROR] {0}", ex.Message));
            }
            finally
            {
                // Clean up by disposing the WebSocket once it is closed/aborted.
                if (webSocket != null)
                {
                    Log(string.Format("[VERBOSE] Websocket for client {0} is being disposed", clientId));
                    webSocket.Dispose();
                }
            }
        }
Exemplo n.º 11
0
        async Task ExecuteRequest(HttpListenerContext listenerContext)
        {
            // By default we will close the stream to cater for failure scenarios
            var keepConnection = false;

            var clientName = listenerContext.Request.RemoteEndPoint;

            WebSocketStream webSocketStream = null;

            try
            {
                var webSocketContext = await listenerContext.AcceptWebSocketAsync("Octopus").ConfigureAwait(false);

                webSocketStream = new WebSocketStream(webSocketContext.WebSocket);

                var req = await webSocketStream.ReadTextMessage().ConfigureAwait(false); // Initial message

                if (string.IsNullOrEmpty(req))
                {
                    log.Write(EventType.Diagnostic, "Ignoring empty request");
                    return;
                }

                if (req.Substring(0, 2) != "MX")
                {
                    log.Write(EventType.Diagnostic, "Appears to be a web browser, sending friendly HTML response");
                    return;
                }

                var authorized = await Authorize(listenerContext, clientName).ConfigureAwait(false);

                if (authorized)
                {
                    // Delegate the open stream to the protocol handler - we no longer own the stream lifetime
                    await ExchangeMessages(webSocketStream).ConfigureAwait(false);

                    // Mark the stream as delegated once everything has succeeded
                    keepConnection = true;
                }
            }
            catch (TaskCanceledException)
            {
                if (!cts.Token.IsCancellationRequested)
                {
                    log.Write(EventType.Error, "A timeout occurred while receiving data");
                }
            }
            catch (Exception ex)
            {
                log.WriteException(EventType.Error, "Unhandled error when handling request from client: {0}", ex, clientName);
            }
            finally
            {
                if (!keepConnection)
                {
                    // Closing an already closed stream or client is safe, better not to leak
                    webSocketStream?.Dispose();
                    listenerContext.Response.Close();
                }
            }
        }
Exemplo n.º 12
0
 public Task <HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol)
 {
     return(inner.AcceptWebSocketAsync(subProtocol));
 }
Exemplo n.º 13
0
        private async void _Accept(HttpListenerContext context)
        {
            System.Net.WebSockets.HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null);

            var webSocket = webSocketContext.WebSocket;


            var status = await Task <System.Net.WebSockets.WebSocketState> .Factory.StartNew(() =>
            {
                while (webSocket.State == System.Net.WebSockets.WebSocketState.Connecting)
                {
                    System.Threading.Thread.Sleep(1);
                }
                return(webSocket.State);
            });

            if (status == System.Net.WebSockets.WebSocketState.Open)
            {
                _AcceptEvent(new Peer(webSocket));
            }
        }
Exemplo n.º 14
0
        public async Task AcceptWebSocketAsync_UnsupportedProtocol_ThrowsWebSocketException()
        {
            HttpListenerContext context = await GetWebSocketContext(new string[] { "MyProtocol" });

            await Assert.ThrowsAsync <WebSocketException>(() => context.AcceptWebSocketAsync("MyOtherProtocol"));
        }
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            Console.WriteLine("TaxcomAgent2");
            HttpListener httpListener = new HttpListener();

            httpListener.Prefixes.Add("http://localhost:4500/");
            httpListener.Start();
            Console.WriteLine("Started!");
            for (; ;)
            {
                HttpListenerContext context = await httpListener.GetContextAsync();

                if (context.Request.IsWebSocketRequest)
                {
                    HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null);

                    WebSocket socket = webSocketContext.WebSocket;
                    while (socket.State == WebSocketState.Open)
                    {
                        const int maxMessageSize             = 4096;
                        byte[]    receiveBuffer              = new byte[maxMessageSize];
                        WebSocketReceiveResult receiveResult = await socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), CancellationToken.None);

                        if (receiveResult.MessageType == WebSocketMessageType.Close)
                        {
                            await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
                        }
                        else if (receiveResult.MessageType == WebSocketMessageType.Binary)
                        {
                            await socket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Cannot accept binary frame", CancellationToken.None);
                        }
                        else
                        {
                            int count = receiveResult.Count;

                            while (receiveResult.EndOfMessage == false)
                            {
                                if (count >= maxMessageSize)
                                {
                                    string closeMessage = string.Format("Maximum message size: {0} bytes.", maxMessageSize);
                                    await socket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None);

                                    return;
                                }

                                receiveResult = await socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer, count, maxMessageSize - count), CancellationToken.None);

                                count += receiveResult.Count;
                            }

                            var receivedString = Encoding.UTF8.GetString(receiveBuffer, 0, count);
                            var echoString     = WebSocketHandler(receivedString);
                            ArraySegment <byte> outputBuffer = new ArraySegment <byte>(Encoding.UTF8.GetBytes(echoString));

                            await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
                        }
                    }
                }
                else
                {
                    context.Response.StatusCode = 400;
                }
            }
        }
Exemplo n.º 16
0
        public async Task AcceptWebSocketAsync_NoClientSubProtocol_ThrowsWebSocketException()
        {
            HttpListenerContext context = await GetWebSocketContext();

            await Assert.ThrowsAsync <WebSocketException>(() => context.AcceptWebSocketAsync("SubProtocol"));
        }
Exemplo n.º 17
0
        public async Task GetResponseAsync(HttpListenerContext context, string localBaseUrl, string remoteBaseUrl, CancellationToken ct)
        {
            string postUri = null;

            if (context.Request.IsWebSocketRequest)
            {
                UriBuilder ub = new UriBuilder(PostUri)
                {
                    Scheme = "wss"
                };
                postUri = ub.Uri.ToString();
            }
            else
            {
                postUri = PostUri.ToString();
            }

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUri);

            request.Method = context.Request.HttpMethod;
            request.ServerCertificateValidationCallback += ValidateCertificate;

            if (!context.Request.IsWebSocketRequest)
            {
                SetRequestHeaders(request, context.Request.Headers, localBaseUrl, remoteBaseUrl);
            }

            // Add RTVS headers
            request.Headers.Add(CustomHttpHeaders.RTVSRequestedURL, GetRemoteUrl(context.Request.Url, remoteBaseUrl));

            if (context.Request.InputStream.CanSeek && context.Request.InputStream.Length > 0)
            {
                using (Stream reqStream = await request.GetRequestStreamAsync()) {
                    await context.Request.InputStream.CopyAndFlushAsync(reqStream);
                }
            }

            HttpWebResponse response = null;

            try {
                response = (HttpWebResponse)await request.GetResponseAsync();
            } catch (WebException wex) {
                if (wex.Status == WebExceptionStatus.ProtocolError)
                {
                    response = wex.Response as HttpWebResponse;
                }
                else
                {
                    throw wex;
                }
            } finally {
                if (response != null)
                {
                    if (context.Request.IsWebSocketRequest && response.StatusCode == HttpStatusCode.SwitchingProtocols)
                    {
                        Stream respStream       = response.GetResponseStream();
                        string subProtocol      = response.Headers[Constants.Headers.SecWebSocketProtocol];
                        var    remoteWebSocket  = CommonWebSocket.CreateClientWebSocket(respStream, subProtocol, TimeSpan.FromMinutes(10), receiveBufferSize: 65335, useZeroMask: true);
                        var    websocketContext = await context.AcceptWebSocketAsync(subProtocol, receiveBufferSize : 65335, keepAliveInterval : TimeSpan.FromMinutes(10));

                        await WebSocketHelper.SendReceiveAsync(websocketContext.WebSocket, remoteWebSocket, ct);
                    }
                    else
                    {
                        context.Response.StatusCode = (int)response.StatusCode;
                        SetResponseHeaders(response, context.Response, localBaseUrl, remoteBaseUrl);
                        using (Stream respStream = response.GetResponseStream())
                            using (Stream outStream = context.Response.OutputStream) {
                                await respStream.CopyAndFlushAsync(outStream);
                            }
                        response.Close();
                    }
                }
            }
        }
Exemplo n.º 18
0
        public async Task AcceptWebSocketAsync_NoSuchSubProtocol_ThrowsWebSocketException(string subProtocol)
        {
            HttpListenerContext context = await GetWebSocketContext();

            await Assert.ThrowsAsync <WebSocketException>(() => context.AcceptWebSocketAsync(subProtocol));
        }
Exemplo n.º 19
0
// ------------------------------------------------------------------------------------
        public async Task Spawn_Context(HttpListenerContext context, uint idx_context)
        {
            // AcceptWebSocketAsync() は、キャンセルトークンをサポートしていない
            // 引数: サポートされている WebSocket サブプロトコル
            HttpListenerWebSocketContext wsc = await context.AcceptWebSocketAsync(null);

            MainForm.StdOut("--- WebSocket 接続完了\r\n");

            using (m_WS = wsc.WebSocket)
                using (WS_Buf_Pool.MemBlock mem_blk = WS_Buf_Pool.Lease_MemBlock())
                {
                    m_read_WS_buf  = new Read_WS_Buf(mem_blk.m_ary_buf);
                    m_write_WS_buf = new Write_WS_Buffer(mem_blk.m_ary_buf);

                    try
                    {
                        // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#if CREATE_TEST_LEXED_CODE
                        // Test Lexed Code を送信する
                        Write_WS_Buffer write_ws_buf = MainForm.ms_DBG_write_WS_buf;
                        await m_WS.SendAsync(
                            new ArraySegment <byte>(write_ws_buf.Get_buf(), 0, write_ws_buf.Get_idx_byte_cur())
                            , WebSocketMessageType.Binary, true, ms_cts_shutdown.Token);
#else
                        // まずはルートフォルダのファイル情報を送信しておく
                        FileLister.Set_DirFileNames(m_write_WS_buf, "./");
                        await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
#endif

                        while (true)
                        {
                            WebSocketReceiveResult rslt = await m_WS.ReceiveAsync(
                                new ArraySegment <byte>(mem_blk.m_ary_buf), ms_cts_shutdown.Token);

                            if (rslt.EndOfMessage == false)
                            {
                                MainForm.StdOut("--- 不正な大きさのデータを受信しました。クライアントを切断します\r\n");
                                break;
                            }
                            if (m_WS.State == WebSocketState.CloseReceived)
                            {
                                MainForm.StdOut("--- クライアントが接続を Close しました\r\n");
                                break;
                            }

                            m_read_WS_buf.Renew(rslt.Count);
                            switch (m_read_WS_buf.Read_ID())
                            {
                            case ID.DirFileList: {
                                ID id = m_read_WS_buf.Read_ID();
                                if (id != ID.Text)
                                {
                                    throw new Exception($"不正なパラメータを受信 DirFileList / id -> {((byte)id).ToString()}");
                                }

                                FileLister.Set_DirFileNames(m_write_WS_buf, m_read_WS_buf.Get_text_cur());
                                await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
                            } continue;

                            case ID.Files_inDir: {
                                ID id = m_read_WS_buf.Read_ID();
                                if (id != ID.Text)
                                {
                                    throw new Exception($"不正なパラメータを受信 Files_inDir / id -> {((byte)id).ToString()}");
                                }

                                string str_path_dir = m_read_WS_buf.Get_text_cur();

                                id = m_read_WS_buf.Read_ID();
                                if (id != ID.Num_int)
                                {
                                    throw new Exception($"不正なパラメータを受信 Files_inDir / id -> {((byte)id).ToString()}");
                                }

                                int SEC_Updated_recv = m_read_WS_buf.Get_Num_int();

                                FileLister.OnFiles_inDir(m_write_WS_buf, str_path_dir, SEC_Updated_recv);
                                await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
                            } continue;

                            case ID.MD_file: {
                                var(path_md_file, SEC_Updated, idx_byte_SEC_updated) = m_read_WS_buf.Read_Req_MD();
                                MainForm.StdOut($"path_md_file : {path_md_file} / SEC_Updated : {SEC_Updated.ToString()}\r\n");

                                // ID.MD_file -> ID_Text (path_dir) -> ID_Text (file name) は Receive時の値を流用
                                m_write_WS_buf.Set_idx_byte(idx_byte_SEC_updated);
                                m_write_WS_buf.Wrt_Num_int(1000);          // 1000 は試験値

                                Lexer.LexFile(m_write_WS_buf, path_md_file);
                                MainForm.StdOut("--- Lexing 処理完了\r\n");

                                m_write_WS_buf.Simplify_Buf();
                                MainForm.StdOut("--- Simplify_Buf 処理完了\r\n");

                                await m_write_WS_buf.SendAsync(m_WS, ms_cts_shutdown);
                            } continue;
                            }



                            MainForm.StdOut($"--- ReceiveAsync() : 受信バイト数 -> {rslt.Count}\r\n");
                            MainForm.HexDump(mem_blk.m_ary_buf, 0, 20);
                            DBG_WS_Buffer.Show_WS_buf(MainForm.ms_RBox_stdout, mem_blk.m_ary_buf, rslt.Count);



                            // 今は、index.md のみを解析するようにしている
//				string ret_str = Lexer.LexFile(m_write_WS_buf, "md_root/index.md");

//				string str_recv = ms_utf16_encoding.GetString(mem_blk.m_ary_buf, 0, rslt.Count);
//				MainForm.StdOut(str_recv);
                        }

                        await m_WS.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "接続を終了します", ms_cts_shutdown.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        MainForm.StdOut("--- サーバーシャットダウンのシグナルを受信しました\r\n");
                    }
                    catch (WebSocketException ex)
                    {
                        MainForm.StdOut($"!!! 例外発を補足しました WebSoketErrorCode : {ex.WebSocketErrorCode.ToString()}\r\n");
                        MainForm.StdOut($"    {ex.ToString()}\r\n");
                    }
                    catch (Exception ex)
                    {
                        MainForm.StdOut($"!!! 例外を補足しました : {ex.ToString()}\r\n");
                    }
                }

            MdSvr.Remove_task_context(idx_context);
            MainForm.StdOut("--- WebSocket 切断完了\r\n");
        }
Exemplo n.º 20
0
        public async Task AcceptWebSocketAsync_InvalidReceiveBufferSize_ThrowsWebSocketException(int receiveBufferSize)
        {
            HttpListenerContext context = await GetWebSocketContext();

            await Assert.ThrowsAsync <ArgumentOutOfRangeException>("receiveBufferSize", () => context.AcceptWebSocketAsync(null, receiveBufferSize, TimeSpan.MaxValue));
        }
Exemplo n.º 21
0
        public async Task GetResponseAsync(HttpListenerContext context, string localBaseUrl, string remoteBaseUrl, CancellationToken ct)
        {
            string postUri;

            if (context.Request.IsWebSocketRequest)
            {
                var ub = new UriBuilder(PostUri)
                {
                    Scheme = "wss"
                };
                postUri = ub.Uri.ToString();
            }
            else
            {
                postUri = PostUri.ToString();
            }

            var request = (HttpWebRequest)WebRequest.Create(postUri);

            request.Method = context.Request.HttpMethod;
            request.ServerCertificateValidationCallback += ValidateCertificate;

            if (!context.Request.IsWebSocketRequest)
            {
                SetRequestHeaders(request, context.Request.Headers, localBaseUrl, remoteBaseUrl);
            }

            // Add RTVS headers
            var remoteUri = GetRemoteUri(context.Request.Url, remoteBaseUrl);

            request.Headers.Add(CustomHttpHeaders.RTVSRequestedURL, remoteUri.ToString());

            if (context.Request.ContentLength64 > 0)
            {
                using (var reqStream = await request.GetRequestStreamAsync()) {
                    await context.Request.InputStream.CopyAndFlushAsync(reqStream, null, ct);
                }
            }

            HttpWebResponse response = null;

            try {
                response = (HttpWebResponse)await request.GetResponseAsync();

                if (response != null)
                {
                    if (context.Request.IsWebSocketRequest && response.StatusCode == HttpStatusCode.SwitchingProtocols)
                    {
                        var respStream       = response.GetResponseStream();
                        var subProtocol      = response.Headers[Constants.Headers.SecWebSocketProtocol];
                        var remoteWebSocket  = CommonWebSocket.CreateClientWebSocket(respStream, subProtocol, TimeSpan.FromMinutes(10), receiveBufferSize: _receiveBufferSize, useZeroMask: true);
                        var websocketContext = await context.AcceptWebSocketAsync(subProtocol, receiveBufferSize : _receiveBufferSize, keepAliveInterval : TimeSpan.FromMinutes(10));

                        await WebSocketHelper.SendReceiveAsync(websocketContext.WebSocket, remoteWebSocket, ct);
                    }
                    else
                    {
                        context.Response.StatusCode = (int)response.StatusCode;
                        SetResponseHeaders(response, context.Response, localBaseUrl, remoteBaseUrl);
                        using (var respStream = response.GetResponseStream())
                            using (var outStream = context.Response.OutputStream) {
                                await respStream.CopyAndFlushAsync(outStream, null, ct);
                            }
                        response.Close();
                    }
                }
            } catch (WebException wex) when(wex.Status == WebExceptionStatus.ProtocolError)
            {
                response = wex.Response as HttpWebResponse;
            } catch (OperationCanceledException) {
                WebServer.Stop(remoteUri.Port);
            } catch (Exception ex) when(!ex.IsCriticalException())
            {
                _log.WriteLine(LogVerbosity.Normal, MessageCategory.Error, Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message));
                _console?.WriteErrorLine(Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message));
                WebServer.Stop(remoteUri.Port);
            } finally {
                response?.Close();
            }
        }
Exemplo n.º 22
0
        public async Task AcceptWebSocketAsync_InvalidCountInArraySegment_ThrowsArgumentNullException(int offset, int count)
        {
            HttpListenerContext context = await GetWebSocketContext();

            ArraySegment <byte> internalBuffer = new FakeArraySegment()
            {
                Array = new byte[10], Offset = offset, Count = count
            }.ToActual();
            await AssertExtensions.ThrowsAsync <ArgumentOutOfRangeException>("internalBuffer.Count", () => context.AcceptWebSocketAsync(null, 1024, TimeSpan.MaxValue, internalBuffer));
        }
Exemplo n.º 23
0
 public async Task <HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol)
 {
     return(await CoreContext.AcceptWebSocketAsync(subProtocol));
 }