/* Remember that pcap descriptor is in nonblocking state. */ int do_actual_pcap_read(struct nevent *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)); nsock_log_debug_all(nse->iod->nsp, "PCAP %s TEST (IOD #%li) (EID #%li)", __func__, nse->iod->id, nse->id); assert(fs_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; fs_cat(&(nse->iobuf), (char *)&npp, sizeof(npp)); fs_cat(&(nse->iobuf), (char *)pkt_data, npp.caplen); n = (nsock_pcap *)fs_str(&(nse->iobuf)); n->packet = (unsigned char *)fs_str(&(nse->iobuf)) + sizeof(npp); nsock_log_debug_all(nse->iod->nsp, "PCAP %s READ (IOD #%li) (EID #%li) size=%i", __func__, nse->iod->id, nse->id, pkt_header->caplen); rc = 1; break; case 0: /* timeout */ rc = 0; break; 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: fatal("Unexpected return code from pcap_next_ex! (%d)\n", rc); } return rc; }
/* If you did a read request, and the result was STATUS_SUCCESS, this function * provides the buffer that was read in as well as the number of chars read. * The buffer should not be modified or free'd */ char *nse_readbuf(nsock_event nse, int *nbytes) { msevent *me = (msevent *)nse; if (nbytes) *nbytes = fs_length(&(me->iobuf)); return fs_str(&(me->iobuf)); }
void nse_readpcap(nsock_event nsev, 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) { struct nevent *nse = (struct nevent *)nsev; struct niod *iod = nse->iod; mspcap *mp = (mspcap *)iod->pcap; nsock_pcap *n; size_t l2l; size_t l3l; n = (nsock_pcap *)fs_str(&(nse->iobuf)); if (fs_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(struct npool *ms, struct nevent *nse, enum nse_status status) { unsigned int count; char *str; int rc, len; struct niod *iod = nse->iod; if (status == NSE_STATUS_TIMEOUT) { nse->event_done = 1; if (fs_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 (fs_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 = fs_length(&nse->iobuf) -1; str = fs_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: fatal("Unknown operation type (%d)", (int)nse->readinfo.read_type); } } } else { fatal("Unknown status (%d)", status); } /* 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(struct npool *ms, struct nevent *nse, enum nse_status status) { int bytesleft; char *str; int res; int err; struct niod *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 = fs_str(&nse->iobuf) + nse->writeinfo.written_so_far; bytesleft = fs_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 (errcode_is_failure(err)) { 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); } }