static void ev_io_on_read(struct ev_loop* mainloop, ev_io* watcher, const int events) { static char read_buf[READ_BUFFER_SIZE]; Request* request = REQUEST_FROM_WATCHER(watcher); ssize_t read_bytes = read( request->client_fd, read_buf, READ_BUFFER_SIZE ); GIL_LOCK(0); if(read_bytes <= 0) { if(errno != EAGAIN && errno != EWOULDBLOCK) { if(read_bytes == 0) DBG_REQ(request, "Client disconnected"); else DBG_REQ(request, "Hit errno %d while read()ing", errno); close(request->client_fd); Request_free(request); ev_io_stop(mainloop, &request->ev_watcher); } goto out; } Request_parse(request, read_buf, (size_t)read_bytes); if(request->state.error_code) { DBG_REQ(request, "Parse error"); request->current_chunk = PyString_FromString( http_error_messages[request->state.error_code]); assert(request->iterator == NULL); } else if(request->state.parse_finished) { if(!wsgi_call_application(request)) { assert(PyErr_Occurred()); PyErr_Print(); assert(!request->state.chunked_response); Py_XCLEAR(request->iterator); request->current_chunk = PyString_FromString( http_error_messages[HTTP_SERVER_ERROR]); } } else { /* Wait for more data */ goto out; } ev_io_stop(mainloop, &request->ev_watcher); ev_io_init(&request->ev_watcher, &ev_io_on_write, request->client_fd, EV_WRITE); ev_io_start(mainloop, &request->ev_watcher); out: GIL_UNLOCK(0); return; }
static void close_connection(struct ev_loop *mainloop, Request* request) { DBG_REQ(request, "Closing socket"); ev_io_stop(mainloop, &request->ev_watcher); close(request->client_fd); Request_free(request); }
static void on_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { Request* request; dprint("go on_read"); request =(Request*)handle->data; GIL_LOCK(0); if (nread <= 0) { //@@@@@@@@@@@@@@@uv_err_t err = uv_last_error(loop); //@@@@@@@@@@@@@@@UVERR(err, "uv read error"); if(nread == 0) dprint("Client disconnected"); uv_close((uv_handle_t*)handle, on_close); Request_free(request); if (buf.base) { free(buf.base); } goto out; } Request_parse(request, buf.base, nread); //处理Request解析 free(buf.base); if(request->state.error_code) { DBG_REQ(request, "Parse error"); request->current_chunk = PyString_FromString(http_error_messages[request->state.error_code]);//处理有错误的信息返回 assert(request->iterator == NULL); //@@@@@@@@@ uv_close((uv_handle_t*) &request->ev_watcher, on_close);//解析有错误的请求直接关闭客户端连接 //@@@@@@@@@@ Request_free(request); //@@@@@@@@@ goto out; } else if(request->state.parse_finished) { // 解析好后 dprint("执行wsgi程序 >>>"); if(!wsgi_call_application(request)) { // 执行wsgi dprint("wsgi执行包含错误"); assert(PyErr_Occurred()); PyErr_Print(); //打印python错误的跟踪堆栈信息 assert(!request->state.chunked_response); Py_XCLEAR(request->iterator); request->current_chunk = PyString_FromString( //返回错误信息给客户端 http_error_messages[HTTP_SERVER_ERROR]); } } else { /* Wait for more data */ goto out; } dprint("开始客户端数据返回 >>>"); while(request->current_chunk){ //客户端返回循环 io_write(request); } out: GIL_UNLOCK(0); return; }
static void on_request(Connection* conn, Request* request) { UNUSED(conn); CXLOG(conn, "ON REQUEST"); /* restart the connection timeout */ conn->f_timer_start(conn, CONNECTION_TIMEOUT_MILLIS); StringBuffer* request_buffer = (StringBuffer*)Request_get_data(request); XFLOG("request >>>>\n%s\n", StringBuffer_value(request_buffer)); Request_free(request); conn->f_send(conn, Response_new(request_buffer), NULL); }
static void ev_io_on_read(struct ev_loop* mainloop, ev_io* watcher, const int events) { char read_buf[READ_BUFFER_SIZE]; Request* request = ADDR_FROM_MEMBER(watcher, Request, ev_watcher); ssize_t read_bytes = read(request->client_fd, read_buf, READ_BUFFER_SIZE); DBG_REQ(request, "read %zd bytes", read_bytes); GIL_LOCK(0); if(read_bytes == -1) { if(errno != EAGAIN && errno != EWOULDBLOCK) { close(request->client_fd); Request_free(request); ev_io_stop(mainloop, &request->ev_watcher); } goto out; } Request_parse(request, read_buf, read_bytes); if(request->state.error) { DBG_REQ(request, "Parse error"); set_error(request, request->state.error_code); } else if(request->state.parse_finished) { DBG_REQ(request, "Parse done"); if(!wsgi_call_application(request)) { assert(PyErr_Occurred()); PyErr_Print(); set_error(request, HTTP_SERVER_ERROR); } } else { DBG_REQ(request, "Waiting for more data"); goto out; } ev_io_stop(mainloop, &request->ev_watcher); ev_io_init(&request->ev_watcher, &ev_io_on_write, request->client_fd, EV_WRITE); ev_io_start(mainloop, &request->ev_watcher); out: GIL_UNLOCK(0); return; }
static void ev_io_on_write(struct ev_loop* mainloop, ev_io* watcher, const int events) { GIL_LOCK(0); Request* request = ADDR_FROM_MEMBER(watcher, Request, ev_watcher); assert(request->current_chunk); if(send_chunk(request)) goto notfinished; if(request->iterable) { PyObject* next_chunk; DBG_REQ(request, "Getting next iterable chunk."); next_chunk = wsgi_iterable_get_next_chunk(request); if(next_chunk == NULL) { if(PyErr_Occurred()) { /* Internal server error. */ PyErr_Print(); set_error(request, HTTP_SERVER_ERROR); goto notfinished; } DBG_REQ(request, "Iterable exhausted"); goto bye; } request->current_chunk = next_chunk; assert(request->current_chunk_p == 0); goto notfinished; } bye: DBG_REQ(request, "Done"); /* Everything done, bye client! */ ev_io_stop(mainloop, &request->ev_watcher); close(request->client_fd); Request_free(request); notfinished: GIL_UNLOCK(0); }
/* XXX too many gotos */ static void ev_io_on_write(struct ev_loop* mainloop, ev_io* watcher, const int events) { Request* request = REQUEST_FROM_WATCHER(watcher); GIL_LOCK(0); if(request->state.use_sendfile) { /* sendfile */ if(request->current_chunk) { /* current_chunk contains the HTTP headers */ if(send_chunk(request)) goto out; assert(!request->current_chunk_p); /* abuse current_chunk_p to store the file fd */ request->current_chunk_p = PyObject_AsFileDescriptor(request->iterable); goto out; } if(do_sendfile(request)) goto out; } else { /* iterable */ if(send_chunk(request)) goto out; if(request->iterator) { PyObject* next_chunk; next_chunk = wsgi_iterable_get_next_chunk(request); if(next_chunk) { if(request->state.chunked_response) { request->current_chunk = wrap_http_chunk_cruft_around(next_chunk); Py_DECREF(next_chunk); } else { request->current_chunk = next_chunk; } assert(request->current_chunk_p == 0); goto out; } else { if(PyErr_Occurred()) { PyErr_Print(); /* We can't do anything graceful here because at least one * chunk is already sent... just close the connection */ DBG_REQ(request, "Exception in iterator, can not recover"); ev_io_stop(mainloop, &request->ev_watcher); close(request->client_fd); Request_free(request); goto out; } Py_CLEAR(request->iterator); } } if(request->state.chunked_response) { /* We have to send a terminating empty chunk + \r\n */ request->current_chunk = PyString_FromString("0\r\n\r\n"); assert(request->current_chunk_p == 0); request->state.chunked_response = false; goto out; } } ev_io_stop(mainloop, &request->ev_watcher); if(request->state.keep_alive) { DBG_REQ(request, "done, keep-alive"); Request_clean(request); Request_reset(request); ev_io_init(&request->ev_watcher, &ev_io_on_read, request->client_fd, EV_READ); ev_io_start(mainloop, &request->ev_watcher); } else { DBG_REQ(request, "done, close"); close(request->client_fd); Request_free(request); } out: GIL_UNLOCK(0); }
static void io_write(Request* request) { //GIL_LOCK(0); if(request->state.use_sendfile) { dprint("发送文件给客户端"); /* sendfile */ if(request->current_chunk && send_chunk(request)) goto out; /* abuse current_chunk_p to store the file fd */ request->current_chunk_p = PyObject_AsFileDescriptor(request->iterable); if(do_sendfile(request)) goto out; } else { dprint("发送字符"); /* iterable */ if(send_chunk(request)){ dprint("一次发送即完成"); //uv_close((uv_handle_t*) &request->ev_watcher, _http_uv__on_close__cb); goto out; } if(request->iterator) { PyObject* next_chunk; dprint("request迭代"); next_chunk = wsgi_iterable_get_next_chunk(request); if(next_chunk) { dprint("下一块chunk发送"); if(request->state.chunked_response) { request->current_chunk = wrap_http_chunk_cruft_around(next_chunk); Py_DECREF(next_chunk); } else { request->current_chunk = next_chunk; } assert(request->current_chunk_p == 0); //io_write(request); goto out; } else { if(PyErr_Occurred()) { uv_err_t err; dprint("迭代出错"); PyErr_Print(); DBG_REQ(request, "Exception in iterator, can not recover"); uv_close((uv_handle_t*) request->ev_watcher, on_close); Request_free(request); err = uv_last_error(loop); UVERR(err, "uv_write error on next chunk"); ASSERT(0); goto out; } dprint("没有下一块chunk"); Py_CLEAR(request->iterator); } } if(request->state.chunked_response) { dprint("如果是chunked_response 发送收尾数据,并置空chunked_response"); /* We have to send a terminating empty chunk + \r\n */ request->current_chunk = PyString_FromString("0\r\n\r\n"); assert(request->current_chunk_p == 0); //io_write(request); request->state.chunked_response = false; goto out; } } dprint("响应完成"); if(request->state.keep_alive) { DBG_REQ(request, "done, keep-alive"); Request_clean(request); Request_reset(request); } else { dprint("done not keep alive"); uv_close((uv_handle_t*) request->ev_watcher, on_close); Request_free(request); } out: dprint("本次字符发送结束"); //GIL_UNLOCK(0); return; }
// Public void Request_cb(struct evhttp_request *req, void * data) { Request_T R = Request_new(req, data); Request_handle(R); Request_free(&R); }