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); } }
static void accept_cb(picoev_loop* loop, int fd, int revents, void* cb_arg) { int newfd; assert((revents & PICOEV_READ) != 0); if ((newfd = accept(fd, NULL, NULL)) != -1) { setup_sock(newfd); picoev_add(loop, newfd, PICOEV_READ, 0, read_cb, NULL); } }
static void accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg) { int newfd = accept(picoev_w32_fd2sock(fd), NULL, NULL); if (newfd != -1) { int sock = picoev_w32_sock2fd(newfd); printf("connected: %d\n", sock); setup_sock(newfd); picoev_add(loop, sock, PICOEV_READ, TIMEOUT_SECS, rw_callback, NULL); } }
static inline void close_conn(client_t *cli, picoev_loop* loop) { client_t *new_client; if(!cli->response_closed){ close_response(cli); } picoev_del(loop, cli->fd); clean_cli(cli); #ifdef DEBUG printf("start close client:%p fd:%d status_code %d \n", cli, cli->fd, cli->status_code); printf("picoev_del client:%p fd:%d \n", cli, cli->fd); printf("remain http pipeline size :%d \n", cli->request_queue->size); #endif if(cli->request_queue->size > 0){ if(check_status_code(cli) > 0){ //process pipeline prepare_call_wsgi(cli); call_wsgi_app(cli, loop); } return ; } if(cli->http != NULL){ PyMem_Free(cli->http); } free_request_queue(cli->request_queue); if(!cli->keep_alive){ close(cli->fd); #ifdef DEBUG printf("close client:%p fd:%d status_code %d \n", cli, cli->fd, cli->status_code); #endif }else{ disable_cork(cli); new_client = new_client_t(cli->fd, cli->remote_addr, cli->remote_port); new_client->keep_alive = 1; init_parser(new_client, server_name, server_port); picoev_add(main_loop, new_client->fd, PICOEV_READ, keep_alive_timeout, r_callback, (void *)new_client); } //PyMem_Free(cli); dealloc_client(cli); #ifdef DEBUG printf("********************\n\n"); #endif }
int main(void) { picoev_loop* loop; int listen_sock, flag; /* listen to port */ assert((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) != -1); flag = 1; assert(setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == 0); struct sockaddr_in listen_addr; listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(PORT); listen_addr.sin_addr.s_addr = htonl(HOST); assert(bind(listen_sock, (struct sockaddr*)&listen_addr, sizeof(listen_addr)) == 0); assert(listen(listen_sock, 5) == 0); setup_sock(listen_sock); /* init picoev */ picoev_init(MAX_FDS); /* create loop */ loop = picoev_create_loop(60); /* add listen socket */ picoev_add(loop, listen_sock, PICOEV_READ, 0, accept_callback, NULL); /* Seccomp sandbox setup */ sandbox_init(); sandbox_setup(); sandbox_lockdown(); /* loop */ while (1) { fputc('.', stdout); fflush(stdout); picoev_loop_once(loop, 10); } /* cleanup */ picoev_destroy_loop(loop); picoev_deinit(); return 0; }
static void accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg) { int client_fd; client_t *client; struct sockaddr_in client_addr; if ((events & PICOEV_TIMEOUT) != 0) { // time out // next turn or other process return; }else if ((events & PICOEV_READ) != 0) { socklen_t client_len = sizeof(client_addr); #ifdef linux client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC); #else client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len); #endif if (client_fd != -1) { #ifdef DEBUG printf("accept fd %d \n", client_fd); #endif setup_sock(client_fd); client = new_client_t(client_fd, client_addr); client->environ = Qnil; rb_gc_register_address(&client->environ); init_parser(client, server_name, server_port); picoev_add(loop, client_fd, PICOEV_READ, READ_LONG_TIMEOUT_SECS, r_callback, (void *)client); }else{ if (errno != EAGAIN && errno != EWOULDBLOCK) { // TODO: // raise exception from errno /* rb_raise(); */ /* write_error_log(__FILE__, __LINE__); */ // die loop_done = 0; } } } }
int main(int argc, char** argv) { int ch, r, flag; struct sockaddr_in listen_addr; picoev_loop* loop; while ((ch = getopt(argc, argv, "p:")) != -1) { switch (ch) { case 'p': assert(sscanf(optarg, "%hu", &port) == 1); break; default: exit(1); } } listen_sock = socket(AF_INET, SOCK_STREAM, 0); assert(listen_sock != -1); flag = 1; r = setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); assert(r == 0); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(port); listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); r = bind(listen_sock, (struct sockaddr*)&listen_addr, sizeof(listen_addr)); assert(r == 0); setup_sock(listen_sock); r = listen(listen_sock, SOMAXCONN); assert(r == 0); picoev_init(1048576 + 10); loop = picoev_create_loop(60); picoev_add(loop, listen_sock, PICOEV_READ, 0, accept_cb, NULL); while (1) { picoev_loop_once(loop, 10); } return 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); } }
static VALUE bossan_run_loop(int argc, VALUE *argv, VALUE self) { int ret; VALUE args1, args2, args3; rb_scan_args(argc, argv, "21", &args1, &args2, &args3); if(listen_sock > 0){ rb_raise(rb_eException, "already set listen socket"); } if (argc == 3){ server_name = StringValuePtr(args1); server_port = NUM2INT(args2); long _port = NUM2INT(args2); if (_port <= 0 || _port >= 65536) { // out of range rb_raise(rb_eArgError, "port number outside valid range"); } server_port = (short)_port; ret = inet_listen(); rack_app = args3; } else { Check_Type(args1, T_STRING); ret = unix_listen(StringValuePtr(args1)); rack_app = args2; } if(ret < 0){ //error listen_sock = -1; } if(listen_sock <= 0){ rb_raise(rb_eTypeError, "not found listen socket"); } /* init picoev */ picoev_init(MAX_FDS); /* create loop */ main_loop = picoev_create_loop(60); loop_done = 1; setsig(SIGPIPE, sigpipe_cb); setsig(SIGINT, sigint_cb); setsig(SIGTERM, sigint_cb); picoev_add(main_loop, listen_sock, PICOEV_READ, ACCEPT_TIMEOUT_SECS, accept_callback, NULL); /* loop */ while (loop_done) { picoev_loop_once(main_loop, 10); } picoev_destroy_loop(main_loop); picoev_deinit(); printf("Bye.\n"); return Qnil; }
int main(int argc, char** argv) { int ch, i, r; picoev_loop* loop; struct timeval start_at, end_at; double elapsed; host.s_addr = htonl(0x7f000001); while ((ch = getopt(argc, argv, "a:c:n:fh:p:")) != -1) { switch (ch) { case 'a': assert(sscanf(optarg, "%d", &active_connections) == 1); break; case 'c': assert(sscanf(optarg, "%d", &num_connections) == 1); break; case 'n': assert(sscanf(optarg, "%d", &num_requests) == 1); break; case 'f': fix_clients = 1; break; case 'h': if (inet_aton(optarg, &host) == 0) { struct hostent* h = gethostbyname(optarg); assert(h != NULL && "host not found"); assert(h->h_addrtype == AF_INET); assert(h->h_length == sizeof(host)); memcpy(&host, h->h_addr_list[0], sizeof(host)); } break; case 'p': assert(sscanf(optarg, "%hu", &port) == 1); break; default: exit(1); } } picoev_init(num_connections + 10); loop = picoev_create_loop(60); /* setup connections */ for (i = 0; i < num_connections; ++i) { int on; struct sockaddr_in addr; int fd = socket(AF_INET, SOCK_STREAM, 0); assert(fd != -1 && "socket(2) failed"); on = 1; addr.sin_family = AF_INET; addr.sin_port = htons(port); memcpy(&addr.sin_addr, &host, sizeof(host)); printf("try to connect\n"); r = connect(fd, (struct sockaddr*)&addr, sizeof(addr)); if (r == -1) { perror("could not connect to server"); exit(2); } r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); assert(r == 0); r = fcntl(fd, F_SETFL, O_NONBLOCK); assert(r == 0); picoev_add(loop, fd, PICOEV_READ, 0, read_cb, NULL); fds[i] = fd; usleep(1000); } gettimeofday(&start_at, NULL); /* fire first active_connections */ printf("fire!\n"); for (i = 0; i < active_connections; ++i) { r = write(fds[next_fd_idx], "hello\n", 6); assert(r == 6); next_fd_idx = (next_fd_idx + 1) % num_connections; } /* the main loop */ while (num_responses < num_requests) { picoev_loop_once(loop, 10); } gettimeofday(&end_at, NULL); elapsed = end_at.tv_sec + end_at.tv_usec / 1000000.0 - (start_at.tv_sec + start_at.tv_usec / 1000000.0); printf("%f reqs./sec. (%d in %f seconds)\n", num_responses / elapsed, num_responses, elapsed); return 0; }