/// <summary> /// The action to perform. /// </summary> /// <param name="chatState">The current chat state.</param> private void Action(Chat.ChatWebSocketState chatState) { try { // Select the member to execute. switch (chatState.ExecutionMember.ToUpper()) { case "DATA": // SendMessage SendMessage(chatState); break; default: throw new Exception("Command not recognised."); } } catch (Exceptions.ErrorCodeException exc) { // Get the error code. chatState.ErrorCode = exc; } catch (Exception ex) { // Internal error. chatState.ErrorCode = new Exceptions.ErrorCodeException(ex.Message, 500); } }
/// <summary> /// Send the message to the client. /// </summary> /// <param name="chatState">The current chat state.</param> /// <returns>True if error; else false.</returns> private bool SendMessage(Chat.ChatWebSocketState chatState) { bool isError = true; // If the headers do not exist. if ((chatState.Headers.Count(m => m.Name.ToUpper().Contains("FSN")) < 1) || (chatState.Headers.Count(m => m.Name.ToUpper().Contains("SENDTO")) < 1)) { // Bad request exception. throw new Exceptions.ErrorCodeException("Invalid Request.", 400); } // Get the header data. string[] sendTo = null; string serviceName = chatState.Headers.First(m => m.Name.ToUpper().Contains("FSN")).Value; // If header send to. if (!String.IsNullOrEmpty(chatState.Headers.First(m => m.Name.ToUpper().Contains("SENDTO")).Value)) { sendTo = chatState.Headers.First(m => m.Name.ToUpper().Contains("SENDTO")).Value.Split(new char[] { ';' }, StringSplitOptions.None); } // Create the buffer byte[] buffer = new byte[chatState.RequestStream.Length]; // Read the current set of bytes. int bytesRead = chatState.RequestStream.Read(buffer, 0, buffer.Length); // Send to clients Common.Helper.SendToReceivers(chatState.Member.UniqueIdentifier, base.ServiceName, serviceName, sendTo, buffer); isError = false; // Return the result. return(isError); }
/// <summary> /// Validate the current user token. /// </summary> /// <param name="chatState">The current chat state.</param> /// <returns>True if valid; else false.</returns> private bool ValidateToken(Chat.ChatWebSocketState chatState) { // If the headers do not exist. if ((chatState.Headers.Count(m => m.Name.ToUpper().Contains("FUI")) < 1) || (chatState.Headers.Count(m => m.Name.ToUpper().Contains("TOKEN")) < 1)) { // Bad request exception. throw new Exceptions.ErrorCodeException("Invalid Request.", 400); } // Get the header data. string uniqueIdentifier = chatState.Headers.First(m => m.Name.ToUpper().Contains("FUI")).Value; string token = chatState.Headers.First(m => m.Name.ToUpper().Contains("TOKEN")).Value; // If the unique identifier // has not been set then the // token has not been verified. if (String.IsNullOrEmpty(chatState.Member.UniqueIdentifier)) { // Is token valid. _token.IsValid(uniqueIdentifier, base.ServiceName, token, (result, permission, state) => { Chat.ChatWebSocketState stateChat = null; try { // Get the state chat. stateChat = (Chat.ChatWebSocketState)state; // If the token is valid. if (result) { // Add this client to the communication store. _communication.AddClient(stateChat.Member.UniqueIdentifier, base.ServiceName, _machineName, null, true, token, stateChat.Member.UniqueIdentifier); // Set the current unique identifier // and the service name. stateChat.Member.ServiceName = base.ServiceName; stateChat.Member.UniqueIdentifier = uniqueIdentifier; // Perform the action. Action(stateChat); } else { // Bad request. stateChat.ErrorCode = new Exceptions.ErrorCodeException("The token is not valid.", 400); } } catch (Exception ex) { // Internal error. stateChat.ErrorCode = new Exceptions.ErrorCodeException(ex.Message, 500); } }, uniqueIdentifier, chatState); // Return false not valid. return(false); } else { // Perform the action. Action(chatState); // Token is valid. return(true); } }
/// <summary> /// On web socket context. /// </summary> /// <param name="webSocketContext">The asp net web socket context.</param> private async void OnChatWebSocketContext(System.Web.WebSockets.AspNetWebSocketContext context) { WebSocket webSocket = null; Nequeo.Net.WebSockets.WebSocketMember member = null; Nequeo.Collections.CircularBuffer <byte> requestBuffer = null; Nequeo.IO.Stream.StreamBufferBase requestStream = null; try { // Get the current web socket. webSocket = context.WebSocket; // Create the web socket member and // add to the member collection. member = new Nequeo.Net.WebSockets.WebSocketMember(webSocket); AddMember(member); // Holds the receive data. bool hasBeenFound = false; byte[] store = new byte[0]; byte[] receiveBuffer = new byte[READ_BUFFER_SIZE]; // Create the stream buffers. requestBuffer = new Collections.CircularBuffer <byte>(base.RequestBufferCapacity); requestStream = new Nequeo.IO.Stream.StreamBufferBase(requestBuffer); requestBuffer.RemoveItemsWritten = true; // Create the current chat state. Chat.ChatWebSocketState chatState = new Chat.ChatWebSocketState() { Member = member, RequestStream = requestStream, WebSocket = webSocket }; CancellationTokenSource receiveCancelToken = new CancellationTokenSource(); // While the WebSocket connection remains open run a // simple loop that receives data and sends it back. while (webSocket.State == WebSocketState.Open) { // Receive the next set of data. ArraySegment <byte> arrayBuffer = new ArraySegment <byte>(receiveBuffer); WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(arrayBuffer, receiveCancelToken.Token); // Assign the member properties. member.ReceiveResult = receiveResult; member.TimeoutTime = DateTime.Now; requestStream.Write(receiveBuffer, 0, receiveResult.Count); // If the connection has been closed. if (receiveResult.MessageType == WebSocketMessageType.Close) { // Close the connection. member.Close(); break; } else { // Store the data. byte[] temp = null; if (!hasBeenFound) { temp = store.CombineParallel(receiveBuffer); // Find the end of the data. hasBeenFound = Nequeo.Net.Utility.IsParse2CRLF(temp); // Store the data until the end. store = temp; temp = null; } else { // If this is the end of the message. if (receiveResult.EndOfMessage) { // Clear the store. store = null; store = new byte[0]; hasBeenFound = false; string resource = ""; // Get the request headers. List <Nequeo.Model.NameValue> headers = base.ParseHeaders(requestStream, out resource, base.HeaderTimeout); // All headers have been found. if (headers != null) { // Get the execution member. // Set the calling member. string executionMember = headers.First(m => m.Name.ToUpper().Contains("MEMBER")).Value; string actionName = headers.First(m => m.Name.ToUpper().Contains("ACTIONNAME")).Value; // Assign the values. chatState.Headers = headers; chatState.ExecutionMember = executionMember; chatState.ErrorCode = new Exceptions.ErrorCodeException("OK", 200); try { // Validate the current user token. bool isTokenValid = ValidateToken(chatState); } catch (Exceptions.ErrorCodeException exc) { // Get the error code. chatState.ErrorCode = exc; } catch (Exception ex) { // Internal error. chatState.ErrorCode = new Exceptions.ErrorCodeException(ex.Message, 500); } // Send a message back to the client indicating that // the message was recivied and was sent. await webSocket.SendAsync(new ArraySegment <byte>( CreateResponse(chatState.ErrorCode.ErrorCode, true, executionMember, actionName, chatState.ErrorCode.Message)), WebSocketMessageType.Binary, true, CancellationToken.None); } } } } } // Cancel the receive request. if (webSocket.State != WebSocketState.Open) { receiveCancelToken.Cancel(); } } catch { } finally { // If a member context exists. if (member != null) { try { // Remove the member context // from the collection. RemoveMember(member); } catch { } member = null; } // Clean up by disposing the WebSocket. if (webSocket != null) { webSocket.Dispose(); } if (requestBuffer != null) { requestBuffer.Dispose(); } if (requestStream != null) { requestStream.Dispose(); } if (_communication != null) { try { // Remove the client from the communication service. _communication.RemoveClient(member.UniqueIdentifier, base.ServiceName, _machineName, null, actionName: member.UniqueIdentifier); } catch { } } } }