FreeCalypso > hg > themwi-system-sw
view mncc/call_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 | 660126bd5f59 |
children | 2ebad02adbe5 |
line wrap: on
line source
/* * In this module we implement setup of new calls: either new MO calls * coming from GSM or new MT calls coming from a ThemWi call socket. */ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <syslog.h> #include "../include/mncc.h" #include "../include/gsm48_const.h" #include "struct.h" #include "gsm_call.h" preen_msc_provided_number(nums) struct gsm_mncc_number *nums; { int len; len = grok_number_string(nums->number, 0); switch (len) { case 4: nums->type = GSM48_TON_NET_SPEC; nums->plan = GSM48_NPI_PRIVATE; break; case 11: if (nums->number[0] != '1') return(0); nums->type = GSM48_TON_INTERNATIONAL; nums->plan = GSM48_NPI_ISDN_E164; break; default: return(0); } nums->screen = GSM48_SCRN_NETWORK; return(1); } void reject_mo_call(callref, cause_loc, cause_val) uint32_t callref; { struct gsm_mncc msg; bzero(&msg, sizeof(struct gsm_mncc)); msg.msg_type = MNCC_REJ_REQ; msg.callref = callref; mncc_set_cause(&msg, cause_loc, cause_val); send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc)); } void process_mo_call_setup(msg) struct gsm_mncc *msg; { struct gsm_call *call; char nanp[11]; int res, is_nanp, is_itn, is_local; if (preen_msc_provided_number(&msg->calling)) msg->fields |= MNCC_F_CALLING; else msg->fields &= ~MNCC_F_CALLING; if (!(msg->fields & MNCC_F_CALLED)) { syslog(LOG_ERR, "rejecting MO call 0x%x: no called number", msg->callref); reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_INVAL_MAND_INF); return; } call = create_gsm_call(msg->callref); if (!call) { syslog(LOG_ERR, "rejecting MO call 0x%x: no memory for call", msg->callref); reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_RESOURCE_UNAVAIL); return; } /* route based on destination address */ refresh_number_db(); is_nanp = is_itn = 0; switch (grok_number_string(msg->called.number, 0)) { case 4: if (msg->called.type != GSM48_TON_UNKNOWN && msg->called.type != GSM48_TON_NET_SPEC && msg->called.type != GSM48_TON_SHORT_CODE) break; if (msg->called.plan != GSM48_NPI_UNKNOWN && msg->called.plan != GSM48_NPI_ISDN_E164 && msg->called.plan != GSM48_NPI_PRIVATE) break; res = lookup_short_dial_number(msg->called.number, nanp); if (!res) { syslog(LOG_ERR, "rejecting MO call 0x%x: invalid short number", msg->callref); reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_UNASSIGNED_NR); call->gc_flag = 1; return; } if (nanp[0]) { is_nanp = 1; msg->called.type = GSM48_TON_INTERNATIONAL; msg->called.plan = GSM48_NPI_ISDN_E164; msg->called.number[0] = '1'; strcpy(msg->called.number+1, nanp); } else { is_itn = 1; msg->called.type = GSM48_TON_NET_SPEC; msg->called.plan = GSM48_NPI_PRIVATE; } break; case 10: if (msg->called.type != GSM48_TON_UNKNOWN && msg->called.type != GSM48_TON_NATIONAL) break; if (msg->called.plan != GSM48_NPI_UNKNOWN && msg->called.plan != GSM48_NPI_ISDN_E164 && msg->called.plan != GSM48_NPI_NATIONAL) break; if (!is_nanp_valid_prefix(msg->called.number)) { syslog(LOG_ERR, "rejecting MO call 0x%x: invalid NANP number", msg->callref); reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_INV_NR_FORMAT); call->gc_flag = 1; return; } is_nanp = 1; /* canonicalize to international format */ bcopy(msg->called.number, msg->called.number+1, 11); msg->called.number[0] = '1'; msg->called.type = GSM48_TON_INTERNATIONAL; msg->called.plan = GSM48_NPI_ISDN_E164; break; case 11: if (msg->called.type != GSM48_TON_UNKNOWN && msg->called.type != GSM48_TON_INTERNATIONAL) break; if (msg->called.plan != GSM48_NPI_UNKNOWN && msg->called.plan != GSM48_NPI_ISDN_E164) break; if (msg->called.number[0] != '1') break; if (!is_nanp_valid_prefix(msg->called.number+1)) { syslog(LOG_ERR, "rejecting MO call 0x%x: invalid NANP number", msg->callref); reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_INV_NR_FORMAT); call->gc_flag = 1; return; } is_nanp = 1; /* canonicalize to international format */ msg->called.type = GSM48_TON_INTERNATIONAL; msg->called.plan = GSM48_NPI_ISDN_E164; break; } is_local = is_itn; if (is_nanp && is_nanp_locally_owned(msg->called.number+1)) is_local = 1; /* weed out attempts to call yourself */ if (is_local && !strcmp(msg->calling.number, msg->called.number)) { syslog(LOG_ERR, "rejecting MO call 0x%x: call to self", msg->callref); reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_INCOMPAT_DEST); call->gc_flag = 1; return; } /* actually route the call */ if (is_local) { internal_switch_mo_setup(call, msg); return; } /* outbound calls remain to be implemented */ syslog(LOG_ERR, "rejecting MO call 0x%x: outbound not implemented", msg->callref); reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_NO_ROUTE); call->gc_flag = 1; } static void reject_mt_call(conn, callref, cause_loc, cause_val) struct socket_conn *conn; uint32_t callref; { struct gsm_mncc msg; bzero(&msg, sizeof(struct gsm_mncc)); msg.msg_type = MNCC_REJ_REQ; msg.callref = callref; mncc_set_cause(&msg, cause_loc, cause_val); mncc_signal_to_socket_nocall(conn, &msg); } void process_ext_mtcall_setup(conn, msg) struct socket_conn *conn; struct gsm_mncc *msg; { struct gsm_call *call; if (!(msg->fields & MNCC_F_CALLED) && !msg->imsi[0]) { syslog(LOG_ERR, "rejecting ext MT: no called number"); reject_mt_call(conn, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_INVAL_MAND_INF); return; } call = create_new_mt_call(); if (!call) { syslog(LOG_ERR, "rejecting ext MT: no memory for call"); reject_mt_call(conn, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_RESOURCE_UNAVAIL); return; } call->socket = conn; call->socket_ref = msg->callref; conn->ncalls++; syslog(LOG_DEBUG, "mapped socket callref 0x%x to GSM callref 0x%x", msg->callref, call->callref); /* forward to GSM MNCC interface */ msg->callref = call->callref; send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); } preen_connected_number(msg) struct gsm_mncc *msg; { if (preen_msc_provided_number(&msg->connected)) msg->fields |= MNCC_F_CONNECTED; else msg->fields &= ~MNCC_F_CONNECTED; }