changeset 52:ffb563a17f23

wrote sip-out-test program
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Sep 2022 00:27:48 -0800
parents 36a30349b490
children 2423f3aac4ce
files .hgignore utils/Makefile utils/sip-out-test.c
diffstat 3 files changed, 266 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Sep 07 17:53:10 2022 -0800
+++ b/.hgignore	Thu Sep 08 00:27:48 2022 -0800
@@ -10,6 +10,7 @@
 
 ^sip-in/themwi-sip-in$
 
+^utils/sip-out-test$
 ^utils/sip-rx-test$
 ^utils/sip-udp-dump$
 ^utils/themwi-check-own$
--- a/utils/Makefile	Wed Sep 07 17:53:10 2022 -0800
+++ b/utils/Makefile	Thu Sep 08 00:27:48 2022 -0800
@@ -1,7 +1,7 @@
 CC=	gcc
 CFLAGS=	-O2
-PROGS=	sip-rx-test sip-udp-dump themwi-check-own themwi-dump-numdb \
-	themwi-short-dial themwi-update-numdb
+PROGS=	sip-out-test sip-rx-test sip-udp-dump themwi-check-own \
+	themwi-dump-numdb themwi-short-dial themwi-update-numdb
 LIBNUMDB=../libnumdb/libnumdb.a
 LIBSIP=	../libsip/libsip.a
 LIBUTIL=../libutil/libutil.a
@@ -9,6 +9,9 @@
 
 all:	${PROGS}
 
+sip-out-test:	sip-out-test.c
+	${CC} ${CFLAGS} -o $@ $@.c
+
 sip-rx-test:	sip-rx-test.o ${LIBSIP}
 	${CC} ${CFLAGS} -o $@ $@.o ${LIBSIP}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/sip-out-test.c	Thu Sep 08 00:27:48 2022 -0800
