5 using System.Collections.Concurrent;
6 using System.Collections.Generic;
7 using System.Security.Cryptography;
14 private static string WebsocketHeaderAcceptKey =
"Sec-WebSocket-Accept";
15 private static string WebsocketHeaderKey =
"Sec-WebSocket-Key";
16 private static string WebsocketProtocolKey =
"Sec-WebSocket-Protocol";
17 private static string WebsocketProtocolVersionKey =
"Sec-WebSocket-Version";
18 private static string GlobalUniqueIdentifier =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
19 private static SHA1 sha1Provider = SHA1.Create();
20 private static RNGCryptoServiceProvider rng =
new RNGCryptoServiceProvider();
21 public enum SocketState
29 public ConcurrentDictionary<ClientData, SocketState> webSockets =
new ConcurrentDictionary<ClientData, SocketState>();
30 ConcurrentQueue<Tuple<ClientData,WebsocketMessage>> messageQueue =
new ConcurrentQueue<Tuple<ClientData, WebsocketMessage>>();
31 List<IWebsocketModule> websocketModules =
new List<IWebsocketModule>();
33 #region Public Methods 41 this.websocketModules.Add(module);
51 sendMessage.
Data = message;
52 sendMessage.
FIN =
true;
53 rng.GetBytes(sendMessage.
Mask);
55 messageQueue.Enqueue(
new Tuple<ClientData, WebsocketMessage>(client, sendMessage));
64 messageQueue.Enqueue(
new Tuple<ClientData, WebsocketMessage>(client, message));
73 websocketMessage.
FIN =
true;
75 websocketMessage.
Masked =
false;
79 #region Handler Implementation 82 SocketState state = SocketState.Initial;
83 while (webSockets.ContainsKey(client))
85 webSockets.TryRemove(client, out state);
89 bool IHandler.HandleClient(Server server, ClientData client)
91 webSockets[client] = SocketState.Initial;
95 bool IHandler.HandleReceivedMessage(Server server, ClientData client, Message message)
97 if (webSockets[client] == SocketState.Initial)
102 request[
HttpMessage.GeneralHeadersEnum.Connection].ToLower() ==
"upgrade" && request.
ContainsHeader(WebsocketProtocolVersionKey) &&
103 request[WebsocketProtocolVersionKey] ==
"13")
108 string base64Key = request[WebsocketHeaderKey];
109 base64Key = base64Key.Trim();
110 string handshakeKey = base64Key + GlobalUniqueIdentifier;
111 string returnBase64Key = Convert.ToBase64String(sha1Provider.ComputeHash(Encoding.UTF8.GetBytes(handshakeKey)));
117 response.StatusCode =
HttpMessage.StatusCodes.SwitchingProtocols;
118 response[
HttpMessage.GeneralHeadersEnum.Upgrade] =
"websocket";
119 response[
HttpMessage.GeneralHeadersEnum.Connection] =
"Upgrade";
120 response[WebsocketHeaderAcceptKey] = returnBase64Key;
122 webSockets[client] = SocketState.Established;
123 server.LogDebug(
"Websocket initialized " + client.TcpClient.Client.RemoteEndPoint.ToString());
131 else if(webSockets[client] == SocketState.Established)
140 client.ToBeRemoved =
true;
141 SocketState outSocketState = SocketState.Closed;
142 while (webSockets.ContainsKey(client))
144 webSockets.TryRemove(client, out outSocketState);
162 bool IHandler.HandleSendMessage(Server server, ClientData client, ref Message message)
167 bool IHandler.PreHandleReceivedMessage(Server server, ClientData client, ref Message message)
172 void IHandler.Tick(Server server)
174 while (messageQueue.Count > 0)
176 Tuple<ClientData, WebsocketMessage> tuple =
null;
177 if (messageQueue.TryDequeue(out tuple))
179 server.QueueMessage(tuple.Item1, tuple.Item2.GetMessageBytes());
186 tuple.Item1.ToBeRemoved =
true;
187 SocketState outSocketState = SocketState.Closed;
188 while (webSockets.ContainsKey(tuple.Item1))
190 webSockets.TryRemove(tuple.Item1, out outSocketState);
Interface for communication handlers.
bool HandleReceivedMessage(Server.Server server, WebsocketHandler handler, ClientData client, WebsocketMessage receivedMessage)
Handle a received message.
void QueueMessage(ClientData client, WebsocketMessage message)
Send a message to the client.
WebsocketHandler AddWebsocketHandler(IWebsocketModule module)
Add a webSocket module onto the server.
void ConnectionClosed(Server.Server server, WebsocketHandler handler, ClientData client)
Called when a connection has been closed.
Structure containing client information.
byte [] Mask
Mask of the message.
Class containing the bytes of a websocket received message.
void ClientRemoved(Server server, ClientData client)
Handles the removal of a client from the server.
Basic server class to handle TCP connections.
byte [] BuildResponse(bool includeContentLengthHeader)
Build the response bytes based on the message contents.
bool ContainsHeader(ResponseHeadersEnum header)
Check if the message contains a header.
void CloseConnection(ClientData client)
Signals that the connetion is closing.
byte [] Data
Data of the message.
void QueueMessage(ClientData client, byte[] message)
Send a message to the client.
Opcodes Opcode
Frame Opcode
void ParseRequest(byte[] requestBytes)
Parse the received bytes and populate the message contents.
void ConnectionInitialized(Server.Server server, WebsocketHandler handler, ClientData client)
Called when a connection has been initialized.