# HG changeset patch # User Mychaela Falconia # Date 1690264149 28800 # Node ID 67289fac8a44c539400ad896498dbc7d6e2ea906 # Parent 10a4b0b0a239f3cee3d039b3800ca5bc027a510a utils: new program tcpserv-dump diff -r 10a4b0b0a239 -r 67289fac8a44 .hgignore --- a/.hgignore Sat Jul 08 13:32:32 2023 -0800 +++ b/.hgignore Mon Jul 24 21:49:09 2023 -0800 @@ -20,6 +20,7 @@ ^utils/sip-out-test$ ^utils/sip-rx-test$ ^utils/sip-udp-dump$ +^utils/tcpserv-dump$ ^utils/themwi-check-own$ ^utils/themwi-dump-numdb$ ^utils/themwi-short-dial$ diff -r 10a4b0b0a239 -r 67289fac8a44 utils/Makefile --- a/utils/Makefile Sat Jul 08 13:32:32 2023 -0800 +++ b/utils/Makefile Mon Jul 24 21:49:09 2023 -0800 @@ -3,7 +3,7 @@ PROGS= sip-out-test sip-rx-test sip-udp-dump themwi-check-own \ themwi-dump-numdb themwi-short-dial themwi-update-numdb \ themwi-update-outrt -NOINST= rtp-alloc-test +NOINST= rtp-alloc-test tcpserv-dump LIBNUMDB=../libnumdb/libnumdb.a LIBRTPA=../librtpalloc/librtpalloc.a LIBSIP= ../libsip/libsip.a @@ -24,6 +24,9 @@ sip-udp-dump: sip-udp-dump.c ${CC} ${CFLAGS} -o $@ $@.c +tcpserv-dump: tcpserv-dump.c + ${CC} ${CFLAGS} -o $@ $@.c + themwi-check-own: themwi-check-own.o ${LIBNUMDB} ${LIBUTIL} ${CC} ${CFLAGS} -o $@ $@.o ${LIBNUMDB} ${LIBUTIL} diff -r 10a4b0b0a239 -r 67289fac8a44 utils/tcpserv-dump.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utils/tcpserv-dump.c Mon Jul 24 21:49:09 2023 -0800 @@ -0,0 +1,173 @@ +/* + * This debug utility binds to a TCP port specified on the command line, + * accepts incoming TCP connections and reads any bytes sent by a client + * on an opened connection - but never sends anything back. A log file + * is written, recording all received connections and bytes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXCONN 10 + +static int tcp_port; +static int listener, nconn, conns[MAXCONN], max_fd; +static FILE *logf; +static struct timeval curtime; +static char fmt_time[32]; + +static void +format_time() +{ + struct tm *tm; + + tm = gmtime(&curtime.tv_sec); + sprintf(fmt_time, "%d-%02d-%02dT%02d:%02d:%02dZ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +static void +handle_accept(newfd, sin) + struct sockaddr_in *sin; +{ + fprintf(logf, "\n%s Accept conn from %s:%u fd %d\n", fmt_time, + inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), newfd); + if (nconn < MAXCONN) { + conns[nconn] = newfd; + nconn++; + if (newfd > max_fd) + max_fd = newfd; + } else { + fprintf(logf, "MAXCONN exceeded, closing new fd\n"); + close(newfd); + } +} + +static int +handle_conn_fd(fd) +{ + u_char buf[512]; + int cc, off, chunk, i, c; + + cc = read(fd, buf, sizeof buf); + fprintf(logf, "\n%s fd %d read %d\n", fmt_time, fd, cc); + if (cc <= 0) { + fprintf(logf, "closing fd\n"); + return(1); + } + for (off = 0; off < cc; off += chunk) { + fprintf(logf, "%04X: ", off); + chunk = cc - off; + if (chunk > 16) + chunk = 16; + for (i = 0; i < 16; i++) { + if (i < chunk) + fprintf(logf, "%02X ", buf[off + i]); + else + fputs(" ", logf); + if (i == 7 || i == 15) + putc(' ', logf); + } + for (i = 0; i < chunk; i++) { + c = buf[off + i]; + if (c < ' ' || c > '~') + c = '.'; + putc(c, logf); + } + putc('\n', logf); + } + return(0); +} + +main(argc, argv) + char **argv; +{ + int max_fd, rc, i; + struct sockaddr_in sin; + socklen_t addrlen; + fd_set fds; + + if (argc != 3) { + fprintf(stderr, "usage: %s port logfile\n", argv[0]); + exit(1); + } + tcp_port = atoi(argv[1]); + listener = socket(AF_INET, SOCK_STREAM, 0); + if (listener < 0) { + perror("socket"); + exit(1); + } + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons(tcp_port); + rc = bind(listener, (struct sockaddr *) &sin, sizeof sin); + if (rc < 0) { + perror("bind"); + exit(1); + } + logf = fopen(argv[2], "a"); + if (!logf) { + perror(argv[2]); + exit(1); + } + rc = listen(listener, 5); + if (rc < 0) { + perror("listen"); + exit(1); + } + gettimeofday(&curtime, 0); + format_time(); + fprintf(logf, "\n%s Test server started\n", fmt_time); + fflush(logf); + nconn = 0; + max_fd = listener; + for (;;) { + FD_ZERO(&fds); + FD_SET(listener, &fds); + for (i = 0; i < nconn; i++) + FD_SET(conns[i], &fds); + rc = select(max_fd+1, &fds, 0, 0, 0); + if (rc < 0) { + if (errno == EINTR) + continue; + perror("select"); + exit(1); + } + gettimeofday(&curtime, 0); + format_time(); + for (i = 0; i < nconn; ) { + if (!FD_ISSET(conns[i], &fds)) { + i++; + continue; + } + if (handle_conn_fd(conns[i])) { + close(conns[i]); + nconn--; + conns[i] = conns[nconn]; + } else + i++; + } + if (FD_ISSET(listener, &fds)) { + addrlen = sizeof(struct sockaddr_in); + rc = accept(listener, (struct sockaddr *) &sin, + &addrlen); + if (rc >= 0) + handle_accept(rc, &sin); + else + fprintf(logf, "\n%s accept syscall error!\n", + fmt_time); + } + fflush(logf); + } +}