/* * Set up a listening endpoint, and give it to the event-handler. */ static int add_listener(char *where, int listen_id) { COMSTACK l; void *ap; IOCHAN lst = NULL; const char *mode; if (control_block.dynamic) mode = "dynamic"; else if (control_block.threads) mode = "threaded"; else mode = "static"; yaz_log(log_server, "Adding %s listener on %s id=%d", mode, where, listen_id); l = cs_create_host(where, 2, &ap); if (!l) { yaz_log(YLOG_FATAL, "Failed to listen on %s", where); return -1; } if (*control_block.cert_fname) cs_set_ssl_certificate_file(l, control_block.cert_fname); if (cs_bind(l, ap, CS_SERVER) < 0) { if (cs_errno(l) == CSYSERR) yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to bind to %s", where); else yaz_log(YLOG_FATAL, "Failed to bind to %s: %s", where, cs_strerror(l)); cs_close(l); return -1; } if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT | EVENT_EXCEPT, listen_id))) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to create IOCHAN-type"); cs_close(l); return -1; } iochan_setdata(lst, l); /* user-defined data for listener is COMSTACK */ l->user = lst; /* user-defined data for COMSTACK is listener chan */ /* Add listener to chain */ lst->next = pListener; pListener = lst; return 0; /* OK */ }
static void inetd_connection(int what) { COMSTACK line; IOCHAN chan; association *assoc; char *addr; if ((line = cs_createbysocket(0, tcpip_type, 0, what))) { if ((chan = iochan_create(cs_fileno(line), ir_session, EVENT_INPUT, 0))) { if ((assoc = create_association(chan, line, control_block.apdufile))) { iochan_setdata(chan, assoc); iochan_settimeout(chan, 60); addr = cs_addrstr(line); yaz_log(log_sessiondetail, "Inetd association from %s", addr ? addr : "[UNKNOWN]"); assoc->cs_get_mask = EVENT_INPUT; } else { yaz_log(YLOG_FATAL, "Failed to create association structure"); } chan->next = pListener; pListener = chan; } else { yaz_log(YLOG_FATAL, "Failed to create iochan"); } } else { yaz_log(YLOG_ERRNO|YLOG_FATAL, "Failed to create comstack on socket 0"); } }
/* Need a Real Function for Perl to call, as cs_fileno() is a macro */ int yaz_socket(COMSTACK cs) { return cs_fileno(cs); }
static void *new_session(void *vp) { char *a; association *newas; IOCHAN new_chan; COMSTACK new_line = (COMSTACK) vp; IOCHAN parent_chan = (IOCHAN) new_line->user; unsigned cs_get_mask, cs_accept_mask, mask = ((new_line->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) | ((new_line->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0); if (mask) { cs_accept_mask = mask; /* accept didn't complete */ cs_get_mask = 0; } else { cs_accept_mask = 0; /* accept completed. */ cs_get_mask = mask = EVENT_INPUT; } if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, mask, parent_chan->chan_id))) { yaz_log(YLOG_FATAL, "Failed to create iochan"); return 0; } if (!(newas = create_association(new_chan, new_line, control_block.apdufile))) { yaz_log(YLOG_FATAL, "Failed to create new assoc."); return 0; } newas->cs_accept_mask = cs_accept_mask; newas->cs_get_mask = cs_get_mask; iochan_setdata(new_chan, newas); iochan_settimeout(new_chan, 60); #if 1 a = cs_addrstr(new_line); #else a = 0; #endif yaz_log_xml_errors(0, YLOG_WARN); yaz_log(log_session, "Session - OK %d %s %ld", no_sessions, a ? a : "[Unknown]", (long) getpid()); if (max_sessions && no_sessions >= max_sessions) control_block.one_shot = 1; if (control_block.threads) { iochan_event_loop(&new_chan); } else { new_chan->next = pListener; pListener = new_chan; } 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; } }