nsock_core.c

来自「Ubuntu packages of security software。 相」· C语言 代码 · 共 1,208 行 · 第 1/3 页

C
1,208
字号
	  case NSE_TYPE_READ:	    match_r = FD_ISSET(nse->iod->sd, &nsp->mioi.fds_results_r);	    match_w = FD_ISSET(nse->iod->sd, &nsp->mioi.fds_results_w);#if HAVE_OPENSSL	    desire_r = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ;	    desire_w = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE;	    if (nse->iod->ssl && ((desire_r && match_r) || (desire_w && match_w)))              handle_read_result(nsp, nse, NSE_STATUS_SUCCESS);	    else#endif	    if (!nse->iod->ssl && match_r)	      handle_read_result(nsp, nse, NSE_STATUS_SUCCESS);	    	    if (!nse->event_done && nse->timeout.tv_sec &&		TIMEVAL_MSEC_SUBTRACT(nse->timeout, nsock_tod) <= 0) {	      handle_read_result(nsp, nse, NSE_STATUS_TIMEOUT);	    }	    break;	    	  case NSE_TYPE_WRITE:	    match_r = FD_ISSET(nse->iod->sd, &nsp->mioi.fds_results_r);	    match_w = FD_ISSET(nse->iod->sd, &nsp->mioi.fds_results_w);#if HAVE_OPENSSL	    desire_r = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ;	    desire_w = nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE;	    if (nse->iod->ssl && ((desire_r && match_r) || 				  (desire_w && match_w)))	      handle_write_result(nsp, nse, NSE_STATUS_SUCCESS);	    else#endif	    if (!nse->iod->ssl && match_w)	      handle_write_result(nsp, nse, NSE_STATUS_SUCCESS);	    if (!nse->event_done && nse->timeout.tv_sec &&		TIMEVAL_MSEC_SUBTRACT(nse->timeout, nsock_tod) <= 0) {	      handle_write_result(nsp, nse, NSE_STATUS_TIMEOUT);	    }	    break;	    	  case NSE_TYPE_TIMER:	    if (nse->timeout.tv_sec && 		TIMEVAL_MSEC_SUBTRACT(nse->timeout, nsock_tod) <= 0) {	      handle_timer_result(nsp, nse, NSE_STATUS_SUCCESS);	    }	    break;#if HAVE_PCAP	  case NSE_TYPE_PCAP_READ:{	    if (nsp->tracelevel > 5)		    nsock_trace(nsp, "PCAP iterating %lu",nse->id);	    /* buffer empty? check it! */	    if ( FILESPACE_LENGTH(&(nse->iobuf))==0 ) 		do_actual_pcap_read(nse);	    /* if already received smth */	    if ( FILESPACE_LENGTH(&(nse->iobuf))>0 )	      handle_pcap_read_result(nsp, nse, NSE_STATUS_SUCCESS);	    	    if (!nse->event_done && nse->timeout.tv_sec &&		TIMEVAL_MSEC_SUBTRACT(nse->timeout, nsock_tod) <= 0)	      handle_pcap_read_result(nsp, nse, NSE_STATUS_TIMEOUT);	    	    #if PCAP_BSD_SELECT_HACK	    /* If event occured, and we're in BSD_HACK mode, than this event was added	     * to two queues. evl.read_event and evl.pcap_read_event 	     * Of coure we should destroy it only once. 	     * I assume we're now in evl.read_event, co just unlink this event from	     * evl.pcap_read_event */	    if(((mspcap *) nse->iod->pcap)->pcap_desc >= 0 &&	       nse->event_done &&	       event_lists[current_list_idx] == &nsp->evl.read_events){	      /* event is done, list is read_events and we're in BSD_HACK mode. 	       * So unlink event from pcap_read_events */	      gh_list_remove(&nsp->evl.pcap_read_events, nse);               if (nsp->tracelevel > 8)                  nsock_trace(nsp, "PCAP NSE #%lu: Removing event from PCAP_READ_EVENTS", nse->id);	    }	    if(((mspcap *) nse->iod->pcap)->pcap_desc >= 0 &&	       nse->event_done &&	       event_lists[current_list_idx] == &nsp->evl.pcap_read_events){ 	      gh_list_remove(&nsp->evl.read_events, nse);               if (nsp->tracelevel > 8)                  nsock_trace(nsp, "PCAP NSE #%lu: Removing event from READ_EVENTS", nse->id);	    }	    #endif	    break;	  }#endif	  default:	    fatal("Event has unknown type (%d)", nse->type);	    break; /* unreached */	  }	}	if (nse->event_done) {          if (nsp->tracelevel > 8)            nsock_trace(nsp, "NSE #%lu: Removing event from event_lists[%i]", nse->id, current_list_idx);	  /* WooHoo!  The event is ready to be sent */	  msevent_dispatch_and_delete(nsp, nse, 1);	  next = GH_LIST_ELEM_NEXT(current);	  gh_list_remove_elem(event_lists[current_list_idx], current);	} else {	  next = GH_LIST_ELEM_NEXT(current);	  /* Is this event the next-to-timeout? */	  if (nse->timeout.tv_sec != 0) {	    if (nsp->evl.next_ev.tv_sec == 0)	      nsp->evl.next_ev = nse->timeout;	    else if (TIMEVAL_MSEC_SUBTRACT(nsp->evl.next_ev, nse->timeout) > 0)	      nsp->evl.next_ev = nse->timeout;	  }	}      }    }}/* 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 occured.  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 > 1) {   if (msec_timeout >= 0) {     nsock_trace(ms, "nsock_loop() started (timeout=%dms). %d events pending", msec_timeout, 		 ms->evl.events_pending);   } else {     nsock_trace(ms, "nsock_loop() started (no timeout). %d events pending", ms->evl.events_pending);   } }while(1) {  if (ms->evl.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 (wait_for_events(ms, msecs_left) == -1) {      quitstatus = NSOCK_LOOP_ERROR;    break;  }    /* Now we go through the event lists, doing callbacks for those which     have completed */  iterate_through_event_lists(ms);  gettimeofday(&nsock_tod, NULL); /* we do this at end because there is one			       at beginning of function */  loopnum++;} return quitstatus;}/* Grab the latest time as recorded by the nsock library, which does   so at least once per event loop (in main_loop).  Not only does this   function (generally) avoid a system call, but in many circumstances   it is better to use nsock's time rather than the system time.  If   nsock has never obtained the time when you call it, it will do so   before returning */const struct timeval *nsock_gettimeofday() {  if (nsock_tod.tv_sec == 0)     gettimeofday(&nsock_tod, NULL);  return &nsock_tod;}/* Adds an event to the appropriate nsp event list, handles housekeeping   such as adjusting the descriptor select/poll lists, registering the   timeout value, etc. */void nsp_add_event(mspool *nsp, msevent *nse) {  if (nsp->tracelevel > 5)      nsock_trace(nsp, "NSE #%lu: Adding event", nse->id);  /* First lets do the event-type independant stuff -- starting with     timeouts */  if (nse->event_done) {     nsp->evl.next_ev = nsock_tod;  } else {    if (nse->timeout.tv_sec != 0) {      if (nsp->evl.next_ev.tv_sec == 0) {	nsp->evl.next_ev = nse->timeout;      } else if (TIMEVAL_MSEC_SUBTRACT(nsp->evl.next_ev, nse->timeout) > 0) {	nsp->evl.next_ev = nse->timeout;      }    }  }  nsp->evl.events_pending++;  /* Now we do the event type specific actions */  switch(nse->type) {  case NSE_TYPE_CONNECT:  case NSE_TYPE_CONNECT_SSL:    if (!nse->event_done) {      assert(nse->iod->sd >= 0);      FD_SET( nse->iod->sd, &nsp->mioi.fds_master_r);      FD_SET( nse->iod->sd, &nsp->mioi.fds_master_w);      FD_SET( nse->iod->sd, &nsp->mioi.fds_master_x);      nsp->mioi.max_sd = MAX(nsp->mioi.max_sd, nse->iod->sd);    }    gh_list_prepend(&nsp->evl.connect_events, nse);    break;  case NSE_TYPE_READ:    if (!nse->event_done) {      assert(nse->iod->sd >= 0);      FD_SET( nse->iod->sd, &nsp->mioi.fds_master_r);      nsp->mioi.max_sd = MAX(nsp->mioi.max_sd, nse->iod->sd);#if HAVE_OPENSSL      if (nse->iod->ssl) nse->sslinfo.ssl_desire = SSL_ERROR_WANT_READ;#endif    }    gh_list_prepend(&nsp->evl.read_events, nse);    break;  case NSE_TYPE_WRITE:    if (!nse->event_done) {      assert(nse->iod->sd >= 0);      FD_SET( nse->iod->sd, &nsp->mioi.fds_master_w);      nsp->mioi.max_sd = MAX(nsp->mioi.max_sd, nse->iod->sd);#if HAVE_OPENSSL      if (nse->iod->ssl) nse->sslinfo.ssl_desire = SSL_ERROR_WANT_WRITE;#endif    }    gh_list_prepend(&nsp->evl.write_events, nse);    break;  case NSE_TYPE_TIMER:    gh_list_prepend(&nsp->evl.timer_events, nse);    break;#if HAVE_PCAP  case NSE_TYPE_PCAP_READ:{    mspcap *mp = (mspcap *) nse->iod->pcap;    assert(mp);    if(mp->pcap_desc >= 0){ /* pcap descriptor present */      if(!nse->event_done){        FD_SET(mp->pcap_desc, &nsp->mioi.fds_master_r);        nsp->mioi.max_sd = MAX(nsp->mioi.max_sd, mp->pcap_desc);      }      if (nsp->tracelevel > 8)          nsock_trace(nsp, "PCAP NSE #%lu: Adding event to READ_EVENTS", nse->id);      gh_list_prepend(&nsp->evl.read_events, nse);            #if PCAP_BSD_SELECT_HACK      /* when using BSD hack we must do pcap_next() after select().        * Let's insert this pcap to bot queues, to selectable and nonselectable.       * This will result in doing pcap_next_ex() just before select() */      if (nsp->tracelevel > 8)          nsock_trace(nsp, "PCAP NSE #%lu: Adding event to PCAP_READ_EVENTS", nse->id);      gh_list_prepend(&nsp->evl.pcap_read_events, nse);      #endif    }else{ /* pcap isn't selectable. Add it to pcap-specific queue. */      if (nsp->tracelevel > 8)          nsock_trace(nsp, "PCAP NSE #%lu: Adding event to PCAP_READ_EVENTS", nse->id);      gh_list_prepend(&nsp->evl.pcap_read_events, nse);    }    break;  }#endif      default:    assert(0);    break; /* unreached */  }}void nsock_trace(mspool *ms, char *fmt, ...) {va_list  ap;int elapsedTimeMS;elapsedTimeMS = TIMEVAL_MSEC_SUBTRACT(nsock_tod, ms->tracebasetime);va_start(ap, fmt);fflush(stdout);printf("NSOCK (%.4fs) ", elapsedTimeMS / 1000.0);vfprintf(stdout, fmt, ap);printf("\n"); va_end(ap);return;}/* An event has been completed and the handler is about to be called.  This function   writes out tracing data about the event if neccessary */void nsock_trace_handler_callback(mspool *ms, msevent *nse) {  msiod *nsi;  char *str;  int strlength = 0;  char displaystr[256];  char errstr[256];    if (ms->tracelevel == 0)    return;  nsi = nse->iod;  if (nse->status == NSE_STATUS_ERROR) {    Snprintf(errstr, sizeof(errstr), "[%s (%d)] ", strerror(nse->errnum), nse->errnum);  } else errstr[0] = '\0';  /* Some types have special tracing treatment */  switch(nse->type) {  case NSE_TYPE_CONNECT:  case NSE_TYPE_CONNECT_SSL:    nsock_trace(ms, "Callback: %s %s %sfor EID %li [%s:%hi]",  		nse_type2str(nse->type), nse_status2str(nse->status), errstr, 		nse->id, inet_ntop_ez(&nsi->peer, nsi->peerlen), nsi_peerport(nsi));    break;  case NSE_TYPE_READ:    if (nse->status != NSE_STATUS_SUCCESS) {      if (nsi->peerlen > 0)	 nsock_trace(ms, "Callback: %s %s %sfor EID %li [%s:%hi]", 		  nse_type2str(nse->type), nse_status2str(nse->status), 		  errstr, nse->id, inet_ntop_ez(&nsi->peer, nsi->peerlen), 		  nsi_peerport(nsi));      else	 nsock_trace(ms, "Callback: %s %s %sfor EID %li (peer unspecified)",		     nse_type2str(nse->type), nse_status2str(nse->status),		     errstr, nse->id);    } else {          str = nse_readbuf(nse, &strlength);      if (ms->tracelevel > 1 && strlength < 80) {	memcpy(displaystr, ": ", 2);	memcpy(displaystr + 2, str, strlength);	displaystr[2 + strlength] = '\0';	replacenonprintable(displaystr + 2, strlength, '.');      } else displaystr[0] = '\0';            if (nsi->peerlen > 0)	nsock_trace(ms, "Callback: %s %s for EID %li [%s:%hi] %s(%d bytes)%s",       		    nse_type2str(nse->type), nse_status2str(nse->status),       		    nse->id, inet_ntop_ez(&nsi->peer, nsi->peerlen),       		    nsi_peerport(nsi), nse_eof(nse)? "[EOF]" : "", strlength,       		    displaystr);      else	nsock_trace(ms, "Callback %s %s for EID %li (peer unspecified) %s(%d bytes)%s",		    nse_type2str(nse->type), nse_status2str(nse->status),		    nse->id, nse_eof(nse)? "[EOF]" : "", strlength, displaystr);    }    break;  case NSE_TYPE_WRITE:    nsock_trace(ms, "Callback: %s %s %sfor EID %li [%s:%hi]", 		nse_type2str(nse->type), nse_status2str(nse->status), errstr, 		nse->id, inet_ntop_ez(&nsi->peer, nsi->peerlen), 		  nsi_peerport(nsi));    break;  case NSE_TYPE_TIMER:    nsock_trace(ms, "Callback: %s %s %sfor EID %li", 		nse_type2str(nse->type), nse_status2str(nse->status), errstr, 		nse->id);	    break;	#if HAVE_PCAP  case NSE_TYPE_PCAP_READ:	 nsock_trace(ms, "Callback: %s %s %sfor EID %li ",		     nse_type2str(nse->type), nse_status2str(nse->status),		     errstr, nse->id);    break;#endif   default:   assert(0);    break;  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?