Пример #1
0
    internal const int FragmentLength = 1016; // Max value is int.MaxValue - 14.

    #endregion

    #region Internal Constructors

    // As server
    internal WebSocket (HttpListenerWebSocketContext context, string protocol, Logger logger)
    {
      _context = context;
      _protocol = protocol;
      _logger = logger;

      _closeContext = context.Close;
      _secure = context.IsSecureConnection;
      _stream = context.Stream;

      init ();
    }
        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);
            }
        }
Пример #3
0
    // As server
    internal WebSocket (HttpListenerWebSocketContext context, string protocol)
    {
      _context = context;
      _protocol = protocol;

      _closeContext = context.Close;
      _logger = context.Log;
      _secure = context.IsSecureConnection;
      _stream = context.Stream;
      _waitTime = TimeSpan.FromSeconds (1);

      init ();
    }
Пример #4
0
        public async Task CloseOutputAsync_HandshakeStartedFromClient_Success(WebSocketCloseStatus status, string statusDescription, WebSocketCloseStatus expectedCloseStatus)
        {
            // [ActiveIssue("https://github.com/dotnet/corefx/issues/20392", TargetFrameworkMonikers.Netcoreapp)]
            string expectedStatusDescription = statusDescription;

            if (statusDescription == null)
            {
                expectedStatusDescription = string.Empty;
            }

            HttpListenerWebSocketContext context = await GetWebSocketContext();

            await ClientConnectTask;

            // Close the server output.
            Task serverCloseTask = context.WebSocket.CloseOutputAsync(status, statusDescription, new CancellationToken());

            byte[] receivedClientBytes = new byte[10];
            Task <WebSocketReceiveResult> clientReceiveTask = Client.ReceiveAsync(new ArraySegment <byte>(receivedClientBytes), new CancellationToken());

            await Task.WhenAll(serverCloseTask, clientReceiveTask);

            WebSocketReceiveResult clientResult = await clientReceiveTask;

            Assert.Equal(new byte[10], receivedClientBytes);
            Assert.Equal(expectedCloseStatus, clientResult.CloseStatus);

            Assert.Equal(expectedStatusDescription, clientResult.CloseStatusDescription);
            Assert.Equal(WebSocketMessageType.Close, clientResult.MessageType);
            Assert.True(clientResult.EndOfMessage);

            Assert.Null(context.WebSocket.CloseStatus);
            Assert.Null(context.WebSocket.CloseStatusDescription);
            Assert.Equal(WebSocketState.CloseSent, context.WebSocket.State);

            // Trying to send if the socket initiated a close should fail.
            await Assert.ThrowsAsync <WebSocketException>(() => context.WebSocket.SendAsync(new ArraySegment <byte>(new byte[10]), WebSocketMessageType.Binary, false, new CancellationToken()));

            // Close the client.
            Task clientCloseTask = Client.CloseAsync(status, statusDescription, new CancellationToken());

            byte[] receivedServerBytes = new byte[10];
            Task <WebSocketReceiveResult> serverReceiveTask = context.WebSocket.ReceiveAsync(new ArraySegment <byte>(receivedServerBytes), new CancellationToken());

            await Task.WhenAll(clientCloseTask, serverReceiveTask);

            WebSocketReceiveResult serverResult = await clientReceiveTask;

            Assert.Equal(new byte[10], receivedServerBytes);
            Assert.Equal(expectedCloseStatus, serverResult.CloseStatus);
            Assert.Equal(expectedStatusDescription, serverResult.CloseStatusDescription);
            Assert.Equal(WebSocketMessageType.Close, serverResult.MessageType);
            Assert.True(serverResult.EndOfMessage);

            Assert.Equal(expectedCloseStatus, context.WebSocket.CloseStatus);
            Assert.Equal(statusDescription, context.WebSocket.CloseStatusDescription);
            Assert.Equal(WebSocketState.Closed, context.WebSocket.State);

            // Trying to read or write if closed should fail.
            await Assert.ThrowsAsync <WebSocketException>(() => context.WebSocket.ReceiveAsync(new ArraySegment <byte>(receivedServerBytes), new CancellationToken()));

            await Assert.ThrowsAsync <WebSocketException>(() => context.WebSocket.SendAsync(new ArraySegment <byte>(receivedServerBytes), WebSocketMessageType.Binary, false, new CancellationToken()));

            // Trying to close again should be a nop.
            await context.WebSocket.CloseAsync(WebSocketCloseStatus.Empty, null, new CancellationToken());

            await context.WebSocket.CloseOutputAsync(WebSocketCloseStatus.Empty, null, new CancellationToken());
        }
