diff mtctest/sig_handler.c @ 21:cc0e1c6e33c3

themwi-test-mtc utility written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 28 Jun 2022 18:25:28 -0800
parents
children e8e82a4bf12b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtctest/sig_handler.c	Tue Jun 28 18:25:28 2022 -0800
@@ -0,0 +1,323 @@
+/*
+ * In this module we handle all incoming messages from MNCC,
+ * printing all of them and generating protocol-required responses
+ * for some.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.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"
+
+extern int disconnect_mode;
+
+static void
+print_bearer_cap(bcap)
+	struct gsm_mncc_bearer_cap *bcap;
+{
+	int i, sv;
+
+	printf("Bearer cap: itcap=%d tmod=%d coding=%d rrq=%d\n",
+		bcap->transfer, bcap->mode, bcap->coding, bcap->radio);
+	printf("  speech: CTM=%d sv", bcap->speech_ctm);
+	for (i = 0; i < 8; i++) {
+		sv = bcap->speech_ver[i];
+		if (sv < 0)
+			break;
+		printf(" %d", sv);
+	}
+	putchar('\n');
+	printf("  data: ra=%d sig=%d async=%d nstop=%d ndata=%d\n",
+		bcap->data.rate_adaption, bcap->data.sig_access,
+		bcap->data.async, bcap->data.nr_stop_bits,
+		bcap->data.nr_data_bits);
+	printf("  urate=%d par=%d irate=%d transp=%d mtype=%d\n",
+		bcap->data.user_rate, bcap->data.parity,
+		bcap->data.interm_rate, bcap->data.transp,
+		bcap->data.modem_type);
+}
+
+static void
+print_cc_cap(cc)
+	struct gsm_mncc_cccap *cc;
+{
+	printf("CC capabilities: DTMF=%d PCP=%d\n", cc->dtmf, cc->pcp);
+}
+
+static void
+print_cause(cause)
+	struct gsm_mncc_cause *cause;
+{
+	int i;
+
+	printf("Cause: loc=%d coding=%d value=%d", cause->location,
+		cause->coding, cause->value);
+	if (cause->rec)
+		printf(" rec=0x%02X", cause->rec_val);
+	for (i = 0; i < cause->diag_len; i++) {
+		if (!(i & 15)) {
+			putchar('\n');
+			putchar(' ');
+		}
+		printf(" %02X", cause->diag[i] & 0xFF);
+	}
+	putchar('\n');
+}
+
+static void
+print_progress(prog)
+	struct gsm_mncc_progress *prog;
+{
+	printf("Progress: loc=%d coding=%d descr=0x%02X", prog->location,
+		prog->coding, prog->descr);
+}
+
+static void
+print_useruser(uu)
+	struct gsm_mncc_useruser *uu;
+{
+	printf("User-User IE: proto=0x%02X\n", uu->proto);
+	/* dump to be implemented if and when we actually get a UU somewhere */
+}
+
+static void
+print_keypad(kp)
+	int kp;
+{
+	if (kp >= '!' && kp <= '~')
+		printf("Keypad code: %c\n", kp);
+	else
+		printf("Keypad code: 0x%02X\n", kp);
+}
+
+static void
+print_facility(fac)
+	struct gsm_mncc_facility *fac;
+{
+	int i;
+
+	printf("Facility IE: %d byte(s)", fac->len);
+	for (i = 0; i < fac->len; i++) {
+		if (!(i & 15)) {
+			putchar('\n');
+			putchar(' ');
+		}
+		printf(" %02X", fac->info[i] & 0xFF);
+	}
+	putchar('\n');
+}
+
+static void
+print_ssver(ssv)
+	struct gsm_mncc_ssversion *ssv;
+{
+	int i;
+
+	printf("SS version IE: %d byte(s)", ssv->len);
+	for (i = 0; i < ssv->len; i++) {
+		if (!(i & 15)) {
+			putchar('\n');
+			putchar(' ');
+		}
+		printf(" %02X", ssv->info[i] & 0xFF);
+	}
+	putchar('\n');
+}
+
+static void
+print_fields(msg)
+	struct gsm_mncc *msg;
+{
+	if (msg->fields & MNCC_F_BEARER_CAP)
+		print_bearer_cap(&msg->bearer_cap);
+	if (msg->fields & MNCC_F_CCCAP)
+		print_cc_cap(&msg->cccap);
+	if (msg->fields & MNCC_F_CAUSE)
+		print_cause(&msg->cause);
+	if (msg->fields & MNCC_F_PROGRESS)
+		print_progress(&msg->progress);
+	if (msg->fields & MNCC_F_USERUSER)
+		print_useruser(&msg->useruser);
+	if (msg->more)
+		printf("More data flag set\n");
+	if (msg->fields & MNCC_F_KEYPAD)
+		print_keypad(msg->keypad);
+	if (msg->fields & MNCC_F_FACILITY)
+		print_facility(&msg->facility);
+	if (msg->fields & MNCC_F_SSVERSION)
+		print_ssver(&msg->ssversion);
+}
+
+static void
+send_connect_ack()
+{
+	struct gsm_mncc ack;
+
+	printf("Sending connect ack\n");
+	bzero(&ack, sizeof(struct gsm_mncc));
+	ack.msg_type = MNCC_SETUP_COMPL_REQ;
+	ack.callref = 1;
+	send_mncc_to_gsm(&ack, sizeof(struct gsm_mncc));
+}
+
+static void
+handle_signaling_msg(msg, msglen)
+	struct gsm_mncc *msg;
+	unsigned msglen;
+{
+	if (msglen != sizeof(struct gsm_mncc)) {
+		fprintf(stderr,
+			"error: Rx MNCC message type 0x%x has wrong length\n",
+			msg->msg_type);
+		exit(1);
+	}
+	if (msg->callref != 1) {
+		fprintf(stderr,
+	"error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n",
+			msg->msg_type, msg->callref);
+		exit(1);
+	}
+	switch (msg->msg_type) {
+	case MNCC_SETUP_CNF:
+		printf("MNCC_SETUP_CNF: call is answered\n");
+		print_fields(msg);
+		send_connect_ack();
+		return;
+	case MNCC_CALL_CONF_IND:
+		printf("MNCC_CALL_CONF_IND: call is confirmed\n");
+		print_fields(msg);
+		return;
+	case MNCC_ALERT_IND:
+		printf("MNCC_ALERT_IND: call is alerting\n");
+		print_fields(msg);
+		return;
+	case MNCC_NOTIFY_IND:
+		printf("NNCC_NOTIFY_IND: NOTIFY byte from MS: 0x%02X\n",
+			msg->notify);
+		return;
+	case MNCC_DISC_IND:
+		printf("MNCC_DISC_IND: MS initiates disconnect\n");
+		print_fields(msg);
+		disconnect_mode = 1;
+		printf("Responding with release request\n");
+		msg->msg_type = MNCC_REL_REQ;
+		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
+		return;
+	case MNCC_FACILITY_IND:
+		printf("MNCC_FACILITY_IND: call-related SS from MS\n");
+		print_fields(msg);
+		return;
+	case MNCC_START_DTMF_IND:
+		printf("MNCC_START_DTMF_IND: MS sending DTMF start\n");
+		print_fields(msg);
+		msg->msg_type = MNCC_START_DTMF_REJ;
+		mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
+				GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
+		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
+		return;
+	case MNCC_STOP_DTMF_IND:
+		printf("MNCC_STOP_DTMF_IND: MS sending DTMF stop\n");
+		msg->msg_type = MNCC_STOP_DTMF_RSP;
+		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
+		return;
+	case MNCC_MODIFY_IND:
+		printf("MNCC_MODIFY_IND: MS requests call modification\n");
+		print_fields(msg);
+		msg->msg_type = MNCC_MODIFY_REJ;
+		mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
+				GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
+		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
+		return;
+	case MNCC_HOLD_IND:
+		printf("MNCC_HOLD_IND: MS requests call hold\n");
+		msg->msg_type = MNCC_HOLD_REJ;
+		mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
+				GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
+		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
+		return;
+	case MNCC_RETRIEVE_IND:
+		printf("MNCC_RETRIEVE_IND: MS requests call retrieve\n");
+		msg->msg_type = MNCC_RETRIEVE_REJ;
+		mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
+				GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
+		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
+		return;
+	case MNCC_USERINFO_IND:
+		printf("MNCC_USERINFO_IND: user-user info\n");
+		print_fields(msg);
+		return;
+	case MNCC_REL_IND:
+		printf("MNCC_REL_IND: final release\n");
+		print_fields(msg);
+		exit(0);
+	case MNCC_REL_CNF:
+		printf("MNCC_REL_CNF: final release in response to request\n");
+		print_fields(msg);
+		exit(0);
+	case MNCC_REJ_IND:
+		printf("MNCC_REJ_IND: MT call rejected\n");
+		print_fields(msg);
+		exit(0);
+	}
+}
+
+static void
+handle_rtp_create(msg, msglen)
+	struct gsm_mncc_rtp *msg;
+	unsigned msglen;
+{
+	if (msglen != sizeof(struct gsm_mncc_rtp)) {
+		fprintf(stderr,
+			"error: Rx MNCC message type 0x%x has wrong length\n",
+			msg->msg_type);
+		exit(1);
+	}
+	if (msg->callref != 1) {
+		fprintf(stderr,
+	"error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n",
+			msg->msg_type, msg->callref);
+		exit(1);
+	}
+	printf("MNCC_RTP_CREATE: RTP info from MSC\n");
+	printf("payload_type=0x%x payload_msg_type=0x%x\n", msg->payload_type,
+		msg->payload_msg_type);
+}
+
+void
+msg_from_mncc(msg, msglen)
+	union mncc_msg *msg;
+	unsigned msglen;
+{
+	switch (msg->msg_type) {
+	case MNCC_SETUP_CNF:
+	case MNCC_CALL_CONF_IND:
+	case MNCC_ALERT_IND:
+	case MNCC_NOTIFY_IND:
+	case MNCC_DISC_IND:
+	case MNCC_FACILITY_IND:
+	case MNCC_START_DTMF_IND:
+	case MNCC_STOP_DTMF_IND:
+	case MNCC_MODIFY_IND:
+	case MNCC_HOLD_IND:
+	case MNCC_RETRIEVE_IND:
+	case MNCC_USERINFO_IND:
+	case MNCC_REL_IND:
+	case MNCC_REL_CNF:
+	case MNCC_REJ_IND:
+		handle_signaling_msg(msg, msglen);
+		return;
+	case MNCC_RTP_CREATE:
+		handle_rtp_create(msg, msglen);
+		return;
+	default:
+		fprintf(stderr,
+			"error: received unexpected MNCC message type 0x%x\n",
+			msg->msg_type);
+		exit(1);
+	}
+}