# HG changeset patch # User Mychaela Falconia # Date 1665587635 28800 # Node ID 0bacca1f2f7bcab974d5ecf8916dacdb7ca47529 # Parent 2730ccb445490e40e1add9eee1fb12133d40ba45 sip-out: handle all INVITE responses, except errors diff -r 2730ccb44549 -r 0bacca1f2f7b sip-out/Makefile --- a/sip-out/Makefile Tue Oct 11 23:30:00 2022 -0800 +++ b/sip-out/Makefile Wed Oct 12 07:13:55 2022 -0800 @@ -1,10 +1,10 @@ CC= gcc CFLAGS= -O2 PROG= themwi-sip-out -OBJS= call_clear.o call_list.o call_setup.o disconnect.o main.o mgw_ops.o \ - mgw_resp.o mgw_sock.o mncc_sig_in.o mncc_sig_out.o mncc_sock.o \ - readconf.o retrans.o shutdown.o sip_log.o sip_uas.o sip_udp.o uac_out.o\ - uac_resp.o +OBJS= call_clear.o call_list.o call_setup.o disconnect.o invite.o main.o \ + mgw_ops.o mgw_resp.o mgw_sock.o mncc_sig_in.o mncc_sig_out.o \ + mncc_sock.o readconf.o retrans.o shutdown.o sip_log.o sip_uas.o \ + sip_udp.o uac_out.o uac_resp.o LIBS= ../liboutrt/liboutrt.a ../libsip/libsip.a ../libutil/libutil.a INSTBIN=/usr/local/bin diff -r 2730ccb44549 -r 0bacca1f2f7b sip-out/invite.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sip-out/invite.c Wed Oct 12 07:13:55 2022 -0800 @@ -0,0 +1,270 @@ +/* + * In this module we handle responses to INVITE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/gsm48_const.h" +#include "../include/out_routes.h" +#include "../libsip/parse.h" +#include "../libsip/sdp.h" +#include "../libsip/out_msg.h" +#include "call.h" + +extern char *get_single_header(); +extern char *extract_to_tag(); + +extern unsigned sip_linger_response_err; + +static +check_sdp_present(msg) + struct sip_pkt_rx *msg; +{ + char *hval; + + if (!msg->msg_body_len) + return 0; + hval = get_single_header(msg, "Content-Type", "c", (int *) 0); + if (!hval) + return 0; + if (!strcasecmp(hval, "application/sdp")) + return 1; + else + return 0; +} + +static +extract_sdp(call, msg) + struct call *call; + struct sip_pkt_rx *msg; +{ + struct sdp_parse sdp_parse; + int rc, use_pcma; + + rc = parse_incoming_sdp(msg->msg_body, msg->msg_body_len, &sdp_parse); + if (rc < 0) + return rc; + switch (sdp_parse.codec_mask) { + case SDP_CODEC_MASK_PCMU: + case SDP_CODEC_MASK_BOTH: + use_pcma = 0; + break; + case SDP_CODEC_MASK_PCMA: + case SDP_CODEC_MASK_BOTH | SDP_CODEC_MASK_PCMA_PREF: + use_pcma = 1; + break; + default: + return -2; + } + call->pstn_rtp_remote.sin_family = AF_INET; + call->pstn_rtp_remote.sin_addr = sdp_parse.ip_addr; + call->pstn_rtp_remote.sin_port = htons(sdp_parse.audio_port); + call->use_pcma = use_pcma; + return 0; +} + +static void +handle_1xx(call, msg, tag, sin) + struct call *call; + struct sip_pkt_rx *msg; + char *tag; + struct sockaddr_in *sin; +{ + int rc; + + switch (call->sip_state) { + case SIP_STATE_INV_SENT: + call->sip_state = SIP_STATE_100_RCVD; + /* FALL THRU */ + case SIP_STATE_100_RCVD: + if (msg->status_code == 180) + call->overall_state = OVERALL_STATE_RINGING; + if (check_sdp_present(msg) && + call->mgw_state == MGW_STATE_ALLOCATED) { + rc = extract_sdp(call, msg); + if (rc < 0) { + syslog(LOG_ERR, "bad SDP in %03u response", + msg->status_code); + call->overall_state = OVERALL_STATE_TEARDOWN; + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_BEARER_CA_UNAVAIL); + disconnect_tmgw(call); + initiate_sip_cancel(call); + return; + } + tmgw_send_mdcx_connect(call, 1); + } else if (msg->status_code == 180) + mncc_signal_alerting(call); + return; + case SIP_STATE_ACCEPT_100: + initiate_sip_cancel(call); + return; + } +} + +static +send_ack(call, tag, sin) + struct call *call; + char *tag; + struct sockaddr_in *sin; +{ + struct sip_msg_out msg; + int rc; + + rc = start_request_out_msg(&msg, "ACK", call->to_uri); + if (rc < 0) + return rc; + rc = add_req_boilerplate(&msg, call, "1 ACK", tag); + if (rc < 0) + return rc; + out_msg_finish(&msg); + sip_tx_packet(&msg, sin); + return 0; +} + +static void +handle_200(call, msg, tag, sin) + struct call *call; + struct sip_pkt_rx *msg; + char *tag; + struct sockaddr_in *sin; +{ + int rc; + + switch (call->sip_state) { + case SIP_STATE_INV_SENT: + case SIP_STATE_100_RCVD: + rc = send_ack(call, tag, sin); + if (rc < 0) { + syslog(LOG_CRIT, + "ACK to %03u response exceeds msg size!", + msg->status_code); + call->overall_state = OVERALL_STATE_TEARDOWN; + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_DEST_OOO); + disconnect_tmgw(call); + call->sip_state = SIP_STATE_ENDED; + sip_mark_end_time(call, sip_linger_response_err); + return; + } + if (tag) + strcpy(call->to_tag, tag); + call->sip_state = SIP_STATE_CONNECTED; + if (!check_sdp_present(msg)) { + syslog(LOG_ERR, "error: %03u response has no SDP", + msg->status_code); + call->overall_state = OVERALL_STATE_TEARDOWN; + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_DEST_OOO); + disconnect_tmgw(call); + initiate_bye(call); + return; + } + rc = extract_sdp(call, msg); + if (rc < 0) { + syslog(LOG_ERR, "bad SDP in %03u response", + msg->status_code); + call->overall_state = OVERALL_STATE_TEARDOWN; + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_BEARER_CA_UNAVAIL); + disconnect_tmgw(call); + initiate_bye(call); + return; + } + call->overall_state = OVERALL_STATE_CONNECTED; + switch (call->mgw_state) { + case MGW_STATE_ALLOCATED: + case MGW_STATE_IBT_CONN: + tmgw_send_mdcx_connect(call, 0); + return; + case MGW_STATE_MDCX_IBT: + return; + default: + syslog(LOG_CRIT, + "FATAL: invalid MGW state 0x%x on INVITE %03u response", + call->mgw_state, msg->status_code); + exit(1); + } + case SIP_STATE_CONNECTED: + case SIP_STATE_BYE_SENT: + if (tag && call->to_tag[0] && strcmp(call->to_tag, tag)) { + syslog(LOG_ERR, + "received %u response with different To tag, ignoring", + msg->status_code); + return; + } + send_ack(call, call->to_tag, sin); + return; + case SIP_STATE_CANCEL_SENT: + case SIP_STATE_ACCEPT_100: + case SIP_STATE_ACCEPT_200: + rc = send_ack(call, tag, sin); + if (rc < 0) { + syslog(LOG_CRIT, + "ACK to %03u response exceeds msg size!", + msg->status_code); + call->sip_state = SIP_STATE_ENDED; + sip_mark_end_time(call, sip_linger_response_err); + return; + } + if (tag) + strcpy(call->to_tag, tag); + initiate_bye(call); + return; + case SIP_STATE_ENDED: + return; + default: + syslog(LOG_CRIT, + "FATAL: invalid SIP state 0x%x on INVITE %03u response", + call->sip_state, msg->status_code); + exit(1); + } +} + +static void +handle_error(call, msg, tag, sin) + struct call *call; + struct sip_pkt_rx *msg; + char *tag; + struct sockaddr_in *sin; +{ + +} + +void +handle_invite_response(call, msg, sin) + struct call *call; + struct sip_pkt_rx *msg; + struct sockaddr_in *sin; +{ + char *tag; + + tag = extract_to_tag(msg, call->to_uri); + if (tag) { + if (!*tag) { + syslog(LOG_ERR, + "To tag in INVITE %03u response is null", + msg->status_code); + tag = 0; + } else if (strlen(tag) > MAX_SIP_TO_TAG) { + syslog(LOG_ERR, + "To tag in INVITE %03u response exceeds length limit", + msg->status_code); + tag = 0; + } + } + if (msg->status_code >= 100 && msg->status_code <= 199) + handle_1xx(call, msg, tag, sin); + else if (msg->status_code >= 200 && msg->status_code <= 299) + handle_200(call, msg, tag, sin); + else + handle_error(call, msg, tag, sin); +} diff -r 2730ccb44549 -r 0bacca1f2f7b sip-out/readconf.c --- a/sip-out/readconf.c Tue Oct 11 23:30:00 2022 -0800 +++ b/sip-out/readconf.c Wed Oct 12 07:13:55 2022 -0800 @@ -24,6 +24,7 @@ unsigned sip_linger_gotbye = 30; unsigned sip_linger_bye_out_ok = 5; unsigned sip_linger_bye_out_err = 180; +unsigned sip_linger_response_err = 180; int block_1900_numbers = 1; static char config_file_pathname[] = "/var/gsm/themwi-sip-out.cfg"; @@ -190,6 +191,10 @@ handler = handle_num; var = &sip_linger_bye_out_err; set_id = 0; + } else if (!strcmp(kw, "sip-linger-response-error")) { + handler = handle_num; + var = &sip_linger_response_err; + set_id = 0; } else if (!strcmp(kw, "max-forwards")) { handler = &handle_num; var = &max_forwards; diff -r 2730ccb44549 -r 0bacca1f2f7b sip-out/uac_resp.c --- a/sip-out/uac_resp.c Tue Oct 11 23:30:00 2022 -0800 +++ b/sip-out/uac_resp.c Wed Oct 12 07:13:55 2022 -0800 @@ -16,8 +16,6 @@ #include "../include/out_routes.h" #include "../libsip/parse.h" #include "../libsip/resp_ident.h" -#include "../libsip/sdp.h" -#include "../libsip/out_msg.h" #include "call.h" extern struct call *find_call_by_sip_id();