/// <summary> /// It will also put user into status 'Online' (means it's available to get messages via socket) if authorized /// and also updated last connection activity (for destroy connections it they was not active some time) /// </summary> /// <param name="client"></param> /// <param name="request"></param> /// <returns></returns> private bool CheckAuthorization(DuplexNetworkClient client, DuplexNetworkRequest request) { client.UpdateActivity(); var errMsg = string.Empty; if (client.User == null) //try to authorize if not yet { client.User = EnergoServer.Current.FindUserByAuthToken(request.AuthToken, out errMsg); } return(client.User != null); }
private async Task DirectResponse <T>(DuplexNetworkClient client, T response) { var message = ""; if (response is string) { message = response.ToString(); } else { response.ToJson(); } var data = message.GetByteSegment(); if (client.Connection.State == WebSocketState.Open) { await client.SendData(data); } }
/// <summary> /// It will expecting to recieve AuthToken as Json parameter from client to join it to network /// </summary> /// <param name="http"></param> /// <param name="next"></param> /// <returns></returns> public async Task HandleRequests(HttpContext http, Func <Task> next) { if (!http.WebSockets.IsWebSocketRequest) { await next(); return; } var webSocket = await http.WebSockets.AcceptWebSocketAsync(); if (webSocket != null && webSocket.State == WebSocketState.Open) { CloseUnactiveConnections(); var client = new DuplexNetworkClient(webSocket); _clients.Add(client); //todo: move this block to the separate method while (webSocket.State == WebSocketState.Open) { try { //todo buffer size means it will trunc or separate requests if they will exceed 4k? Need to handle this case? var buffer = new ArraySegment <byte>(new byte[4096]); var received = await webSocket.ReceiveAsync(buffer, CancellationToken.None); //todo: handle only text? switch (received.MessageType) { case WebSocketMessageType.Close: CloseUnactiveConnections(new[] { WebSocketState.CloseReceived }); break; case WebSocketMessageType.Text: var socketMessage = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count).Trim('\0'); var request = socketMessage.ToObject <DuplexNetworkRequest>(); if (CheckAuthorization(client, request)) { OnRequestRecieved(client.User, request.Type, socketMessage); } else { var response = new { IsSuccess = false, Message = "You are not authorized" }; await DirectResponse(client, response); ServerContext.Current.Logger.Log(LogDestination.Console, LogType.Info, "Websocket Unauthorized client trying to send something"); } break; case WebSocketMessageType.Binary: //todo: not impl yet for binary - do we need this case? ServerContext.Current.Logger.Log(LogDestination.Console, LogType.Info, "Websocket Binary recieved:"); ServerContext.Current.Logger.Log(LogDestination.Console, LogType.Info, buffer.Array); break; } } catch (Exception ex) { ServerContext.Current.Logger.LogError(LogDestination.Console, ex); break; } } //todo: handle closed socket - remove? } else { // Nothing to do here, pass downstream. await next(); } }