Пример #5
0
        private async void GetContextCallback(IAsyncResult iar)
        {
            if (IsRunning)
            {
                HttpListenerContext ctx = Listener.EndGetContext(iar);
                Listener.BeginGetContext(GetContextCallback, null);
                if (ctx.Request.IsWebSocketRequest)
                {
                    HttpListenerWebSocketContext wsctx = await ctx.AcceptWebSocketAsync("latipium");

                    ArraySegment <byte> buffer = new ArraySegment <byte>(new byte[MaxReceiveSize]);
#pragma warning disable 4014
                    wsctx.WebSocket.ReceiveAsync(buffer, CancellationTokenSource.Token).ContinueWith(task => WebsocketRead(task, wsctx.WebSocket, buffer, null));
#pragma warning restore 4014
                }
                else
                {
                    string tmp;
                    if ((ctx.Request.UrlReferrer != null && AuthorizedHosts.Contains(ctx.Request.UrlReferrer.Host.ToLower())) || ctx.Request.UserAgent == "Latipium Daemon (https://github.com/latipium/daemon)")
                    {
                        if (!string.IsNullOrWhiteSpace(tmp = ctx.Request.Headers["Origin"]))
                        {
                            if (AuthorizedOrigins.Contains(tmp))
                            {
                                ctx.Response.AddHeader("Access-Control-Allow-Origin", tmp);
                            }
                        }
                        if (!string.IsNullOrWhiteSpace(tmp = ctx.Request.Headers["Access-Control-Request-Headers"]))
                        {
                            ctx.Response.AddHeader("Access-Control-Allow-Headers", tmp.Split(new [] { ", ", "," }, StringSplitOptions.RemoveEmptyEntries)
                                                   .Where(h => AuthorizedHeaders.Any(i => h.ToLower() == i.ToLower()))
                                                   .Aggregate((a, b) => string.Concat(a, ",", b)));
                        }
                        if (!string.IsNullOrWhiteSpace(tmp = ctx.Request.Headers["Access-Control-Request-Method"]))
                        {
                            if (AuthorizedMethods.Contains(tmp.ToUpper()))
                            {
                                ctx.Response.AddHeader("Access-Control-Allow-Methods", tmp);
                            }
                        }
                        ctx.Response.AddHeader("Access-Control-Max-Age", "600");
                        if (ctx.Request.HttpMethod.ToUpper() != "OPTIONS")
                        {
                            string request;
                            using (TextReader reader = new StreamReader(ctx.Request.InputStream)) {
                                request = reader.ReadToEnd();
                            }
                            Guid clientId = Guid.Empty;
                            Guid.TryParse(ctx.Request.Headers["X-Latipium-Client-Id"] ?? "", out clientId);
                            string response = Handle(ctx.Request.Url.AbsolutePath.Replace("//", "/"), request, Clients.ContainsKey(clientId) ? Clients[clientId].Ping() : null);
                            ctx.Response.ContentType = "application/json";
                            using (TextWriter writer = new StreamWriter(ctx.Response.OutputStream)) {
                                writer.Write(response);
                            }
                        }
                    }
                    else
                    {
                        ctx.Response.StatusCode        = 403;
                        ctx.Response.StatusDescription = "Forbidden";
                        if (ctx.Request.UrlReferrer != null)
                        {
                            WindowsService.WriteLog(string.Format("Request with invalid referrer '{0}'", ctx.Request.UrlReferrer));
                        }
                    }
                    ctx.Response.Close();
                }
            }
        }
