view mtctest/setup.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 08d7794cdd0a
children 5141e21596bb
line wrap: on
line source

/*
 * In this module we compose the MNCC_SETUP_REQ message
 * initiating our test MT call.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "../include/mncc.h"
#include "../include/gsm48_const.h"

struct gsm_mncc setup_msg;

static void
set_called_number(arg)
	char *arg;
{
	int rc, ndig;
	char short_num[5], long_num[12];

	if (!strncmp(arg, "imsi:", 5)) {
		rc = grok_imsi_user_arg(arg, setup_msg.imsi);
		if (rc < 0) {
			fprintf(stderr,
			"error: call-by-IMSI destination \"%s\" is invalid\n",
				arg);
			exit(1);
		}
		return;
	}
	if (arg[0] == '+') {
		if (arg[1] != '1') {
			fprintf(stderr,
	"error: plus-format call destination number must begin with 1\n");
			exit(1);
		}
		if (grok_number_string(arg+1, 1) != 11) {
bad_plus1:		fprintf(stderr,
			"error: malformed +1 call destination number\n");
			exit(1);
		}
		dehyphen_number_string(arg+1, setup_msg.called.number);
		if (!is_nanp_valid_prefix(setup_msg.called.number+1))
			goto bad_plus1;
		setup_msg.called.type = GSM48_TON_INTERNATIONAL;
		setup_msg.called.plan = GSM48_NPI_ISDN_E164;
		setup_msg.fields |= MNCC_F_CALLED;
		return;
	}
	ndig = grok_number_string(arg, 1);
	switch (ndig) {
	case 4:
		dehyphen_number_string(arg, short_num);
		if (read_number_db() < 0) {
			fprintf(stderr, "error reading number database\n");
			exit(1);
		}
		rc = lookup_short_dial_number(short_num, long_num);
		if (!rc) {
			fprintf(stderr,
				"error: short dial number %s is not valid\n",
				short_num);
			exit(1);
		}
		if (long_num[0]) {
			setup_msg.called.type = GSM48_TON_INTERNATIONAL;
			setup_msg.called.plan = GSM48_NPI_ISDN_E164;
			setup_msg.called.number[0] = '1';
			strcpy(setup_msg.called.number+1, long_num);
		} else {
			setup_msg.called.type = GSM48_TON_NET_SPEC;
			setup_msg.called.plan = GSM48_NPI_PRIVATE;
			strcpy(setup_msg.called.number, short_num);
		}
		setup_msg.fields |= MNCC_F_CALLED;
		return;
	case 10:
		dehyphen_number_string(arg, long_num);
		if (!is_nanp_valid_prefix(long_num))
			break;
		setup_msg.called.type = GSM48_TON_INTERNATIONAL;
		setup_msg.called.plan = GSM48_NPI_ISDN_E164;
		setup_msg.called.number[0] = '1';
		strcpy(setup_msg.called.number+1, long_num);
		setup_msg.fields |= MNCC_F_CALLED;
		return;
	case 11:
		dehyphen_number_string(arg, long_num);
		if (long_num[0] != '1')
			break;
		if (!is_nanp_valid_prefix(long_num+1))
			break;
		setup_msg.called.type = GSM48_TON_INTERNATIONAL;
		setup_msg.called.plan = GSM48_NPI_ISDN_E164;
		strcpy(setup_msg.called.number, long_num);
		setup_msg.fields |= MNCC_F_CALLED;
		return;
	}
	fprintf(stderr, "error: call destination number \"%s\" is invalid\n",
		arg);
	exit(1);
}

static void
set_calling_number(arg)
	char *arg;
{
	unsigned ndig;
	int c;

	if (!strcmp(arg, "unavail")) {
		setup_msg.calling.present = GSM48_PRES_UNAVAIL;
		return;
	}
	if (!strcmp(arg, "blocked")) {
		setup_msg.calling.present = GSM48_PRES_RESTR;
		return;
	}
	if (*arg == '+') {
		setup_msg.calling.type = GSM48_TON_INTERNATIONAL;
		arg++;
	}
	for (ndig = 0; *arg; ) {
		c = *arg++;
		if (c == ',')
			break;
		if (c == '-')
			continue;
		if (!is_valid_ext_digit(c)) {
			fprintf(stderr,
	"error: calling number argument contains invalid digit \'%c\'\n",
				c);
			exit(1);
		}
		if (ndig >= 32) {
			fprintf(stderr,
				"error: calling number argument is too long\n");
			exit(1);
		}
		setup_msg.calling.number[ndig] = c;
		ndig++;
	}
	if (!ndig) {
		fprintf(stderr,
			"error: calling number argument has no digits\n");
		exit(1);
	}
	setup_msg.calling.plan = GSM48_NPI_ISDN_E164;
	for (;;) {
		while (*arg == ',')
			arg++;
		if (!*arg)
			return;
		if (!strncmp(arg, "ton=", 4)) {
			arg += 4;
			if (arg[0] >= '0' && arg[1] <= '7' && !isdigit(arg[1])){
				setup_msg.calling.type = *arg - '0';
				arg++;
			} else {
				fprintf(stderr,
		"error: calling number argument contains invalid ton= part\n");
				exit(1);
			}
		} else if (!strncmp(arg, "npi=", 4)) {
			arg += 4;
			if (arg[0] >= '0' && arg[1] <= '9' && !isdigit(arg[1])){
				setup_msg.calling.plan = *arg - '0';
				arg++;
			} else if (arg[0] == '1' && arg[1] >= '0' &&
				   arg[1] <= '5' && !isdigit(arg[2])) {
				setup_msg.calling.plan = atoi(arg);
				arg += 2;
			} else {
				fprintf(stderr,
		"error: calling number argument contains invalid npi= part\n");
				exit(1);
			}
		} else if (!strncmp(arg, "restr", 5)) {
			arg += 5;
			setup_msg.calling.present = GSM48_PRES_RESTR;
		} else if (!strncmp(arg, "vp", 2)) {
			arg += 2;
			setup_msg.calling.screen = GSM48_SCRN_USER_PASS;
		} else if (!strncmp(arg, "vf", 2)) {
			arg += 2;
			setup_msg.calling.screen = GSM48_SCRN_USER_FAIL;
		} else if (!strncmp(arg, "net", 3)) {
			arg += 3;
			setup_msg.calling.screen = GSM48_SCRN_NETWORK;
		} else {
inv_qual:		fprintf(stderr,
		"error: calling number argument contains invalid qualifier\n");
			exit(1);
		}
		if (!*arg)
			return;
		if (*arg != ',')
			goto inv_qual;
	}
}

void
init_setup_msg(from, to)
	char *from, *to;
{
	setup_msg.msg_type = MNCC_SETUP_REQ;
	setup_msg.callref = 1;
	set_called_number(to);
	if (from) {
		set_calling_number(from);
		setup_msg.fields |= MNCC_F_CALLING;
	}
}

void
send_setup_msg()
{
	if (setup_msg.imsi[0])
		printf("Calling IMSI %s\n", setup_msg.imsi);
	else
		printf("Calling %s%s\n",
			setup_msg.called.type == GSM48_TON_INTERNATIONAL ? "+"
									 : "",
			setup_msg.called.number);
	send_mncc_to_gsm(&setup_msg, sizeof(struct gsm_mncc));
}