static void setup_server_env(void) { setup_sock(listen_sock); cache_time_init(); setup_static_env(server_name, server_port); }
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); } }
int main(int argc, char * argv[]) { int sock; if (argc < 2) { printf("Usage: %s port\n", argv[0]); exit(EXIT_FAILURE); } sock = setup_sock(atoi(argv[1])); echo(sock); close(sock); }
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; }
void CGI_prefork_server(const char *host, int port, const char *pidfile, int maxproc, int minidle, int maxidle, int maxreq, void (*callback)(void)) { int i, sock, fd; struct score_state message; struct score_board *scb; pid_t pid; FILE *fp; int pfd[2]; char **realenv, **tmpenv; char *tmpbuf; extern char **environ; /* sanity check arguments */ if (callback == 0) { syslog(LOG_ERR, "CGI_prefork_server(): null callback " "function pointer"); return; } if (minidle <= 0) { minidle = 2; } if (maxidle <= minidle) { maxidle = minidle + 2; } if (maxproc <= 0) { maxproc = maxidle; } if (maxproc > SCORE_MAX_PROC) { maxproc = SCORE_MAX_PROC; } syslog(LOG_INFO, "CGI_prefork_server(): maxproc = %d, minidle = %d, " "maxidle = %d, maxreq = %d", maxproc, minidle, maxidle, maxreq); /* parent puts self into the background */ if (fork() != 0) { _exit(0); } setsid(); set_handler(SIGTERM, terminate); set_handler(SIGCHLD, child_handler); if ( freopen("/dev/null", "r", stdin) != 0 ) printf("freopen error\n"); if ( freopen("/dev/null", "w", stdout) != 0 ) printf("freopen2 error\n"); /* write our pid to pidfile */ if (pidfile != 0 && *pidfile != 0 && (fp = fopen(pidfile, "w")) != 0) { fprintf(fp, "%d\n", getpid()); fclose(fp); } /* create child process scoreboard */ scb = score_new(maxproc, minidle, maxidle); /* parent opens the listen socket, children accept() connections */ if ((sock = setup_sock(host, port)) < 0) { syslog(LOG_ERR, "CGI_prefork_server(): setup_sock() failed: %m"); return; } /* open pipe to receive messages from child processes */ if ( pipe(pfd) != 0 ) printf("pipe error\n"); /* parent manages child processes */ for (;;) { /* fork child if necessary */ if (scb->numidle < scb->minidle && scb->numproc < scb->maxproc) { if ((pid = fork()) == 0) { break; } else if (pid > 0) { score_add(scb, pid); continue; } else { syslog(LOG_ERR, "CGI_prefork_server(): fork() failed: %m"); if (scb->numproc == 0) { return; } } } /* * read status message from child. The read() call returns with * an error if we catch SIGCHLD or SIGTERM. */ if (child_exited == 0 && terminate_flag == 0 && read(pfd[0], &message, sizeof(message)) == sizeof(message)) { score_update(scb, &message); } /* kill everything and exit if we got SIGTERM */ if (terminate_flag != 0) { set_handler(SIGTERM, SIG_IGN); kill(0, SIGTERM); /* kill process group */ while(wait(0) >= 0) ; exit(0); } /* kill idle child if necessary */ if (scb->numidle > scb->maxidle) { score_kill(scb); } /* wait for exited children */ child_exited = 0; while ((pid = waitpid(-1, 0, WNOHANG)) > 0) { score_remove(scb, pid); } } /* child handles maxreq requests and exits */ set_handler(SIGTERM, SIG_DFL); set_handler(SIGCHLD, SIG_DFL); close(pfd[0]); message.pid = getpid(); realenv = environ; for (i = 0; i < maxreq || maxreq <= 0; i++) { /* accept connection from SCGI client (httpd) */ if ((fd = accept(sock, 0, 0)) < 0) { syslog(LOG_ERR, "CGI_prefork_server(): accept() failed: %m"); break; } /* notify parent we are busy */ message.state = SCORE_BUSY; if ( write(pfd[1], &message, sizeof(message)) != sizeof(message) ) printf("write error\n"); /* redirect stdin and stdout to socket */ dup2(fd, 0); dup2(fd, 1); close(fd); /* read environment and call callback */ if ((tmpenv = read_env()) != 0) { tmpbuf = tmpenv[0]; environ = tmpenv; callback(); } else { fputs("Content-type: text/plain\r\n\r\n" "CGI_prefork_server() could not read environment.\r\n", stdout); syslog(LOG_ERR, "CGI_prefork_server(): could not read " "environment"); } /* close socket and restore environment */ if ( freopen("/dev/null", "r", stdin) != 0 ) printf("freopen3 error\n"); if ( freopen("/dev/null", "w", stdout) != 0 ) printf("freopen4 error\n"); environ = realenv; if (tmpenv != 0) { free(tmpbuf); free(tmpenv); } /* notify parent we are idle */ message.state = SCORE_IDLE; if ( write(pfd[1], &message, sizeof(message)) != sizeof(message) ) printf("write2 error\n"); } _exit(0); }