Exemplo n.º 1
0
 /// <summary>
 /// Thread that reads messages from each websocket connect
 /// BIG TODO: process acknowledgements by using some sort of notification queue
 /// of outbound notifications
 /// </summary>
 /// <param name="sender">TODO: this needs to contain something that will identify the websocket
 /// in order to handle acknowledgements and take the notification off the queue.</param>
 /// <param name="e"></param>
 private async void webSocketReader_DoWork(object sender, DoWorkEventArgs e)
 {
     Log("Websocket reader starting...");
     while (true)
     {
         string socketData = null;
         try
         {
             socketData = await ReceiveStringAsync(_ws, CancellationToken.None);
         }
         catch (Exception ex)
         {
             System.Diagnostics.Debug.WriteLine(ex.ToString());
             Log("Exception occurred reading websocket:\r\n" + ex.Message);
         }
         if (string.IsNullOrEmpty(socketData))
         {
             if (_ws.State != WebSocketState.Open)
             {
                 Log("Websocket is closed - the reader is terminating...");
                 // dispose of the socket and remove the connection
                 ResetWebSocket();
                 // TODO: reset UI. Other cleanup?
                 break;
             }
             continue;
         }
         // it's either an acknowledgement or an event notification...
         // it's either an acknowledgement or an event notification...
         Notification notification = JsonConvert.DeserializeObject <Notification>(socketData);
         if (null != notification.Event)
         {
             Log($"Event notification received:\r\n{notification.Event}");
             // send success response to client
             WebSocketResponse wsResponse = new WebSocketResponse
             {
                 Timestamp  = DateTime.Now,
                 Status     = "OK",
                 StatusCode = 200
             };
             await SendStringAsync(_ws, wsResponse.ToString());
         }
         else if (null != notification.Status)
         {
             Log($"Acknowledgement response received:\r\n{notification.Status} ({notification.StatusCode})");
         }
         else
         {
             Log($"Unexpected websocket message received:\r\n{socketData}");
             WebSocketResponse wsResponse = new WebSocketResponse
             {
                 Timestamp  = DateTime.Now,
                 Status     = "FAIL",
                 StatusCode = 400
             };
             await SendStringAsync(_ws, wsResponse.ToString());
         }
     }
     Log("Websocket reader terminated.");
 }
Exemplo n.º 2
0
        public async static Task <WebSocketResponse> ProcessRequest(WebSocketRequest request, IMemoryCache memoryCache)
        {
            var bl       = new CacheBL(memoryCache, request.authorization, request.cacheKey, request.cacheLifespanSeconds);
            var response = new WebSocketResponse
            {
                cacheEntry      = null,
                responseCode    = "OK",
                responseMessage = ""
            };

            switch (request.method)
            {
            case "GET":
                response.cacheEntry = await bl.GetFromDictionary(request.autoPopulateEndpoint);

                break;

            case "POST":
                bl.PostToDictionary(request.values);
                break;

            case "DELETE":
                bl.DeleteFromDictionary();
                break;
            }

            return(response);
        }
        public WebSocketContext(WebSocketServer webSocketServer, ReqRespHandler<WebSocketRequest, WebSocketResponse> webSocketReqHandler)
        {
            this.webSocketReqHandler = webSocketReqHandler;
            this.webSocketServer = webSocketServer;
            connectionId = System.Threading.Interlocked.Increment(ref connectionIdTotal);
            //-------------------
            //send,resp 
            sockAsyncSender = new SocketAsyncEventArgs();
            sockAsyncSender.SetBuffer(new byte[RECV_BUFF_SIZE], 0, RECV_BUFF_SIZE); 
            sendIO = new SendIO(sockAsyncSender, 0, RECV_BUFF_SIZE, sendIO_SendCompleted);
            sockAsyncSender.Completed += new EventHandler<SocketAsyncEventArgs>((s, e) =>
            {
                switch (e.LastOperation)
                {
                    default:
                        {
                        }
                        break;
                    case SocketAsyncOperation.Send:
                        {
                            sendIO.ProcessWaitingData();
                        }
                        break;
                    case SocketAsyncOperation.Receive:
                        {
                        }
                        break;
                }
            });
            webSocketResp = new WebSocketResponse(this, sendIO);

            //------------------------------------------------------------------------------------
            //recv,req ,new socket
            sockAsyncListener = new SocketAsyncEventArgs();
            sockAsyncListener.SetBuffer(new byte[RECV_BUFF_SIZE], 0, RECV_BUFF_SIZE);
            recvIO = new RecvIO(sockAsyncListener, 0, RECV_BUFF_SIZE, HandleReceivedData);
            sockAsyncListener.Completed += new EventHandler<SocketAsyncEventArgs>((s, e) =>
            {
                switch (e.LastOperation)
                {
                    default:
                        {
                        }
                        break;
                    case SocketAsyncOperation.Send:
                        {
                        }
                        break;
                    case SocketAsyncOperation.Receive:
                        {
                            recvIO.ProcessReceivedData();
                        }
                        break;
                }
            });
            //------------------------------------------------------------------------------------             
            this.webSocketReqParser = new WebSocketProtocolParser(recvIO);

        }
Exemplo n.º 4
0
        private void WebSocket_OnMessage(object sender, MessageEventArgs e)
        {
            if (e.Data.IsNullOrWhiteSpace())
            {
                return;
            }
            WebSocketResponse <MarketDiffUpdate> result = JsonConvert.DeserializeObject <WebSocketResponse <MarketDiffUpdate> >(e.Data);

            this.OnMarketDiffUpdate?.Invoke(this, result.Data);
        }
Exemplo n.º 5
0
        protected override void OnNewSessionConnected(SuperWebSocket.WebSocketSession session)
        {
            var response = new WebSocketResponse();
            response.RemoteHandler = string.Format(@"appendMsg('{0}')","有新用户进入!");
            string json = new JavaScriptSerializer().Serialize(response);

            foreach (var s in Sessions)
            {
                s.Send(json);
            }
        }
