/// <summary> /// Handle a HTTP Upgrade request. /// </summary> /// <param name="req"></param> /// <param name="conn"></param> public void HandleUpgrade(HttpServerRequest req, TcpSocket socket, ArraySegment <byte> head) { if (!socket.Readable || !socket.Writable) { socket.Destroy(); return; } if (OnConnection == null) { AbortConnection(socket, 400); return; } var upgrade = req.Headers["upgrade"]; var version = req.Headers["sec-websocket-version"]; if ((version != "13" && version != "8") || !string.Equals(upgrade, "websocket", StringComparison.InvariantCultureIgnoreCase)) { socket.Write(Encoding.ASCII.GetBytes( "HTTP/1.1 400 Bad Request\r\n" + "Connection: close\r\n" + "Sec-WebSocket-Version: 13, 8\r\n")); socket.Close(); return; } string acceptKey; using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider()) { var key = req.Headers["sec-websocket-key"]; acceptKey = Convert.ToBase64String(sha1.ComputeHash(Encoding.ASCII.GetBytes(key + GUID))); } socket.Write(Encoding.UTF8.GetBytes( "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + acceptKey + "\r\n\r\n")); socket.Flush(); OnConnection.Invoke(new WebSocket(socket, req, head)); }
private void OnData(TcpSocket sender, ArraySegment <byte> data) { switch (_receiveState) { case ReceiveState.Header: if (_headerBuffer[0] != FCGI_VERSION_1) { _socket.Destroy(); return; } var contentLength = _headerBuffer[4] << 8 | _headerBuffer[5]; if (contentLength == 0) { data = new ArraySegment <byte>(BufferData.EmptyBytes); goto case ReceiveState.Body; } else { _socket.ReceiveBuffer(new ArraySegment <byte>(new byte[contentLength])); _receiveState = ReceiveState.Body; } break; case ReceiveState.Body: try { var type = (RecordType)_headerBuffer[1]; var requestId = (_headerBuffer[2] << 8) | _headerBuffer[3]; OnRecordReceived(type, requestId, data); } catch { _socket.Destroy(); _socket = null; return; } _receiveSkip = _headerBuffer[6]; if (_receiveSkip > 0) { data = new ArraySegment <byte>(); _receiveState = ReceiveState.Padding; goto case ReceiveState.Padding; } else { _receiveState = ReceiveState.Header; _socket.ReceiveBuffer(new ArraySegment <byte>(_headerBuffer)); } break; case ReceiveState.Padding: _receiveSkip -= data.Count; if (_receiveSkip > 0) { var len = Math.Min(_headerBuffer.Length, _receiveSkip); _socket.ReceiveBuffer(new ArraySegment <byte>(_headerBuffer, 0, len)); } else { _receiveState = ReceiveState.Header; _socket.ReceiveBuffer(new ArraySegment <byte>(_headerBuffer)); } break; } }