Пример #6
0
        private async ValueTask ProcessRequestAsync(HttpListenerContext context, IPrincipal principal)
        {
            if (context.Request.RawUrl.StartsWith("/favicon.ico"))
            {
                Http404(context);
            }
            if (Logger.IsEnabled(LogLevel.Trace))
            {
                Logger.LogTrace($"[http RequestTraceIdentifier]:{context.Request.RequestTraceIdentifier.ToString()}-{context.Request.RemoteEndPoint.ToString()}");
            }
            string sim     = context.Request.QueryString.Get("sim");
            string channel = context.Request.QueryString.Get("channel");

            if (string.IsNullOrEmpty(sim) || string.IsNullOrEmpty(channel))
            {
                await Http400(context);

                return;
            }
            int.TryParse(channel, out int channelNo);
            if (context.Request.IsWebSocketRequest)
            {
                HttpListenerWebSocketContext wsContext = await context.AcceptWebSocketAsync(null);

                var jT1078HttpContext = new JT1078HttpContext(context, wsContext, principal);
                jT1078HttpContext.Sim       = sim;
                jT1078HttpContext.ChannelNo = channelNo;
                //todo: add session manager
                await wsContext.WebSocket.SendAsync(Encoding.UTF8.GetBytes("hello,jt1078"), WebSocketMessageType.Text, true, CancellationToken.None);

                await Task.Factory.StartNew(async(state) =>
                {
                    //https://www.bejson.com/httputil/websocket/
                    //ws://127.0.0.1:15555?token=22&sim=1221&channel=1
                    var websocketContext = state as JT1078HttpContext;
                    while (websocketContext.WebSocketContext.WebSocket.State == WebSocketState.Open ||
                           websocketContext.WebSocketContext.WebSocket.State == WebSocketState.Connecting)
                    {
                        var buffer = ArrayPool <byte> .Shared.Rent(256);
                        try
                        {
                            WebSocketReceiveResult receiveResult = await websocketContext.WebSocketContext.WebSocket.ReceiveAsync(buffer, CancellationToken.None);
                            if (receiveResult.EndOfMessage)
                            {
                                if (receiveResult.Count > 0)
                                {
                                    var data = buffer.AsSpan().Slice(0, receiveResult.Count).ToArray();
                                    if (Logger.IsEnabled(LogLevel.Trace))
                                    {
                                        Logger.LogTrace($"[ws receive]:{Encoding.UTF8.GetString(data)}");
                                    }
                                    await websocketContext.WebSocketContext.WebSocket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
                                }
                            }
                        }
                        finally
                        {
                            ArrayPool <byte> .Shared.Return(buffer);
                        }
                    }
                    if (Logger.IsEnabled(LogLevel.Trace))
                    {
                        Logger.LogTrace($"[ws close]:{websocketContext}");
                    }
                    //todo:session close notice
                    await websocketContext.WebSocketContext.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "normal", CancellationToken.None);
                }, jT1078HttpContext);
            }
            else
            {
                var jT1078HttpContext = new JT1078HttpContext(context, principal);
                jT1078HttpContext.Sim       = sim;
                jT1078HttpContext.ChannelNo = channelNo;

                //todo:add session manager

                //todo:set http chunk

                //todo:session close notice

                byte[] b = Encoding.UTF8.GetBytes("ack");
                context.Response.StatusCode      = 200;
                context.Response.KeepAlive       = true;
                context.Response.ContentLength64 = b.Length;
                await context.Response.OutputStream.WriteAsync(b, 0, b.Length);

                context.Response.Close();
            }
        }
Пример #7
0
        public async Task SendAsync_InvalidMessageType_ThrowsArgumentNullException(WebSocketMessageType messageType)
        {
            HttpListenerWebSocketContext context = await GetWebSocketContext();

            await AssertExtensions.ThrowsAsync <ArgumentException>("messageType", () => context.WebSocket.SendAsync(new ArraySegment <byte>(), messageType, false, new CancellationToken()));
        }
Пример #8
0
 public JT1078HttpContext(HttpListenerContext context, HttpListenerWebSocketContext webSocketContext, IPrincipal user)
 {
     Context          = context;
     WebSocketContext = webSocketContext;
     User             = user;
 }
 public ListenerWebSocketTransport(HttpListenerWebSocketContext context)
     : base(context.WebSocket)
 {
     this.Principal = context.User;
 }
 public SystemHttpListenerWebSocketContext(HttpListenerWebSocketContext context)
 {
     _context = context;
 }
        /// <summary>
        /// Accepts a WebSocket handshake request.
        /// </summary>
        /// <returns>
        /// A <see cref="HttpListenerWebSocketContext"/> that represents
        /// the WebSocket handshake request.
        /// </returns>
        /// <param name="protocol">
        /// A <see cref="string"/> that represents the subprotocol supported on
        /// this WebSocket connection.
        /// </param>
        /// <exception cref="ArgumentException">
        ///   <para>
        ///   <paramref name="protocol"/> is empty.
        ///   </para>
        ///   <para>
        ///   -or-
        ///   </para>
        ///   <para>
        ///   <paramref name="protocol"/> contains an invalid character.
        ///   </para>
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// This method has already been called.
        /// </exception>
        public HttpListenerWebSocketContext AcceptWebSocket(string protocol)
        {
            if (_websocketContext != null)
            throw new InvalidOperationException ("The accepting is already in progress.");

              if (protocol != null) {
            if (protocol.Length == 0)
              throw new ArgumentException ("An empty string.", "protocol");

            if (!protocol.IsToken ())
              throw new ArgumentException ("Contains an invalid character.", "protocol");
              }

              _websocketContext = new HttpListenerWebSocketContext (this, protocol);
              return _websocketContext;
        }
