FreeCalypso > hg > themwi-system-sw
diff sip-out/uac_out.c @ 154:e54b0a9e322f
beginning of themwi-sip-out
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 11 Oct 2022 23:04:01 -0800 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sip-out/uac_out.c Tue Oct 11 23:04:01 2022 -0800 @@ -0,0 +1,190 @@ +/* + * In this module we implement generation of outgoing SIP messages + * in the UAC role. + */ + +#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/out_routes.h" +#include "../libsip/out_msg.h" +#include "../libsip/sdp.h" +#include "call.h" + +extern struct call *find_call_by_sip_id(); + +extern struct in_addr sip_bind_ip; +extern unsigned sip_bind_port; +extern unsigned max_forwards; +extern struct timeval cur_event_time; + +add_req_boilerplate(msg, call, cseq, to_tag) + struct sip_msg_out *msg; + struct call *call; + char *cseq, *to_tag; +{ + char strbuf[256]; + int rc; + + sprintf(strbuf, "SIP/2.0/UDP %s:%u", + inet_ntoa(sip_bind_ip), sip_bind_port); + rc = out_msg_add_header(msg, "Via", strbuf); + if (rc < 0) + return rc; + rc = out_msg_add_header(msg, "From", call->from_header); + if (rc < 0) + return rc; + if (to_tag && to_tag[0]) { + sprintf(strbuf, "<%s>;tag=%s", call->to_uri, to_tag); + rc = out_msg_add_header(msg, "To", strbuf); + } else + rc = out_msg_add_header(msg, "To", call->to_uri); + if (rc < 0) + return rc; + rc = out_msg_add_header(msg, "Call-ID", call->sip_call_id); + if (rc < 0) + return rc; + rc = out_msg_add_header(msg, "CSeq", cseq); + if (rc < 0) + return rc; + sprintf(strbuf, "%u", max_forwards); + return out_msg_add_header(msg, "Max-Forwards", strbuf); +} + +add_contact_header(msg) + struct sip_msg_out *msg; +{ + char strbuf[80]; + + sprintf(strbuf, "<sip:%s:%u;transport=udp>", + inet_ntoa(sip_bind_ip), sip_bind_port); + return out_msg_add_header(msg, "Contact", strbuf); +} + +fill_invite_req_msg(msg, call) + struct sip_msg_out *msg; + struct call *call; +{ + struct sdp_gen sdp; + int rc; + + rc = start_request_out_msg(msg, "INVITE", call->to_uri); + if (rc < 0) + return rc; + rc = add_req_boilerplate(msg, call, "1 INVITE", (char *) 0); + if (rc < 0) + return rc; + rc = add_contact_header(msg); + if (rc < 0) + return rc; + rc = out_msg_add_header(msg, "Content-Type", "application/sdp"); + if (rc < 0) + return rc; + bzero(&sdp, sizeof sdp); + sdp.conn_ip = call->pstn_rtp_local.sin_addr; + sdp.conn_port = ntohs(call->pstn_rtp_local.sin_port); + sdp.codec_mask = SDP_CODEC_MASK_BOTH; + sdp.session_id = sdp.conn_port << 16; + sdp.owner_ip = sip_bind_ip; + return out_msg_finish_sdp(msg, &sdp); +} + +fill_cancel_req_msg(msg, call) + struct sip_msg_out *msg; + struct call *call; +{ + int rc; + + rc = start_request_out_msg(msg, "CANCEL", call->to_uri); + if (rc < 0) + return rc; + rc = add_req_boilerplate(msg, call, "1 CANCEL", (char *) 0); + if (rc < 0) + return rc; + out_msg_finish(msg); + return 0; +} + +fill_bye_req_msg(msg, call) + struct sip_msg_out *msg; + struct call *call; +{ + int rc; + + rc = start_request_out_msg(msg, "BYE", call->to_uri); + if (rc < 0) + return rc; + rc = add_req_boilerplate(msg, call, "2 BYE", call->to_tag); + if (rc < 0) + return rc; + out_msg_finish(msg); + return 0; +} + +void +start_sip_out(call) + struct call *call; +{ + struct sip_msg_out msg; + int rc; + + sprintf(call->sip_call_id, "%08u_%u@%s", + (unsigned)(cur_event_time.tv_sec % 100000000), + ntohs(call->pstn_rtp_local.sin_port), inet_ntoa(sip_bind_ip)); + if (find_call_by_sip_id(call->sip_call_id)) { + syslog(LOG_ERR, "generated Call-ID collision!"); + call->overall_state = OVERALL_STATE_TEARDOWN; + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_SWITCH_CONG); + disconnect_tmgw(call); + return; + } + sprintf(call->from_header, "<sip:%s@%s>;tag=out%u", call->from_user, + inet_ntoa(sip_bind_ip), ntohs(call->pstn_rtp_local.sin_port)); + rc = fill_invite_req_msg(&msg, call); + if (rc < 0) { + syslog(LOG_CRIT, "generated SIP INVITE req exceeds msg size!"); + call->overall_state = OVERALL_STATE_TEARDOWN; + disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_NETWORK_OOO); + disconnect_tmgw(call); + return; + } + sip_tx_packet(&msg, &call->udp_sin); + call->overall_state = OVERALL_STATE_SIP_OUT; + call->sip_call_exists = 1; + call->sip_state = SIP_STATE_INV_SENT; + call->sip_tx_count = 1; +} + +void +initiate_sip_cancel(call) + struct call *call; +{ + struct sip_msg_out msg; + + fill_cancel_req_msg(&msg, call); + sip_tx_packet(&msg, &call->udp_sin); + call->sip_state = SIP_STATE_CANCEL_SENT; + call->sip_tx_count = 1; +} + +void +initiate_bye(call) + struct call *call; +{ + struct sip_msg_out msg; + + fill_bye_req_msg(&msg, call); + sip_tx_packet(&msg, &call->udp_sin); + call->sip_state = SIP_STATE_BYE_SENT; + call->sip_tx_count = 1; +}