void ev_writedone() { if (_state == _State.Failure) { Dispose(); } else if (_state == _State.Send100Continue) { ev_requestbodyready(); _HandleCurrentState(); } else if (_state == _State.SendResponseBody) { _state = _State.ResponseBodyUserWait; var cb = _responsebody_user_cb; var buf = _responsebody_buffer; _server._DispatchCallback(() => cb(buf)); } else if (_state == _State.SendResponseBodyLast) { // clear out all state _tx = null; _readoff = 0; _readcount = 0; _readbuf = new byte[4096]; _readoff = 0; _readcount = 0; _headerstate = _HeaderState.FirstLine; _linems = new MemoryStream(); _firstline = null; _headerlines = new List<string>(); _writeoff = 0; _writecount = 0; _writebytes = null; _requestbody_left = 0; _requestbody_full = null; _requestbody_multipart = null; _requestbody_streaming_started = false; _requestbody_buffer = null; _requestbody_user_cb = null; _responsebody_streaming_started = false; _responsebody_buffer = null; _responsebody_user_cb = null; _responsebody_done_cb = null; _responsebody_left = -1; _state = _State.RequestHeaders; if (_isconnectionclose || _ishttp10) { Dispose(); } else { _HandleCurrentState(); } } else if (_state == _State.SendResponseHeaders) { _state = _State.ResponseBodyUserWait; _server._DispatchCallback(() => _responsebody_user_cb(_responsebody_buffer)); } else { throw new InvalidOperationException(); } }
void ev_requestbodyready() { // // There are four strategies for handling the request body // // (1) Content-Length is 0: Nothing to do // // (2) Content-Length > 0 + Content-Type is application/x-www-form-urlencoded: Read it now. // // (3) Content-Length > 0 + Content-Type is application/x-www-urlencoded: Read it now. // // (4) Content-Length > 0 + Content-Type is something else: Let the user stream the request body. // // (5) Transfer-Encoding is chunked: Fail with NotImplemented (for now--may support this in future) // _server.ev_debug("request body ready"); if (_tx.Request.Headers.IsChunkedEncoding) { _Fail(HttpStatusCode.NotImplemented); // case (4) -- fail return; } var contentlength = _tx.Request.Headers.ContentLength ?? 0; if (contentlength == 0) { _state = _State.ResponseHeadersUserWait; _server.ev_debug(" ==> case 1 (nothing to do)"); ev_requestready(); // case (1) -- nothing to do } else { if (_tx.Request.Method == HttpMethod.Post && _tx.Request.Headers.ContentType != null && _tx.Request.Headers.ContentType.Contains("multipart/form-data")) { _server.ev_debug(" ==> case 1 (multipart)"); var boundary = _ParseBoundary(_tx.Request.Headers.ContentType); _requestbody_multipart = new HttpMultiPartFormDataHandler(boundary, _tx.Request.Headers.ContentEncoding); _requestbody_left = contentlength; _state = _State.RequestBodyMultiPart; // case (2) -- read request body now } else if (_tx.Request.Method == HttpMethod.Post && _tx.Request.Headers.ContentType != null && _tx.Request.Headers.ContentType.Contains("application/x-www-form-urlencoded")) { _server.ev_debug(" ==> case 1 (urlencoded)"); _requestbody_full = new MemoryStream(); _requestbody_left = contentlength; _state = _State.RequestBodyFull; // case (2) -- read request body now } else { _server.ev_debug(" ==> case 1 (userstream)"); _state = _State.RequestBodyUserWait; // case (3) -- let user stream request body _requestbody_left = contentlength; _requestbody_streaming_started = false; _tx.Request.SetStreamingRequestBody(true); ev_requestready(); } } }