/* If nsp_new returned success, you must free the nsp when you are done with it * to conserve memory (and in some cases, sockets). After this call, nsp may no * longer be used. Any pending events are sent an NSE_STATUS_KILL callback and * all outstanding iods are deleted. */ void nsp_delete(nsock_pool ms_pool) { mspool *nsp = (mspool *)ms_pool; msevent *nse; msiod *nsi; int i; gh_list_elem *current, *next; gh_list *event_lists[] = { &nsp->connect_events, &nsp->read_events, &nsp->write_events, &nsp->timer_events, #if HAVE_PCAP &nsp->pcap_read_events, #endif NULL }; assert(nsp); /* First I go through all the events sending NSE_STATUS_KILL */ for (i = 0; event_lists[i] != NULL; i++) { while (GH_LIST_COUNT(event_lists[i]) > 0) { nse = (msevent *)gh_list_pop(event_lists[i]); assert(nse); nse->status = NSE_STATUS_KILL; nsock_trace_handler_callback(nsp, nse); nse->handler(nsp, nse, nse->userdata); if (nse->iod) { nse->iod->events_pending--; assert(nse->iod->events_pending >= 0); } msevent_delete(nsp, nse); } gh_list_free(event_lists[i]); } /* foreach msiod */ for (current = GH_LIST_FIRST_ELEM(&nsp->active_iods); current != NULL; current = next) { next = GH_LIST_ELEM_NEXT(current); nsi = (msiod *)GH_LIST_ELEM_DATA(current); nsi_delete(nsi, NSOCK_PENDING_ERROR); gh_list_remove_elem(&nsp->active_iods, current); gh_list_prepend(&nsp->free_iods, nsi); } /* Now we free all the memory in the free iod list */ while ((nsi = (msiod *)gh_list_pop(&nsp->free_iods))) { free(nsi); } while ((nse = (msevent *)gh_list_pop(&nsp->free_events))) { free(nse); } gh_list_free(&nsp->active_iods); gh_list_free(&nsp->free_iods); gh_list_free(&nsp->free_events); nsock_engine_destroy(nsp); #if HAVE_OPENSSL if (nsp->sslctx != NULL) SSL_CTX_free(nsp->sslctx); #endif free(nsp); }
/* Create a new event structure -- must be deleted later with event_delete, * unless it returns NULL (failure). NULL can be passed in for the struct niod * and the userdata if not available */ struct nevent *event_new(struct npool *nsp, enum nse_type type, struct niod *iod, int timeout_msecs, nsock_ev_handler handler, void *userdata) { struct nevent *nse; gh_lnode_t *lnode; /* Bring us up to date for the timeout calculation. */ gettimeofday(&nsock_tod, NULL); if (iod) { iod->events_pending++; assert(iod->state != NSIOD_STATE_DELETED); } /* First we check if one is available from the free list ... */ lnode = gh_list_pop(&nsp->free_events); if (!lnode) nse = (struct nevent *)safe_malloc(sizeof(*nse)); else nse = lnode_nevent(lnode); memset(nse, 0, sizeof(*nse)); nse->id = get_new_event_id(nsp, type); nse->type = type; nse->status = NSE_STATUS_NONE; gh_hnode_invalidate(&nse->expire); #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(iod != NULL); mp = (mspcap *)iod->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 = iod; nse->handler = handler; nse->userdata = userdata; if (nse->iod == NULL) nsock_log_debug("%s (IOD #NULL) (EID #%li)", __func__, nse->id); else nsock_log_debug("%s (IOD #%li) (EID #%li)", __func__, nse->iod->id, nse->id); return nse; }
/* If nsp_new returned success, you must free the nsp when you are done with it * to conserve memory (and in some cases, sockets). After this call, nsp may no * longer be used. Any pending events are sent an NSE_STATUS_KILL callback and * all outstanding iods are deleted. */ void nsp_delete(nsock_pool ms_pool) { mspool *nsp = (mspool *)ms_pool; msevent *nse; msiod *nsi; int i; gh_lnode_t *current, *next; gh_list_t *event_lists[] = { &nsp->connect_events, &nsp->read_events, &nsp->write_events, #if HAVE_PCAP &nsp->pcap_read_events, #endif NULL }; assert(nsp); /* First I go through all the events sending NSE_STATUS_KILL */ for (i = 0; event_lists[i] != NULL; i++) { while (gh_list_count(event_lists[i]) > 0) { gh_lnode_t *lnode = gh_list_pop(event_lists[i]); assert(lnode); #if HAVE_PCAP if (event_lists[i] == &nsp->pcap_read_events) nse = lnode_msevent2(lnode); else #endif nse = lnode_msevent(lnode); assert(nse); nse->status = NSE_STATUS_KILL; nsock_trace_handler_callback(nsp, nse); nse->handler(nsp, nse, nse->userdata); if (nse->iod) { nse->iod->events_pending--; assert(nse->iod->events_pending >= 0); } msevent_delete(nsp, nse); } gh_list_free(event_lists[i]); } /* Kill timers too, they're not in event lists */ while (gh_heap_count(&nsp->expirables) > 0) { gh_hnode_t *hnode; hnode = gh_heap_pop(&nsp->expirables); nse = container_of(hnode, msevent, expire); if (nse->type == NSE_TYPE_TIMER) { nse->status = NSE_STATUS_KILL; nsock_trace_handler_callback(nsp, nse); nse->handler(nsp, nse, nse->userdata); msevent_delete(nsp, nse); gh_list_append(&nsp->free_events, &nse->nodeq_io); } } gh_heap_free(&nsp->expirables); /* foreach msiod */ for (current = gh_list_first_elem(&nsp->active_iods); current != NULL; current = next) { next = gh_lnode_next(current); nsi = container_of(current, msiod, nodeq); nsi_delete(nsi, NSOCK_PENDING_ERROR); gh_list_remove(&nsp->active_iods, current); gh_list_prepend(&nsp->free_iods, &nsi->nodeq); } /* Now we free all the memory in the free iod list */ while ((current = gh_list_pop(&nsp->free_iods))) { nsi = container_of(current, msiod, nodeq); free(nsi); } while ((current = gh_list_pop(&nsp->free_events))) { nse = lnode_msevent(current); free(nse); } gh_list_free(&nsp->active_iods); gh_list_free(&nsp->free_iods); gh_list_free(&nsp->free_events); nsock_engine_destroy(nsp); #if HAVE_OPENSSL if (nsp->sslctx != NULL) SSL_CTX_free(nsp->sslctx); #endif free(nsp); }
int main(int argc, char *argv[]) { gh_list lists[16]; gh_list_elem *current, *next; int num = 0; int ret; int i; for(i=0; i < 16; i++) gh_list_init(&lists[i]); for(num=25000; num < 50000; num++) { for(i=0; i < 16; i++) { gh_list_append(&lists[i], (void *)num); } } for(num=24999; num >= 0; num--) { for(i=0; i < 16; i++) { gh_list_prepend(&lists[i], (void *)num); } } for(num=0; num < 50000; num++) { for(i=0; i < 16; i++) { ret = (int) gh_list_pop(&lists[i]); if (ret != num) fatal("prepend_test: Bogus return value %d when expected %d\n", ret, num); } } for(i=0; i < 16; i++) { ret = (int) gh_list_pop(&lists[i]); if (ret != 0) fatal("Ret is bogus for list %d", i); } printf("Done with first set\n"); for(num=24999; num >= 0; num--) { for(i=0; i < 16; i++) { gh_list_prepend(&lists[i], (void *)num); } } for(num=25000; num < 50000; num++) { for(i=0; i < 16; i++) { gh_list_append(&lists[i], (void *)num); } } for(num=0; num < 50000; num++) { for(i=0; i < 16; i++) { ret = (int) gh_list_pop(&lists[i]); if (ret != num) fatal("prepend_test: Bogus return value %d when expected %d\n", ret, num); } } printf("Done with second set\n"); for(num=25000; num < 50000; num++) { for(i=0; i < 16; i++) { gh_list_append(&lists[i], (void *)num); } } for(num=24999; num >= 0; num--) { for(i=0; i < 16; i++) { gh_list_prepend(&lists[i], (void *)num); } } for(num=0; num < 50000; num++) { for(i=0; i < 16; i++) { ret = (int) gh_list_pop(&lists[i]); if (ret != num) fatal("prepend_test: Bogus return value %d when expected %d\n", ret, num); } } printf("Done with third set ...\n"); for(num=24999; num >= 0; num--) { for(i=0; i < 16; i++) { gh_list_prepend(&lists[i], (void *)num); } } for(num=25000; num < 50000; num++) { for(i=0; i < 16; i++) { gh_list_append(&lists[i], (void *)num); } } for(i=0; i < 16; i++) { num=0; for(current = GH_LIST_FIRST_ELEM(&lists[i]); current; current = next) { next = GH_LIST_ELEM_NEXT(current); if ((int)GH_LIST_ELEM_DATA(current) != num) fatal("Got %d when I expected %d\n", (int)GH_LIST_ELEM_DATA(current), num); gh_list_remove_elem(&lists[i], current); num++; } if (num != 50000) fatal("Number is %d, even though %d was expected", num, 50000); if (GH_LIST_COUNT(&lists[i]) != 0) { fatal("List should be empty, but instead it has %d members!\n", GH_LIST_COUNT(&lists[i])); } } printf("Done with fourth set, freeing buffers\n"); for(i=0; i < 16; i++) { gh_list_free(&lists[i]); } }