@@ -0,0 +1,260 @@
+/*
+ * This program is a contraption for testing manually constructed
+ * outgoing SIP calls to BulkVS.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#define	MAX_SIP_TX_PACKET	1472
+
+static struct in_addr local_ip, remote_ip;
+static unsigned local_sip_port, local_rtp_port, remote_port;
+static char *invite_filename, *log_filename;
+static char invite_packet[MAX_SIP_TX_PACKET];
+static unsigned invite_packet_len;
+static FILE *logF;
+static struct timeval curtime;
+
+static void
+read_invite_file()
+{
+	FILE *inf;
+	char linebuf[128], *cp, *dp;
+	int lineno;
+	unsigned size_accum, linelen;
+
+	inf = fopen(invite_filename, "r");
+	if (!inf) {
+		perror(invite_filename);
+		exit(1);
+	}
+	size_accum = 0;
+	dp = invite_packet;
+	for (lineno = 1; fgets(linebuf, sizeof(linebuf), inf); lineno++) {
+		cp = index(linebuf, '\n');
+		if (!cp) {
+			fprintf(stderr,
+				"%s line %d: too long or missing newline\n",
+				invite_filename, lineno);
+			exit(1);
+		}
+		*cp = '\0';
+		linelen = cp - linebuf;
+		if (size_accum + linelen + 2 > MAX_SIP_TX_PACKET) {
+			fprintf(stderr, "%s line %d: packet overflow\n",
+				invite_filename, lineno);
+			exit(1);
+		}
+		bcopy(linebuf, dp, linelen);
+		dp += linelen;
+		*dp++ = '\r';
+		*dp++ = '\n';
+		size_accum += linelen + 2;
+	}
+	fclose(inf);
+	if (!size_accum) {
+		fprintf(stderr, "error: %s is empty\n", invite_filename);
+		exit(1);
+	}
+	invite_packet_len = size_accum;
+}
+
+static void
+log_common(msg, msglen, sin, dir, outf)
+	char *msg, *dir;
+	unsigned msglen;
+	struct sockaddr_in *sin;
+	FILE *outf;
+{
+	unsigned sec, ms;
+
+	sec = curtime.tv_sec % 86400;
+	ms = curtime.tv_usec / 1000;
+	fprintf(outf, "Msg %s %s:%u %u bytes %02u:%02u:%02u.%03u\n", dir,
+		inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), msglen,
+		sec / 3600, (sec / 60) % 60, sec % 60, ms);
+	fwrite(msg, 1, msglen, outf);
+	putc('\n', outf);
+	fflush(outf);
+}
+
+static void
+log_sip_msg_rx(msg, msglen, sin)
+	char *msg;
+	unsigned msglen;
+	struct sockaddr_in *sin;
+{
+	log_common(msg, msglen, sin, "from", stdout);
+	if (logF)
+		log_common(msg, msglen, sin, "from", logF);
+}
+
+static void
+log_sip_msg_tx(msg, msglen, sin)
+	char *msg;
+	unsigned msglen;
+	struct sockaddr_in *sin;
+{
+	log_common(msg, msglen, sin, "to", stdout);
+	if (logF)
+		log_common(msg, msglen, sin, "to", logF);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	struct sockaddr_in sin_local, sin_rtp, sin_rtcp, sin_remote, sin_rx;
+	int sock_sip, sock_rtp, sock_rtcp, max_fd;
+	socklen_t addrlen;
+	fd_set fds;
+	char recv_buf[4096];
+	int rc;
+
+	/* grok command line arguments */
+	if (argc < 7 || argc > 8) {
+		fprintf(stderr,
+"usage: %s local-ip local-sip local-rtp remote-ip remote-sip inv-file [logfile]\n",
+			argv[0]);
+		exit(1);
+	}
+	local_ip.s_addr = inet_addr(argv[1]);
+	if (local_ip.s_addr == INADDR_NONE) {
+		fprintf(stderr, "error: invalid IP address \"%s\"\n", argv[1]);
+		exit(1);
+	}
+	local_sip_port = atoi(argv[2]);
+	local_rtp_port = atoi(argv[3]);
+	remote_ip.s_addr = inet_addr(argv[4]);
+	if (remote_ip.s_addr == INADDR_NONE) {
+		fprintf(stderr, "error: invalid IP address \"%s\"\n", argv[4]);
+		exit(1);
+	}
+	remote_port = atoi(argv[5]);
+	invite_filename = argv[6];
+	log_filename = argv[7];
+	/* fill sin structures */
+	sin_local.sin_family = AF_INET;
+	sin_local.sin_addr = local_ip;
+	sin_local.sin_port = htons(local_sip_port);
+	sin_rtp.sin_family = AF_INET;
+	sin_rtp.sin_addr = local_ip;
+	sin_rtp.sin_port = htons(local_rtp_port);
+	sin_rtcp.sin_family = AF_INET;
+	sin_rtcp.sin_addr = local_ip;
+	sin_rtcp.sin_port = htons(local_rtp_port+1);
+	sin_remote.sin_family = AF_INET;
+	sin_remote.sin_addr = remote_ip;
+	sin_remote.sin_port = htons(remote_port);
+	/* create and bind sockets */
+	sock_sip = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sock_sip < 0) {
+		perror("socket");
+		exit(1);
+	}
+	rc = bind(sock_sip, (struct sockaddr *) &sin_local,
+		  sizeof(struct sockaddr_in));
+	if (rc < 0) {
+		perror("bind");
+		exit(1);
+	}
+	sock_rtp = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sock_rtp < 0) {
+		perror("socket");
+		exit(1);
+	}
+	rc = bind(sock_rtp, (struct sockaddr *) &sin_rtp,
+		  sizeof(struct sockaddr_in));
+	if (rc < 0) {
+		perror("bind");
+		exit(1);
+	}
+	sock_rtcp = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sock_rtcp < 0) {
+		perror("socket");
+		exit(1);
+	}
+	rc = bind(sock_rtcp, (struct sockaddr *) &sin_rtcp,
+		  sizeof(struct sockaddr_in));
+	if (rc < 0) {
+		perror("bind");
+		exit(1);
+	}
+	/* read the INVITE packet */
+	read_invite_file();
+	/* open the log file, if we have one */
+	if (log_filename) {
+		logF = fopen(log_filename, "a");
+		if (!logF) {
+			perror(log_filename);
+			exit(1);
+		}
+	}
+	/* now get down to business */
+	max_fd = sock_sip;
+	if (sock_rtp > max_fd)
+		max_fd = sock_rtp;
+	if (sock_rtcp > max_fd)
+		max_fd = sock_rtcp;
+	addrlen = sizeof(struct sockaddr_in);
+	rc = sendto(sock_sip, invite_packet, invite_packet_len, 0,
+			(struct sockaddr *) &sin_remote, addrlen);
+	if (rc < 0) {
+		perror("sendto");
+		exit(1);
+	}
+	gettimeofday(&curtime, 0);
+	log_sip_msg_tx(invite_packet, invite_packet_len, &sin_remote);
+	/* main select loop */
+	for (;;) {
+		FD_ZERO(&fds);
+		FD_SET(sock_sip, &fds);
+		FD_SET(sock_rtp, &fds);
+		FD_SET(sock_rtcp, &fds);
+		rc = select(max_fd+1, &fds, 0, 0, 0);
+		if (rc < 0) {
+			if (errno == EINTR)
+				continue;
+			perror("select");
+			exit(1);
+		}
+		gettimeofday(&curtime, 0);
+		if (FD_ISSET(sock_sip, &fds)) {
+			addrlen = sizeof(struct sockaddr_in);
+			rc = recvfrom(sock_sip, recv_buf, sizeof recv_buf, 0,
+					(struct sockaddr *) &sin_rx, &addrlen);
+			if (rc < 0) {
+				perror("recvfrom");
+				exit(1);
+			}
+			log_sip_msg_rx(recv_buf, rc, &sin_rx);
+		}
+		if (FD_ISSET(sock_rtp, &fds)) {
+			addrlen = sizeof(struct sockaddr_in);
+			rc = recvfrom(sock_rtp, recv_buf, sizeof recv_buf, 0,
+					(struct sockaddr *) &sin_rx, &addrlen);
+			if (rc < 0) {
+				perror("recvfrom");
+				exit(1);
+			}
+		}
+		if (FD_ISSET(sock_rtcp, &fds)) {
+			addrlen = sizeof(struct sockaddr_in);
+			rc = recvfrom(sock_rtp, recv_buf, sizeof recv_buf, 0,
+					(struct sockaddr *) &sin_rx, &addrlen);
+			if (rc < 0) {
+				perror("recvfrom");
+				exit(1);
+			}
+		}
+	}
+}