Esempio n. 1
0
/* If msiod_new returned success, you must free the iod when you are
   done with it to conserve memory (and in some cases, sockets).
   After this call, nsockiod may no longer be used -- you need to
   create a new one with nsi_new().  pending_response tells what to do
   with any events that are pending on this nsock_iod.  This can be
   NSOCK_PENDING_NOTIFY (send a KILL notification to each event),
   NSOCK_PENDING_SILENT (do not send notification to the killed
   events), or NSOCK_PENDING_ERROR (print an error message and quiit
   the program) */
void nsi_delete(nsock_iod nsockiod, int pending_response) {
  msiod *nsi = (msiod *) nsockiod;
  gh_list *elist_ar[3];
  int elist;
  gh_list_elem *currev_elem, *next_elem;
  msevent *currev;
  assert(nsi);

  if (nsi->state == NSIOD_STATE_DELETED) {
    fatal("nsi_delete() called on nsock_iod which appears to have already been deleted");
  }

  if (nsi->events_pending > 0) {
    /* shit -- they killed the msiod while an event was still pending
       on it.  Maybe I should store the pending events in the msiod.
       On the other hand, this should be a pretty rare occurance and
       so I'll save space and hassle by just locating the events here
       by searching through the active events list */
    if (pending_response == NSOCK_PENDING_ERROR)
      fatal("nsi_delete called with argument NSOCK_PENDING_ERROR on a nsock_iod that has %d pending event(s) associated with it", nsi->events_pending);
    assert(pending_response == NSOCK_PENDING_NOTIFY ||
	   pending_response == NSOCK_PENDING_SILENT);
    elist_ar[0] = &(nsi->nsp->evl.read_events);
    elist_ar[1] = &(nsi->nsp->evl.write_events);
    elist_ar[2] = &(nsi->nsp->evl.connect_events);
    for(elist = 0; elist < 3 && nsi->events_pending > 0; elist++) {
      currev_elem = GH_LIST_FIRST_ELEM(elist_ar[elist]);
      while(currev_elem) {
	currev = (msevent *) GH_LIST_ELEM_DATA(currev_elem);
	next_elem = GH_LIST_ELEM_NEXT(currev_elem);
	if (currev->iod == nsi) {
	  // OK - we found an event pending on this IOD.  Kill it.
	  // printf("Found an outstanding event (out of %d), removing\n", nsi->events_pending);
	  msevent_cancel(nsi->nsp, currev, elist_ar[elist], currev_elem, pending_response == NSOCK_PENDING_NOTIFY);
	}
	if (nsi->events_pending == 0)
	  break;
	currev_elem = next_elem;
      }
    }
  }
  
  if (nsi->events_pending != 0)
    fatal("Trying to delete NSI, but could not find %d of the purportedly pending events on that IOD.\n", nsi->events_pending);

#if HAVE_OPENSSL
  /* Close any SSL resources */
  if (nsi->ssl) {
    /* No longer free session because copy nsi stores is not reference counted */
    /*    if (nsi->ssl_session)
	  SSL_SESSION_free(nsi->ssl_session); 
	  nsi->ssl_session = NULL; */
    if (SSL_shutdown(nsi->ssl) == -1) {
      if (nsi->nsp->tracelevel > 1)
	nsock_trace(nsi->nsp, 
		    "nsi_delete(): SSL shutdown failed (%s) on NSI %li",
		    ERR_reason_error_string(SSL_get_error(nsi->ssl, -1)), 
		    nsi->id);
    }
    /* I don't really care if the SSL_shutdown() succeeded politely.  I could
       make the SD blocking temporarily for this, but I'm hoping it will
       succeed 95% of the time because we can usually write to a socket. */
    SSL_free(nsi->ssl);
    nsi->ssl = NULL;

  }
#endif

  if (nsi->sd >= 0) {
    close(nsi->sd);
    nsi->sd = -1;
  }

  nsi->state = NSIOD_STATE_DELETED;
  nsi->userdata = NULL;

  gh_list_remove_elem(&nsi->nsp->active_iods, nsi->entry_in_nsp_active_iods);
  gh_list_prepend(&nsi->nsp->free_iods, nsi);

}
Esempio n. 2
0
/* Cancel an event (such as a timer or read request).  If notify is nonzero, the
 * requester will be sent an event CANCELLED status back to the given handler.
 * But in some cases there is no need to do this (like if the function deleting
 * it is the one which created it), in which case 0 can be passed to skip the
 * step.  This function returns zero if the event is not found, nonzero
 * otherwise. */
