Esempio n. 1
0
        public static void OnReceiveAsync(HttpContext context, WebSocket webSocket, WebSocketReceiveResult?wsResult, string bufferStr)
        {
            DashboardClient?client = null;

            lock (DashboardClient.g_clients)    // find client from the same IP, assuming connection in the last 1000ms
            {
                client = DashboardClient.g_clients.Find(r => r.WsWebSocket == webSocket);
            }
            if (client != null)
            {
                var    semicolonInd = bufferStr.IndexOf(':');
                string msgCode      = bufferStr.Substring(0, semicolonInd);
                string msgObjStr    = bufferStr.Substring(semicolonInd + 1);

                bool isHandled = client.OnReceiveWsAsync_MktHealth(wsResult, msgCode, msgObjStr);
                if (!isHandled)
                {
                    isHandled = client.OnReceiveWsAsync_BrAccViewer(wsResult, msgCode, msgObjStr);
                }
                if (!isHandled)
                {
                    isHandled = client.OnReceiveWsAsync_QckflNews(wsResult, msgCode, msgObjStr);
                }
                if (!isHandled)
                {
                    // throw new Exception($"Unexpected websocket received msgCode '{msgCode}'");
                    Utils.Logger.Error($"Unexpected websocket received msgCode '{msgCode}'");
                }
            }
        }
        public bool OnReceiveWsAsync_BrAccViewer(WebSocketReceiveResult?wsResult, string msgCode, string msgObjStr)
        {
            switch (msgCode)
            {
            case "BrAccViewer.ChangeLookback":
                Utils.Logger.Info("OnReceiveWsAsync_BrAccViewer(): changeLookback");
                // m_lastLookbackPeriodStr = msgObjStr;
                // SendHistoricalWs();
                return(true);

            case "BrAccViewer.ChangeNav":
                Utils.Logger.Info($"OnReceiveWsAsync_BrAccViewer(): changeNav to '{msgObjStr}'"); // DC.IM
                string sqTicker = "N/" + msgObjStr;                                               // turn DC.IM to N/DC.IM
                m_braccSelectedNavAsset = MemDb.gMemDb.AssetsCache.GetAsset(sqTicker) as BrokerNav;
                BrAccViewerSendSnapshotAndHist();
                // var navAsset = MemDb.gMemDb.AssetsCache.GetAsset(sqTicker);
                // RtMktSummaryStock? navStock = m_mktSummaryStocks.FirstOrDefault(r => r.SqTicker == g_brNavVirtualTicker);
                // if (navStock != null)
                //     navStock.AssetId = navAsset!.AssetId;

                // SendHistoricalWs();
                // SendRealtimeWs();
                return(true);

            default:
                return(false);
            }
        }
Esempio n. 3
0
        public static void OnReceiveAsync(HttpContext context, WebSocket webSocket, WebSocketReceiveResult?wsResult, string bufferStr)
        {
            var    semicolonInd = bufferStr.IndexOf(':');
            string msgCode      = bufferStr.Substring(0, semicolonInd);
            string msgObjStr    = bufferStr.Substring(semicolonInd + 1);

            if (msgCode == "startStreamingCode")
            {
                _ = Task.Run(async() =>  // do CPU-bound work on a ThreadPool background thread.  '_' is a discard variable in C# 7.0
                {
                    for (int i = 0; i < 15; i++)
                    {
                        string msg     = "priceQuoteFromServerCode:" + "TSLA price is: $" + (new Random().NextDouble() * 1000.0).ToString("0.00");
                        var encodedMsg = Encoding.UTF8.GetBytes(msg);
                        if (webSocket !.State == WebSocketState.Open)
                        {
                            await webSocket.SendAsync(new ArraySegment <Byte>(encodedMsg, 0, encodedMsg.Length), WebSocketMessageType.Text, true, CancellationToken.None);
                        }

                        Thread.Sleep(2000);
                    }
                });
            }
            else
            {
                string msg        = "msgCode1:" + $"simple messageReceived:'{bufferStr}'";
                byte[] encodedMsg = Encoding.UTF8.GetBytes(msg);
                if (webSocket !.State == WebSocketState.Open)
                {
                    webSocket.SendAsync(new ArraySegment <Byte>(encodedMsg, 0, encodedMsg.Length), WebSocketMessageType.Text, true, CancellationToken.None);
                }
            }
        }
