FreeCalypso > hg > themwi-system-sw
diff sip-out/mgw_resp.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/mgw_ops.c@0ecbc3dc8f93 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sip-out/mgw_resp.c Tue Oct 11 23:04:01 2022 -0800 @@ -0,0 +1,212 @@ +/* + * In this module we implement our handling of all responses + * from themwi-mgw. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <syslog.h> +#include "../include/gsm48_const.h" +#include "../include/tmgw_ctrl.h" +#include "../include/tmgw_const.h" +#include "../include/out_routes.h" +#include "call.h" + +extern struct call *find_call_with_mgw_xact(); + +static void +crcx_response(call, msg) + struct call *call; + struct tmgw_ctrl_resp *msg; +{ + int cause; + + if (msg->res == TMGW_RESP_OK) { + call->mgw_state = MGW_STATE_ALLOCATED; + call->mgw_ep_id = msg->ep_id; + bcopy(&msg->gsm_addr, &call->gsm_rtp_tmgw, + sizeof(struct sockaddr_storage)); + bcopy(&msg->pstn_addr, &call->pstn_rtp_local, + sizeof(struct sockaddr_in)); + switch (call->overall_state) { + case OVERALL_STATE_CRCX: + send_rtp_connect(call); + start_sip_out(call); + return; + case OVERALL_STATE_TEARDOWN: + tmgw_send_dlcx(call); + return; + default: + bad_state: + syslog(LOG_CRIT, + "FATAL: invalid overall state 0x%x on CRCX response", + call->overall_state); + exit(1); + } + } else { + switch (call->overall_state) { + case OVERALL_STATE_CRCX: + call->overall_state = OVERALL_STATE_TEARDOWN; + switch (msg->res) { + case TMGW_RESP_ERR_RSRC: + cause = GSM48_CC_CAUSE_RESOURCE_UNAVAIL; + break; + case TMGW_RESP_ERR_NOTSUP: + cause = GSM48_CC_CAUSE_BEARER_CA_UNAVAIL; + break; + default: + cause = GSM48_CC_CAUSE_PROTO_ERR; + } + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, cause); + return; + case OVERALL_STATE_TEARDOWN: + check_dead_call(call); + return; + default: + goto bad_state; + } + } +} + +static void +mdcx_response(call, msg) + struct call *call; + struct tmgw_ctrl_resp *msg; +{ + if (call->overall_state == OVERALL_STATE_TEARDOWN) { + tmgw_send_dlcx(call); + return; + } + if (msg->res != TMGW_RESP_OK) { + call->overall_state = OVERALL_STATE_TEARDOWN; + tmgw_send_dlcx(call); + if (msg->res == TMGW_RESP_ERR_RSRC && + (call->mgw_state == MGW_STATE_MDCX_IBT || + call->mgw_state == MGW_STATE_MDCX_CONN)) + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_RESOURCE_UNAVAIL); + else + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_NETWORK_OOO); + disconnect_sip(call); + return; + } + switch (call->mgw_state) { + case MGW_STATE_MDCX_IBT: + call->mgw_state = MGW_STATE_IBT_CONN; + mncc_signal_ibt_ring(call); + if (call->sip_state == SIP_STATE_CONNECTED) + tmgw_send_mdcx_connect(call, 0); + return; + case MGW_STATE_MDCX_CONN: + call->mgw_state = MGW_STATE_COMPLETE; + mncc_signal_answer_sup(call); + return; + case MGW_STATE_MDCX_HOLD: + call->mgw_state = MGW_STATE_HELD; + mncc_send_hold_ack(call); + return; + case MGW_STATE_MDCX_RETR: + call->mgw_state = MGW_STATE_COMPLETE; + mncc_send_retrieve_ack(call); + return; + default: + syslog(LOG_CRIT, + "FATAL: invalid MGW state 0x%x on MDCX response", + call->mgw_state); + exit(1); + } +} + +static void +dlcx_response(call, msg) + struct call *call; + struct tmgw_ctrl_resp *msg; +{ + if (msg->res != TMGW_RESP_OK) { + syslog(LOG_CRIT, "FATAL: TMGW DLCX failed with code 0x%x", + msg->res); + exit(1); + } + call->mgw_state = MGW_STATE_NO_EXIST; + check_dead_call(call); +} + +static void +dtmf_start_response(call, msg) + struct call *call; + struct tmgw_ctrl_resp *msg; +{ + if (call->overall_state == OVERALL_STATE_TEARDOWN) { + tmgw_send_dlcx(call); + return; + } + if (msg->res == TMGW_RESP_OK) + mncc_dtmf_start_ok(call); + else + mncc_dtmf_start_err(call); + if (call->dtmf_pending_stop) + tmgw_send_dtmf_stop(call); + else + call->mgw_state = MGW_STATE_COMPLETE; +} + +static void +dtmf_stop_response(call, msg) + struct call *call; + struct tmgw_ctrl_resp *msg; +{ + if (call->overall_state == OVERALL_STATE_TEARDOWN) { + tmgw_send_dlcx(call); + return; + } + mncc_dtmf_stop_ok(call); + call->mgw_state = MGW_STATE_COMPLETE; + call->dtmf_pending_stop = 0; +} + +void +process_tmgw_response(msg) + struct tmgw_ctrl_resp *msg; +{ + struct call *call; + unsigned opc; + + call = find_call_with_mgw_xact(msg->transact_ref); + if (!call) { + syslog(LOG_CRIT, + "FATAL: response from TMGW xact 0x%x does not match any call", + msg->transact_ref); + exit(1); + } + opc = call->mgw_xact; + call->mgw_xact = 0; + switch (opc) { + case TMGW_CTRL_OP_CRCX: + crcx_response(call, msg); + return; + case TMGW_CTRL_OP_MDCX: + mdcx_response(call, msg); + return; + case TMGW_CTRL_OP_DLCX: + dlcx_response(call, msg); + return; + case TMGW_CTRL_OP_DTMF_START: + dtmf_start_response(call, msg); + return; + case TMGW_CTRL_OP_DTMF_STOP: + dtmf_stop_response(call, msg); + return; + default: + syslog(LOG_CRIT, + "FATAL: invalid opcode 0x%x in call->msg_xact", opc); + exit(1); + } +}