changeset 53:2423f3aac4ce

libsip: SDP parsing implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Sep 2022 10:45:50 -0800
parents ffb563a17f23
children 9f045dcff60e
files libsip/Makefile libsip/sdp.h libsip/sdp_parse.c
diffstat 3 files changed, 129 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libsip/Makefile	Thu Sep 08 00:27:48 2022 -0800
+++ b/libsip/Makefile	Thu Sep 08 10:45:50 2022 -0800
@@ -1,7 +1,7 @@
 CC=	gcc
 CFLAGS=	-O2
 OBJS=	get_header.o grok_from.o out_msg.o primary_parse.o req_supp.o \
-	uas_basic.o uri_utils.o
+	sdp_parse.o uas_basic.o uri_utils.o
 LIB=	libsip.a
 
 all:	${LIB}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libsip/sdp.h	Thu Sep 08 10:45:50 2022 -0800
@@ -0,0 +1,24 @@
+/*
+ * This header file defines structures to be used for SDP
+ * parsing and generation.
+ */
+
+struct sdp_parse {
+	struct in_addr	ip_addr;
+	unsigned	audio_port;
+	unsigned	codec_mask;
+};
+
+struct sdp_gen {
+	unsigned	session_id;
+	unsigned	version;
+	struct in_addr	owner_ip;
+	struct in_addr	conn_ip;
+	unsigned	conn_port;
+	unsigned	codec_mask;
+};
+
+#define	SDP_CODEC_MASK_PCMU		1
+#define	SDP_CODEC_MASK_PCMA		2
+#define	SDP_CODEC_MASK_BOTH		3
+#define	SDP_CODEC_MASK_PCMA_PREF	4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libsip/sdp_parse.c	Thu Sep 08 10:45:50 2022 -0800
@@ -0,0 +1,104 @@
+/*
+ * Here we implement the function that parses received SDP descriptions.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include "../include/tmgw_const.h"
+#include "sdp.h"
+
+parse_incoming_sdp(body, bodylen, dist)
+	char *body;
+	unsigned bodylen;
+	struct sdp_parse *dist;
+{
+	char *cp, *endp;
+	int got_c = 0, got_m = 0, prefer_pcma = 0;
+	unsigned codec;
+
+	cp = body;
+	endp = body + bodylen;
+	while (cp < endp) {
+		if (!islower(cp[0]) || cp[1] != '=')
+			return(-1);
+		switch (cp[0]) {
+		case 'c':
+			if (got_c)
+				return(-1);
+			got_c = 1;
+			if (strncmp(cp + 2, "IN IP4 ", 7))
+				return(-1);
+			cp += 9;
+			dist->ip_addr.s_addr = inet_addr(cp);
+			if (dist->ip_addr.s_addr == INADDR_NONE)
+				return(-1);
+			break;
+		case 'm':
+			if (got_m)
+				return(-1);
+			got_m = 1;
+			if (strncmp(cp + 2, "audio ", 6))
+				return(-1);
+			cp += 8;
+			if (!isdigit(*cp))
+				return(-1);
+			dist->audio_port = strtoul(cp, &cp, 10);
+			if (!strncmp(cp, " RTP/AVP", 8))
+				return(-1);
+			cp += 8;
+			dist->codec_mask = 0;
+			for (;;) {
+				if (*cp == '\r' || *cp == '\n')
+					break;
+				if (*cp++ != ' ')
+					return(-1);
+				codec = strtoul(cp, &cp, 10);
+				switch (codec) {
+				case PSTN_CODEC_PCMU:
+					dist->codec_mask |= SDP_CODEC_MASK_PCMU;
+					break;
+				case PSTN_CODEC_PCMA:
+					if (!dist->codec_mask)
+						prefer_pcma = 1;
+					dist->codec_mask |= SDP_CODEC_MASK_PCMA;
+					break;
+				}
+			}
+			if (dist->codec_mask == SDP_CODEC_MASK_BOTH &&
+			    prefer_pcma)
+				dist->codec_mask |= SDP_CODEC_MASK_PCMA_PREF;
+			break;
+		default:
+			cp += 2;
+		}
+		for (;;) {
+			if (cp >= endp)
+				return(-1);
+			if (!*cp)
+				return(-1);
+			if (*cp == '\n') {
+				cp++;
+				break;
+			}
+			if (*cp == '\r') {
+				cp++;
+				if (cp >= endp)
+					return(-1);
+				if (*cp++ != '\n')
+					return(-1);
+				break;
+			}
+			cp++;
+		}
+	}
+	if (got_c && got_m)
+		return(0);
+	else
+		return(-1);
+}