Exemplo n.º 6
0
        protected override void OnSessionClosed(SuperWebSocket.WebSocketSession session,SuperSocket.SocketBase.CloseReason value)
        {
            var response = new WebSocketResponse();
            response.RemoteHandler = string.Format(@"appendMsg('{0}')","用户退出!");
            string json = new JavaScriptSerializer().Serialize(response);

            foreach (var s in Sessions)
            {
                s.Send(json);
            }
        }
Exemplo n.º 7
0
        static void Main(string[] args)
        {
            string key = "--YOURKEYGOESHERE--";
            JavaScriptSerializer js     = new JavaScriptSerializer();
            PushbulletClient     Client = new PushbulletClient(key, TimeZoneInfo.Local);

            DateTime lastChecked = DateTime.Now;

            using (var ws = new WebSocket(string.Concat("wss://stream.pushbullet.com/websocket/", key)))
            {
                ws.OnMessage += (sender, e) =>
                {
                    WebSocketResponse response = js.Deserialize <WebSocketResponse>(e.Data);

                    switch (response.Type)
                    {
                    case "nop":
                        Console.WriteLine(string.Format("Updated {0}", DateTime.Now));
                        break;

                    case "tickle":
                        Console.WriteLine(string.Format("Tickle recieved on {0}. Go check it out.", DateTime.Now));
                        PushResponseFilter filter = new PushResponseFilter()
                        {
                            Active       = true,
                            ModifiedDate = lastChecked
                        };

                        var pushes = Client.GetPushes(filter);
                        foreach (var push in pushes.Pushes)
                        {
                            Console.WriteLine(push.Title);
                        }

                        lastChecked = DateTime.Now;
                        break;

                    case "push":
                        Console.WriteLine(string.Format("New push recieved on {0}.", DateTime.Now));
                        Console.WriteLine("Push Type: {0}", response.Push.Type);
                        Console.WriteLine("Response SubType: {0}", response.Subtype);
                        break;

                    default:
                        Console.WriteLine("new type that is not supported");
                        break;
                    }
                };
                ws.Connect();
                Console.ReadKey(true);
            }
        }
Exemplo n.º 8
0
        public override WebResponse OnPreprocess(Session session, WebSocketRequest request)
        {
            if (request.opcode != OpCode.Ping)
            {
                return(null);
            }

            var pong = new WebSocketResponse();

            pong.opcode  = OpCode.Pong;
            pong.content = request.content;
            return(pong);
        }
Exemplo n.º 9
0
        private void Ws_OnMessage(object sender, MessageEventArgs e)
        {
            if (this._HesDeadJim)
            {
                return;
            }
            JavaScriptSerializer js       = new JavaScriptSerializer();
            WebSocketResponse    response = js.Deserialize <WebSocketResponse>(e.Data);

            this.BeginInvoke(new Action(() => {
                this.HandleResponseMainThread(response);
            }));
        }
Exemplo n.º 10
0
        private void WebsocketRead(Task <WebSocketReceiveResult> task, WebSocket ws, ArraySegment <byte> buffer, List <byte[]> messageParts)
        {
            switch (task.Result.MessageType)
            {
            case WebSocketMessageType.Binary:
                ws.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Binary messages are not supported", CancellationTokenSource.Token);
                break;

            case WebSocketMessageType.Text:
                if (task.Result.EndOfMessage)
                {
                    string message;
                    if (messageParts == null)
                    {
                        message = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, task.Result.Count);
                    }
                    else
                    {
                        message = Encoding.UTF8.GetString(messageParts.SelectMany(a => a).Concat(buffer.Array.Skip(buffer.Offset).Take(task.Result.Count)).ToArray());
                    }
                    WebSocketRequest  req    = JsonConvert.DeserializeObject <WebSocketRequest>(message);
                    ApiClient         client = Clients.ContainsKey(req.ClientId) ? Clients[req.ClientId].Ping() : null;
                    WebSocketResponse res    = new WebSocketResponse()
                    {
                        Responses = new string[req.Tasks.Length]
                    };
                    for (int i = 0; i < req.Tasks.Length; ++i)
                    {
                        res.Responses[i] = Handle(req.Tasks[i].Url, req.Tasks[i].Request, client);
                    }
                    WebsocketSendPart(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(res)), 0, ws, buffer);
                }
                else
                {
                    if (messageParts == null)
                    {
                        messageParts = new List <byte[]>();
                    }
                    messageParts.Add(buffer.Array.Skip(buffer.Offset).Take(task.Result.Count).ToArray());
                    ws.ReceiveAsync(buffer, CancellationTokenSource.Token).ContinueWith(tsk => WebsocketRead(tsk, ws, buffer, messageParts));
                }
                break;

            case WebSocketMessageType.Close:
                ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client closed", CancellationTokenSource.Token);
                break;
            }
        }
Exemplo n.º 11
0
    protected async Task BroadcastToSelfClients(long userId, WebSocketResponse response)
    {
        foreach (var key in currentListeners.Keys.ToList())
        {
            WebsocketListenerData?listener;
            if (currentListeners.TryGetValue(key, out listener))
            {
                if (listener.userId != userId)
                {
                    continue;
                }

                await listener.sendQueue.SendAsync(response);
            }
        }
    }
Exemplo n.º 12
0
        private static void AssertResponseIsValid(WebSocketResponse response)
        {
            Assert.NotNull(response);
            Assert.True(response.Payload?.Message == null, response.Payload?.Message);
            Assert.True(response.Payload?.Errors == null || response.Payload?.Errors?.Count == 0, response.Payload?.Errors?[0].Message);

            var data = response.Payload?.Data;

            Assert.NotNull(data);

            Assert.True(data.Errors == null || data.Errors?.Count == 0, data.Errors?[0].Message);
            Assert.True(data.AddAction?.Message == null, data.AddAction?.Message);
            Assert.True(data.EditAction?.Message == null, data.EditAction?.Message);
            Assert.True(data.SubscribeAdventure?.Error.Message == null, data.SubscribeAdventure?.Error.Message);
            Assert.True(data.Adventure?.Error?.Message == null, data.Adventure?.Error?.Message);
        }
