FreeCalypso > hg > themwi-system-sw
view sip-out/mgw_resp.c @ 191:6ac96217c442
sip-manual-out: add SDP response parsing
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 17 Mar 2023 12:07:17 -0800 |
parents | e54b0a9e322f |
children |
line wrap: on
line source
/* * 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); } }