int query_string_cb (http_parser *p, const char *buf, size_t len, char partial) { client_t *client = get_client(p); request *req = client->req; buffer_result ret = MEMORY_ERROR; if(req->query_string){ ret = write2buf(req->query_string, buf, len); }else{ req->query_string = new_buffer(1024*2, LIMIT_QUERY_STRING); ret = write2buf(req->query_string, buf, len); } switch(ret){ case MEMORY_ERROR: client->bad_request_code = 500; return -1; case LIMIT_OVER: client->bad_request_code = 400; return -1; default: break; } return 0; }
int fragment_cb (http_parser *p, const char *buf, size_t len, char partial) { client_t *client = get_client(p); register request *req = client->req; buffer_result ret = MEMORY_ERROR; if(req->fragment){ ret = write2buf(req->fragment, buf, len); }else{ req->fragment = new_buffer(1024, LIMIT_FRAGMENT); ret = write2buf(req->fragment, buf, len); } switch(ret){ case MEMORY_ERROR: client->bad_request_code = 500; return -1; case LIMIT_OVER: client->bad_request_code = 400; return -1; default: break; } return 0; }
static int url_cb(http_parser *p, const char *buf, size_t len) { request *req = get_current_request(p); buffer_result ret = MEMORY_ERROR; if(unlikely(req->path)){ ret = write2buf(req->path, buf, len); }else{ req->path = new_buffer(1024, LIMIT_PATH); ret = write2buf(req->path, buf, len); } switch(ret){ case MEMORY_ERROR: req->bad_request_code = 500; return -1; case LIMIT_OVER: req->bad_request_code = 400; return -1; default: break; } return 0; }
static PyObject* create_status(PyObject *bytes, int bytelen, int http_minor) { buffer_result r; buffer_t *b = new_buffer(256, 0); if(b == NULL){ return NULL; } if(http_minor == 1){ r = write2buf(b, "HTTP/1.1 ", 9); }else{ r = write2buf(b, "HTTP/1.0 ", 9); } if(r != WRITE_OK){ goto error; } r = write2buf(b, PyBytes_AS_STRING(bytes), bytelen); if(r != WRITE_OK){ goto error; } r = write2buf(b, "\r\n", 2); if(r != WRITE_OK){ goto error; } return getPyString(b); error: free_buffer(b); return NULL; }
int header_value_cb (http_parser *p, const char *buf, size_t len, char partial) { uint32_t i; header *h; client_t *client = get_client(p); request *req = client->req; buffer_result ret = MEMORY_ERROR; i = req->num_headers; h = req->headers[i]; if(h){ ret = write2buf(h->value, buf, len); } switch(ret){ case MEMORY_ERROR: client->bad_request_code = 500; return -1; case LIMIT_OVER: client->bad_request_code = 400; return -1; default: break; } req->last_header_element = VAL; return 0; }
int header_field_cb (http_parser *p, const char *buf, size_t len, char partial) { uint32_t i; header *h; client_t *client = get_client(p); request *req = client->req; char temp[len]; buffer_result ret = MEMORY_ERROR; if (req->last_header_element != FIELD){ if(LIMIT_REQUEST_FIELDS <= req->num_headers){ client->bad_request_code = 400; return -1; } req->num_headers++; } i = req->num_headers; h = req->headers[i]; key_upper(temp, buf, len); if(h){ ret = write2buf(h->field, temp, len); }else{ req->headers[i] = h = new_header(128, LIMIT_REQUEST_FIELD_SIZE, 1024, LIMIT_REQUEST_FIELD_SIZE); rack_header_type type = check_header_type(temp); if(type == OTHER){ ret = write2buf(h->field, "HTTP_", 5); } ret = write2buf(h->field, temp, len); //printf("%s \n", getString(h->field)); } switch(ret){ case MEMORY_ERROR: client->bad_request_code = 500; return -1; case LIMIT_OVER: client->bad_request_code = 400; return -1; default: break; } req->last_header_element = FIELD; return 0; }
static int write_body2mem(request *req, const char *buf, size_t buf_len) { buffer_t *body = (buffer_t*)req->body; write2buf(body, buf, buf_len); req->body_readed += buf_len; DEBUG("write_body2mem %d bytes", (int)buf_len); return req->body_readed; }
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; } }
buffer_t* get_converted_query(char *query, size_t len, PyObject *args) { buffer_t *qbuf; char *buf, *st; size_t buflen; int c, qlen, ret; buffer_result bret; PyObject *iter = NULL, *item = NULL; qbuf = new_buffer(1024 * 4, 0); if ( qbuf == NULL) { return NULL; } buf = st = query; buflen = len; if (args != NULL) { iter = PyObject_GetIter(args); if (iter == NULL || PyErr_Occurred()) { free_buffer(qbuf); return NULL; } } while(buflen > 0){ c = *buf++; if (c == '?'){ qlen = buf - st - 1; bret = write2buf(qbuf, st, qlen); if (bret != WRITE_OK) { goto error; } if (iter) { item = PyIter_Next(iter); if (item == NULL) { //TODO Set Error goto error; } //ret = convert_object(item); if (ret == -1) { goto error; } } st = buf; } buflen--; } DEBUG("%s", query); qlen = buf - st; bret = write2buf(qbuf, st, qlen); if (bret != WRITE_OK) { goto error; } return qbuf; error: free_buffer(qbuf); Py_XDECREF(item); Py_XDECREF(iter); return NULL; }