/* Write some data to the socket. If the write is not COMPLETED within * timeout_msecs , NSE_STATUS_TIMEOUT will be returned. If you are supplying * NUL-terminated data, you can optionally pass -1 for datalen and nsock_write * will figure out the length itself */ nsock_event_id nsock_write(nsock_pool ms_pool, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs, void *userdata, const char *data, int datalen) { mspool *nsp = (mspool *)ms_pool; msiod *nsi = (msiod *)ms_iod; msevent *nse; char displaystr[256]; nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata); assert(nse); nse->writeinfo.dest.ss_family = AF_UNSPEC; if (datalen < 0) datalen = (int)strlen(data); if (nsp->loglevel == NSOCK_LOG_DBG_ALL && datalen < 80) { memcpy(displaystr, ": ", 2); memcpy(displaystr + 2, data, datalen); displaystr[2 + datalen] = '\0'; replacenonprintable(displaystr + 2, datalen, '.'); } else { displaystr[0] = '\0'; } nsock_log_debug(nsp, "Write request for %d bytes to IOD #%li EID %li [%s]%s", datalen, nsi->id, nse->id, get_peeraddr_string(nsi), displaystr); fs_cat(&nse->iobuf, data, datalen); nsp_add_event(nsp, nse); return nse->id; }
nsock_event_id nsock_sendto(nsock_pool ms_pool, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs, void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port, const char *data, int datalen) { mspool *nsp = (mspool *) ms_pool; msiod *nsi = (msiod *) ms_iod; msevent *nse; char displaystr[256]; struct sockaddr_in *sin = (struct sockaddr_in *) saddr; #if HAVE_IPV6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) saddr; #endif nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata); assert(nse); if (sin->sin_family == AF_INET) { sin->sin_port = htons(port); } else { assert(sin->sin_family == AF_INET6); #if HAVE_IPV6 sin6->sin6_port = htons(port); #else fatal("IPv6 address passed to nsock_connect_* call, but nsock was not compiled w/IPv6 support"); #endif } assert(sslen <= sizeof(nse->writeinfo.dest)); memcpy(&nse->writeinfo.dest, saddr, sslen); nse->writeinfo.destlen = sslen; assert(sslen <= sizeof(nse->iod->peer)); memcpy(&nse->iod->peer, saddr, sslen); nse->iod->peerlen = sslen; if (datalen < 0) datalen = (int) strlen(data); if (nsp->tracelevel > 0) { if (nsp->tracelevel > 1 && datalen < 80) { memcpy(displaystr, ": ", 2); memcpy(displaystr + 2, data, datalen); displaystr[2 + datalen] = '\0'; replacenonprintable(displaystr + 2, datalen, '.'); } else { displaystr[0] = '\0'; } nsock_trace(nsp, "Sendto request for %d bytes to IOD #%li EID %li [%s:%hu]%s", datalen, nsi->id, nse->id, inet_ntop_ez(&nse->writeinfo.dest, nse->writeinfo.destlen), port, displaystr); } fscat(&nse->iobuf, data, datalen); nsp_add_event(nsp, nse); return nse->id; }
nsock_event_id nsock_sendto(nsock_pool ms_pool, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs, void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port, const char *data, int datalen) { mspool *nsp = (mspool *)ms_pool; msiod *nsi = (msiod *)ms_iod; msevent *nse; char displaystr[256]; struct sockaddr_in *sin = (struct sockaddr_in *)saddr; #if HAVE_IPV6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)saddr; #endif nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata); assert(nse); if (saddr->sa_family == AF_INET) { sin->sin_port = htons(port); #if HAVE_SYS_UN_H } else if (saddr->sa_family == AF_INET6) { #else } else { #endif assert(saddr->sa_family == AF_INET6); #if HAVE_IPV6 sin6->sin6_port = htons(port); #else fatal("IPv6 address passed to %s call, but nsock was not compiled w/IPv6 support", __func__); #endif } assert(sslen <= sizeof(nse->writeinfo.dest)); memcpy(&nse->writeinfo.dest, saddr, sslen); nse->writeinfo.destlen = sslen; assert(sslen <= sizeof(nse->iod->peer)); memcpy(&nse->iod->peer, saddr, sslen); nse->iod->peerlen = sslen; if (datalen < 0) datalen = (int) strlen(data); if (nsp->loglevel == NSOCK_LOG_DBG_ALL && datalen < 80) { memcpy(displaystr, ": ", 2); memcpy(displaystr + 2, data, datalen); displaystr[2 + datalen] = '\0'; replacenonprintable(displaystr + 2, datalen, '.'); } else { displaystr[0] = '\0'; } nsock_log_debug(nsp, "Sendto request for %d bytes to IOD #%li EID %li [%s]%s", datalen, nsi->id, nse->id, get_peeraddr_string(nse->iod), displaystr); fs_cat(&nse->iobuf, data, datalen); nsp_add_event(nsp, nse); return nse->id; }
/* Write some data to the socket. If the write is not COMPLETED within timeout_msecs , NSE_STATUS_TIMEOUT will be returned. If you are supplying NUL-terminated data, you can optionally pass -1 for datalen and nsock_write will figure out the length itself */ nsock_event_id nsock_write(nsock_pool ms_pool, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs, void *userdata, const char *data, int datalen) { mspool *nsp = (mspool *) ms_pool; msiod *nsi = (msiod *) ms_iod; msevent *nse; char displaystr[256]; nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata); assert(nse); nse->writeinfo.dest.ss_family = AF_UNSPEC; if (datalen < 0) datalen = (int) strlen(data); if (nsp->tracelevel > 0) { if (nsp->tracelevel > 1 && datalen < 80) { memcpy(displaystr, ": ", 2); memcpy(displaystr + 2, data, datalen); displaystr[2 + datalen] = '\0'; replacenonprintable(displaystr + 2, datalen, '.'); } else displaystr[0] = '\0'; if (nsi->peerlen > 0) nsock_trace(nsp, "Write request for %d bytes to IOD #%li EID %li [%s:%hu]%s", datalen, nsi->id, nse->id, inet_ntop_ez(&nsi->peer, nsi->peerlen), nsi_peerport(nsi), displaystr); else nsock_trace(nsp, "Write request for %d bytes to IOD #%li EID %li (peer unspecified)%s", datalen, nsi->id, nse->id, displaystr); } fscat(&nse->iobuf, data, datalen); nsp_add_event(nsp, nse); return nse->id; }
/* An event has been completed and the handler is about to be called. This * function writes out tracing data about the event if necessary */ void nsock_trace_handler_callback(struct npool *ms, struct nevent *nse) { struct niod *nsi; char *str; int strlength = 0; char displaystr[256]; char errstr[256]; if (NsockLogLevel > NSOCK_LOG_INFO) return; nsi = nse->iod; if (nse->status == NSE_STATUS_ERROR) Snprintf(errstr, sizeof(errstr), "[%s (%d)] ", socket_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_log_info("Callback: %s %s %sfor EID %li [%s]", nse_type2str(nse->type), nse_status2str(nse->status), errstr, nse->id, get_peeraddr_string(nsi)); break; case NSE_TYPE_READ: if (nse->status != NSE_STATUS_SUCCESS) { nsock_log_info("Callback: %s %s %sfor EID %li [%s]", nse_type2str(nse->type), nse_status2str(nse->status), errstr, nse->id, get_peeraddr_string(nsi)); } else { str = nse_readbuf(nse, &strlength); if (strlength < 80) { memcpy(displaystr, ": ", 2); memcpy(displaystr + 2, str, strlength); displaystr[2 + strlength] = '\0'; replacenonprintable(displaystr + 2, strlength, '.'); } else { displaystr[0] = '\0'; } nsock_log_info("Callback: %s %s for EID %li [%s] %s(%d bytes)%s", nse_type2str(nse->type), nse_status2str(nse->status), nse->id, get_peeraddr_string(nsi), nse_eof(nse) ? "[EOF]" : "", strlength, displaystr); } break; case NSE_TYPE_WRITE: nsock_log_info("Callback: %s %s %sfor EID %li [%s]", nse_type2str(nse->type), nse_status2str(nse->status), errstr, nse->id, get_peeraddr_string(nsi)); break; case NSE_TYPE_TIMER: nsock_log_info("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_log_info("Callback: %s %s %sfor EID %li ", nse_type2str(nse->type), nse_status2str(nse->status), errstr, nse->id); break; #endif default: fatal("Invalid nsock event type (%d)", nse->type); } }
/* An event has been completed and the handler is about to be called. This * function writes out tracing data about the event if necessary */ 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)] ", socket_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]", nse_type2str(nse->type), nse_status2str(nse->status), errstr, nse->id, get_peeraddr_string(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]", nse_type2str(nse->type), nse_status2str(nse->status), errstr, nse->id, get_peeraddr_string(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] %s(%d bytes)%s", nse_type2str(nse->type), nse_status2str(nse->status), nse->id, get_peeraddr_string(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]", nse_type2str(nse->type), nse_status2str(nse->status), errstr, nse->id, get_peeraddr_string(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; } }
/* Same as nsock_write except you can use a printf-style format and you can only use this for ASCII strings */ nsock_event_id nsock_printf(nsock_pool ms_pool, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs, void *userdata, char *format, ...) { mspool *nsp = (mspool *)ms_pool; msiod *nsi = (msiod *)ms_iod; msevent *nse; char buf[4096]; char *buf2 = NULL; int res, res2; int strlength = 0; char displaystr[256]; va_list ap; va_start(ap,format); nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata); assert(nse); res = Vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); if (res != -1) { if (res > sizeof(buf)) { buf2 = (char * )safe_malloc(res + 16); res2 = Vsnprintf(buf2, sizeof(buf), format, ap); if (res2 == -1 || res2 > res) { free(buf2); buf2 = NULL; } else strlength = res2; } else { buf2 = buf; strlength = res; } } if (!buf2) { nse->event_done = 1; nse->status = NSE_STATUS_ERROR; nse->errnum = EMSGSIZE; } else { if (strlength == 0) { nse->event_done = 1; nse->status = NSE_STATUS_SUCCESS; } else { fs_cat(&nse->iobuf, buf2, strlength); } } if (nsp->loglevel == NSOCK_LOG_DBG_ALL && nse->status != NSE_STATUS_ERROR && strlength < 80) { memcpy(displaystr, ": ", 2); memcpy(displaystr + 2, buf2, strlength); displaystr[2 + strlength] = '\0'; replacenonprintable(displaystr + 2, strlength, '.'); } else { displaystr[0] = '\0'; } nsock_log_debug(nsp, "Write request for %d bytes to IOD #%li EID %li [%s]%s", strlength, nsi->id, nse->id, get_peeraddr_string(nsi), displaystr); if (buf2 != buf) free(buf2); nsp_add_event(nsp, nse); return nse->id; }