public async Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken) { if (mState == WebSocketState.Closed || mState == WebSocketState.CloseSent) { throw new HttpException(500, "Websocket: Sent 'close' message after connection was already closed. Connection state=" + mState); } mState = mState == WebSocketState.CloseReceived ? WebSocketState.Closed : WebSocketState.CloseSent; // Prepend two bytes for status var message = Encoding.UTF8.GetBytes("XX" + statusDescription); message[0] = (byte)((int)closeStatus >> 8); message[1] = (byte)(int)closeStatus; await SendAsync(new ArraySegment <byte>(message), WebSocketMessageType.Close, true, cancellationToken); await mWriter.FlushAsync(); }
/// <summary> /// Process requests as long as there is not an error /// </summary> async Task ProcessRequests(HttpContext context, HttpReader reader, HttpWriter writer) { int persistentConnections = 0; do { persistentConnections++; try { // Read header reader.ReadTimeout = HeaderTimeout; var buffer = await reader.ReadHttpHeaderAsyncInternal(); reader.PositionInternal = 0; reader.LengthInternal = HttpContext.HTTP_HEADER_MAX_SIZE; if (buffer.Count == 0) { return; // Connection closed } // Parse header context.ResetRequestInternal(HttpRequest.Parse(buffer), new HttpResponse()); } catch (Exception ex) { Log.Write("HTTP header exception: " + ex.GetType() + " - " + ex.Message); return; // Close connection } // Handle body reader.ReadTimeout = BodyTimeout; writer.WriteTimeout = BodyTimeout; try { // Process HTTP request var handler = HttpHandler; if (handler == null) { throw new HttpException(503, "HTTP request handler not installed"); } await handler(context).ConfigureAwait(false); } catch (HttpException ex) when(ex.KeepConnectionOpen && !context.Response.HeaderSent) { // Keep the persistent connection open only if it's OK to do so. await ProcessExceptionAsync(context, ex); } await writer.FlushAsync(); // Any of these problems will terminate a persistent connection var response = context.Response; var request = context.Request; var isWebsocket = request.IsWebSocketRequest; if (!response.HeaderSent) { throw new HttpException(500, "Request handler did not send a response for: " + context.Request.Path); } if (!isWebsocket && reader.Position != request.ContentLength && request.ContentLength >= 0) { throw new HttpException(500, "Request handler did not read correct number of bytes: " + request.Path); } if (!isWebsocket && writer.Position != response.ContentLength) { throw new HttpException(500, "Request handler did not write correct number of bytes: " + request.Path); } } while (!context.Request.IsWebSocketRequest && context.Response.Connection == "keep-alive"); }