//parent proc int parentproc( int port) { int childstatus; unsigned long long timeoutlong=0; struct timeval timeout; int ret; fd_set read_fd_set; fd_set write_fd_set; fd_set except_fd_set; int maxfd = -1; struct SPDY_Daemon *daemon; SPDY_init(); daemon = SPDY_start_daemon(port, DATA_DIR "cert-and-key.pem", DATA_DIR "cert-and-key.pem", NULL,&session_closed_handler,&standard_request_handler,NULL,CLS,SPDY_DAEMON_OPTION_END); if(NULL==daemon){ printf("no daemon\n"); return 1; } do { FD_ZERO(&read_fd_set); FD_ZERO(&write_fd_set); FD_ZERO(&except_fd_set); ret = SPDY_get_timeout(daemon, &timeoutlong); if(SPDY_NO == ret || timeoutlong > 1000) { timeout.tv_sec = 1; timeout.tv_usec = 0; } else { timeout.tv_sec = timeoutlong / 1000; timeout.tv_usec = (timeoutlong % 1000) * 1000; } maxfd = SPDY_get_fdset (daemon, &read_fd_set, &write_fd_set, &except_fd_set); ret = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout); switch(ret) { case -1: printf("select error: %i\n", errno); killchild(child, "select error"); break; case 0: break; default: SPDY_run(daemon); break; } } while(waitpid(child,&childstatus,WNOHANG) != child); //give chance to the client to close socket and handle this in run usleep(100000); SPDY_run(daemon); SPDY_stop_daemon(daemon); SPDY_deinit(); return WEXITSTATUS(childstatus); }
int main (int argc, char *const *argv) { unsigned long long timeoutlong=0; struct timeval timeout; int ret; fd_set read_fd_set; fd_set write_fd_set; fd_set except_fd_set; int maxfd = -1; struct SPDY_Daemon *daemon; if(argc != 2) { return 1; } SPDY_init(); daemon = SPDY_start_daemon(atoi(argv[1]), DATA_DIR "cert-and-key.pem", DATA_DIR "cert-and-key.pem", NULL, NULL, &standard_request_handler, NULL, NULL, SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 1800, SPDY_DAEMON_OPTION_END); if(NULL==daemon) { printf("no daemon\n"); return 1; } do { FD_ZERO(&read_fd_set); FD_ZERO(&write_fd_set); FD_ZERO(&except_fd_set); ret = SPDY_get_timeout(daemon, &timeoutlong); if(SPDY_NO == ret || timeoutlong > 1000) { timeout.tv_sec = 1; timeout.tv_usec = 0; } else { timeout.tv_sec = timeoutlong / 1000; timeout.tv_usec = (timeoutlong % 1000) * 1000; } maxfd = SPDY_get_fdset (daemon, &read_fd_set, &write_fd_set, &except_fd_set); ret = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout); switch(ret) { case -1: printf("select error: %i\n", errno); break; case 0: break; default: SPDY_run(daemon); break; } } while(run); SPDY_stop_daemon(daemon); SPDY_deinit(); return 0; }
//parent proc int parentproc(int child) { int childstatus = 0; unsigned long long timeoutlong=0; struct timeval timeout; int ret; fd_set read_fd_set; fd_set write_fd_set; fd_set except_fd_set; int maxfd = -1; struct SPDY_Daemon *daemon; SPDY_init(); daemon = SPDY_start_daemon(port, DATA_DIR "cert-and-key.pem", DATA_DIR "cert-and-key.pem", &new_session_callback,NULL,NULL,NULL,CLS,SPDY_DAEMON_OPTION_END); if(NULL==daemon){ printf("no daemon\n"); return 1; } do { FD_ZERO(&read_fd_set); FD_ZERO(&write_fd_set); FD_ZERO(&except_fd_set); ret = SPDY_get_timeout(daemon, &timeoutlong); if(SPDY_NO == ret || timeoutlong > 1000) { timeout.tv_sec = 1; timeout.tv_usec = 0; } else { timeout.tv_sec = timeoutlong / 1000; timeout.tv_usec = (timeoutlong % 1000) * 1000; } maxfd = SPDY_get_fdset (daemon, &read_fd_set, &write_fd_set, &except_fd_set); ret = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout); switch(ret) { case -1: printf("select error: %i\n", errno); killchild(child, "select error"); break; case 0: break; default: SPDY_run(daemon); break; } } while(loop && waitpid(child,&childstatus,WNOHANG) != child); SPDY_stop_daemon(daemon); SPDY_deinit(); if(loop) return WEXITSTATUS(childstatus); if(waitpid(child,&childstatus,WNOHANG) == child) return WEXITSTATUS(childstatus); kill(child,SIGKILL); waitpid(child,&childstatus,0); return 0; }
static int parentproc() { int childstatus; unsigned long long timeoutlong=0; struct timeval timeout; int ret; fd_set read_fd_set; fd_set write_fd_set; fd_set except_fd_set; int maxfd = -1; struct SPDY_Daemon *daemon; unsigned long long beginning = 0; unsigned long long now; SPDY_init(); daemon = SPDY_start_daemon(port, DATA_DIR "cert-and-key.pem", DATA_DIR "cert-and-key.pem", &new_session_cb, &closed_session_cb, NULL, NULL, NULL, SPDY_DAEMON_OPTION_SESSION_TIMEOUT, TIMEOUT, SPDY_DAEMON_OPTION_END); if(NULL==daemon){ printf("no daemon\n"); return 1; } do { do_sleep=0; FD_ZERO(&read_fd_set); FD_ZERO(&write_fd_set); FD_ZERO(&except_fd_set); ret = SPDY_get_timeout(daemon, &timeoutlong); if(new_session && !closed_session) { if(SPDY_NO == ret) { killchild("SPDY_get_timeout returned wrong SPDY_NO"); } /*if(timeoutlong) { killchild("SPDY_get_timeout returned wrong timeout"); }*/ now = monotonic_time (); if(now - beginning > TIMEOUT*1000 + SELECT_MS_TIMEOUT) { printf("Started at: %llums\n",beginning); printf("Now is: %llums\n",now); printf("Timeout is: %i\n",TIMEOUT); printf("Select Timeout is: %ims\n",SELECT_MS_TIMEOUT); printf("SPDY_get_timeout gave: %llums\n",timeoutlong); killchild("Timeout passed but session was not closed"); } if(timeoutlong > beginning + TIMEOUT *1000) { printf("Started at: %llums\n",beginning); printf("Now is: %llums\n",now); printf("Timeout is: %i\n",TIMEOUT); printf("Select Timeout is: %ims\n",SELECT_MS_TIMEOUT); printf("SPDY_get_timeout gave: %llums\n",timeoutlong); killchild("SPDY_get_timeout returned wrong timeout"); } } else { if(SPDY_YES == ret) { killchild("SPDY_get_timeout returned wrong SPDY_YES"); } } if(SPDY_NO == ret || timeoutlong >= 1000) { timeout.tv_sec = 1; timeout.tv_usec = 0; } else { timeout.tv_sec = timeoutlong / 1000; timeout.tv_usec = (timeoutlong % 1000) * 1000; } //ignore values timeout.tv_sec = 0; timeout.tv_usec = SELECT_MS_TIMEOUT * 1000; maxfd = SPDY_get_fdset (daemon, &read_fd_set, &write_fd_set, &except_fd_set); ret = select(maxfd+1, &read_fd_set, &write_fd_set, &except_fd_set, &timeout); switch(ret) { case -1: printf("select error: %i\n", errno); break; case 0: /*if(new_session) { killchild("select returned wrong number"); }*/ break; default: SPDY_run(daemon); if(0 == beginning) { beginning = monotonic_time (); } /*if(do_sleep) { sleep(TIMEOUT); do_sleep = 0; }*/ break; } } while(waitpid(child,&childstatus,WNOHANG) != child); if(!new_session || !closed_session) { killchild("child is dead, callback wasn't called"); } ret = SPDY_get_timeout(daemon, &timeoutlong); if(SPDY_YES == ret) { killchild("SPDY_get_timeout returned wrong SPDY_YES after child died"); } SPDY_stop_daemon(daemon); SPDY_deinit(); return 0; }
static int run () { unsigned long long timeoutlong = 0; unsigned long long timeout_spdy = 0; long timeout_curl = -1; struct timeval timeout; int ret; int ret_curl; int ret_spdy; fd_set rs; fd_set ws; fd_set es; int maxfd = -1; int maxfd_curl = -1; struct SPDY_Daemon *daemon; CURLMsg *msg; int msgs_left; struct Proxy *proxy; struct sockaddr_in *addr; struct addrinfo hints; char service[NI_MAXSERV]; struct addrinfo *gai; enum SPDY_IO_SUBSYSTEM io = glob_opt.notls ? SPDY_IO_SUBSYSTEM_RAW : SPDY_IO_SUBSYSTEM_OPENSSL; enum SPDY_DAEMON_FLAG flags = SPDY_DAEMON_FLAG_NO; signal(SIGPIPE, SIG_IGN); if (signal(SIGINT, catch_signal) == SIG_ERR) PRINT_VERBOSE("signal failed"); srand(time(NULL)); if(init_parse_uri(&uri_preg)) DIE("Regexp compilation failed"); SPDY_init(); if(glob_opt.nodelay) flags |= SPDY_DAEMON_FLAG_NO_DELAY; if(NULL == glob_opt.listen_host) { daemon = SPDY_start_daemon(glob_opt.listen_port, glob_opt.cert, glob_opt.cert_key, &new_session_cb, &session_closed_cb, &standard_request_handler, NULL, NULL, SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 1800, SPDY_DAEMON_OPTION_IO_SUBSYSTEM, io, SPDY_DAEMON_OPTION_FLAGS, flags, SPDY_DAEMON_OPTION_END); } else { snprintf (service, sizeof(service), "%u", glob_opt.listen_port); memset (&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; ret = getaddrinfo(glob_opt.listen_host, service, &hints, &gai); if(ret != 0) DIE("problem with specified host"); addr = (struct sockaddr_in *) gai->ai_addr; daemon = SPDY_start_daemon(0, glob_opt.cert, glob_opt.cert_key, &new_session_cb, &session_closed_cb, &standard_request_handler, NULL, NULL, SPDY_DAEMON_OPTION_SESSION_TIMEOUT, 1800, SPDY_DAEMON_OPTION_IO_SUBSYSTEM, io, SPDY_DAEMON_OPTION_FLAGS, flags, SPDY_DAEMON_OPTION_SOCK_ADDR, addr, SPDY_DAEMON_OPTION_END); } if(NULL==daemon){ printf("no daemon\n"); return 1; } multi_handle = curl_multi_init(); if(NULL==multi_handle) DIE("no multi_handle"); timeout.tv_usec = 0; do { FD_ZERO(&rs); FD_ZERO(&ws); FD_ZERO(&es); ret_spdy = SPDY_get_timeout(daemon, &timeout_spdy); if(SPDY_NO == ret_spdy || timeout_spdy > 5000) timeoutlong = 5000; else timeoutlong = timeout_spdy; PRINT_VERBOSE2("SPDY timeout %i; %i", timeout_spdy, ret_spdy); if(CURLM_OK != (ret_curl = curl_multi_timeout(multi_handle, &timeout_curl))) { PRINT_VERBOSE2("curl_multi_timeout failed (%i)", ret_curl); //curl_timeo = timeoutlong; } else if(timeoutlong > timeout_curl) timeoutlong = timeout_curl; PRINT_VERBOSE2("curl timeout %i", timeout_curl); timeout.tv_sec = timeoutlong / 1000; timeout.tv_usec = (timeoutlong % 1000) * 1000; maxfd = SPDY_get_fdset (daemon, &rs, &ws, &es); assert(-1 != maxfd); if(CURLM_OK != (ret = curl_multi_fdset(multi_handle, &rs, &ws, &es, &maxfd_curl))) { PRINT_INFO2("curl_multi_fdset failed (%i)", ret); abort(); } if(maxfd_curl > maxfd) maxfd = maxfd_curl; PRINT_VERBOSE2("timeout before %i %i", timeout.tv_sec, timeout.tv_usec); ret = select(maxfd+1, &rs, &ws, &es, &timeout); PRINT_VERBOSE2("timeout after %i %i; ret is %i", timeout.tv_sec, timeout.tv_usec, ret); /*switch(ret) { case -1: PRINT_INFO2("select error: %i", errno); break; case 0: break; default:*/ //the second part should not happen with current implementation if(ret > 0 || (SPDY_YES == ret_spdy && 0 == timeout_spdy)) { PRINT_VERBOSE("run spdy"); SPDY_run(daemon); call_spdy_run = false; } if(ret > 0 || (CURLM_OK == ret_curl && 0 == timeout_curl) || call_curl_run) { PRINT_VERBOSE("run curl"); if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running)) && CURLM_CALL_MULTI_PERFORM != ret) { PRINT_INFO2("curl_multi_perform failed (%i)", ret); abort(); } call_curl_run = false; } /*break; }*/ while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { if (msg->msg == CURLMSG_DONE) { if(CURLE_OK == msg->data.result) { if(CURLE_OK != (ret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &proxy))) { PRINT_INFO2("err %i",ret); abort(); } proxy->done = true; call_spdy_run = true; } else { PRINT_VERBOSE2("bad curl result for '%s'", proxy->url); proxy->done = true; call_spdy_run = true; //TODO spdy should be notified to send RST_STREAM } } else PRINT_INFO("shouldn't happen"); } if(call_spdy_run) { PRINT_VERBOSE("second call to SPDY_run"); SPDY_run(daemon); call_spdy_run = false; } if(glob_opt.verbose) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) PRINT_VERBOSE2("time now %i %i", ts.tv_sec, ts.tv_nsec); } } while(loop); curl_multi_cleanup(multi_handle); SPDY_stop_daemon(daemon); SPDY_deinit(); deinit_parse_uri(&uri_preg); return 0; }