static int loop(int type) { void (*workfn) (int ci); void (*deadfn) (int ci); int rv, i; rv = setup_config(type); if (rv < 0) goto fail; rv = setup_timer(); if (rv < 0) goto fail; rv = setup_transport(); if (rv < 0) goto fail; rv = setup_ticket(); if (rv < 0) goto fail; rv = setup_listener(BOOTHC_SOCK_PATH); if (rv < 0) goto fail; client_add(rv, process_listener, NULL); while (1) { rv = poll(pollfd, client_maxi + 1, poll_timeout); if (rv == -1 && errno == EINTR) continue; if (rv < 0) { log_error("poll errno %d", errno); goto fail; } for (i = 0; i <= client_maxi; i++) { if (client[i].fd < 0) continue; if (pollfd[i].revents & POLLIN) { workfn = client[i].workfn; if (workfn) workfn(i); } if (pollfd[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { deadfn = client[i].deadfn; if (deadfn) deadfn(i); } } process_timerlist(); } return 0; fail: return -1; }
static int serve(lua_State* l) { int port = luaL_checkint(l, 1); luaL_checktype(l, 2, LUA_TFUNCTION); if(port <= 0 || port > 65535) { return luaL_error(l, "port number must be within between 1 and 65535"); } orka_server_t* server = malloc(sizeof(*server)); server->port = port; server->lua = l; lua_pushvalue(l, 2); server->handler_ref = luaL_ref(l, LUA_REGISTRYINDEX); server->fd = setup_listener("0.0.0.0", server->port); if(server->fd < 0) { free(server); return orka_error(l, "setup_listener"); } if(pthread_create(&server->thread, NULL, server_thread_main, server) < 0) { return orka_error(l, "pthread_create"); } return 0; }
static int setup(int type) { int rv; rv = setup_config(type); if (rv < 0) goto fail; rv = setup_timer(); if (rv < 0) goto fail; rv = setup_transport(); if (rv < 0) goto fail; rv = setup_ticket(); if (rv < 0) goto fail; rv = setup_listener(BOOTHC_SOCK_PATH); if (rv < 0) goto fail; client_add(rv, process_listener, NULL); return 0; fail: return -1; }
int _main(config_t *config) { pthread_t server_tid= 0; signal(SIGTERM, sig_handler); signal(SIGINT, sig_handler); signal(SIGPIPE, sig_handler); signal(SIGHUP, sig_handler); setproctitle("starting"); s_listen = mallocz_or_die(sizeof(*s_listen)); worker_pool_init_static(config); server_tid= setup_listener(config); graphite_worker= mallocz_or_die(sizeof(graphite_worker_t)); pthread_create(&graphite_worker->tid, NULL, graphite_worker_thread, graphite_worker); for (;;) { int abort; abort= get_abort_val(); if (abort & STOP) { break; } else if (abort & RELOAD) { if (config_reload(config)) { stop_listener(server_tid); server_tid= setup_listener(config); worker_pool_reload_static(config); /* XXX: check me */ /* check and see if we need to stop the old graphite processor and replace it */ graphite_worker_destroy(graphite_worker); pthread_create(&graphite_worker->tid, NULL, graphite_worker_thread, graphite_worker); } unset_abort_bits(RELOAD); } mark_second_elapsed(); sleep(1); } final_shutdown(server_tid); SAY("bye"); closelog(); return(0); }
int main(int argc, char **argv) { int fd; int nfd; int c; /* process arguments */ while ((c = getopt(argc, argv, POS "d")) != -1) { switch (c) { case 'd': debug = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 2) usage(); fd = setup_listener(atoi(argv[0])); if (fd == -1) exit(1); /* don't bother reaping, this is a test program... */ signal(SIGCHLD, SIG_IGN); for (;;) { pid_t kid; nfd = accept(fd, NULL, NULL); kid = fork(); switch (kid) { case -1: /* XXXrcd: error. */ close(nfd); fprintf(stderr, "fork: %s\n", strerror(errno)); break; case 0: close(fd); serve_file(nfd, argv[1]); exit(0); default: close(nfd); break; } } }
int main(int argc, char *argv[]) { cfg.prog = argv[0]; cfg.prog=argv[0]; cfg.pid = getpid(); int n, signo, opt, *fd; siginfo_t info; utarray_new(cfg.fds,&ut_int_icd); while ( (opt=getopt(argc,argv,"vp:a:h")) != -1) { switch(opt) { case 'v': cfg.verbose++; break; case 'p': cfg.port=atoi(optarg); break; case 'a': cfg.addr=inet_addr(optarg); break; case 'h': default: usage(); break; } } if (cfg.addr == INADDR_NONE) usage(); if (cfg.port==0) usage(); /* block all signals. we only take signals synchronously in sigwaitinfo */ sigset_t all; sigfillset(&all); sigprocmask(SIG_SETMASK,&all,NULL); /* make a set of the signals we accept in sigwaitinfo. others blocked */ sigset_t sw; sigemptyset(&sw); for(n=0; n < sizeof(sigs)/sizeof(*sigs); n++) sigaddset(&sw, sigs[n]); if (setup_listener()) goto done; alarm(1); while ( (signo = sigwaitinfo(&sw, &info)) > 0) { switch (signo) { case SIGALRM: if ((++cfg.ticks % 10) == 0) periodic(); alarm(1); break; case SIGIO: service_network(); break; default: printf("got signal %d\n", signo); goto done; } } done: fd=NULL; while ( (fd=(int*)utarray_next(cfg.fds,fd))) close(*fd); utarray_free(cfg.fds); return 0; }
int main(int argc, char **argv){ if(argc != 3){ printf("Usage: rfss mode<s|c> port\n"); exit(1); } if(strcmp(argv[1],"c")==0) set_mode(CLIENT); else if(strcmp(argv[1],"s")==0) set_mode(SERVER); else{ printf("Invalid mode: mode can take value of s or c only\n"); exit(1); } char *endptr; int port = (int) strtol(argv[2], &endptr, 10); if(*endptr != 0){ printf("Invalid port\n"); exit(1); } setup_listener(port); setbuf(stdout, NULL); rfss_process_command(); }
static void run_listener(const char* fifo, const guint16 port, const char* proto_name) { struct sockaddr_in clientaddr; int clientlen = sizeof(clientaddr); socket_handle_t sock; char* buf; ssize_t buflen; FILE* fp = NULL; if (signal(SIGINT, exit_from_loop) == SIG_ERR) { g_warning("Can't set signal handler"); return; } if (setup_dumpfile(fifo, &fp) == EXIT_FAILURE) { if (fp) fclose(fp); return; } if (setup_listener(port, &sock) == EXIT_FAILURE) return; g_debug("Listener running on port %u", port); buf = (char*)g_malloc(PKT_BUF_SIZE); while(run_loop == TRUE) { memset(buf, 0x0, PKT_BUF_SIZE); buflen = recvfrom(sock, buf, PKT_BUF_SIZE, 0, (struct sockaddr *)&clientaddr, &clientlen); if (buflen < 0) { switch(errno) { case EAGAIN: case EINTR: break; default: #ifdef _WIN32 { wchar_t *errmsg = NULL; int err = WSAGetLastError(); FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&errmsg, 0, NULL); g_warning("Error in recvfrom: %S (err=%d)", errmsg, err); LocalFree(errmsg); } #else g_warning("Error in recvfrom: %s (errno=%d)", strerror(errno), errno); #endif run_loop = FALSE; break; } } else { if (dump_packet(proto_name, port, buf, buflen, clientaddr, fp) == EXIT_FAILURE) run_loop = FALSE; } } fclose(fp); closesocket(sock); g_free(buf); }
int main(int argc, char **argv) { char *user, *group, *interface, *root, *port, *cmd; int niceinc; int nofork; int timeout; int instances; int queue; int reuse; int keepalive; int what; int value; int offset; int i, j; char c; int lfd; int nfd; struct sigaction sag; sigset_t sst; int status; int hang; int busy; int tos; int ttl; int sane; int just; #ifdef USE_IDSA int exitcode; int killcode; int flags; unsigned int arisk, crisk, irisk, risk; #endif double limit_load = 0.0; port = NULL; user = NULL; group = NULL; root = NULL; interface = NULL; cmd = NULL; just = 0; sane = 1; reuse = 1; keepalive = 1; niceinc = 0; nofork = 0; timeout = 0; instances = 0; queue = 5; tos = 0; ttl = 0; offset = 0; #ifdef USE_IDSA flags = 0; arisk = idsa_risk_make(-0.3,0.8); crisk = IDSA_R_UNKNOWN; irisk = IDSA_R_PARTIAL; #endif i = j = 1; while (i < argc) { if (argv[i][0] == '-') { c = argv[i][j]; switch (c) { case 'c': printf("(c) 2002,2007 Marc Welz: Distributed under the terms of the GNU General Public License\n"); exit(0); break; case 'h': /* print brief help message */ case '?': usage(argv[0]); exit(0); break; case 'v': #ifdef USE_IDSA printf("linetd %s-i\n", VERSION); #else printf("linetd %s\n", VERSION); #endif exit(0); break; /* flags */ case 'f': /* keep in foreground */ nofork = 1; j++; break; case 'a' : /* disable reuse of address */ j++; c = argv[i][j]; switch (c) { case 'r': reuse = 0; break; case 'k': keepalive = 0; break; case '\0': fatal_failure(LINET_USAGE, 0, "option -a requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -a%c", c); break; } j++; if (argv[i][j] == '\0') { j = 1; i++; } break; case 'd' : /* disable sanity checks */ sane = 0; j++; break; /* strings */ case 'u': case 'g': case 'p': case 'r': case 'b': j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c); } switch (c) { case 'u': user = argv[i] + j; break; case 'g': group = argv[i] + j; break; case 'p': port = argv[i] + j; break; case 'r': root = argv[i] + j; break; case 'b': interface = argv[i] + j; break; } i++; j = 1; break; case 'l': j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c); } if (!isdigit(argv[i][j])) { fatal_failure(LINET_USAGE, 0, "option -%c requires a floating point value", c); } load_fd = open(LOADAVG, O_RDONLY); if(load_fd < 0){ fatal_failure(LINET_SYSTEM, errno, "unable to open %s to read load average", LOADAVG); } limit_load = atof(argv[i] + j); i++; j = 1; break; case 'n': case 'm': case 'i': case 'j': case 'q': case 't': j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c); } if (!isdigit(argv[i][j])) { fatal_failure(LINET_USAGE, 0, "option -%c requires a numeric value", c); } value = atoi(argv[i] + j); switch (c) { case 'n': niceinc = value; break; case 'm': timeout = value; break; case 'i': instances = value; break; case 'j': just = value; break; case 'q': queue = value; break; case 't': ttl = value; break; } i++; j = 1; break; case 'o': j++; c = argv[i][j]; switch (c) { case 'c': tos = IPTOS_LOWCOST; break; case 'd': tos = IPTOS_LOWDELAY; break; case 'r': tos = IPTOS_RELIABILITY; break; case 't': tos = IPTOS_THROUGHPUT; break; case '\0': fatal_failure(LINET_USAGE, 0, "option -o requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -o%c", c); break; } j++; if (argv[i][j] == '\0') { j = 1; i++; } break; #ifdef USE_IDSA case 'k' : /* risk ratings */ j++; c = argv[i][j]; j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -k%c requires a parameter", c); } risk = idsa_risk_parse(argv[i]+j); switch (c) { case 'a': arisk = risk; break; case 'c': crisk = risk; break; case 'i': irisk = risk; break; } i++; j = 1; break; case 'x': j++; c = argv[i][j]; switch (c) { case 'e': flags |= IDSA_F_ENV; /* honour IDSA_SOCKET */ break; case 'o': flags |= IDSA_F_FAILOPEN; /* continue on failure */ break; case 'u': flags |= IDSA_F_UPLOAD; /* allow uploading of rules */ break; case '\0': fatal_failure(LINET_USAGE, 0, "option -x requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -x%c", c); break; } j++; if (argv[i][j] == '\0') { j = 1; i++; } break; #endif case 's': j++; c = argv[i][j]; what = 0; switch (c) { case 'c': what = RLIMIT_CORE; break; case 'd': what = RLIMIT_DATA; break; case 'f': what = RLIMIT_FSIZE; break; case 'l': what = RLIMIT_MEMLOCK; break; case 'm': what = RLIMIT_RSS; break; case 'n': what = RLIMIT_NOFILE; break; case 's': what = RLIMIT_STACK; break; case 't': what = RLIMIT_CPU; break; case 'u': what = RLIMIT_NPROC; break; case 'v': what = RLIMIT_AS; break; case '\0': fatal_failure(LINET_USAGE, 0, "option -s requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -s%c", c); break; } j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -s%c requires a parameter", c); } if (!isdigit(argv[i][j])) { fatal_failure(LINET_USAGE, 0, "option -s%c requires a numeric value", c); } value = atoi(argv[i] + j); if(resource_count >= LINET_MAXRES){ fatal_failure(LINET_USAGE, 0, "too many resource restrictions", c); } resource_table[resource_count][0] = what; resource_table[resource_count][1] = value; resource_count++; i++; j = 1; break; case '-': j++; break; case '\0': j = 1; i++; break; default: fatal_failure(LINET_USAGE, 0, "unknown option -%c", argv[i][j]); break; } } else { cmd = argv[i]; offset = i + 1; if (sane) { if (i + 1 >= argc){ fprintf(stderr, "%s: warning: zeroth argument should be specified\n", argv[0]); offset = i; } } i = argc; } } if (cmd == NULL) { fatal_failure(LINET_USAGE, 0, "require a command to run"); } if (!nofork) { fork_parent(argv[0]); } #ifdef USE_IDSA if (ic == NULL) { ic = idsa_open(LINETD, NULL, flags); } if (ic == NULL) { fprintf(stderr, "%s: unable to open idsa connection\n", argv[0]); exit(EX_UNAVAILABLE); } #endif sigfillset(&(sag.sa_mask)); sag.sa_flags = 0; sag.sa_handler = handle_child; if (sigaction(SIGCHLD, &sag, NULL)) { fatal_failure(LINET_SYSTEM, errno, "unable to set signal handler"); } sag.sa_handler = handle_stop; if (sigaction(SIGTERM, &sag, NULL)) { fatal_failure(LINET_SYSTEM, errno, "unable to set signal handler"); } lfd = setup_listener(argv[0], port, interface, queue, ttl, tos, reuse, keepalive); drop_root(argv[0], user, group, root); if(sane){ if(access(cmd, X_OK)){ fatal_failure(LINET_SYSTEM, errno, "\"%s\" %s", cmd, (cmd[0] == '/') ? "appears unavailable" : "might need an absolute path"); } } if (niceinc) { nice(niceinc); } #ifdef USE_IDSA if(idsa_set(ic, LINET_DR, LINET_SCHEME, 1, IDSA_R_SUCCESS, IDSA_R_UNKNOWN, IDSA_R_UNKNOWN, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_SSTART, "version", IDSA_T_STRING, VERSION, NULL) != IDSA_L_ALLOW){ fprintf(stderr, "%s: start disallowed\n", LINETD); return EX_NOPERM; } #endif if (!nofork) { close(STDERR_FILENO); } sigemptyset(&sst); sigaddset(&sst, SIGCHLD); sigaddset(&sst, SIGTERM); sigprocmask(SIG_BLOCK, &sst, NULL); /* disable child signal for everything execpt accept and sleep */ while (run) { #ifdef USE_IDSA nfd = accept_connection(lfd, arisk, crisk, irisk); #else nfd = accept_connection(lfd); #endif if (nfd >= 0) { run_command(lfd, cmd, &argv[offset], nfd, timeout); if(just){ just--; if(just == 0){ run = 0; } } } do{ /* check children and load */ busy = 0; hang = ((instances > 0) && (child_count >= instances)); /* actually wait for child */ if (zombies || hang) { if (waitpid(WAIT_ANY, &status, hang ? 0 : WNOHANG) > 0) { /* collect pids without risk of EINTR */ #ifdef USE_IDSA /* in theory this could parse signals and exit codes. Eg SIG{SEGV,BUS} == ES_INTERNAL etc */ if (WIFEXITED(status)) { exitcode = WEXITSTATUS(status); if (exitcode == 0) { idsa_set(ic, LINET_JD, LINET_SCHEME, 0, IDSA_R_NONE, IDSA_R_UNKNOWN, IDSA_R_UNKNOWN, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WSTOP, NULL); } else { idsa_set(ic, LINET_JE, LINET_SCHEME, 0, IDSA_R_PARTIAL, IDSA_R_UNKNOWN, IDSA_R_PARTIAL, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WFAIL, IDSA_ES, IDSA_T_STRING, IDSA_ES_OTHER, "exit", IDSA_T_INT, &exitcode, NULL); } } else if (WIFSIGNALED(status)) { killcode = WTERMSIG(status); idsa_set(ic, LINET_JS, LINET_SCHEME, 0, IDSA_R_PARTIAL, IDSA_R_UNKNOWN, IDSA_R_PARTIAL, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WFAIL, IDSA_ES, IDSA_T_STRING, IDSA_ES_OTHER, "signal", IDSA_T_INT, &killcode, NULL); } #endif child_count--; busy = ! hang; } else { /* nothing more to collect */ zombies = 0; } } if((load_fd >= 0) && (zombies == 0)){ /* if zombies then loop will run again, defer load check */ if(get_load() > limit_load){ /* go to sleep if overloaded */ sigprocmask(SIG_UNBLOCK, &sst, NULL); /* enable child|term signal */ sleep(LINET_SLEEP); sigprocmask(SIG_BLOCK, &sst, NULL); /* disable child|term signal */ busy = run; } } } while (busy); /* end of child and delay loop */ } /* end of main loop */ if(lfd >= 0){ close(lfd); } if(load_fd >= 0){ close(load_fd); } #ifdef USE_IDSA idsa_set(ic, LINET_DE, LINET_SCHEME, 0, IDSA_R_TOTAL, IDSA_R_NONE, IDSA_R_UNKNOWN, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_SSTOP, "version", IDSA_T_STRING, VERSION, NULL); idsa_close(ic); #endif return 0; }
/* process client requests */ int srv_loop( const char* ipaddr, int port, const char* mcast_addr ) { int rc, maxfd, err, nrdy, i; fd_set rset; struct timeval tmout, idle_tmout, *ptmout = NULL; tmfd_t *asock = NULL; size_t n = 0, nasock = 0, max_nasock = LQ_BACKLOG; sigset_t oset, bset; static const long IDLE_TMOUT_SEC = 30; assert( (port > 0) && mcast_addr && ipaddr ); (void)tmfprintf( g_flog, "Server is starting up, max clients = [%u]\n", g_uopt.max_clients ); asock = calloc (max_nasock, sizeof(*asock)); if (!asock) { mperror (g_flog, ENOMEM, "%s: calloc", __func__); return ERR_INTERNAL; } init_server_ctx( &g_srv, g_uopt.max_clients, (ipaddr[0] ? ipaddr : "0.0.0.0") , (uint16_t)port, mcast_addr ); g_srv.rcv_tmout = (u_short)g_uopt.rcv_tmout; g_srv.snd_tmout = RLY_SOCK_TIMEOUT; /* NB: server socket is non-blocking! */ if( 0 != (rc = setup_listener( ipaddr, port, &g_srv.lsockfd, g_uopt.lq_backlog )) ) { return rc; } sigemptyset (&bset); sigaddset (&bset, SIGINT); sigaddset (&bset, SIGQUIT); sigaddset (&bset, SIGCHLD); sigaddset (&bset, SIGTERM); (void) sigprocmask (SIG_BLOCK, &bset, &oset); TRACE( (void)tmfprintf( g_flog, "Entering server loop [%s]\n", SLOOP_TAG) ); while (1) { FD_ZERO( &rset ); FD_SET( g_srv.lsockfd, &rset ); FD_SET( g_srv.cpipe[0], &rset ); maxfd = (g_srv.lsockfd > g_srv.cpipe[0] ) ? g_srv.lsockfd : g_srv.cpipe[0]; for (i = 0; (size_t)i < nasock; ++i) { assert (asock[i].fd >= 0); FD_SET (asock[i].fd, &rset); if (asock[i].fd > maxfd) maxfd = asock[i].fd; } /* if there are accepted sockets - apply specified time-out */ tmout.tv_sec = g_uopt.ssel_tmout; tmout.tv_usec = 0; idle_tmout.tv_sec = IDLE_TMOUT_SEC; idle_tmout.tv_usec = 0; /* enforce *idle* select(2) timeout to alleviate signal contention */ ptmout = ((nasock > 0) && (g_uopt.ssel_tmout > 0)) ? &tmout : &idle_tmout; TRACE( (void)tmfprintf( g_flog, "Waiting for input from [%ld] fd's, " "%s timeout\n", (long)(2 + nasock), (ptmout ? "with" : "NO"))); if (ptmout && ptmout->tv_sec) { TRACE( (void)tmfprintf (g_flog, "select() timeout set to " "[%ld] seconds\n", ptmout->tv_sec) ); } (void) sigprocmask (SIG_UNBLOCK, &bset, NULL); if( must_quit() ) { TRACE( (void)tmfputs( "Must quit now\n", g_flog ) ); rc = 0; break; } nrdy = select (maxfd + 1, &rset, NULL, NULL, ptmout); err = errno; (void) sigprocmask (SIG_BLOCK, &bset, NULL); if( must_quit() ) { TRACE( (void)tmfputs( "Must quit now\n", g_flog ) ); rc = 0; break; } wait_terminated( &g_srv ); if( nrdy < 0 ) { if (EINTR == err) { TRACE( (void)tmfputs ("INTERRUPTED, yet " "will continue.\n", g_flog) ); rc = 0; continue; } mperror( g_flog, err, "%s: select", __func__ ); break; } TRACE( (void)tmfprintf (g_flog, "Got %ld requests\n", (long)nrdy) ); if (0 == nrdy) { /* time-out */ tmout_requests (asock, &nasock); rc = 0; continue; } if( FD_ISSET(g_srv.cpipe[0], &rset) ) { (void) tpstat_read( &g_srv ); if (--nrdy <= 0) continue; } if ((0 < nasock) && (0 < (nrdy - (FD_ISSET(g_srv.lsockfd, &rset) ? 1 : 0)))) { process_requests (asock, &nasock, &rset, &g_srv); /* n now contains # (yet) unprocessed accepted sockets */ } if (FD_ISSET(g_srv.lsockfd, &rset)) { if (nasock >= max_nasock) { (void) tmfprintf (g_flog, "Cannot accept sockets beyond " "the limit [%ld/%ld], skipping\n", (long)nasock, (long)max_nasock); } else { n = max_nasock - nasock; /* append asock */ accept_requests (g_srv.lsockfd, &(asock[nasock]), &n); nasock += n; } } } /* server loop */ TRACE( (void)tmfprintf( g_flog, "Exited server loop [%s]\n", SLOOP_TAG) ); for (i = 0; (size_t)i < nasock; ++i) { if (asock[i].fd > 0) (void) close (asock[i].fd); } free (asock); /* receive additional (blocked signals) */ (void) sigprocmask (SIG_SETMASK, &oset, NULL); wait_terminated( &g_srv ); terminate_all_clients( &g_srv ); wait_all( &g_srv ); if (0 != close( g_srv.lsockfd )) { mperror (g_flog, errno, "server socket close"); } free_server_ctx( &g_srv ); (void)tmfprintf( g_flog, "Server exits with rc=[%d]\n", rc ); return rc; }
/** * Main server event loop. */ static int child (const int8_t index, const uint8_t *server_port) { int listensock, epollfd; struct epoll_event event, *events; /* setup listen socket */ if ((listensock = setup_listener (server_port)) < 0) { err (1, "Could not setup listen socket"); } fprintf (stdout, "proc %d: Listening on port %s...\n", index, (char *) server_port); /* initialize cache */ if (cache_init ((const uint8_t *) CACHE_BASEDIR) < 0) { err (1, "Could not create cache dir"); } fprintf (stdout, "proc %d: Initialized cache...\n", index); /* initialize epoll */ if ((epollfd = epoll_create1 (0)) < 0) { err (1, "Could not initialize epoll"); } /* add epoll event for handling listen socket */ struct command *lcmd = calloc (1, sizeof (struct command)); lcmd->cfd = listensock; epoll_add (epollfd, lcmd); /* event buffer */ events = calloc (MAXEVENTS, sizeof (event)); fprintf (stdout, "proc %d: Entering main loop...\n", index); for (;;) { /* block until we get some events to process */ int numevents = epoll_wait (epollfd, events, MAXEVENTS, -1); struct command *command; /* process all events */ for (int i = 0; i < numevents; i++) { /* get command */ command = events[i].data.ptr; /* epoll error */ if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /* notified but nothing ready for processing */ warn ("epoll error"); close (command->cfd); close (command->rfd); continue; } /* ACCEPT */ else if (command->cfd == listensock) { do_accept (listensock, epollfd); /* processed all incoming events on listensock, continue to * next event. */ continue; } /* HANDLE COMMANDS */ else { switch (command->cmd) { case READ_CMD: do_read_cmd (epollfd, command); break; case READ_REMOTE: ; /* hack needed for variable defs inside switch */ uint8_t buf[BUFLEN] = { 0 }; ssize_t buflen; /* command is free'd in d_r_r() */ int cfd = command->cfd; do_read_remote (command, buf, &buflen); /* verify that we actually have data to relay back */ if (buflen > 0) { if (!sendall (cfd, buf, (size_t *) &buflen)) { warn ("Could not relay back data to client"); } } break; default: break; } } } } free (events); close (listensock); return EXIT_SUCCESS; }