Пример #12
0
 public static void AcceptSocket(HttpListenerWebSocketContext c)
 {
     Task.Run(() => handleReceiving(c.WebSocket, c).ConfigureAwait(false));
 }
Пример #13
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");
        }
        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;
                }
            }
        }
Пример #15
0
 public SystemNetWebSocketContext(HttpListenerWebSocketContext ctx)
 {
     this.ctx = ctx;
 }
Пример #16
0
 /// <summary>
 /// WSChannel
 /// </summary>
 /// <param name="webSocketContext"></param>
 public WSChannel(HttpListenerWebSocketContext webSocketContext)
 {
     Id = ++_id;
     this.webSocketContext = webSocketContext;
     webSocket             = webSocketContext.WebSocket;
 }
        static public async Task RunWebSocketServer()
        {
            try
            {
                while (true)
                {
                    HttpListenerContext context = await s_listener.GetContextAsync().ConfigureAwait(false);

                    if (!context.Request.IsWebSocketRequest)
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                        context.Response.Close();
                    }

                    HttpListenerWebSocketContext webSocketContext = await context
                                                                    .AcceptWebSocketAsync(WebSocketConstants.SubProtocols.Amqpwsb10, 8 * 1024, s_fiveMinutes)
                                                                    .ConfigureAwait(false);

                    var buffer            = new byte[1 * 1024];
                    var arraySegment      = new ArraySegment <byte>(buffer);
                    var cancellationToken = new CancellationToken();
                    WebSocketReceiveResult receiveResult = await webSocketContext.WebSocket
                                                           .ReceiveAsync(arraySegment, cancellationToken)
                                                           .ConfigureAwait(false);

                    // Echo the data back to the client
                    var responseCancellationToken = new CancellationToken();
                    var responseBuffer            = new byte[receiveResult.Count];
                    for (int i = 0; i < receiveResult.Count; i++)
                    {
                        responseBuffer[i] = arraySegment.Array[i];
                    }

                    var responseSegment = new ArraySegment <byte>(responseBuffer);
                    await webSocketContext.WebSocket
                    .SendAsync(responseSegment, WebSocketMessageType.Binary, true, responseCancellationToken)
                    .ConfigureAwait(false);

                    // Have a pending read
                    using var source = new CancellationTokenSource(s_oneMinute);
                    WebSocketReceiveResult result = await webSocketContext.WebSocket
                                                    .ReceiveAsync(arraySegment, source.Token)
                                                    .ConfigureAwait(false);

                    int bytes = result.Count;
                }
            }
            catch (TaskCanceledException)
            {
                return;
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (WebSocketException)
            {
                return;
            }
            catch (HttpListenerException)
            {
                return;
            }
        }
Пример #18
0
            //-------------------
            // Task: when a connection is requested, depending on whether it's an HTTP request or WebSocket request, do different things.
            private async Task HandleConnection(Task <HttpListenerContext> listenerContext)
            {
                HttpListenerContext httpContext = listenerContext.Result;

                if (httpContext.Request.IsWebSocketRequest)
                {
                    // Kick off an async task to upgrade the web socket and do send/recv messaging, but fail if it takes more than a second to finish.
                    try
                    {
                        _logger?.Invoke("WebSocketServer.HandleConnection - websocket detected.  Upgrading connection.", 1);
                        using (CancellationTokenSource upgradeTimeout = new CancellationTokenSource(_connectionMS))
                        {
                            HttpListenerWebSocketContext webSocketContext = await Task.Run(async() => { return(await httpContext.AcceptWebSocketAsync(null).ConfigureAwait(false)); }, upgradeTimeout.Token);

                            _logger?.Invoke("WebSocketServer.HandleConnection - websocket detected.  Upgraded.", 1);

                            RGWebSocket rgws = new RGWebSocket(_onReceiveMsgText, _onReceiveMsgBinary, OnDisconnection, _logger, httpContext.Request.RemoteEndPoint.ToString(), webSocketContext.WebSocket, 25);
                            _websockets.TryAdd(rgws._uniqueId, rgws);
                            _websocketConnection(rgws);
                        }
                    }
                    catch (OperationCanceledException)                      // timeout
                    {
                        _logger?.Invoke("WebSocketServer.HandleConnection - websocket upgrade timeout", 1);
                        httpContext.Response.StatusCode = 500;
                        httpContext.Response.Close();
                    }
                    catch                     // anything else
                    {
                        _logger?.Invoke("WebSocketServer.HandleConnection - websocket upgrade exception", 1);
                        httpContext.Response.StatusCode = 500;
                        httpContext.Response.Close();
                    }
                }
                else                  // let the application specify what the HTTP response is, but we do the async write here to free up the app to do other things
                {
                    try
                    {
                        _logger?.Invoke("WebSocketServer.HandleConnection - normal http request", 1);
                        using (CancellationTokenSource responseTimeout = new CancellationTokenSource(_connectionMS))
                        {
                            byte[] buffer = null;
                            httpContext.Response.StatusCode      = _httpRequestCallback(httpContext, out buffer);
                            httpContext.Response.ContentLength64 = buffer.Length;
                            await httpContext.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length, responseTimeout.Token);
                        }
                    }
                    catch (OperationCanceledException)                      // timeout
                    {
                        _logger?.Invoke("WebSocketServer.HandleConnection - http response timeout", 1);
                        httpContext.Response.StatusCode = 500;
                    }
                    catch                     // anything else
                    {
                        _logger?.Invoke("WebSocketServer.HandleConnection - http callback handler exception", 1);
                        httpContext.Response.StatusCode = 500;
                    }
                    finally
                    {
                        httpContext.Response.Close();
                    }
                }
            }
