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 + -
显示快捷键?