Exemplo n.º 13
0
        public override WebResponse OnPreprocess(Session session, WebSocketRequest request)
        {
            if (request.opcode != OpCode.Close)
            {
                return(null);
            }
            if (session.state != SessionState.Opened)
            {
                return(null);
            }

            var close = new WebSocketResponse();

            close.opcode  = OpCode.Close;
            close.content = request.content;

            throw new CloseSessionException(close);
        }
Exemplo n.º 14
0
        public async Task <GameTokenCode> GetGameTokenCode(string accessToken)
        {
            await _ws.ConnectAsync(accessToken);

            JwtSecurityToken jwt = new JwtSecurityToken(accessToken);

            await _ws.SendAsync(JsonConvert.SerializeObject(new WebSocketRequest {
                Id     = Guid.NewGuid().ToString(),
                Method = "getGameAccount",
                Params = new GetGameAccountParams {
                    MasterId = jwt.Subject,
                }
            }));

            string responseString1 = await _ws.RecieveAsync();

            GameAccount gameAccount = JsonConvert
                                      .DeserializeObject <WebSocketResponse <GameAccount[]> >(responseString1).Result[0];

            await _ws.SendAsync(JsonConvert.SerializeObject(new WebSocketRequest {
                Id     = Guid.NewGuid().ToString(),
                Method = "createGameTokenCode",
                Params = new CreateGameTokenCodeParams {
                    AccessToken             = accessToken,
                    IgnoreLicenseAcceptance = false,
                    Login    = gameAccount.Login,
                    MasterId = jwt.Subject
                }
            }));

            string responseString2 = await _ws.RecieveAsync();

            WebSocketResponse <GameTokenCode> response = JsonConvert
                                                         .DeserializeObject <WebSocketResponse <GameTokenCode> >(responseString2);

            await _ws.DisconnectAsync();

            if (response.Error == null)
            {
                return(response.Result);
            }

            throw new Exception(response.Error.Code);
        }
Exemplo n.º 15
0
    //This is VERY inefficient, like oh my goodness, but until it becomes a problem, this is how it'll be.
    //It's inefficient because each user does the status lookup and that's entirely unnecessary.
    protected async Task AlertUserlistUpdate(long contentId)
    {
        foreach (var key in currentListeners.Keys.ToList())
        {
            WebsocketListenerData?listener;
            if (currentListeners.TryGetValue(key, out listener))
            {
                var statuses = await GetUserStatusesAsync(listener.userId, contentId);

                //Note that the listener could be invalid here, but it's OK because after this, hopefully nothing will be
                //holding onto it or whatever.
                var response = new WebSocketResponse()
                {
                    type = "userlistupdate",
                    data = statuses
                };
                await listener.sendQueue.SendAsync(response);
            }
        }
    }
Exemplo n.º 16
0
    protected async Task ListenLoop(CancellationToken cancelToken, int lastId, BufferBlock <object> sendQueue, string token)
    {
        var      userId = ValidateToken(token);
        UserView user;

        if (userId == 0)
        {
            user = new UserView()
            {
                id = userId, super = false
            };
        }
        else
        {
            using (var search = services.dbFactory.CreateSearch())
            {
                user = await search.GetById <UserView>(RequestType.user, userId, true);
            }
        }

        while (!cancelToken.IsCancellationRequested)
        {
            //NOTE: the ReceiveObjectAsync throws an exception on close
            LiveData listenResult;

            listenResult = await eventQueue.ListenAsync(user, lastId, cancelToken);

            userId = ValidateToken(token); // Validate every time
            lastId = listenResult.lastId;

            var response = new WebSocketResponse()
            {
                type          = "live",
                data          = listenResult,
                requestUserId = userId
            };

            //At this point we're re-validated, so do whatever
            sendQueue.Post(response);
        }
    }
Exemplo n.º 17
0
        public void HandleWebSocket(WebSocketRequest req, WebSocketResponse resp)
        {
            if (req.OpCode == Opcode.Text)
            {
                string clientMsg = req.ReadAsString();

                if (clientMsg == null)
                {
                    resp.Write("");
                    return;
                }

                string serverMsg = null;
                if (clientMsg.StartsWith("LOOPBACK"))
                {
                    serverMsg = "from SERVER " + clientMsg;
                }
                else
                {
                    serverMsg = "server:" + (count++);
                }

                resp.Write(serverMsg);
#if DEBUG
                System.Diagnostics.Debug.WriteLine(serverMsg);
#endif
            }
            else if (req.OpCode == Opcode.Binary)
            {
                //this is binary data
                byte[] binaryData = req.ReadAsBinary();
#if DEBUG
                count++;
                string serverMsg = count + " binary_len" + binaryData.Length;
                System.Diagnostics.Debug.WriteLine(serverMsg);
                resp.Write(serverMsg);
#endif
            }
        }
Exemplo n.º 18
0
        public IActionResult TestSockets()
        {
            int requestCount                  = 1000;
            WebSocketResponse response        = null;
            Stopwatch         watch           = new Stopwatch();
            IPHostEntry       ipHostInfo      = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress         remoteIPAddress = ipHostInfo.AddressList[0];
            int remotePort = GlobalSettings.WebSocketPort;

            watch.Start();
            for (int i = 0; i < requestCount; i++)
            {
                response = SynchronousSocketClient.StartClient(new WebSocketRequest
                {
                    authorization = "Testing",
                    cacheKey      = "ComplexData",
                    method        = "GET"
                }, remoteIPAddress, remotePort);
            }
            watch.Stop();

            return(Ok($"{requestCount} requests done in {watch.ElapsedMilliseconds}ms {JsonSerializer.Serialize(response)}"));
        }
