/* UNIX listener */ static void listener(IOCHAN h, int event) { COMSTACK line = (COMSTACK) iochan_getdata(h); int res; if (event == EVENT_INPUT) { COMSTACK new_line; if ((res = cs_listen_check(line, 0, 0, control_block.check_ip, control_block.daemon_name)) < 0) { yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_listen failed"); return; } else if (res == 1) { yaz_log(YLOG_WARN, "cs_listen incomplete"); return; } new_line = cs_accept(line); if (!new_line) { yaz_log(YLOG_FATAL, "Accept failed."); iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ return; } yaz_log(log_sessiondetail, "Connect from %s", cs_addrstr(new_line)); no_sessions++; if (control_block.dynamic) { if ((res = fork()) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "fork"); iochan_destroy(h); return; } else if (res == 0) /* child */ { char nbuf[100]; IOCHAN pp; for (pp = pListener; pp; pp = iochan_getnext(pp)) { COMSTACK l = (COMSTACK)iochan_getdata(pp); cs_close(l); iochan_destroy(pp); } sprintf(nbuf, "%s(%d)", me, no_sessions); yaz_log_init_prefix(nbuf); /* ensure that bend_stop is not called when each child exits - only for the main process .. */ control_block.bend_stop = 0; } else /* parent */ { cs_close(new_line); return; } } if (control_block.threads) { #if YAZ_POSIX_THREADS pthread_t child_thread; pthread_create(&child_thread, 0, new_session, new_line); pthread_detach(child_thread); #elif YAZ_GNU_THREADS pth_attr_t attr; pth_t child_thread; attr = pth_attr_new(); pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); pth_attr_set(attr, PTH_ATTR_STACK_SIZE, 32*1024); pth_attr_set(attr, PTH_ATTR_NAME, "session"); yaz_log(YLOG_DEBUG, "pth_spawn begin"); child_thread = pth_spawn(attr, new_session, new_line); yaz_log(YLOG_DEBUG, "pth_spawn finish"); pth_attr_destroy(attr); #else new_session(new_line); #endif } else new_session(new_line); } else if (event == EVENT_TIMEOUT) { yaz_log(log_server, "Shutting down listener."); iochan_destroy(h); } else { yaz_log(YLOG_FATAL, "Bad event on listener."); iochan_destroy(h); } }
int main(int argc, char *argv[]) { sqlite3 *db; if (sqlite3_open("db/cs.db", &db) != SQLITE_OK) { E("sqlite3_open() failed."); return -1; } int ret = sockfd_list_init(1024); if (ret < 0) { E("sockfd_list_init() failed."); return -1; } int servfd = socket(AF_INET, SOCK_STREAM, 0); if (servfd == -1) { E("%s", strerror(errno)); return -1; } int optval = 1; ret = setsockopt(servfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); if (ret == -1) { E("%s", strerror(errno)); return -1; } #ifdef SO_REUSEPORT optval = 1; ret = setsockopt(servfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); if (ret == -1) { E("%s", strerror(errno)); return -1; } #endif struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); memset(&addr, '\0', addrlen); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = INADDR_ANY; ret = bind(servfd, (struct sockaddr *)&addr, addrlen); if (ret == -1) { E("%s", strerror(errno)); return -1; } int backlog = 20; ret = listen(servfd, backlog); if (ret == -1) { E("%s", strerror(errno)); return -1; } FD_ZERO(&rfds_g); FD_ZERO(&wfds_g); FD_ZERO(&efds_g); register_readfd(servfd); fd_set rfds, wfds, efds; struct timeval timeout; int n = 0; int i = 0; //DIP(INADDR_ANY); D("cs start 0.0.0.0 %d", PORT); while (1) { rfds = rfds_g; wfds = wfds_g; efds = efds_g; timeout.tv_sec = 1; timeout.tv_usec = 0; n = select(maxfd + 1, &rfds, &wfds, &efds, &timeout); if (n < 0) { if (errno == EINTR) continue; E("select() faile."); break; } else if (n == 0) { //D("timeout, nothing to be done."); } else { /* FIXME: while (n--) */ for (i = 0; i <= maxfd; i++) { if (FD_ISSET(i, &rfds)) { if (i == servfd) { ret = cs_accept(i); if (ret == -1) { E("cs_accept() failed."); break; } } else { ret = cs_routine(i, db); if (ret == -1) { E("cs_routine() failed."); break; } } } else if (FD_ISSET(i, &wfds)) { D("write occurrence."); } else if (FD_ISSET(i, &efds)) { E("except occurrence."); } else { //E("undefined occurrence."); } } } } close(servfd); sqlite3_close(db); return 0; }
/* WIN32 listener */ static void listener(IOCHAN h, int event) { COMSTACK line = (COMSTACK) iochan_getdata(h); IOCHAN parent_chan = line->user; association *newas; int res; HANDLE newHandle; if (event == EVENT_INPUT) { COMSTACK new_line; IOCHAN new_chan; if ((res = cs_listen(line, 0, 0)) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "cs_listen failed"); return; } else if (res == 1) return; /* incomplete */ yaz_log(YLOG_DEBUG, "listen ok"); new_line = cs_accept(line); if (!new_line) { yaz_log(YLOG_FATAL, "Accept failed."); return; } yaz_log(YLOG_DEBUG, "Accept ok"); if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, EVENT_INPUT, parent_chan->chan_id))) { yaz_log(YLOG_FATAL, "Failed to create iochan"); iochan_destroy(h); return; } yaz_log(YLOG_DEBUG, "Creating association"); if (!(newas = create_association(new_chan, new_line, control_block.apdufile))) { yaz_log(YLOG_FATAL, "Failed to create new assoc."); iochan_destroy(h); return; } newas->cs_get_mask = EVENT_INPUT; newas->cs_put_mask = 0; newas->cs_accept_mask = 0; yaz_log(YLOG_DEBUG, "Setting timeout %d", control_block.idle_timeout); iochan_setdata(new_chan, newas); iochan_settimeout(new_chan, 60); /* Now what we need todo is create a new thread with this iochan as the parameter */ newHandle = (HANDLE) _beginthread(event_loop_thread, 0, new_chan); if (newHandle == (HANDLE) -1) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create new thread."); iochan_destroy(h); return; } /* We successfully created the thread, so add it to the list */ statserv_add(newHandle, new_chan); yaz_log(YLOG_DEBUG, "Created new thread, id = %ld iochan %p",(long) newHandle, new_chan); iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ } else { yaz_log(YLOG_FATAL, "Bad event on listener."); iochan_destroy(h); return; } }