Пример #19
0
        public async Task SendAsync_NoInnerBuffer_ThrowsArgumentNullException()
        {
            HttpListenerWebSocketContext context = await GetWebSocketContext();

            await AssertExtensions.ThrowsAsync <ArgumentNullException>("buffer.Array", () => context.WebSocket.SendAsync(new ArraySegment <byte>(), WebSocketMessageType.Text, false, new CancellationToken()));
        }
Пример #20
0
        private static void RunHttpListener()
        {
            _httpListener = new HttpListener();

            if (!IsNullOrEmpty(_options.AdapterAddress))
            {
            }

            var prefix = Format(UrlPrefix, "+", _options.ListenPort);

            _httpListener.Prefixes.Add(prefix + _options.UrlIdentifier + "/");

            try
            {
                _httpListener.Start();
            }
            catch (Exception ex)
            {
                PrintToConsole("Exception creating web listener: " + ex.Message);
                PrintToConsole("Probably the URL is not reserved - either reserve, or run as admin!");
                PrintToConsole("For reference, type from elevated command prompt:");
                PrintToConsole($@"netsh http add urlacl url={prefix} user=BUILTIN\users");
                PrintToConsole("");
                PrintToConsole("Hit any key to exit");
                Console.ReadLine();
                Environment.Exit((int)ExitCodes.UrlAccessDenied);
            }

            ThreadPool.QueueUserWorkItem(o =>
            {
                try
                {
                    while (_httpListener.IsListening)
                    {
                        ThreadPool.QueueUserWorkItem(c =>
                        {
                            var ctx = c as HttpListenerContext;
                            try
                            {
                                if (ctx == null)
                                {
                                    return;
                                }

                                ctx.Response.ContentType = "video/mp2t";
                                ctx.Response.Headers.Add("Access-Control-Allow-Origin", "*");

                                if (ctx.Request.RemoteEndPoint == null)
                                {
                                    return;
                                }

                                var streamClient = new StreamClient(_ringBuffer)
                                {
                                    ClientAddress = ctx.Request.RemoteEndPoint.ToString()
                                };

                                if (ctx.Request.IsWebSocketRequest)
                                {
                                    HttpListenerWebSocketContext webSocketContext = ctx.AcceptWebSocketAsync(null).Result;
                                    WebSocket webSocket    = webSocketContext.WebSocket;
                                    streamClient.WebSocket = webSocket;
                                }
                                else
                                {
                                    streamClient.OutputWriter = new BinaryWriter(ctx.Response.OutputStream);
                                }

                                lock (StreamingClients)
                                {
                                    StreamingClients.Add(streamClient);
                                }

                                streamClient.Start();
                            }
                            catch (Exception ex)
                            {
                                PrintToConsole($"Exception: {ex.Message}");
                            }
                        }, _httpListener.GetContext());
                    }
                }
                catch (Exception ex)
                {
                    PrintToConsole($"Exception: {ex.Message}");
                }
            });
        }
Пример #21
0
 internal WebSocket(HttpListenerWebSocketContext context)
     : this()
 {
     _uri         = context.Path.ToUri();
       _context     = context;
       _httpContext = context.BaseContext;
       _wsStream    = context.Stream;
       _endPoint    = context.ServerEndPoint;
       _isClient    = false;
       _isSecure    = context.IsSecureConnection;
 }