Exemplo n.º 19
0
        public async Task <JObject> Handle(WebSocketRequest <JObject> message, CancellationToken cancellationToken)
        {
            this.logger.LogJson(message);

            var response = new WebSocketResponse {
                Type = WebSocketResponseType.Reply
            };

            if (string.IsNullOrWhiteSpace(message.TypeName))
            {
                return(response.ToJObject());
            }

            var type = TypeExtensions.GetAppDomainType(message.TypeName);

            if (type.IsMediatorRequest())
            {
                var command = this.mapper.Map(message.Typed ?? new JObject(), typeof(JObject), type);
                response.Data = await this.mediator.Result(command).NoCapture();
            }

            this.logger.LogJson(response);
            return(response.ToJObject());
        }
        public bool ParseNegotiation(WebSocketResponse resp)
        {
            // Search for any returned neogitation offer
            var headerValues = resp.GetHeaderValues("Sec-WebSocket-Extensions");
            if (headerValues == null)
                return false;

            for (int i = 0; i < headerValues.Count; ++i)
            {
                // If found, tokenize it
                HeaderParser parser = new HeaderParser(headerValues[i]);

                for (int cv = 0; cv < parser.Values.Count; ++cv)
                {
                    HeaderValue value = parser.Values[i];

                    if (!string.IsNullOrEmpty(value.Key) && value.Key.StartsWith("permessage-deflate", StringComparison.OrdinalIgnoreCase))
                    {
                        HTTPManager.Logger.Information("PerMessageCompression", "Enabled with header: " + headerValues[i]);

                        HeaderValue option;
                        if (value.TryGetOption("client_no_context_takeover", out option))
                            this.ClientNoContextTakeover = true;

                        if (value.TryGetOption("server_no_context_takeover", out option))
                            this.ServerNoContextTakeover = true;

                        if (value.TryGetOption("client_max_window_bits", out option))
                            if (option.HasValue)
                            {
                                int windowBits;
                                if (int.TryParse(option.Value, out windowBits))
                                    this.ClientMaxWindowBits = windowBits;
                            }

                        if (value.TryGetOption("server_max_window_bits", out option))
                            if (option.HasValue)
                            {
                                int windowBits;
                                if (int.TryParse(option.Value, out windowBits))
                                    this.ServerMaxWindowBits = windowBits;
                            }

                        return true;
                    }
                }
            }

            return false;
        }
Exemplo n.º 21
0
 public void HandleWebSocket(WebSocketRequest req, WebSocketResponse resp)
 {
     resp.Write("server:" + (count++));
 }
Exemplo n.º 22
0
        private void WebSocket_OnMessage(object sender, MessageEventArgs e)
        {
            WebSocketResponse <KLineUpdate> result = JsonConvert.DeserializeObject <WebSocketResponse <KLineUpdate> >(e.Data);

            this.OnCandleStickUpdate?.Invoke(this, result.Data);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Webservice thread that reads messages from each websocket connect
        /// BIG TODO: process acknowledgements by using some sort of notification queue
        /// of outbound notifications.
        /// </summary>
        /// <param name="sender">TODO: this needs to contain something that will identify the websocket
        /// in order to handle acknowledgements and take the notification off the queue.</param>
        /// <param name="e"></param>
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            if (!context.WebSockets.IsWebSocketRequest)
            {
                await next(context);
            }
            else
            {
                string            path = context.Request.Path.Value;
                string[]          args = String.IsNullOrEmpty(path) ? null : path.TrimStart('/').Split('/');
                CancellationToken ct   = context.RequestAborted;
                WebSocket         ws   = null;
                if (null != args && args.Length == 1)
                {
                    // accept socket request
                    ws = await context.WebSockets.AcceptWebSocketAsync();

                    string topic = args[0];
                    this.logger.LogDebug($"Websocket connection requested; topic:{topic}.");
                    // validate topic, and get user name from the database configuration
                    //TODO
                    bool validated = true;
                    if (!validated)
                    {
                        this.logger.LogInformation("Topic not validated. Message rejected.");
                        WebSocketResponse response = new WebSocketResponse
                        {
                            Timestamp  = DateTime.Now,
                            Status     = "FAIL",
                            StatusCode = 400
                        };
                        await SendStringAsync(ws, response.ToString());
                    }
                    else
                    {
                        this.logger.LogInformation($"Accepted websocket request: Topic {topic}, IP: {context.Connection.RemoteIpAddress.ToString()}:{context.Connection.RemotePort}");
                        // store this websocket connection in our dictionary
                        this.connections.AddConnection(topic, ws);
                        // send success response to client
                        WebSocketResponse response = new WebSocketResponse
                        {
                            Timestamp  = DateTime.Now,
                            Status     = "OK",
                            StatusCode = 200
                        };
                        await SendStringAsync(ws, response.ToString());

                        // Loop here until the socket is disconnected - reading and handling
                        // each message sent by the client
                        while (true)
                        {
                            string socketData = null;
                            try
                            {
                                socketData = await ReceiveStringAsync(ws, ct);
                            }
                            catch (Exception ex)
                            {
                                this.logger.LogError($"Exception occurred reading from websocket:\r\n{ex.ToString()}");
                            }
                            if (string.IsNullOrEmpty(socketData))
                            {
                                if (ws.State != WebSocketState.Open)
                                {
                                    this.logger.LogError($"The websocket connection on port {context.Connection.RemotePort} is closed. Terminating this subscription...");
                                    break;
                                }
                                continue;
                            }
                            // it's either an acknowledgement or an event notification...
                            Notification notification = JsonConvert.DeserializeObject <Notification>(socketData);
                            if (null != notification.Event)
                            {
                                this.logger.LogInformation($"Event notification received:\r\n{notification.Event.ToString()}");
                                // send success response to client
                                WebSocketResponse wsResponse = new WebSocketResponse
                                {
                                    Timestamp  = DateTime.Now,
                                    Status     = "OK",
                                    StatusCode = 200
                                };
                                await SendStringAsync(ws, wsResponse.ToString());

                                // Forward notifications to Websocket connected subscribers
                                var subs = this.subscriptions.GetSubscriptions(notification.Event.Topic, notification.Event.HubEvent);
                                foreach (var sub in subs)
                                {
                                    await this.notifications.SendNotification(notification, sub);
                                }
                            }
                            else if (null != notification.Status)
                            {
                                this.logger.LogInformation($"Acknowledgement response received:\r\n{notification.Status} ({notification.StatusCode})");
                            }
                            else
                            {
                                this.logger.LogError($"Unexpected websocket message received:\r\n{response}");
                            }
                        }
                        await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct);

                        //TODO: remove subscription
                        ws.Dispose();
                    }
                }
                else
                {
                    await next(context);
                }
            }
        }
