public async Task ConnectAsync (Uri uri, CancellationToken cancellationToken) { state = WebSocketState.Connecting; var httpUri = new UriBuilder (uri); if (uri.Scheme == "wss") httpUri.Scheme = "https"; else httpUri.Scheme = "http"; req = (HttpWebRequest)WebRequest.Create (httpUri.Uri); req.ReuseConnection = true; if (options.Cookies != null) req.CookieContainer = options.Cookies; if (options.CustomRequestHeaders.Count > 0) { foreach (var header in options.CustomRequestHeaders) req.Headers[header.Key] = header.Value; } var secKey = Convert.ToBase64String (Encoding.ASCII.GetBytes (Guid.NewGuid ().ToString ().Substring (0, 16))); string expectedAccept = StreamWebSocket.CreateAcceptKey (secKey); req.Headers["Upgrade"] = "WebSocket"; req.Headers["Sec-WebSocket-Version"] = VersionTag; req.Headers["Sec-WebSocket-Key"] = secKey; req.Headers["Sec-WebSocket-Origin"] = uri.Host; if (options.SubProtocols.Count > 0) req.Headers["Sec-WebSocket-Protocol"] = string.Join (",", options.SubProtocols); if (options.Credentials != null) req.Credentials = options.Credentials; if (options.ClientCertificates != null) req.ClientCertificates = options.ClientCertificates; if (options.Proxy != null) req.Proxy = options.Proxy; req.UseDefaultCredentials = options.UseDefaultCredentials; req.Connection = "Upgrade"; HttpWebResponse resp = null; try { resp = (HttpWebResponse)(await req.GetResponseAsync ().ConfigureAwait (false)); } catch (Exception e) { throw new WebSocketException (WebSocketError.Success, e); } if (resp.StatusCode != HttpStatusCode.SwitchingProtocols) throw new WebSocketException ("The server returned status code '" + (int)resp.StatusCode + "' when status code '101' was expected"); if (!string.Equals (resp.Headers["Upgrade"], "WebSocket", StringComparison.OrdinalIgnoreCase) || !string.Equals (resp.Headers["Connection"], "Upgrade", StringComparison.OrdinalIgnoreCase) || !string.Equals (resp.Headers["Sec-WebSocket-Accept"], expectedAccept)) throw new WebSocketException ("HTTP header error during handshake"); if (resp.Headers["Sec-WebSocket-Protocol"] != null) { if (!options.SubProtocols.Contains (resp.Headers["Sec-WebSocket-Protocol"])) throw new WebSocketException (WebSocketError.UnsupportedProtocol); subProtocol = resp.Headers["Sec-WebSocket-Protocol"]; } state = WebSocketState.Open; connection = req.StoredConnection; internalWebSocket = new StreamWebSocket(connection.nstream, connection.nstream, connection.socket, subProtocol, true, new ArraySegment<byte>(new byte[0])); }
public async Task<HttpListenerWebSocketContext> AcceptWebSocketAsync (string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval) { if (subProtocol != null && subProtocol == "") { throw new ArgumentException ("subProtocol must not empty string"); } if (receiveBufferSize < 16 || receiveBufferSize > 64 * 1024) { throw new ArgumentOutOfRangeException ("receiveBufferSize should be >=16 and <=64K bytes"); } if (!request.IsWebSocketRequest) { throw new WebSocketException ("Request is not WebSocket Handshake"); } string secKey = request.Headers ["Sec-WebSocket-Key"]; if (secKey == null) { throw new WebSocketException ("Request doesn't contain Sec-WebSocket-Key header"); } string acceptKey = StreamWebSocket.CreateAcceptKey (secKey); ArraySegment<byte> preloaded; var stream = new NetworkStream (cnc.Hijack (out preloaded)); string header = "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + acceptKey + "\r\n\r\n"; var headerBytes = Encoding.ASCII.GetBytes (header); await stream.WriteAsync (headerBytes, 0, headerBytes.Length); var ws = new StreamWebSocket (stream, stream, null, subProtocol, false, preloaded); return new HttpListenerWebSocketContext (ws, request, user); }
internal HttpListenerWebSocketContext(StreamWebSocket websocket, HttpListenerRequest request, IPrincipal user) { this.websocket = websocket; this.request = request; this.user = user; }