|
Alchemy Websockets
An extremely efficient C# WebSocket server.
|
00001 using System; 00002 using System.Collections.Generic; 00003 using System.Linq; 00004 using System.Web; 00005 using Alchemy.Classes; 00006 00007 namespace Alchemy.Handlers.WebSocket.hybi00 00008 { 00013 public class ClientHandshake 00014 { 00018 private const String Handshake = 00019 "GET {0} HTTP/1.1\r\n" + 00020 "Upgrade: WebSocket\r\n" + 00021 "Connection: Upgrade\r\n" + 00022 "Origin: {1}\r\n" + 00023 "Host: {2}\r\n" + 00024 "Sec-Websocket-Key1: {3}\r\n" + 00025 "Sec-Websocket-Key2: {4}\r\n" + 00026 "{5}"; 00027 00028 public string Host = String.Empty; 00029 public string Key1 = String.Empty; 00030 public string Key2 = String.Empty; 00031 public string Origin = String.Empty; 00032 public string ResourcePath = String.Empty; 00033 00034 public ClientHandshake() 00035 {} 00036 00042 public ClientHandshake(ArraySegment<byte> challengeBytes, Header header) 00043 { 00044 ChallengeBytes = challengeBytes; 00045 ResourcePath = header.RequestPath; 00046 Key1 = header["sec-websocket-key1"]; 00047 Key2 = header["sec-websocket-key2"]; 00048 SubProtocol = header["sec-websocket-protocol"]; 00049 Origin = header["origin"]; 00050 Host = header["host"]; 00051 Cookies = header.Cookies; 00052 } 00053 00054 public ArraySegment<byte> ChallengeBytes { get; set; } 00055 public HttpCookieCollection Cookies { get; set; } 00056 public string SubProtocol { get; set; } 00057 public Dictionary<string, string> AdditionalFields { get; set; } 00058 00065 public bool IsValid() 00066 { 00067 return ( 00068 (Host != null) && 00069 (Key1 != null) && 00070 (Key2 != null) && 00071 (Origin != null) && 00072 (ResourcePath != null) 00073 ); 00074 } 00075 00082 public override string ToString() 00083 { 00084 string additionalFields = String.Empty; 00085 00086 if (Cookies != null) 00087 { 00088 additionalFields += "Cookie: " + Cookies + "\r\n"; 00089 } 00090 if (SubProtocol != null) 00091 { 00092 additionalFields += "Sec-Websocket-Protocol: " + SubProtocol + "\r\n"; 00093 } 00094 00095 if (additionalFields != String.Empty) 00096 { 00097 additionalFields = AdditionalFields.Aggregate(additionalFields, 00098 (current, field) => 00099 current + (field.Key + ": " + field.Value + "\r\n")); 00100 } 00101 additionalFields += "\r\n"; 00102 00103 return String.Format(Handshake, ResourcePath, Origin, Host, Key1, Key2, additionalFields); 00104 } 00105 } 00106 00111 public class ServerHandshake 00112 { 00116 private const string Handshake = 00117 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" + 00118 "Upgrade: WebSocket\r\n" + 00119 "Connection: Upgrade\r\n" + 00120 "Sec-WebSocket-Origin: {0}\r\n" + 00121 "Sec-WebSocket-Location: {1}\r\n" + 00122 "{2}" + 00123 " "; //Empty space for challenge answer 00124 00125 public string Location = String.Empty; 00126 public string Origin = String.Empty; 00127 public byte[] AnswerBytes { get; set; } 00128 public string SubProtocol { get; set; } 00129 public Dictionary<string, string> AdditionalFields { get; set; } 00130 00137 public override string ToString() 00138 { 00139 string additionalFields = String.Empty; 00140 if (SubProtocol != null) 00141 { 00142 additionalFields += "Sec-WebSocket-Protocol: " + SubProtocol + "\r\n"; 00143 } 00144 additionalFields += "\r\n"; 00145 00146 return String.Format(Handshake, Origin, Location, additionalFields); 00147 } 00148 } 00149 }