Exemplo n.º 24
0
        internal static void OnUpdate()
        {
            IsCallingCallbacks = true;
            try
            {
                for (int i = 0; i < ActiveConnections.Count; i++)
                {
                    HTTPConnection hTTPConnection = ActiveConnections[i];
                    switch (hTTPConnection.State)
                    {
                    case HTTPConnectionStates.Processing:
                        if (hTTPConnection.CurrentRequest.UseStreaming && hTTPConnection.CurrentRequest.Response != null && hTTPConnection.CurrentRequest.Response.HasStreamedFragments())
                        {
                            hTTPConnection.HandleCallback();
                        }
                        break;

                    case HTTPConnectionStates.Redirected:
                        SendRequest(hTTPConnection.CurrentRequest);
                        RecycleConnection(hTTPConnection);
                        break;

                    case HTTPConnectionStates.WaitForRecycle:
                        hTTPConnection.CurrentRequest.FinishStreaming();
                        hTTPConnection.HandleCallback();
                        RecycleConnection(hTTPConnection);
                        break;

                    case HTTPConnectionStates.Upgraded:
                        hTTPConnection.HandleCallback();
                        break;

                    case HTTPConnectionStates.WaitForProtocolShutdown:
                    {
                        WebSocketResponse webSocketResponse = hTTPConnection.CurrentRequest.Response as WebSocketResponse;
                        webSocketResponse.HandleEvents();
                        if (webSocketResponse.IsClosed)
                        {
                            hTTPConnection.HandleCallback();
                            hTTPConnection.Dispose();
                            RecycleConnection(hTTPConnection);
                        }
                        break;
                    }

                    case HTTPConnectionStates.Closed:
                        hTTPConnection.CurrentRequest.FinishStreaming();
                        hTTPConnection.HandleCallback();
                        RecycleConnection(hTTPConnection);
                        Connections[hTTPConnection.ServerAddress].Remove(hTTPConnection);
                        break;

                    case HTTPConnectionStates.Free:
                        if (hTTPConnection.IsRemovable)
                        {
                            hTTPConnection.Dispose();
                            Connections[hTTPConnection.ServerAddress].Remove(hTTPConnection);
                        }
                        break;
                    }
                }
            }
            finally
            {
                IsCallingCallbacks = false;
            }
            if (RecycledConnections.Count > 0)
            {
                for (int j = 0; j < RecycledConnections.Count; j++)
                {
                    if (RecycledConnections[j].IsFree)
                    {
                        ActiveConnections.Remove(RecycledConnections[j]);
                    }
                }
                RecycledConnections.Clear();
            }
            if (RequestQueue.Count > 0)
            {
                HTTPRequest[] array = RequestQueue.ToArray();
                RequestQueue.Clear();
                for (int k = 0; k < array.Length; k++)
                {
                    SendRequest(array[k]);
                }
            }
        }
Exemplo n.º 25
0
    protected async Task ReceiveLoop(CancellationToken cancelToken, WebSocket socket, BufferBlock <object> sendQueue, string token)
    {
        using var memStream = new MemoryStream();

        while (!cancelToken.IsCancellationRequested)
        {
            //NOTE: the ReceiveObjectAsync throws an exception on close
            var receiveItem = await socket.ReceiveObjectAsync <WebSocketRequest>(memStream, cancelToken);

            var userId = ValidateToken(token); // Validate every time
            services.logger.LogDebug($"WS request '{receiveItem.id}'({receiveItem.type}) from {userId}");
            var response = new WebSocketResponse()
            {
                id            = receiveItem.id,
                type          = receiveItem.type,
                requestUserId = userId
            };

            if (receiveItem.type == "ping")
            {
                response.data = new {
                    serverTime = DateTime.UtcNow
                };
            }
            else if (receiveItem.type == "selfbroadcast")
            {
                response.data = receiveItem.data;

                await BroadcastToSelfClients(userId, response);

                //This skips the sending of the response, because in a broadcast, you'll receive it anyway
                continue;
            }
            else if (receiveItem.type == "userlist")
            {
                response.data = await GetUserStatusesAsync(userId);
            }
            else if (receiveItem.type == "setuserstatus")
            {
                try
                {
                    if (receiveItem.data == null)
                    {
                        throw new RequestException("Must set data to a dictionary of contentId:status");
                    }

                    var statuses = (((JObject)receiveItem.data).ToObject <Dictionary <string, string> >() ?? throw new RequestException("Couldn't parse sent userlist!"))
                                   .ToDictionary(x => long.Parse(x.Key), y => y.Value);//(Dictionary<long, string>)receiveItem.data;

                    //TODO: this will need to do some magic to send the userlist to everyone. I suppose if I
                    //had a list of all waiters and their send queues.... hmmmm that would actually just work.
                    foreach (var status in statuses)
                    {
                        await AddUserStatusAsync(userId, status.Key, status.Value);
                    }
                }
                catch (Exception ex)
                {
                    if (!(ex is RequestException))
                    {
                        services.logger.LogWarning($"Error when user {userId} set statuses to {receiveItem.data}: {ex}");
                    }
                    response.error = $"Error while setting statuses: {ex.Message}";
                }
            }
            else if (receiveItem.type == "request")
            {
                try
                {
                    if (receiveItem.data == null)
                    {
                        throw new RequestException("Must provide search criteria for request!");
                    }

                    var searchRequest = ((JObject)receiveItem.data).ToObject <SearchRequests>() ??
                                        throw new RequestException("Couldn't parse search criteria!");

                    using (var search = services.dbFactory.CreateSearch())
                    {
                        var searchResult = await search.Search(searchRequest, userId);

                        response.data = searchResult;
                    }
                }
                catch (Exception ex)
                {
                    response.error = $"Error during search: {ex.Message}";
                }
            }
            else if (receiveItem.type == "write")
            {
                try
                {
                    if (receiveItem.data == null)
                    {
                        throw new RequestException("Must provide write item for request!");
                    }

                    var writeData = ((JObject)receiveItem.data).ToObject <WebsocketWriteData>() ??
                                    throw new RequestException("Couldn't parse write data! Must provide type, etc");

                    var writeObject = writeData.@object ?? throw new RequestException("Couldn't parse 'object' before type is known!"); //((JObject)writeData.@object);
                    var type        = writeData.type;

                    //This sucks. Wonder if I can make it better
                    if (type == nameof(RequestType.message))
                    {
                        response.data = await WriteAsync(writeObject.ToObject <MessageView>() ?? throw new RequestException($"Couldn't parse {type}!"), userId, writeData.activityMessage);
                    }
                    else if (type == nameof(RequestType.content))
                    {
                        response.data = await WriteAsync(writeObject.ToObject <ContentView>() ?? throw new RequestException($"Couldn't parse {type}!"), userId, writeData.activityMessage);
                    }
                    else if (type == nameof(RequestType.user))
                    {
                        response.data = await WriteAsync(writeObject.ToObject <UserView>() ?? throw new RequestException($"Couldn't parse {type}!"), userId, writeData.activityMessage);
                    }
                    else if (type == nameof(RequestType.uservariable))
                    {
                        response.data = await WriteAsync(writeObject.ToObject <UserVariableView>() ?? throw new RequestException($"Couldn't parse {type}!"), userId, writeData.activityMessage);
                    }
                    else if (type == nameof(RequestType.watch))
                    {
                        response.data = await WriteAsync(writeObject.ToObject <WatchView>() ?? throw new RequestException($"Couldn't parse {type}!"), userId, writeData.activityMessage);
                    }
                    else if (type == nameof(RequestType.vote))
                    {
                        response.data = await WriteAsync(writeObject.ToObject <VoteView>() ?? throw new RequestException($"Couldn't parse {type}!"), userId, writeData.activityMessage);
                    }
                    else if (type == nameof(RequestType.ban))
                    {
                        response.data = await WriteAsync(writeObject.ToObject <BanView>() ?? throw new RequestException($"Couldn't parse {type}!"), userId, writeData.activityMessage);
                    }
                    else
                    {
                        throw new RequestException($"Unknown write type {type}");
                    }
                }
                catch (Exception ex)
                {
                    response.error = $"{ex.GetType().Name}: {ex.Message}";
                }
            }
            else
            {
                response.error = $"Unknown request type {receiveItem.type}";
            }

            sendQueue.Post(response);
        }
    }