Пример #22
0
        private async Task HandleListener(CancellationToken token)
        {
            try
            {
                // TODO: Handle server cap URL
                HttpListenerContext context = await _httpListener.GetContextAsync();

                if (token.IsCancellationRequested)
                {
                    CleanUpContext(context);
                    return;
                }

                var headers = GetWebSocketHeaders(context.Request.Headers, context.Request.QueryString);
                if (!context.Request.IsWebSocketRequest)
                {
                    CleanUpContext(context);
                    return;
                }

                if (!EtpWebSocketValidation.IsWebSocketRequestUpgrading(headers))
                {
                    context.Response.StatusCode        = (int)HttpStatusCode.UpgradeRequired;
                    context.Response.StatusDescription = "Invalid web socket request";
                    CleanUpContext(context);
                    return;
                }

                var preferredProtocol = EtpWebSocketValidation.GetPreferredSubProtocol(headers);
                if (preferredProtocol == null)
                {
                    context.Response.StatusCode        = (int)HttpStatusCode.BadRequest;
                    context.Response.StatusDescription = "Invalid web socket request";
                    CleanUpContext(context);
                    return;
                }

                if (!EtpWebSocketValidation.IsEtpEncodingValid(headers))
                {
                    context.Response.StatusCode        = (int)HttpStatusCode.PreconditionFailed;
                    context.Response.StatusDescription = "Invalid etp-encoding header";
                    CleanUpContext(context);
                    return;
                }

                HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(preferredProtocol);

                if (token.IsCancellationRequested)
                {
                    webSocketContext.WebSocket.Dispose();
                    context.Response.Close();
                    return;
                }

                var server = new EtpServer(webSocketContext.WebSocket, ApplicationName, ApplicationVersion, headers);

                server.SupportedObjects = SupportedObjects;
                RegisterAll(server);

                _servers[server.SessionId]     = server;
                _serverTasks[server.SessionId] = Task.Run(async() =>
                {
                    try
                    {
                        InvokeSessionConnected(server);
                        await server.HandleConnection(token);
                    }
                    finally
                    {
                        InvokeSessionClosed(server);
                        CleanUpServer(server);
                        webSocketContext.WebSocket.Dispose();
                        CleanUpContext(context);
                    }
                }, token);
            }
            catch (Exception ex)
            {
                if (!ex.ExceptionMeansConnectionTerminated())
                {
                    Log("Error: Exception caught when handling a websocket connection: {0}", ex.Message);
                    Logger.DebugFormat("Exception caught when handling a websocket connection: {0}", ex);
                    throw;
                }
            }
        }
Пример #23
0
        static async Task handleWebSocket(HttpListenerContext context, Authentication authentication)
        {
            User user = UserManager.Instance.GetUserFromId(authentication.UserID);

            HttpListenerWebSocketContext websocket = await context.AcceptWebSocketAsync(null);

            Action <string, bool> onWriteLine = null;

            onWriteLine = delegate(string line, bool dontHttpEncode)
            {
                if (websocket == null || websocket.WebSocket.State != WebSocketState.Open)
                {
                    Console.WriteLine("error, websocket is not connected");
                    return;
                }

                if (!dontHttpEncode)
                {
                    line = System.Web.HttpUtility.HtmlEncode(line);
                }

                line = line.Replace("\n", "<br>");

                byte[] buffer = Encoding.UTF8.GetBytes(line);

                websocket.WebSocket.SendAsync(new ArraySegment <byte>(buffer), WebSocketMessageType.Text, true, System.Threading.CancellationToken.None).ConfigureAwait(true).GetAwaiter().GetResult();
            };

            OutputConsole.OnWriteLine += onWriteLine;

            OutputConsole.WriteLine(user.Username + " connected to console!");

            CancellationTokenSource token = new CancellationTokenSource();
            DateTime lastHeartBeat        = DateTime.Now;

            Task.Factory.StartNew(async delegate
            {
                while (true)
                {
                    if (websocket == null)
                    {
                        return;
                    }

                    byte[] heartbeatBuffer = new byte[16];
                    await websocket.WebSocket.ReceiveAsync(new ArraySegment <byte>(heartbeatBuffer, 0, heartbeatBuffer.Length), token.Token);
                    lastHeartBeat = DateTime.Now;
                }
            }, token.Token);
            Task.Factory.StartNew(async delegate
            {
                while (true)
                {
                    await Task.Delay(1000);

                    TimeSpan time = DateTime.Now - lastHeartBeat;

                    if (time.TotalSeconds > 3)
                    {
                        OutputConsole.OnWriteLine -= onWriteLine;
                        websocket.WebSocket.Abort();
                        websocket.WebSocket.Dispose();
                        websocket = null;
                        token.Cancel();

                        OutputConsole.WriteLine(user.Username + " disconnected (Connection timed out)");
                        return;
                    }
                }
            }, token.Token);
        }