int nsock_event_cancel(nsock_pool ms_pool, nsock_event_id id, int notify) {
  mspool *nsp = (mspool *)ms_pool;
  enum nse_type type;
  unsigned int i;
  gh_list_t *event_list = NULL, *event_list2 = NULL;
  gh_lnode_t *current, *next;
  msevent *nse = NULL;

  assert(nsp);

  type = get_event_id_type(id);
  nsock_log_info(nsp, "Event #%li (type %s) cancelled", id, nse_type2str(type));

  /* First we figure out what list it is in */
  switch (type) {
    case NSE_TYPE_CONNECT:
    case NSE_TYPE_CONNECT_SSL:
      event_list = &nsp->connect_events;
      break;

    case NSE_TYPE_READ:
      event_list = &nsp->read_events;
      break;

    case NSE_TYPE_WRITE:
      event_list = &nsp->write_events;
      break;

    case NSE_TYPE_TIMER:
      for (i = 0; i < gh_heap_count(&nsp->expirables); i++) {
        gh_hnode_t *hnode;

        hnode = gh_heap_find(&nsp->expirables, i);
        nse = container_of(hnode, msevent, expire);
        if (nse->id == id)
          return msevent_cancel(nsp, nse, NULL, NULL, notify);
      }
      return 0;

#if HAVE_PCAP
    case NSE_TYPE_PCAP_READ:
      event_list  = &nsp->read_events;
      event_list2 = &nsp->pcap_read_events;
      break;
#endif

    default:
      fatal("Bogus event type in nsock_event_cancel"); break;
  }

  /* Now we try to find the event in the list */
  for (current = gh_list_first_elem(event_list); current != NULL; current = next) {
    next = gh_lnode_next(current);
    nse = lnode_msevent(current);
    if (nse->id == id)
      break;
  }

  if (current == NULL && event_list2) {
    event_list = event_list2;
    for (current = gh_list_first_elem(event_list); current != NULL; current = next) {
      next = gh_lnode_next(current);
      nse = lnode_msevent2(current);
      if (nse->id == id)
        break;
    }
  }
  if (current == NULL)
    return 0;

  return msevent_cancel(nsp, nse, event_list, current, notify);
}
Esempio n. 3
0
/* Cancel an event (such as a timer or read request).  If notify is nonzero, the
 * requester will be sent an event CANCELLED status back to the given handler.
 * But in some cases there is no need to do this (like if the function deleting
 * it is the one which created it), in which case 0 can be passed to skip the
 * step.  This function returns zero if the event is not found, nonzero
 * otherwise. */
int nsock_event_cancel(nsock_pool ms_pool, nsock_event_id id, int notify) {
  mspool *nsp = (mspool *)ms_pool;
  enum nse_type type;
  gh_list *event_list = NULL, *event_list2 = NULL;
  gh_list_elem *current, *next;
  msevent *nse = NULL;

  assert(nsp);

  type = get_event_id_type(id);
  nsock_log_info(nsp, "Event #%li (type %s) cancelled", id, nse_type2str(type));

  /* First we figure out what list it is in */
  switch(type) {
    case NSE_TYPE_CONNECT:
      event_list = &nsp->connect_events;
      break;

    case NSE_TYPE_READ:
      event_list = &nsp->read_events;
      break;

    case NSE_TYPE_WRITE:
      event_list = &nsp->write_events;
      break;

    case NSE_TYPE_TIMER:
      event_list = &nsp->timer_events;
      break;

#if HAVE_PCAP
    case NSE_TYPE_PCAP_READ:
      event_list  = &nsp->read_events;
      event_list2 = &nsp->pcap_read_events;
      break;
#endif

    default:
      fatal("Bogus event type in nsock_event_cancel"); break;
  }

  /* Now we try to find the event in the list */
  for (current = GH_LIST_FIRST_ELEM(event_list); current != NULL;  current = next) {
    next = GH_LIST_ELEM_NEXT(current);
    nse = (msevent *)GH_LIST_ELEM_DATA(current);
    if (nse->id == id)
      break;
  }

  if (current == NULL && event_list2){
    event_list = event_list2;
    for (current = GH_LIST_FIRST_ELEM(event_list); current != NULL; current = next) {
      next = GH_LIST_ELEM_NEXT(current);
      nse = (msevent *)GH_LIST_ELEM_DATA(current);
      if (nse->id == id)
        break;
    }
  }
  if (current == NULL)
    return 0;

  return msevent_cancel(nsp, nse, event_list, current, notify);
}