Exemplo n.º 26
0
    public async Task <ActionResult <string> > WebSocketListenAsync([FromQuery] string token, [FromQuery] int?lastId = null)
    {
        try
        {
            services.logger.LogDebug($"ws METHOD: {HttpContext.Request.Method}, HEADERS: " +
                                     JsonConvert.SerializeObject(HttpContext.Request.Headers,
                                                                 Formatting.None, new JsonSerializerSettings()
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            }));

            if (!HttpContext.WebSockets.IsWebSocketRequest)
            {
                return(BadRequest("You must send a websocket request to this endpoint!"));
            }

            //None of these will throw exceptions that we can match anyway, so they'll bubble up accordingly...
            //well that might not be entirely true if we're returning 500 errors specifically but... change it if you need.
            using var cancelSource = new CancellationTokenSource();
            using var dualCancel   = CancellationTokenSource.CreateLinkedTokenSource(cancelSource.Token, appLifetime.ApplicationStopping, appLifetime.ApplicationStopped);
            var         sendQueue    = new BufferBlock <object>();
            List <Task> runningTasks = new List <Task>();
            long        userId       = 0;
            int         realLastId   = lastId == null?eventQueue.GetCurrentLastId() : lastId.Value;

            using var socket = await HttpContext.WebSockets.AcceptWebSocketAsync(acceptContextGenerator ());

            try
            {
                //ALWAYS add the sendloop first so we can process outgoing messages
                runningTasks.Add(SendLoop(dualCancel.Token, socket, sendQueue));

                //You want to keep this validation token thing inside the main exception handler, as ANY of the
                //below tasks could throw the token validation exception!
                userId = ValidateToken(token);
                services.logger.LogInformation($"Websocket started for user {userId}");

                //ALWAYS send the lastId message, it's basically our "this is the websocket and you're connected"
                var response = new WebSocketResponse()
                {
                    type          = "lastId",
                    data          = realLastId,
                    requestUserId = userId
                };

                sendQueue.Post(response);

                if (!currentListeners.TryAdd(trackerId, new WebsocketListenerData()
                {
                    userId = userId, sendQueue = sendQueue
                }))
                {
                    throw new InvalidOperationException("INTERNAL ERROR: couldn't add you to the listener array!");
                }

                //Can send and receive at the same time, but CAN'T send/receive multiple at the same time.
                runningTasks.Add(ReceiveLoop(dualCancel.Token, socket, sendQueue, token));
                runningTasks.Add(ListenLoop(dualCancel.Token, realLastId, sendQueue, token));

                var completedTask = await Task.WhenAny(runningTasks);

                runningTasks.Remove(completedTask);
                await completedTask; //To throw the exception, if there is one
            }
            catch (OperationCanceledException ex)
            {
                services.logger.LogDebug($"Websocket was cancelled by system, we're probably shutting down: {ex.Message}");

                // ALL should output an operation cancel exception but
                // I'm ASSUMING that this will specifically not exit until they're ALL done...
                try { await Task.WhenAll(runningTasks); }
                catch (OperationCanceledException) { } //Fine
                catch (Exception exi) { services.logger.LogError($"CRITICAL: EXCEPTION THROWN FROM CANCELED WEBSOCKET WAS UNEXPECTED TYPE: {exi}"); }
                finally { runningTasks.Clear(); }
            }
            catch (TokenException ex)
            {
                //Note: it is OK to use sendQueue even if the sender loop isn't started, because we dump the
                //remaining queue anyway in the finalizer
                services.logger.LogError($"Token exception in websocket: {ex}");
                sendQueue.Post(new WebSocketResponse()
                {
                    type = "badtoken", error = ex.Message
                });
            }
            catch (data.ClosedException ex)
            {
                services.logger.LogDebug($"User {userId} closed websocket on their end, this is normal: {ex.Message}");
            }
            //ALl other unhandled exceptions
            catch (Exception ex)
            {
                services.logger.LogError("Unhandled exception in websocket: " + ex.ToString());
                sendQueue.Post(new WebSocketResponse()
                {
                    type = "unexpected", error = $"Unhandled exception: {ex}"
                });
            }
            finally
            {
                if (runningTasks.Count > 0)
                {
                    //Cause the cancel source to close naturally after 2 seconds, giving us enough time to send
                    //out remaining messages, but also allowing us to close immediately if everything was already completed
                    //(because we wait on the tasks themselves, which could complete earlier than the cancel)
                    cancelSource.CancelAfter(2000);

                    try { await Task.WhenAll(runningTasks); }
                    catch (ClosedException ex) { services.logger.LogDebug($"Client closed connection manually, this is normal!: {ex.Message}"); }
                    catch (OperationCanceledException ex) { services.logger.LogDebug($"Websocket task cancelled, this is normal: {ex.Message}"); }
                    catch (Exception ex) { services.logger.LogError($"WEBSOCKET CRITICAL: UNHANDLED EXCEPTION DURING CANCEL: {ex}"); }
                }

                if (currentListeners.ContainsKey(trackerId) && !currentListeners.TryRemove(trackerId, out _))
                {
                    services.logger.LogDebug($"Couldn't remove listener {trackerId}, this could be a serious error!");
                }

                //This won't catch errors in every case but do it anyway
                if (socket.State == WebSocketState.Open)
                {
                    await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Force closing due to end of task", dualCancel.Token);
                }
            }

            //Just return an empty result if we get all the way to the end. This shouldn't happen but...
            return(new EmptyResult());
        }
        finally
        {
            //This is SO IMPORTANT that I want to do it way out here!
            await RemoveStatusesByTrackerAsync();
        }
    }