Пример #24
0
 internal WebSocketData(HttpListenerWebSocketContext context, string subProtocol)
 {
     Context     = context;
     SubProtocol = subProtocol;
 }
Пример #25
0
 public DotNetWebSocketClient(HttpListenerContext httpContext, HttpListenerWebSocketContext webSocketContext, string guid)
 {
     this.Guid             = guid;
     this.httpContext      = httpContext;
     this.webSocketContext = webSocketContext;
 }
Пример #26
0
        private async Task HandleListenerCore(CancellationToken token)
        {
            try
            {
                HttpListenerContext context = await _httpListener.GetContextAsync().ConfigureAwait(false);

                if (token.IsCancellationRequested)
                {
                    CleanUpContext(context);
                    return;
                }

                var headers = GetCombinedHeaders(context.Request.Headers, context.Request.QueryString);
                if (IsServerCapabilitiesRequest(context.Request))
                {
                    Logger.Info($"Handling ServerCapabilities request from {context.Request.RemoteEndPoint}.");
                    HandleServerCapabilitiesRequest(context.Response, headers);
                    CleanUpContext(context);
                    return;
                }

                if (!context.Request.IsWebSocketRequest)
                {
                    CleanUpContext(context);
                    return;
                }

                Logger.Info($"Handling WebSocket request from {context.Request.RemoteEndPoint}.");

                if (!EtpWebSocketValidation.IsWebSocketRequestUpgrading(headers))
                {
                    context.Response.StatusCode = (int)HttpStatusCode.UpgradeRequired;
                    Logger.Debug($"Invalid web socket request");
                    context.Response.StatusDescription = "Invalid web socket request";
                    CleanUpContext(context);
                    return;
                }

                var preferredProtocol = EtpWebSocketValidation.GetPreferredSubProtocol(headers);
                if (preferredProtocol == null)
                {
                    context.Response.StatusCode        = (int)HttpStatusCode.BadRequest;
                    context.Response.StatusDescription = "Invalid web socket request";
                    Logger.Debug($"Invalid web socket request");
                    CleanUpContext(context);
                    return;
                }

                var encoding = EtpWebSocketValidation.GetEtpEncoding(headers);
                if (encoding == null)
                {
                    context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed;
                    Logger.Debug($"Error getting ETP encoding.");
                    context.Response.StatusDescription = "Invalid etp-encoding header";
                    CleanUpContext(context);
                    return;
                }
                if (!Details.IsEncodingSupported(encoding.Value))
                {
                    context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed;
                    Logger.Debug($"Encoding not supported: {encoding.Value}");
                    context.Response.StatusDescription = "Unsupported etp-encoding";
                    CleanUpContext(context);
                    return;
                }

                HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(preferredProtocol).ConfigureAwait(false);

                if (token.IsCancellationRequested)
                {
                    webSocketContext.WebSocket.Dispose();
                    context.Response.Close();
                    return;
                }

                var version = EtpWebSocketValidation.GetEtpVersion(preferredProtocol);
                if (!Details.IsVersionSupported(version))
                {
                    context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed;
                    Logger.Debug($"Sub protocol not supported: {preferredProtocol}");
                    context.Response.StatusDescription = "Sub protocol not supported";
                    CleanUpContext(context);
                    return;
                }

                var ws = new EtpServerWebSocket {
                    WebSocket = webSocketContext.WebSocket
                };
                var server = ServerManager.CreateServer(ws, version, encoding.Value, headers);
                server.Start();
            }
            catch (Exception ex)
            {
                if (!ex.ExceptionMeansConnectionTerminated())
                {
                    ServerManager.Log("Error: Exception caught when handling a websocket connection: {0}", ex.Message);
                    Logger.DebugFormat("Exception caught when handling a websocket connection: {0}", ex);
                    throw;
                }
            }
        }
Пример #27
0
        // As server
        internal WebSocket(HttpListenerWebSocketContext context, Logger logger)
        {
            _context = context;
              _logger = logger;

              _closeContext = context.Close;
              _secure = context.IsSecureConnection;
              _stream = context.Stream;
              _uri = context.Path.ToUri ();

              init ();
        }
