Esempio n. 1
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;
    }
  }
}
Esempio n. 2
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;
        }
    }