Exemplo n.º 27
0
        public static void OnUpdate()
        {
            object locker = HTTPManager.Locker;

            lock (locker)
            {
                HTTPManager.IsCallingCallbacks = true;
                try
                {
                    for (int i = 0; i < HTTPManager.ActiveConnections.Count; i++)
                    {
                        HTTPConnection hTTPConnection = HTTPManager.ActiveConnections[i];
                        switch (hTTPConnection.State)
                        {
                        case HTTPConnectionStates.Processing:
                            hTTPConnection.HandleProgressCallback();
                            if (hTTPConnection.CurrentRequest.UseStreaming && hTTPConnection.CurrentRequest.Response != null && hTTPConnection.CurrentRequest.Response.HasStreamedFragments())
                            {
                                hTTPConnection.HandleCallback();
                            }
                            if (((!hTTPConnection.CurrentRequest.UseStreaming && hTTPConnection.CurrentRequest.UploadStream == null) || hTTPConnection.CurrentRequest.EnableTimoutForStreaming) && DateTime.UtcNow - hTTPConnection.StartTime > hTTPConnection.CurrentRequest.Timeout)
                            {
                                hTTPConnection.Abort(HTTPConnectionStates.TimedOut);
                            }
                            break;

                        case HTTPConnectionStates.Redirected:
                            HTTPManager.SendRequest(hTTPConnection.CurrentRequest);
                            HTTPManager.RecycleConnection(hTTPConnection);
                            break;

                        case HTTPConnectionStates.Upgraded:
                            hTTPConnection.HandleCallback();
                            break;

                        case HTTPConnectionStates.WaitForProtocolShutdown:
                        {
                            WebSocketResponse webSocketResponse = hTTPConnection.CurrentRequest.Response as WebSocketResponse;
                            if (webSocketResponse != null)
                            {
                                webSocketResponse.HandleEvents();
                            }
                            if (webSocketResponse == null || webSocketResponse.IsClosed)
                            {
                                hTTPConnection.HandleCallback();
                                hTTPConnection.Dispose();
                                HTTPManager.RecycleConnection(hTTPConnection);
                            }
                            break;
                        }

                        case HTTPConnectionStates.WaitForRecycle:
                            hTTPConnection.CurrentRequest.FinishStreaming();
                            hTTPConnection.HandleCallback();
                            HTTPManager.RecycleConnection(hTTPConnection);
                            break;

                        case HTTPConnectionStates.AbortRequested:
                        {
                            WebSocketResponse webSocketResponse = hTTPConnection.CurrentRequest.Response as WebSocketResponse;
                            if (webSocketResponse != null)
                            {
                                webSocketResponse.HandleEvents();
                                if (webSocketResponse.IsClosed)
                                {
                                    hTTPConnection.HandleCallback();
                                    hTTPConnection.Dispose();
                                    HTTPManager.RecycleConnection(hTTPConnection);
                                }
                            }
                            break;
                        }

                        case HTTPConnectionStates.TimedOut:
                            if (DateTime.UtcNow - hTTPConnection.TimedOutStart > TimeSpan.FromMilliseconds(500.0))
                            {
                                HTTPManager.Logger.Information("HTTPManager", "Hard aborting connection becouse of a long waiting TimedOut state");
                                hTTPConnection.CurrentRequest.Response = null;
                                hTTPConnection.CurrentRequest.State    = HTTPRequestStates.TimedOut;
                                hTTPConnection.HandleCallback();
                                HTTPManager.RecycleConnection(hTTPConnection);
                            }
                            break;

                        case HTTPConnectionStates.Closed:
                            hTTPConnection.CurrentRequest.FinishStreaming();
                            hTTPConnection.HandleCallback();
                            HTTPManager.RecycleConnection(hTTPConnection);
                            break;
                        }
                    }
                }
                finally
                {
                    HTTPManager.IsCallingCallbacks = false;
                }
                if (HTTPManager.RecycledConnections.Count > 0)
                {
                    for (int j = 0; j < HTTPManager.RecycledConnections.Count; j++)
                    {
                        HTTPConnection hTTPConnection2 = HTTPManager.RecycledConnections[j];
                        if (hTTPConnection2.IsFree)
                        {
                            HTTPManager.ActiveConnections.Remove(hTTPConnection2);
                            HTTPManager.FreeConnections.Add(hTTPConnection2);
                        }
                    }
                    HTTPManager.RecycledConnections.Clear();
                }
                if (HTTPManager.FreeConnections.Count > 0)
                {
                    for (int k = 0; k < HTTPManager.FreeConnections.Count; k++)
                    {
                        HTTPConnection hTTPConnection3 = HTTPManager.FreeConnections[k];
                        if (hTTPConnection3.IsRemovable)
                        {
                            List <HTTPConnection> list = null;
                            if (HTTPManager.Connections.TryGetValue(hTTPConnection3.ServerAddress, out list))
                            {
                                list.Remove(hTTPConnection3);
                            }
                            hTTPConnection3.Dispose();
                            HTTPManager.FreeConnections.RemoveAt(k);
                            k--;
                        }
                    }
                }
                if (HTTPManager.CanProcessFromQueue())
                {
                    if (HTTPManager.RequestQueue.Find((HTTPRequest req) => req.Priority != 0) != null)
                    {
                        HTTPManager.RequestQueue.Sort((HTTPRequest req1, HTTPRequest req2) => req1.Priority - req2.Priority);
                    }
                    HTTPRequest[] array = HTTPManager.RequestQueue.ToArray();
                    HTTPManager.RequestQueue.Clear();
                    for (int l = 0; l < array.Length; l++)
                    {
                        HTTPManager.SendRequest(array[l]);
                    }
                }
            }
            if (HTTPManager.heartbeats != null)
            {
                HTTPManager.heartbeats.Update();
            }
        }