Пример #28
0
        public void Start(string url)
        {
            if (!url.EndsWith("/"))
            {
                url += "/";
            }

            ServiceEventSource.Current.Message("Starting web socket listener on " + url);

            this.httpListener = new HttpListener();
            this.httpListener.Prefixes.Add(url);
            this.httpListener.Start();

            Task.Run(
                async() =>
            {
                CancellationToken cancellationToken = this.cancellationSource.Token;

                // This loop continuously listens for incoming client connections
                // as you might normally do with a web socket server.
                while (true)
                {
                    ServiceEventSource.Current.Message("Waiting for connection..");

                    cancellationToken.ThrowIfCancellationRequested();

                    HttpListenerContext context = await this.httpListener.GetContextAsync();

                    Task <Task> acceptTask = context.AcceptWebSocketAsync(null).ContinueWith(
                        async task =>
                    {
                        HttpListenerWebSocketContext websocketContext = task.Result;

                        ServiceEventSource.Current.Message("Connection from " + websocketContext.Origin);

                        using (WebSocket browserSocket = websocketContext.WebSocket)
                        {
                            while (true)
                            {
                                cancellationToken.ThrowIfCancellationRequested();

                                string response = await this.visualObjectBox.GetObjectsAsync(cancellationToken);
                                byte[] buffer   = Encoding.UTF8.GetBytes(response);

                                try
                                {
                                    await
                                    browserSocket.SendAsync(
                                        new ArraySegment <byte>(buffer, 0, buffer.Length),
                                        WebSocketMessageType.Text,
                                        true,
                                        cancellationToken);

                                    if (browserSocket.State != WebSocketState.Open)
                                    {
                                        break;
                                    }
                                }
                                catch (WebSocketException ex)
                                {
                                    // If the browser quit or the socket was closed, exit this loop so we can get a new browser socket.
                                    ServiceEventSource.Current.Message(ex.InnerException != null ? ex.InnerException.Message : ex.Message);

                                    break;
                                }

                                // wait a bit and continue. This determines the client refresh rate.
                                await Task.Delay(TimeSpan.FromMilliseconds(5), cancellationToken);
                            }
                        }

                        ServiceEventSource.Current.Message("Client disconnected.");
                    },
                        TaskContinuationOptions.OnlyOnRanToCompletion);
                }
            },
                this.cancellationSource.Token);
        }
Пример #29
0
 internal WebSocket(HttpListenerWebSocketContext context)
     : this()
 {
     _stream = context.Stream;
       _closeContext = () => context.Close ();
       init (context);
 }
Пример #30
0
        private async Task <WebSocketClientTermination> AcceptAsync(
            HttpListenerWebSocketContext context,
            CapturedId capturedId,
            CapturedShutdownReason capturedShutdownReason,
            QbservableServiceOptions options,
            Func <IQbservableProtocol, IParameterizedQbservableProvider> providerFactory,
            CancellationToken cancel)
        {
            Contract.Requires(context != null);
            Contract.Requires(capturedId != null);
            Contract.Requires(capturedShutdownReason != null);
            Contract.Requires(options != null);
            Contract.Requires(providerFactory != null);

            ReceivingConnection(idOverride: capturedId.Value);

            prepareSocket(context.WebSocket);

            var watch = Stopwatch.StartNew();

            var exceptions     = new List <ExceptionDispatchInfo>();
            var shutdownReason = QbservableProtocolShutdownReason.None;

            try
            {
                using (var stream = new WebSocketStream(context.WebSocket))
                    using (var protocol = await NegotiateServerAsync(capturedId.Value, stream, formatterFactory(), options, cancel).ConfigureAwait(false))
                    {
                        capturedId.Value = protocol.ClientId;

                        var provider = providerFactory(protocol);

                        ReceivedConnection(idOverride: capturedId.Value);

                        try
                        {
                            await protocol.ExecuteServerAsync(provider).ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        {
                        }
                        catch (Exception ex)
                        {
                            exceptions.Add(ExceptionDispatchInfo.Capture(ex));
                        }
                        finally
                        {
                            shutdownReason = protocol.ShutdownReason;
                        }

                        var protocolExceptions = protocol.Exceptions;

                        if (protocolExceptions != null)
                        {
                            foreach (var exception in protocolExceptions)
                            {
                                exceptions.Add(exception);
                            }
                        }
                    }
            }
            catch (OperationCanceledException)
            {
                shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationCanceled;
            }
            catch (Exception ex)
            {
                shutdownReason = QbservableProtocolShutdownReason.ProtocolNegotiationError;

                exceptions.Add(ExceptionDispatchInfo.Capture(ex));
            }
            finally
            {
                capturedShutdownReason.Value = shutdownReason;
            }

            return(new WebSocketClientTermination(Uri, context.Origin, watch.Elapsed, shutdownReason, exceptions));
        }