Beispiel #1
0
static inline void
call_wsgi_app(client_t *client, picoev_loop* loop)
{
    int ret;
    ret = process_wsgi_app(client);

#ifdef DEBUG
    printf("call_wsgi_app result %d \n", ret);
#endif
    switch(ret){
        case -1:
            //Internal Server Error
            client->bad_request_code = 500;
            send_error_page(client);
            close_conn(client, loop);
            return;
        case 0:
            // suspend
            return;
        default:
            break;
    }
    
    
    if(client->response_closed){
        //closed
        close_conn(client, loop);
        return;
    }
    ret = response_start(client);
#ifdef DEBUG
    printf("response_start result %d \n", ret);
#endif
    switch(ret){
        case -1:
            // Internal Server Error
            client->bad_request_code = 500;
            send_error_page(client);
            close_conn(client, loop);
            return;
        case 0:
            // continue
            // set callback
#ifdef DEBUG
            printf("set write callback %d \n", ret);
#endif
            //clear event
            picoev_del(loop, client->fd);
            picoev_add(loop, client->fd, PICOEV_WRITE, 0, w_callback, (void *)client);
            return;
        default:
            // send OK
            close_conn(client, loop);
    }
    
    
}
Beispiel #2
0
static void
call_rack_app(client_t *client, picoev_loop* loop)
{
  int ret;
  if(!process_rack_app(client)){
    //Internal Server Error
    client->bad_request_code = 500;
    send_error_page(client);
    close_conn(client, loop);
    return;
  }

  ret = response_start(client);
  /* printf("response_start done: %d\n", ret); */
  switch(ret){
  case -1:
    // Internal Server Error
    client->bad_request_code = 500;
    send_error_page(client);
    close_conn(client, loop);
    return;
  case 0:
    // continue
    // set callback
#ifdef DEBUG
    printf("set write callback %d \n", ret);
#endif
    //clear event
    picoev_del(loop, client->fd);
    picoev_add(loop, client->fd, PICOEV_WRITE, WRITE_TIMEOUT_SECS, w_callback, (void *)client);
    return;
  default:
    // send OK
    close_conn(client, loop);
  }
}
Beispiel #3
0
static inline int
check_status_code(client_t *client)
{
    request *req;
    req = client->request_queue->head;
    if(req->bad_request_code > 200){
        //error
        //shift 
#ifdef DEBUG
        printf("bad_request_code \n");
#endif 
        set_current_request(client);
        send_error_page(client);
        close_conn(client, main_loop);
        return 0;
    }
    return 1;
    
}
Beispiel #4
0
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;
    }
  }
}
Beispiel #5
0
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;
        }
    }
Beispiel #6
0
static inline void
prepare_call_wsgi(client_t *client)
{
    PyObject *input = NULL, *c = NULL;
    char *val;
    
    set_current_request(client);
    
    //check Expect
    if(client->http->http_minor == 1){
        c = PyDict_GetItemString(client->environ, "HTTP_EXPECT");
        if(c){
            val = PyString_AS_STRING(c);
            if(!strcasecmp(val, "100-continue")){
                int ret = write(client->fd, "HTTP/1.1 100 Continue\r\n\r\n", 25);
                if(ret < 0){
                    PyErr_SetFromErrno(PyExc_IOError);
                    write_error_log(__FILE__, __LINE__); 
                    client->keep_alive = 0;
                    client->status_code = 500;
                    send_error_page(client);
                    close_conn(client, main_loop);
                    return;
                }
            }else{
                //417
                client->keep_alive = 0;
                client->status_code = 417;
                send_error_page(client);
                close_conn(client, main_loop);
                return;
            }
        }
    }
    if(client->body_type == BODY_TYPE_TMPFILE){
        FILE *tmp = (FILE *)client->body;
        fflush(tmp);
        rewind(tmp);
        input = PyFile_FromFile(tmp, "<tmpfile>", "r", fclose);
        PyDict_SetItem((PyObject *)client->environ, wsgi_input_key, input);
        Py_DECREF(input);
        client->body = NULL;
    }else{
        if(client->body_type == BODY_TYPE_BUFFER){
            input = StringIOObject_New((buffer *)client->body);
            PyDict_SetItem((PyObject *)client->environ, wsgi_input_key, input);
        }else{
            if(client->body){
                input = StringIOObject_New((buffer *)client->body);
            }else{
                input = StringIOObject_New(new_buffer(0, 0));
            }
            PyDict_SetItem((PyObject *)client->environ, wsgi_input_key, input);
        }
        client->body = NULL;;
        Py_DECREF(input);
    }

    if(is_keep_alive){
        //support keep-alive
        c = PyDict_GetItemString(client->environ, "HTTP_CONNECTION");
        if(client->http->http_minor == 1){
            //HTTP 1.1
            if(c){
                val = PyString_AS_STRING(c);
                if(!strcasecmp(val, "close")){
                    client->keep_alive = 0;
                }else{
                    client->keep_alive = 1;
                }
            }else{
                client->keep_alive = 1;
            }
        }else{
            //HTTP 1.0
            if(c){
                val = PyString_AS_STRING(c);
                if(!strcasecmp(val, "keep-alive")){
                    client->keep_alive = 1;
                }else{
                    client->keep_alive = 0;
                }
            }else{
                client->keep_alive = 0;
            }
        }
    }
}