Esempio n. 4
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, AppDbContext appDbContext)
        {
            appDbContext.Database.EnsureCreated();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseWebSockets(new WebSocketOptions
            {
                ReceiveBufferSize = 4 * 1024
            });
            app.Use(async(context, next) =>
            {
                // 如果Request為WebSocket且路徑爲/watchDog
                if (context.WebSockets.IsWebSocketRequest && context.Request.Path == "/watchDog")
                {
                    // 容許WebSocket連線並取得WebSocket實例
                    var webSocket = await context.WebSockets.AcceptWebSocketAsync();
                    while (webSocket.State == WebSocketState.Open)
                    {
                        WebSocketReceiveResult?receivedData = null;
                        // 接收一次訊息中的所有段落
                        do
                        {
                            // 接收緩衝區
                            ArraySegment <byte> buffer = new ArraySegment <byte>(new byte[4 * 1024]);
                            // 接收
                            receivedData = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
                        } while (!receivedData.EndOfMessage); // 是否為最後的段落
                    }
                }
                else
                {
                    await next();
                }
            });

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
Esempio n. 5
0
 public bool OnReceiveWsAsync_QckflNews(WebSocketReceiveResult? wsResult, string msgCode, string msgObjStr)
 {
     switch (msgCode)
     {
         case "ReloadQuickfolio":
             Utils.Logger.Info("OnReceiveWsAsync_QckflNews(): ReloadQuickfolio");
             ReloadQuickfolioMsgArrived();
             return true;
         default:
             return false;
     }
 }
        public async Task ReceiveAsync(
            PipeWriter writer,
            CancellationToken cancellationToken)
        {
            WebSocket?webSocket = _webSocket;

            if (_disposed || webSocket == null)
            {
                return;
            }

            try
            {
                WebSocketReceiveResult?socketResult = null;
                do
                {
                    Memory <byte> memory  = writer.GetMemory(_maxMessageSize);
                    bool          success = MemoryMarshal.TryGetArray(memory, out ArraySegment <byte> buffer);

                    if (success)
                    {
                        try
                        {
                            socketResult = await webSocket.ReceiveAsync(buffer, cancellationToken);

                            if (socketResult.Count == 0)
                            {
                                break;
                            }

                            writer.Advance(socketResult.Count);
                        }
                        catch
                        {
                            break;
                        }

                        FlushResult result = await writer.FlushAsync(cancellationToken);

                        if (result.IsCompleted)
                        {
                            break;
                        }
                    }
                } while (socketResult == null || !socketResult.EndOfMessage);
            }
            catch (ObjectDisposedException)
            {
                // we will just stop receiving
            }
        }
        public async Task ReceiveAsync(
            PipeWriter writer,
            CancellationToken cancellationToken = default)
        {
            if (IsClosed)
            {
                return;
            }

            try
            {
                WebSocketReceiveResult?socketResult = null;
                do
                {
                    Memory <byte> memory = writer.GetMemory(_maxMessageSize);
                    if (MemoryMarshal.TryGetArray(memory, out ArraySegment <byte> buffer))
                    {
                        try
                        {
                            socketResult = await _socketClient.Socket
                                           .ReceiveAsync(buffer, cancellationToken)
                                           .ConfigureAwait(false);

                            if (socketResult.Count == 0)
                            {
                                break;
                            }

                            writer.Advance(socketResult.Count);
                        }
                        catch
                        {
                            break;
                        }

                        FlushResult result = await writer
                                             .FlushAsync(cancellationToken)
                                             .ConfigureAwait(false);

                        if (result.IsCompleted)
                        {
                            break;
                        }
                    }
                } while (socketResult == null || !socketResult.EndOfMessage);
            }
            catch (ObjectDisposedException)
            {
                // we will just stop receiving
            }
        }
Esempio n. 8
0
        public async Task HandleRequestAsync(HttpContext context, WebSocketHandler webSocketHandler)
        {
            if (!context.WebSockets.IsWebSocketRequest)
            {
                context.Response.StatusCode = 400;
            }

            var socket = await context.WebSockets.AcceptWebSocketAsync();

            var socketFinishedTcs = new TaskCompletionSource <object?>();

            var socketId = await webSocketHandler.AddConnectionAsync(socket, socketFinishedTcs, context.RequestAborted);

            WebSocketReceiveResult?result = null;

            _ = Task.Run(async() =>
            {
                while (socket.State == WebSocketState.Open)
                {
                    try
                    {
                        using var ms = new MemoryStream();
                        result       = await this.ReadMessageAsync(socket, ms, context.RequestAborted);

                        if (result.MessageType == WebSocketMessageType.Binary || result.MessageType == WebSocketMessageType.Text)
                        {
                            await webSocketHandler.ReceiveAsync(socketId, result, ms, context.RequestAborted);
                        }

                        else if (result.MessageType == WebSocketMessageType.Close)
                        {
                            await webSocketHandler.CloseConnectionAsync(socket, "Connection Closed");
                        }
                    }
                    catch (WebSocketException ex) when(ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)
                    {
                        await webSocketHandler.CloseConnectionAsync(socket, "Connection Closed Prematurely");
                        return;
                    }
                    catch (TaskCanceledException) when(socket.State == WebSocketState.Aborted)
                    {
                        await webSocketHandler.CloseConnectionAsync(socket, "WebSocket Aborted");
                        return;
                    }
                }
            });

            await socketFinishedTcs.Task;
        }
Esempio n. 9
0
    public static async Task ListenAsync(this WebSocket webSocket, HandleMessage onReceived, CancellationToken token)
    {
        WebSocketReceiveResult?result = null;

        do
        {
            var buffer = ArrayPool <byte> .Shared.Rent(Constants.MaxMessageSize);

            try
            {
                Array.Clear(buffer);
                result = await webSocket.ReceiveAsync(buffer, token);

                if (result.MessageType == WebSocketMessageType.Close)
                {
                    return;
                }
                if (!result.EndOfMessage)
                {
                    await webSocket.SendAckAsync(Ack.ExpectedEndOfMessage, token);
                }
Esempio n. 10
0
        public bool OnReceiveWsAsync_MktHealth(WebSocketReceiveResult?wsResult, string msgCode, string msgObjStr)
        {
            switch (msgCode)
            {
            case "MktHlth.ChangeLookback":
                Utils.Logger.Info("OnReceiveWsAsync_MktHealth(): changeLookback");
                m_lastLookbackPeriodStr = msgObjStr;
                SendHistoricalWs();
                return(true);

            case "MktHlth.ChangeNav":
                Utils.Logger.Info($"OnReceiveWsAsync_MktHealth(): changeNav to '{msgObjStr}'"); // DC.IM
                string sqTicker = "N/" + msgObjStr;                                             // turn DC.IM to N/DC.IM
                var    navAsset = MemDb.gMemDb.AssetsCache.GetAsset(sqTicker);
                this.m_mkthSelectedNavAsset = navAsset as BrokerNav;

                SendHistoricalWs();
                SendRealtimeWs();
                return(true);

            default:
                return(false);
            }
        }
Esempio n. 11
0
        // When using a WebSocket, you must keep this middleware pipeline running for the duration of the connection.
        // The code receives a message and immediately sends back the same message. Messages are sent and received in a loop until the client closes the connection.
        private async Task WebSocketLoopKeptAlive(HttpContext context, string p_requestRemainigPath)
        {
            WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();  // this accept immediately send back the client that connection is accepted.

            switch (p_requestRemainigPath)
            {
            case "/dashboard":
                await DashboardWs.OnConnectedAsync(context, webSocket);

                break;

            case "/example-ws1":      // client sets this URL: connectionUrl.value = scheme + "://" + document.location.hostname + port + "/ws/example-ws1" ;
                await ExampleWs.OnConnectedAsync(context, webSocket);

                break;

            case "/ExSvPush":
                await ExSvPushWs.OnConnectedAsync(context, webSocket);

                break;

            default:
                throw new Exception($"Unexpected websocket connection '{p_requestRemainigPath}' in WebSocketLoopKeptAlive()");
            }

            ArraySegment <Byte> buffer    = new ArraySegment <byte>(new Byte[8192]);
            string bufferStr              = string.Empty;
            WebSocketReceiveResult?result = null;

            // loop until the client closes the connection. The server receives a disconnect message only if the client sends it, which can't be done if the internet connection is lost.
            // If the client isn't always sending messages and you don't want to timeout just because the connection goes idle, have the client use a timer to send a ping message every X seconds.
            // On the server, if a message hasn't arrived within 2*X seconds after the previous one, terminate the connection and report that the client disconnected.
            while (webSocket.State == WebSocketState.Open && (result?.CloseStatus == null || !result.CloseStatus.HasValue))
            {
                try
                {
                    // convert binary array to string message: https://stackoverflow.com/questions/24450109/how-to-send-receive-messages-through-a-web-socket-on-windows-phone-8-using-the-c
                    bufferStr = string.Empty;
                    using (var ms = new MemoryStream())
                    {
                        do
                        {
                            result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);  // client can send CloseStatus = NormalClosure for initiating close

                            ms.Write(buffer.Array !, buffer.Offset, result.Count);
                        } while (!result.EndOfMessage);

                        ms.Seek(0, SeekOrigin.Begin);
                        using (var reader = new StreamReader(ms, Encoding.UTF8))
                            bufferStr = reader.ReadToEnd();
                    }
                    // gLogger.Trace($"WebSocketLoopKeptAlive(). received msg: '{bufferStr}'"); // logging takes 1ms

                    // if result.CloseStatus = NormalClosure message received, or any other fault, don't pass msg to listeners. We manage complexity in this class.
                    bool isGoodNonClientClosedConnection = webSocket.State == WebSocketState.Open && result != null && (result.CloseStatus == null || !result.CloseStatus.HasValue);
                    if (isGoodNonClientClosedConnection && result != null)
                    {
                        switch (p_requestRemainigPath)
                        {
                        case "/dashboard":
                            DashboardWs.OnReceiveAsync(context, webSocket, result, bufferStr);      // no await. There is no need to Wait until all of its async inner methods are completed
                            break;

                        case "/example-ws1":
                            ExampleWs.OnReceiveAsync(context, webSocket, result, bufferStr);
                            break;

                        case "/ExSvPush":
                            ExSvPushWs.OnReceiveAsync(context, webSocket, result, bufferStr);
                            break;

                        default:
                            throw new Exception($"Unexpected websocket connection '{p_requestRemainigPath}' in WebSocketLoopKeptAlive()");
                        }
                    }

                    // If Client never sent any proper data, and closes browser tabpage, ReceiveAsync() returns without Exception and result.CloseStatus = EndpointUnavailable
                    // If Client sent any proper data, and closes browser tabpage, ReceiveAsync() returns with Exception WebSocketError.ConnectionClosedPrematurely
                }
                catch (System.Net.WebSockets.WebSocketException e)
                {
                    if (e.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) // 'The remote party closed the WebSocket connection without completing the close handshake.'
                    {
                        gLogger.Trace($"WebSocketLoopKeptAlive(). Expected exception: '{e.Message}'");
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            if (result?.CloseStatus != null)    // if client sends Close request then result.CloseStatus = NormalClosure and websocket.State == CloseReceived. In that case, we just answer back that we are closing.
            {
                await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
            }
        }
Esempio n. 12
0
        internal static void OnReceiveAsync(HttpContext context, WebSocket webSocket, WebSocketReceiveResult?lastResult, string bufferStr)
        {
            // if it is not a Close-message from client, send it back temporarily
            var encoded = Encoding.UTF8.GetBytes(bufferStr);
            var buffer  = new ArraySegment <Byte>(encoded, 0, encoded.Length);

            webSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
        }
        protected async Task <string> ReceiveTillEnd(CancellationToken ct)
        {
            ArraySegment <Byte> buffer = new ArraySegment <byte>(new Byte[8192]);

            using (var ms = new MemoryStream())
            {
                WebSocketReceiveResult?result = null;
                do
                {
                    try
                    {
                        result = await wsAmiVoice.ReceiveAsync(buffer, CancellationToken.None);

                        ms.Write(buffer.ToArray(), 0, result.Count);
                        if (result.CloseStatus != null)
                        {
                            Debug.WriteLine(result.CloseStatusDescription);
                        }
                        if (result.MessageType == WebSocketMessageType.Close)
                        {
                            Debug.WriteLine("WebSocket Close Recieved");
                            break;
                        }
                        if (ct.IsCancellationRequested)
                        {
                            break;
                        }
                    }
                    catch (WebSocketException ex)
                    {
                        var errStr = String.Format("WebSocketError: {0} - {1}", ex.WebSocketErrorCode, ex.Message);
                        ErrorOccured?.Invoke(this, errStr);
                        Debug.WriteLine(ex.Message);
                        Debug.WriteLine(ex.StackTrace);
                        if (wsAmiVoice.CloseStatus != null)
                        {
                            Debug.WriteLine(wsAmiVoice.CloseStatusDescription);
                        }
                        Debug.WriteLine(ex.WebSocketErrorCode);

                        string temp;
                        try
                        {
                            temp = Encoding.UTF8.GetString(ms.ToArray());
                            Debug.WriteLine(temp);
                        }
                        catch (Exception encex) when(encex is ArgumentException || encex is ArgumentNullException)
                        {
                        }

                        return("");
                    }
                } while ((result == null || result.EndOfMessage != true) && (wsAmiVoice.State == WebSocketState.Open || wsAmiVoice.State == WebSocketState.CloseSent));

                var payload = ms.ToArray();
                try
                {
                    var encodedData = System.Text.Encoding.UTF8.GetString(payload);
                    Debug.WriteLine(encodedData);
                    return(encodedData);
                }
                catch (Exception ex) when(ex is ArgumentException || ex is ArgumentNullException || ex is DecoderFallbackException)
                {
                    return("");
                }
            }
        }