static void r_callback(picoev_loop* loop, int fd, int events, void* cb_arg) { client_t *cli = ( client_t *)(cb_arg); if ((events & PICOEV_TIMEOUT) != 0) { #ifdef DEBUG printf("** r_callback timeout ** \n"); #endif //timeout cli->keep_alive = 0; close_conn(cli, loop); } else if ((events & PICOEV_READ) != 0) { #ifdef DEBUG printf("ready read \n"); #endif /* update timeout, and read */ int finish = 0, nread; char buf[INPUT_BUF_SIZE]; ssize_t r; if(!cli->keep_alive){ picoev_set_timeout(loop, cli->fd, SHORT_TIMEOUT_SECS); } r = read(cli->fd, buf, sizeof(buf)); switch (r) { case 0: finish = 1; break; case -1: /* error */ if (errno == EAGAIN || errno == EWOULDBLOCK) { /* try again later */ break; } else { /* fatal error */ rb_raise(rb_eException, "fatal error"); // TODO: // raise exception from errno /* rb_raise(); */ /* write_error_log(__FILE__, __LINE__); */ cli->keep_alive = 0; cli->status_code = 500; close_conn(cli, loop); return; } break; default: #ifdef DEBUG printf("read request fd %d bufsize %d \n", cli->fd, r); #endif nread = execute_parse(cli, buf, r); if(cli->bad_request_code > 0){ #ifdef DEBUG printf("fd %d bad_request code %d \n", cli->fd, cli->bad_request_code); #endif send_error_page(cli); close_conn(cli, loop); return; } if( nread != r ){ // parse error #ifdef DEBUG printf("fd %d parse error %d \n", cli->fd, cli->bad_request_code); #endif cli->bad_request_code = 400; send_error_page(cli); close_conn(cli, loop); return; } #ifdef DEBUG printf("parse ok, fd %d %d nread \n", cli->fd, nread); #endif if(parser_finish(cli) > 0){ finish = 1; } break; } if(finish == 1){ prepare_call_rack(cli); call_rack_app(cli, loop); return; } } }
static void r_callback(picoev_loop* loop, int fd, int events, void* cb_arg) { client_t *cli = ( client_t *)(cb_arg); //PyObject *body = NULL; char *key = NULL; int finish = 0, nread; if ((events & PICOEV_TIMEOUT) != 0) { #ifdef DEBUG printf("** r_callback timeout %d ** \n", fd); #endif //timeout cli->keep_alive = 0; if(cli->request_queue->size > 0){ //piplining set_bad_request_code(cli, 408); finish = 1; }else{ close_conn(cli, loop); } } else if ((events & PICOEV_READ) != 0) { char buf[INPUT_BUF_SIZE]; ssize_t r; if(!cli->keep_alive){ picoev_set_timeout(loop, cli->fd, READ_TIMEOUT_SECS); } Py_BEGIN_ALLOW_THREADS r = read(cli->fd, buf, sizeof(buf)); Py_END_ALLOW_THREADS switch (r) { case 0: cli->keep_alive = 0; //503?? if(cli->request_queue->size > 0){ //piplining set_bad_request_code(cli, 503); finish = 1; }else{ cli->status_code = 503; send_error_page(cli); close_conn(cli, loop); return; } case -1: /* error */ if (errno == EAGAIN || errno == EWOULDBLOCK) { /* try again later */ break; } else { /* fatal error */ if(cli->request_queue->size > 0){ //piplining set_bad_request_code(cli, 500); if(errno != ECONNRESET){ PyErr_SetFromErrno(PyExc_IOError); write_error_log(__FILE__, __LINE__); } finish = 1; }else{ if(cli->keep_alive && errno == ECONNRESET){ cli->keep_alive = 0; cli->status_code = 500; cli->header_done = 1; cli->response_closed = 1; }else{ PyErr_SetFromErrno(PyExc_IOError); write_error_log(__FILE__, __LINE__); cli->keep_alive = 0; cli->status_code = 500; if(errno != ECONNRESET){ send_error_page(cli); }else{ cli->header_done = 1; cli->response_closed = 1; } } close_conn(cli, loop); return; } } break; default: #ifdef DEBUG printf("********************\n%s\n", buf); #endif nread = execute_parse(cli, buf, r); #ifdef DEBUG printf("read request fd %d readed %d nread %d \n", cli->fd, r, nread); #endif if(cli->bad_request_code > 0){ #ifdef DEBUG printf("fd %d bad_request code %d \n",cli->fd, cli->bad_request_code); #endif set_bad_request_code(cli, cli->bad_request_code); ///force end finish = 1; break; } if(!cli->upgrade && nread != r){ // parse error #ifdef DEBUG printf("fd %d parse error Bad Request %d \n", cli->fd, cli->bad_request_code); #endif set_bad_request_code(cli, 400); ///force end finish = 1; break; } #ifdef DEBUG printf("parse ok, fd %d %d nread \n", cli->fd, nread); #endif if(parser_finish(cli) > 0){ if(cli->upgrade){ //WebSocket Key #ifdef DEBUG printf("upgrade websocket %d \n", cli->fd); #endif key = buf + nread + 1; buffer *b = new_buffer(r - nread -1, r - nread -1); if(write2buf(b, key, r - nread -1) == WRITE_OK){ cli->request_queue->tail->body = b; }else{ free_buffer(b); } } finish = 1; } break; } }