/* Remember that pcap descriptor is in nonblocking state. */ int do_actual_pcap_read(msevent *nse) { mspcap *mp = (mspcap *)nse->iod->pcap; nsock_pcap npp; nsock_pcap *n; struct pcap_pkthdr *pkt_header; const unsigned char *pkt_data = NULL; int rc; memset(&npp, 0, sizeof(nsock_pcap)); if (nse->iod->nsp->tracelevel > 2) nsock_trace(nse->iod->nsp, "PCAP do_actual_pcap_read TEST (IOD #%li) (EID #%li)", nse->iod->id, nse->id); assert( FILESPACE_LENGTH(&(nse->iobuf)) == 0 ); rc = pcap_next_ex(mp->pt, &pkt_header, &pkt_data); switch(rc) { case 1: /* read good packet */ #ifdef PCAP_RECV_TIMEVAL_VALID npp.ts = pkt_header->ts; #else /* on these platforms time received from pcap is invalid. It's better to set current time */ memcpy(&npp.ts, nsock_gettimeofday(), sizeof(struct timeval)); #endif npp.len = pkt_header->len; npp.caplen = pkt_header->caplen; npp.packet = pkt_data; fscat(&(nse->iobuf), (char *)&npp, sizeof(npp)); fscat(&(nse->iobuf), (char *)pkt_data, npp.caplen); n = (nsock_pcap *)FILESPACE_STR(&(nse->iobuf)); n->packet = (unsigned char *)FILESPACE_STR(&(nse->iobuf)) + sizeof(npp); if (nse->iod->nsp->tracelevel > 2) nsock_trace(nse->iod->nsp, "PCAP do_actual_pcap_read READ (IOD #%li) (EID #%li) size=%i", nse->iod->id, nse->id, pkt_header->caplen); return(1); case 0: /* timeout */ return(0); case -1: /* error */ fatal("pcap_next_ex() fatal error while reading from pcap: %s\n", pcap_geterr(mp->pt)); break; case -2: /* no more packets in savefile (if reading from one) */ default: assert(0); } return 0; }
void nse_readpcap(nsock_event nsee, const unsigned char **l2_data, size_t *l2_len, const unsigned char **l3_data, size_t *l3_len, size_t *packet_len, struct timeval *ts) { msevent *nse = (msevent *)nsee; msiod *iod = nse->iod; mspcap *mp = (mspcap *) iod->pcap; size_t l2l; size_t l3l; nsock_pcap *n = (nsock_pcap *) FILESPACE_STR(&(nse->iobuf)); if(FILESPACE_LENGTH(&(nse->iobuf)) < sizeof(nsock_pcap)){ if(l2_data) *l2_data = NULL; if(l2_len ) *l2_len = 0; if(l3_data) *l3_data = NULL; if(l3_len ) *l3_len = 0; if(packet_len) *packet_len = 0; return; } l2l = MIN(mp->l3_offset, n->caplen); l3l = MAX(0, n->caplen-mp->l3_offset); if(l2_data) *l2_data = n->packet; if(l2_len ) *l2_len = l2l; if(l3_data) *l3_data = l3l>0? n->packet+l2l : NULL; if(l3_len ) *l3_len = l3l; if(packet_len) *packet_len = n->len; if(ts) *ts = n->ts; return; }
void handle_read_result(mspool *ms, msevent *nse, enum nse_status status) { unsigned int count; char *str; int rc, len; msiod *iod = nse->iod; if (status == NSE_STATUS_TIMEOUT) { nse->event_done = 1; if (FILESPACE_LENGTH(&nse->iobuf) > 0) nse->status = NSE_STATUS_SUCCESS; else nse->status = NSE_STATUS_TIMEOUT; } else if (status == NSE_STATUS_CANCELLED) { nse->status = status; nse->event_done = 1; } else if (status == NSE_STATUS_SUCCESS) { rc = do_actual_read(ms, nse); /* printf("DBG: Just read %d new bytes%s.\n", rc, iod->ssl? "( SSL!)" : ""); */ if (rc > 0) { nse->iod->read_count += rc; /* We decide whether we have read enough to return */ switch(nse->readinfo.read_type) { case NSOCK_READ: nse->status = NSE_STATUS_SUCCESS; nse->event_done = 1; break; case NSOCK_READBYTES: if (FILESPACE_LENGTH(&nse->iobuf) >= nse->readinfo.num) { nse->status = NSE_STATUS_SUCCESS; nse->event_done = 1; } /* else we are not done */ break; case NSOCK_READLINES: /* Lets count the number of lines we have ... */ count = 0; len = FILESPACE_LENGTH(&nse->iobuf) -1; str = FILESPACE_STR(&nse->iobuf); for (count=0; len >= 0; len--) { if (str[len] == '\n') { count++; if ((int)count >= nse->readinfo.num) break; } } if ((int) count >= nse->readinfo.num) { nse->event_done = 1; nse->status = NSE_STATUS_SUCCESS; } /* Else we are not done */ break; default: assert(0); break; /* unreached */ } } } else { assert(0); /* Currently we only know about TIMEOUT, CANCELLED, and SUCCESS callbacks */ } /* If there are no more reads for this IOD, we are done reading on the socket * so we can take it off the descriptor list ... */ if (nse->event_done && iod->sd >= 0) { int ev = EV_NONE; #if HAVE_OPENSSL if (nse->iod->ssl != NULL) ev |= socket_count_dec_ssl_desire(nse); else #endif ev |= socket_count_read_dec(nse->iod); update_events(nse->iod, ms, EV_NONE, ev); } }
void handle_write_result(mspool *ms, msevent *nse, enum nse_status status) { int bytesleft; char *str; int res; int err; msiod *iod = nse->iod; if (status == NSE_STATUS_TIMEOUT || status == NSE_STATUS_CANCELLED) { nse->event_done = 1; nse->status = status; } else if (status == NSE_STATUS_SUCCESS) { str = FILESPACE_STR(&nse->iobuf) + nse->writeinfo.written_so_far; bytesleft = FILESPACE_LENGTH(&nse->iobuf) - nse->writeinfo.written_so_far; if (nse->writeinfo.written_so_far > 0) assert(bytesleft > 0); #if HAVE_OPENSSL if (iod->ssl) res = SSL_write(iod->ssl, str, bytesleft); else #endif if (nse->writeinfo.dest.ss_family == AF_UNSPEC) res = send(nse->iod->sd, str, bytesleft, 0); else res = sendto(nse->iod->sd, str, bytesleft, 0, (struct sockaddr *)&nse->writeinfo.dest, (int)nse->writeinfo.destlen); if (res == bytesleft) { nse->event_done = 1; nse->status = NSE_STATUS_SUCCESS; } else if (res >= 0) { nse->writeinfo.written_so_far += res; } else { assert(res == -1); if (iod->ssl) { #if HAVE_OPENSSL err = SSL_get_error(iod->ssl, res); if (err == SSL_ERROR_WANT_READ) { int evclr; evclr = socket_count_dec_ssl_desire(nse); socket_count_read_inc(iod); update_events(iod, ms, EV_READ, evclr); nse->sslinfo.ssl_desire = err; } else if (err == SSL_ERROR_WANT_WRITE) { int evclr; evclr = socket_count_dec_ssl_desire(nse); socket_count_write_inc(iod); update_events(iod, ms, EV_WRITE, evclr); nse->sslinfo.ssl_desire = err; } else { /* Unexpected error */ nse->event_done = 1; nse->status = NSE_STATUS_ERROR; nse->errnum = EIO; } #endif } else { err = socket_errno(); if (err != EINTR && err != EAGAIN #ifndef WIN32 && err != EBUSY #endif ) { nse->event_done = 1; nse->status = NSE_STATUS_ERROR; nse->errnum = err; } } } if (res >= 0) nse->iod->write_count += res; } if (nse->event_done && nse->iod->sd != -1) { int ev = EV_NONE; #if HAVE_OPENSSL if (nse->iod->ssl != NULL) ev |= socket_count_dec_ssl_desire(nse); else #endif ev |= socket_count_write_dec(nse->iod); update_events(nse->iod, ms, EV_NONE, ev); } return; }