Exemplo n.º 28
0
        public bool ParseNegotiation(WebSocketResponse resp)
        {
            // Search for any returned neogitation offer
            var headerValues = resp.GetHeaderValues("Sec-WebSocket-Extensions");

            if (headerValues == null)
            {
                return(false);
            }

            for (int i = 0; i < headerValues.Count; ++i)
            {
                // If found, tokenize it
                HeaderParser parser = new HeaderParser(headerValues[i]);

                for (int cv = 0; cv < parser.Values.Count; ++cv)
                {
                    HeaderValue value = parser.Values[i];

                    if (!string.IsNullOrEmpty(value.Key) && value.Key.StartsWith("permessage-deflate", StringComparison.OrdinalIgnoreCase))
                    {
                        HTTPManager.Logger.Information("PerMessageCompression", "Enabled with header: " + headerValues[i]);

                        HeaderValue option;
                        if (value.TryGetOption("client_no_context_takeover", out option))
                        {
                            this.ClientNoContextTakeover = true;
                        }

                        if (value.TryGetOption("server_no_context_takeover", out option))
                        {
                            this.ServerNoContextTakeover = true;
                        }

                        if (value.TryGetOption("client_max_window_bits", out option))
                        {
                            if (option.HasValue)
                            {
                                int windowBits;
                                if (int.TryParse(option.Value, out windowBits))
                                {
                                    this.ClientMaxWindowBits = windowBits;
                                }
                            }
                        }

                        if (value.TryGetOption("server_max_window_bits", out option))
                        {
                            if (option.HasValue)
                            {
                                int windowBits;
                                if (int.TryParse(option.Value, out windowBits))
                                {
                                    this.ServerMaxWindowBits = windowBits;
                                }
                            }
                        }

                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 29
0
 private static void Websocket_OnWebsocketUpdated(WebSocketResponse response, string raw)
 {
 }
Exemplo n.º 30
0
 public void HandleWebSocket(WebSocketRequest req, WebSocketResponse resp)
 {
     resp.Write("server:" + (count++));
 }
Exemplo n.º 31
0
 public WebSocketResponse Analyze(WebSocketRequest request,WebSocketResponse response)
 {
     response.Data = request.Body;
     return response;
 }
Exemplo n.º 32
0
        public void HandleResponseMainThread(WebSocketResponse response)
        {
            switch (response.Type)
            {
            // Heartbeat
            case "nop":
                Logger.WriteLine("PushBullet Heartbeat");
                if (!this.hasHiddenOnStartup)
                {
                    this.hasHiddenOnStartup = true;
                    this.Hide();
                    Logger.WriteLine("Saving access token to: " + Path.Combine(TextSettings.Folder, fileName));
                    TextSettings.Save(fileName, this.Client.AccessToken);
                }
                break;

            case "tickle":
                PushResponseFilter filter = new PushResponseFilter()
                {
                    Active       = true,
                    ModifiedDate = lastChecked
                };

                var pushes = Client.GetPushes(filter);
                foreach (var push in pushes.Pushes)
                {
                    if ((push.Created - lastChecked).TotalDays > 0)
                    {
                        lastChecked = push.Created;

                        using (Logger.Time("Processing Request"))
                        {
                            for (int i = 0; i < 3; i++)     // 3 attempts.
                            {
                                using (Logger.Time("Attempt " + i))
                                {
                                    try
                                    {
                                        this._RequestHandler.NewNotification(push.Title, push.Body);
                                        break;
                                    }
                                    catch (Exception exc)
                                    {
                                        Logger.WriteException(this, "FindBestMatchAndPlay", exc);
                                        System.Threading.Thread.Sleep(500);     // Give itunes a breath.
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        Logger.WriteLine("Ignoring Old PushBullet: " + push.Title);
                    }
                }
                break;

            case "push":
                Logger.WriteLine(string.Format("New push recieved on {0}.", DateTime.Now));
                Logger.WriteLine("Push Type: " + response.Push.Type);
                Logger.WriteLine("Response SubType: " + response.Subtype);
                break;

            default:
                Logger.WriteLine("PushBullet type not supported!");
                break;
            }
        }