/// <summary> /// Called by the socket listener when an inbound socket is accepted. /// </summary> /// <param name="sock">The accepted socket.</param> /// <param name="endPoint">The endpoint the socket was accepted from.</param> private void OnAccept(EnhancedSocket sock, IPEndPoint endPoint) { var httpState = new HttpAsyncState(); var recvBuf = new byte[RecvBlockSize]; using (TimedLock.Lock(syncLock)) { if (connections.Count >= maxConnections) { sock.AsyncSendClose(new HttpResponse(HttpStatus.ServiceUnavailable, "Server is too busy").Serialize(SendBlockSize)); return; } connections.Add(sock, sock); } httpState.FirstRequest = true; httpState.Request = new HttpRequest(); httpState.Socket = sock; httpState.Buffer = recvBuf; httpState.RecvSize = 0; httpState.Request.BeginParse(((IPEndPoint)sock.LocalEndPoint).Port); sock.BeginReceive(recvBuf, 0, recvBuf.Length, SocketFlags.None, onRecv, httpState); }
/// <summary> /// Handles socket receive completions. /// </summary> /// <param name="ar"></param> private void OnReceive(IAsyncResult ar) { HttpAsyncState httpState = (HttpAsyncState)ar.AsyncState; HttpRequest request = httpState.Request; EnhancedSocket sock = httpState.Socket; byte[] recvBuf = httpState.Buffer; int cbRecv; HttpResponse response; bool closeCon; bool close; bool firstRequest; try { cbRecv = sock.EndReceive(ar); } catch { using (TimedLock.Lock(syncLock)) connections.Remove(sock); sock.Close(); return; } if (cbRecv == 0) { using (TimedLock.Lock(syncLock)) connections.Remove(sock); sock.ShutdownAndClose(); return; } if (perfBytesRecv != null) { perfBytesRecv.IncrementBy(cbRecv); } httpState.RecvSize += cbRecv; if (httpState.RecvSize > cbQueryMax) { // The request is too large so respond with a HttpStatus.RequestEntityTooLarge // and close the socket. response = new HttpResponse(HttpStatus.RequestEntityTooLarge); sock.AsyncSendClose(response.Serialize(SendBlockSize)); using (TimedLock.Lock(syncLock)) connections.Remove(sock); return; } if (!request.Parse(recvBuf, cbRecv)) { recvBuf = new byte[RecvBlockSize]; httpState.Buffer = recvBuf; sock.BeginReceive(recvBuf, 0, recvBuf.Length, SocketFlags.None, onRecv, httpState); return; } // We have a complete request so process it. request.EndParse(); firstRequest = httpState.FirstRequest; httpState.FirstRequest = false; try { sock.AppState = this; // Indicate that we're processing a request closeCon = false; for (int i = 0; i < modules.Length; i++) { response = modules[i].OnRequest(this, request, firstRequest, out close); closeCon = closeCon || close; if (response != null) { BlockArray blocks; // Make sure the response version is reasonable if (request.HttpVersion < response.HttpVersion) { response.HttpVersion = request.HttpVersion; } // Truncate any content data for HEAD requests if (request.Method == "HEAD") { response.Content = null; if (response["Content-Length"] != null) { response["Content-Length"] = "0"; } } blocks = response.Serialize(SendBlockSize); if (perfBytesSent != null) { perfBytesSent.IncrementBy(blocks.Size); } if (closeCon) { sock.AsyncSendClose(blocks); using (TimedLock.Lock(syncLock)) connections.Remove(sock); } else { sock.BeginSendAll(blocks, SocketFlags.None, onSend, httpState); } break; } } } finally { sock.AppState = null; // Indicate that we're done processing the request } }