/* Here is the all important looping function that tells the event engine to * start up and begin processing events. It will continue until all events have * been delivered (including new ones started from event handlers), or the * msec_timeout is reached, or a major error has occurred. Use -1 if you don't * want to set a maximum time for it to run. A timeout of 0 will return after 1 * non-blocking loop. The nsock loop can be restarted again after it returns. * For example you could do a series of 15 second runs, allowing you to do other * stuff between them */ enum nsock_loopstatus nsock_loop(nsock_pool nsp, int msec_timeout) { mspool *ms = (mspool *)nsp; struct timeval loop_timeout; int msecs_left; unsigned long loopnum = 0; enum nsock_loopstatus quitstatus = NSOCK_LOOP_ERROR; gettimeofday(&nsock_tod, NULL); if (msec_timeout < -1) { ms->errnum = EINVAL; return NSOCK_LOOP_ERROR; } TIMEVAL_MSEC_ADD(loop_timeout, nsock_tod, msec_timeout); msecs_left = msec_timeout; if (ms->tracelevel > 2) { if (msec_timeout >= 0) nsock_trace(ms, "nsock_loop() started (timeout=%dms). %d events pending", msec_timeout, ms->events_pending); else nsock_trace(ms, "nsock_loop() started (no timeout). %d events pending", ms->events_pending); } while (1) { if (ms->quit) { /* We've been asked to quit the loop through nsock_loop_quit. */ ms->quit = 0; quitstatus = NSOCK_LOOP_QUIT; break; } if (ms->events_pending == 0) { /* if no events at all are pending, then none can be created until * we quit nsock_loop() -- so we do that now. */ quitstatus = NSOCK_LOOP_NOEVENTS; break; } if (msec_timeout >= 0) { msecs_left = MAX(0, TIMEVAL_MSEC_SUBTRACT(loop_timeout, nsock_tod)); if (msecs_left == 0 && loopnum > 0) { quitstatus = NSOCK_LOOP_TIMEOUT; break; } } if (ms->engine->loop(ms, msecs_left) == -1) { quitstatus = NSOCK_LOOP_ERROR; break; } gettimeofday(&nsock_tod, NULL); /* we do this at end because there is one * at beginning of function */ loopnum++; } return quitstatus; }
/* Create a new event structure -- must be deleted later with msevent_delete, * unless it returns NULL (failure). NULL can be passed in for the msiod and * the userdata if not available */ msevent *msevent_new(mspool *nsp, enum nse_type type, msiod *msiod, int timeout_msecs, nsock_ev_handler handler, void *userdata) { msevent *nse; /* Bring us up to date for the timeout calculation. */ gettimeofday(&nsock_tod, NULL); if (msiod) { msiod->events_pending++; assert(msiod->state != NSIOD_STATE_DELETED); } /* First we check if one is available from the free list ... */ nse = (msevent *)gh_list_pop(&nsp->free_events); if (!nse) nse = (msevent *)safe_malloc(sizeof(msevent)); memset(nse, 0, sizeof(msevent)); nse->id = get_new_event_id(nsp, type); nse->type = type; nse->status = NSE_STATUS_NONE; #if HAVE_OPENSSL nse->sslinfo.ssl_desire = SSL_ERROR_NONE; #endif if (type == NSE_TYPE_READ || type == NSE_TYPE_WRITE) filespace_init(&(nse->iobuf), 1024); #if HAVE_PCAP if (type == NSE_TYPE_PCAP_READ) { mspcap *mp; int sz; assert(msiod != NULL); mp = (mspcap *)msiod->pcap; assert(mp); sz = mp->snaplen+1 + sizeof(nsock_pcap); filespace_init(&(nse->iobuf), sz); } #endif if (timeout_msecs != -1) { assert(timeout_msecs >= 0); TIMEVAL_MSEC_ADD(nse->timeout, nsock_tod, timeout_msecs); } nse->iod = msiod; nse->handler = handler; nse->userdata = userdata; if (nse->iod == NULL) nsock_log_debug(nsp, "msevent_new (IOD #NULL) (EID #%li)", nse->id); else nsock_log_debug(nsp, "msevent_new (IOD #%li) (EID #%li)", nse->iod->id, nse->id); return nse; }