view libsip/sdp_parse.c @ 53:2423f3aac4ce

libsip: SDP parsing implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Sep 2022 10:45:50 -0800
parents
children bea761629c5b
line wrap: on
line source

/*
 * 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);
}