/* Print message to buffer. If buffer is large enough to hold the message, * return buffer. If buffer is to small, allocate large enough buffer on heap, * and return allocated buffer. */ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap) { va_list ap_copy; int len; va_copy(ap_copy, ap); len = vsnprintf(*buf, size, fmt, ap_copy); va_end(ap_copy); if (len < 0) { /* eCos and Windows are not standard-compliant and return -1 when * the buffer is too small. Keep allocating larger buffers until we * succeed or out of memory. */ *buf = NULL; while (len < 0) { NS_FREE(*buf); size *= 2; if ((*buf = (char *) NS_MALLOC(size)) == NULL) break; va_copy(ap_copy, ap); len = vsnprintf(*buf, size, fmt, ap_copy); va_end(ap_copy); } } else if (len > (int) size) { /* Standard-compliant code path. Allocate a buffer that is large enough. */ if ((*buf = (char *) NS_MALLOC(len + 1)) == NULL) { len = -1; } else { va_copy(ap_copy, ap); len = vsnprintf(*buf, len + 1, fmt, ap_copy); va_end(ap_copy); } } return len; }
void ns_hexdump_connection(struct ns_connection *nc, const char *path, int num_bytes, int ev) { const struct mbuf *io = ev == NS_SEND ? &nc->send_mbuf : &nc->recv_mbuf; FILE *fp; char *buf, src[60], dst[60]; int buf_size = num_bytes * 5 + 100; if ((fp = fopen(path, "a")) != NULL) { ns_sock_to_str(nc->sock, src, sizeof(src), 3); ns_sock_to_str(nc->sock, dst, sizeof(dst), 7); fprintf(fp, "%lu %p %s %s %s %d\n", (unsigned long) time(NULL), nc->user_data, src, ev == NS_RECV ? "<-" : ev == NS_SEND ? "->" : ev == NS_ACCEPT ? "<A" : ev == NS_CONNECT ? "C>" : "XX", dst, num_bytes); if (num_bytes > 0 && (buf = (char *) NS_MALLOC(buf_size)) != NULL) { ns_hexdump(io->buf + (ev == NS_SEND ? 0 : io->len) - (ev == NS_SEND ? 0 : num_bytes), num_bytes, buf, buf_size); fprintf(fp, "%s", buf); NS_FREE(buf); } fclose(fp); } }
/* * Create a connection, associate it with the given socket and event handler, * and add to the manager. * * See the `ns_add_sock_opts` structure for a description of the options. */ struct ns_connection *ns_add_sock_opt(struct ns_mgr *s, sock_t sock, ns_event_handler_t callback, struct ns_add_sock_opts opts) { struct ns_connection *conn; if ((conn = (struct ns_connection *) NS_MALLOC(sizeof(*conn))) != NULL) { memset(conn, 0, sizeof(*conn)); ns_set_non_blocking_mode(sock); ns_set_close_on_exec(sock); conn->sock = sock; conn->handler = callback; conn->mgr = s; conn->last_io_time = time(NULL); conn->flags = opts.flags; conn->user_data = opts.user_data; ns_add_conn(s, conn); DBG(("%p %d", conn, sock)); } return conn; }
NS_INTERNAL struct ns_connection *ns_create_connection( struct ns_mgr *mgr, ns_event_handler_t callback, struct ns_add_sock_opts opts) { struct ns_connection *conn; if ((conn = (struct ns_connection *) NS_MALLOC(sizeof(*conn))) != NULL) { memset(conn, 0, sizeof(*conn)); conn->sock = INVALID_SOCKET; conn->handler = callback; conn->mgr = mgr; conn->last_io_time = time(NULL); conn->flags = opts.flags & _NS_ALLOWED_CONNECT_FLAGS_MASK; conn->user_data = opts.user_data; /* * SIZE_MAX is defined as a long long constant in * system headers on some platforms and so it * doesn't compile with pedantic ansi flags. */ conn->recv_mbuf_limit = ~0; } return conn; }