diff utils/sip-rx-test.c @ 42:891ebfb55e6b

sip-rx-test program written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 04 Sep 2022 17:55:40 -0800
parents
children 5995660dcbac
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/sip-rx-test.c	Sun Sep 04 17:55:40 2022 -0800
@@ -0,0 +1,128 @@
+/*
+ * This test program is the next level above sip-udp-dump: it binds
+ * to UDP port 5060, waits for a packet to come in, and when a SIP
+ * packet does arrive (call one of the numbers from BulkVS while this
+ * test program is running, to make BulkVS send SIP INVITE), it does
+ * two things with the captured packet:
+ *
+ * 1) The captured packet is written raw into one file named on the
+ *    command line;
+ *
+ * 2) The packet is parsed with parse_incoming_sip_msg(), and the
+ *    parsed structure is written out into the other file named on
+ *    the command line.
+ *
+ * This program is intended to serve as a unit test for the parsing
+ * function.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include "../libsip/parse.h"
+
+static int sock;
+static struct sockaddr_in sin;
+static struct sip_pkt_rx pkt;
+
+static void
+save_raw_packet(filename)
+	char *filename;
+{
+	int fd;
+
+	fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+	if (fd < 0) {
+		perror(filename);
+		exit(1);
+	}
+	write(fd, pkt.pkt_buffer, pkt.pkt_length);
+	close(fd);
+}
+
+static void
+write_parse_output(filename)
+	char *filename;
+{
+	FILE *of;
+	unsigned n;
+
+	of = fopen(filename, "w");
+	if (!of) {
+		perror(filename);
+		exit(1);
+	}
+	switch (pkt.parse_msgtype) {
+	case SIP_MSG_TYPE_REQ:
+		fprintf(of, "Message is a request\n");
+		fprintf(of, "Method: %s\n", pkt.req_method);
+		fprintf(of, "Request-URI: %s\n", pkt.req_uri);
+		break;
+	case SIP_MSG_TYPE_RESP:
+		fprintf(of, "Message is a response\n");
+		fprintf(of, "Status code: %u\n", pkt.status_code);
+		fprintf(of, "Status string: %s\n", pkt.status_str);
+		break;
+	default:
+		fprintf(of, "Parsed returned unknown message type %d\n",
+			pkt.parse_msgtype);
+	}
+	fprintf(of, "Number of header fields: %u\n", pkt.num_hdr_fields);
+	for (n = 0; n < pkt.num_hdr_fields; n++) {
+		fprintf(of, "Header field %u:\n", n);
+		fprintf(of, "  Field name: %s\n",
+			pkt.hdr_fields[n].field_name);
+		fprintf(of, "  Field value: %s\n",
+			pkt.hdr_fields[n].field_value);
+	}
+	fprintf(of, "Message body length: %u\n", pkt.msg_body_len);
+	fclose(of);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	int rc;
+	socklen_t addrlen;
+
+	if (argc != 3) {
+		fprintf(stderr, "usage: %s raw-file parsed-file\n", argv[0]);
+		exit(1);
+	}
+	sock = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sock < 0) {
+		perror("socket");
+		exit(1);
+	}
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = INADDR_ANY;
+	sin.sin_port = htons(5060);
+	rc = bind(sock, (struct sockaddr *) &sin, sizeof sin);
+	if (rc < 0)
+		perror("bind");
+	addrlen = sizeof sin;
+	rc = recvfrom(sock, pkt.pkt_buffer, MAX_SIP_RX_PACKET, 0,
+			(struct sockaddr *) &sin, &addrlen);
+	if (rc < 0) {
+		perror("recvfrom");
+		exit(1);
+	}
+	pkt.pkt_length = rc;
+	printf("Rx from %s:%u, %u bytes\n", inet_ntoa(sin.sin_addr),
+		ntohs(sin.sin_port), pkt.pkt_length);
+	save_raw_packet(argv[1]);
+	rc = parse_incoming_sip_msg(&pkt);
+	if (rc < 0) {
+		printf("Parse error: %d\n", rc);
+		exit(0);
+	}
+	write_parse_output(argv[2]);
+	exit(0);
+}