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(); } }
internal void _BeginResponse(HttpResponse response, HttpStatusCode status, Action<HttpBuffer> ev_buffer, Action/*?*/ ev_done = null) { lock (_server._lock) { if (_isdisposed) return; // this is not the right place to throw if (_state != _State.ResponseHeadersUserWait && _state != _State.RequestBodyUserWait) throw new InvalidOperationException("invalid state for response body streaming (" + _state + ")"); if (_responsebody_streaming_started) throw new InvalidOperationException("request body can only be streamed once"); if (_tx == null || _tx.Response != response) throw new InvalidOperationException("this request object is not active"); _server.ev_debug("begin response"); _responsebody_buffer = new ResponseBodyBuffer(this); _responsebody_user_cb = ev_buffer; if (_responsebody_done_cb != null) throw new InvalidOperationException("resources may have leaked"); _responsebody_done_cb = ev_done; if (!response.Headers.ContentLength.HasValue && !_ishttp10) { response.Headers.SetChunkedEncoding(); } StringBuilder sb = new StringBuilder(); sb.AppendFormat("HTTP/{0} {1} {2}\r\n", (_ishttp10?"1.0":"1.1"), (int)status, _Utils.Stringify(status)); response.Headers.Write(sb, response.Cookies.Values); _server.ev_debug("{0}", sb.ToString()); _server.ev_debug("--------------------------------------"); _responsebody_left = response.Headers.ContentLength ?? -1; _writebytes = Encoding.UTF8.GetBytes(sb.ToString()); _writecount = _writebytes.Length; _writeoff = 0; if (_state == _State.RequestBodyUserWait) { // if we are still waiting for the user to read the request body, dump it _state = _State.RequestBodyDump; } else { _state = _State.SendResponseHeaders; } _HandleCurrentState(); } }