view sip-manual-out/readconf.c @ 124:7e04d28fae8b

sip-in: default use-100rel to no BulkVS servers act badly when we send a reliable 180 Ringing response to an incoming call, even though they advertise 100rel support in the Supported header in the INVITE packet, and we probably won't be implementing 100rel for outbound because doing per-the-spec PRACK as a UAC is just too burdensome. Therefore, we need to consider 100rel extension as not-really-supported in themwi-system-sw.
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 01 Oct 2022 15:54:50 -0800
parents d74b545a3c2a
children
line wrap: on
line source

/*
 * In this module we implement the reading of destination configuration
 * for sip-manual-out.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

struct in_addr sip_bind_ip, sip_dest_ip;
unsigned sip_bind_port, sip_dest_port = 5060;
char sip_dest_domain[64];

struct parse_state {
	char *filename;
	int lineno;
	int set_mask;
};

static void
handle_ip(st, kw, var, arg)
	struct parse_state *st;
	char *kw, *arg;
	struct in_addr *var;
{
	var->s_addr = inet_addr(arg);
	if (var->s_addr == INADDR_NONE) {
		fprintf(stderr,
			"%s line %d: invalid IP address argument \"%s\"\n",
			st->filename, st->lineno, arg);
		exit(1);
	}
}

static void
handle_num(st, kw, var, arg)
	struct parse_state *st;
	char *kw, *arg;
	unsigned *var;
{
	char *endp;

	*var = strtoul(arg, &endp, 10);
	if (*endp) {
		fprintf(stderr, "%s line %d: invalid numeric argument \"%s\"\n",
			st->filename, st->lineno, arg);
		exit(1);
	}
}

static void
handle_str(st, kw, var, arg)
	struct parse_state *st;
	char *kw, *arg, *var;
{
	strcpy(var, arg);
}

static void
process_line(st, line)
	struct parse_state *st;
	char *line;
{
	char *cp, *np, *arg;
	void (*handler)(), *var;
	int set_id;

	if (!index(line, '\n')) {
		fprintf(stderr, "%s line %d: too long or missing newline\n",
			st->filename, st->lineno);
		exit(1);
	}
	for (cp = line; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#')
		return;
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	if (!strcmp(np, "bind-ip")) {
		handler = handle_ip;
		var = &sip_bind_ip;
		set_id = 1;
	} else if (!strcmp(np, "bind-port")) {
		handler = handle_num;
		var = &sip_bind_port;
		set_id = 2;
	} else if (!strcmp(np, "dest-ip")) {
		handler = handle_ip;
		var = &sip_dest_ip;
		set_id = 4;
	} else if (!strcmp(np, "dest-port")) {
		handler = handle_num;
		var = &sip_dest_port;
		set_id = 0;
	} else if (!strcmp(np, "dest-domain")) {
		handler = handle_str;
		var = sip_dest_domain;
		set_id = 8;
	} else {
		fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n",
			st->filename, st->lineno, np);
		exit(1);
	}
	if (st->set_mask & set_id) {
		fprintf(stderr, "%s line %d: duplicate %s setting\n",
			st->filename, st->lineno, np);
		exit(1);
	}
	while (isspace(*cp))
		cp++;
	if (*cp == '\0' || *cp == '#') {
inv_syntax:	fprintf(stderr,
			"%s line %d: %s setting requires one argument\n",
			st->filename, st->lineno, np);
		exit(1);
	}
	for (arg = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp != '\0' && *cp != '#')
		goto inv_syntax;
	handler(st, np, var, arg);
	st->set_mask |= set_id;
}

read_config_file(filename)
	char *filename;
{
	FILE *inf;
	struct parse_state pst;
	char linebuf[256];

	inf = fopen(filename, "r");
	if (!inf) {
		perror(filename);
		exit(1);
	}
	pst.set_mask = 0;
	pst.filename = filename;
	for (pst.lineno = 1; fgets(linebuf, sizeof linebuf, inf); pst.lineno++)
		process_line(&pst, linebuf);
	fclose(inf);
	if (pst.set_mask != 15) {
		fprintf(stderr, "error: %s did not set all required settings\n",
			filename);
		exit(1);
	}
}