FreeCalypso > hg > themwi-system-sw
comparison sip-out/call_setup.c @ 154:e54b0a9e322f
beginning of themwi-sip-out
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Tue, 11 Oct 2022 23:04:01 -0800 |
| parents | sip-in/call_setup.c@1bbe57df74f6 |
| children | e89619893c1e |
comparison
equal
deleted
inserted
replaced
| 153:99fd4ae573ae | 154:e54b0a9e322f |
|---|---|
| 1 /* | |
| 2 * In this module we implement our initial handling of MNCC_SETUP_IND. | |
| 3 */ | |
| 4 | |
| 5 #include <sys/types.h> | |
| 6 #include <sys/socket.h> | |
| 7 #include <sys/time.h> | |
| 8 #include <netinet/in.h> | |
| 9 #include <stdio.h> | |
| 10 #include <stdint.h> | |
| 11 #include <stdlib.h> | |
| 12 #include <string.h> | |
| 13 #include <strings.h> | |
| 14 #include <syslog.h> | |
| 15 #include "../include/mncc.h" | |
| 16 #include "../include/gsm48_const.h" | |
| 17 #include "../include/out_routes.h" | |
| 18 #include "call.h" | |
| 19 | |
| 20 extern struct call *find_call_by_mncc_callref(); | |
| 21 | |
| 22 extern int block_1900_numbers; | |
| 23 extern struct call *call_list; | |
| 24 | |
| 25 static void | |
| 26 reject_mo_call(mncc, callref, cause_loc, cause_val) | |
| 27 struct mncc_conn *mncc; | |
| 28 uint32_t callref; | |
| 29 { | |
| 30 struct gsm_mncc msg; | |
| 31 | |
| 32 bzero(&msg, sizeof(struct gsm_mncc)); | |
| 33 msg.msg_type = MNCC_REJ_REQ; | |
| 34 msg.callref = callref; | |
| 35 mncc_set_cause(&msg, cause_loc, cause_val); | |
| 36 send_mncc_to_sock(mncc, &msg, sizeof(struct gsm_mncc)); | |
| 37 } | |
| 38 | |
| 39 static void | |
| 40 send_call_proceeding(call) | |
| 41 struct call *call; | |
| 42 { | |
| 43 struct gsm_mncc msg; | |
| 44 | |
| 45 bzero(&msg, sizeof(struct gsm_mncc)); | |
| 46 msg.msg_type = MNCC_CALL_PROC_REQ; | |
| 47 msg.callref = call->mncc_callref; | |
| 48 send_mncc_to_sock(call->mncc, &msg, sizeof(struct gsm_mncc)); | |
| 49 } | |
| 50 | |
| 51 void | |
| 52 handle_setup_ind(mncc, msg, msglen) | |
| 53 struct mncc_conn *mncc; | |
| 54 struct gsm_mncc *msg; | |
| 55 unsigned msglen; | |
| 56 { | |
| 57 struct call *call; | |
| 58 struct sip_out_dest *dest; | |
| 59 struct special_num_route *special_rt; | |
| 60 char to_sip_user[MAX_SIP_USER_PART+1]; | |
| 61 int rc; | |
| 62 | |
| 63 if (msglen != sizeof(struct gsm_mncc)) { | |
| 64 syslog(LOG_CRIT, | |
| 65 "FATAL: Rx MNCC_SETUP_IND has wrong length"); | |
| 66 exit(1); | |
| 67 } | |
| 68 /* check for duplicates */ | |
| 69 call = find_call_by_mncc_callref(mncc, msg->callref); | |
| 70 if (call) { | |
| 71 syslog(LOG_ERR, "duplicate MNCC_SETUP_IND for callref 0x%x", | |
| 72 msg->callref); | |
| 73 /* drop it like OsmoMSC's mncc_builtin does */ | |
| 74 return; | |
| 75 } | |
| 76 if (!(msg->fields & MNCC_F_CALLED) || | |
| 77 !(msg->fields & MNCC_F_BEARER_CAP)) { | |
| 78 syslog(LOG_ERR, "rejecting MO call 0x%x: missing mandatory IE", | |
| 79 msg->callref); | |
| 80 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, | |
| 81 GSM48_CC_CAUSE_INVAL_MAND_INF); | |
| 82 return; | |
| 83 } | |
| 84 /* route based on destination address */ | |
| 85 refresh_out_routes_db(); | |
| 86 if (msg->called.type == GSM48_TON_INTERNATIONAL) { | |
| 87 rc = grok_number_string(msg->called.number, 0); | |
| 88 if (rc < 2 || rc > MAX_E164_NUMBER) { | |
| 89 inv_nr_format: reject_mo_call(mncc, msg->callref, | |
| 90 GSM48_CAUSE_LOC_PRN_S_LU, | |
| 91 GSM48_CC_CAUSE_INV_NR_FORMAT); | |
| 92 return; | |
| 93 } | |
| 94 if (msg->called.number[0] == '0') | |
| 95 goto inv_nr_format; | |
| 96 if (msg->called.number[0] == '1') { | |
| 97 if (rc != 11) | |
| 98 goto inv_nr_format; | |
| 99 if (!is_nanp_valid_prefix(msg->called.number+1)) | |
| 100 goto inv_nr_format; | |
| 101 if (msg->called.number[1] == '9' && | |
| 102 msg->called.number[2] == '0' && | |
| 103 msg->called.number[3] == '0' && | |
| 104 block_1900_numbers) { | |
| 105 call_barred: reject_mo_call(mncc, msg->callref, | |
| 106 GSM48_CAUSE_LOC_PRN_S_LU, | |
| 107 GSM48_CC_CAUSE_OP_DET_BARRING); | |
| 108 return; | |
| 109 } | |
| 110 } | |
| 111 rc = route_e164_number(msg->called.number, &dest); | |
| 112 if (!rc) { | |
| 113 no_route_to_dest: reject_mo_call(mncc, msg->callref, | |
| 114 GSM48_CAUSE_LOC_PRN_S_LU, | |
| 115 GSM48_CC_CAUSE_NO_ROUTE); | |
| 116 return; | |
| 117 } | |
| 118 to_sip_user[0] = '+'; | |
| 119 strcpy(to_sip_user+1, msg->called.number); | |
| 120 } else { | |
| 121 rc = route_special_number(msg->called.number, &dest, | |
| 122 &special_rt); | |
| 123 if (!rc) | |
| 124 goto no_route_to_dest; | |
| 125 strcpy(to_sip_user, special_rt->sip_user); | |
| 126 } | |
| 127 /* validate From number */ | |
| 128 if (!(msg->fields & MNCC_F_CALLING)) | |
| 129 goto call_barred; | |
| 130 if (msg->calling.type != GSM48_TON_INTERNATIONAL) | |
| 131 goto call_barred; | |
| 132 if (grok_number_string(msg->calling.number, 0) != 11 || | |
| 133 msg->calling.number[0] != '1') | |
| 134 goto call_barred; | |
| 135 /* speech-only restriction */ | |
| 136 if (msg->bearer_cap.transfer != GSM48_BCAP_ITCAP_SPEECH || | |
| 137 msg->bearer_cap.mode != GSM48_BCAP_TMOD_CIRCUIT) { | |
| 138 syslog(LOG_ERR, "rejecting MO call 0x%x: bad bearer cap", | |
| 139 msg->callref); | |
| 140 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, | |
| 141 GSM48_CC_CAUSE_BEARER_CA_UNAVAIL); | |
| 142 return; | |
| 143 } | |
| 144 /* TMGW must be up and running */ | |
| 145 rc = connect_tmgw_socket(); | |
| 146 if (rc < 0) { | |
| 147 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, | |
| 148 GSM48_CC_CAUSE_NETWORK_OOO); | |
| 149 return; | |
| 150 } | |
| 151 /* allocate struct call and being stateful processing */ | |
| 152 call = malloc(sizeof(struct call)); | |
| 153 if (!call) { | |
| 154 syslog(LOG_CRIT, "failed malloc for outbound call!"); | |
| 155 reject_mo_call(mncc, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU, | |
| 156 GSM48_CC_CAUSE_RESOURCE_UNAVAIL); | |
| 157 return; | |
| 158 } | |
| 159 bzero(call, sizeof(struct call)); | |
| 160 call->mncc = mncc; | |
| 161 call->mncc_callref = msg->callref; | |
| 162 call->from_user[0] = '+'; | |
| 163 strcpy(call->from_user+1, msg->calling.number); | |
| 164 sprintf(call->to_uri, "sip:%s@%s", to_sip_user, dest->domain); | |
| 165 bcopy(&dest->sin, &call->udp_sin, sizeof(struct sockaddr_in)); | |
| 166 call->next = call_list; | |
| 167 call_list = call; | |
| 168 send_call_proceeding(call); | |
| 169 call->overall_state = OVERALL_STATE_GSM_RTP; | |
| 170 call->mncc_state = MNCC_STATE_MO_PROC; | |
| 171 } |
