FreeCalypso > hg > themwi-system-sw
changeset 146:54c2f271380d
sip-in: implement play-along responses to re-INVITEs
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 08 Oct 2022 19:53:23 -0800 |
parents | 4b685a5d9bd4 |
children | 94b5831c017f |
files | sip-in/invite_dup.c |
diffstat | 1 files changed, 84 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/sip-in/invite_dup.c Sat Oct 08 19:31:05 2022 -0800 +++ b/sip-in/invite_dup.c Sat Oct 08 19:53:23 2022 -0800 @@ -1,12 +1,19 @@ /* * Here we process SIP INVITE retransmissions and/or re-INVITEs - * for existing calls. + * for existing calls. Our new approach is that we shall generate + * the same stateless response without caring if it's a retransmission + * or a re-INVITE, using CSeq and Via from the (re-)INVITE packet + * we are responding to. Our previous approach was to reject all + * re-INVITE requests, but it turns out that we have to support them + * in order to satisfy BulkVS and other calling servers that use + * session timers. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> +#include <arpa/inet.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> @@ -19,6 +26,66 @@ #include "../libsip/out_msg.h" #include "call.h" +extern struct in_addr sip_bind_ip; +extern unsigned sip_bind_port; + +static +fill_reinvite_resp(msg, call, ess) + struct sip_msg_out *msg; + struct call *call; + struct uas_parse_hdrs *ess; +{ + char cseq_str[32]; + int rc; + + rc = out_msg_add_header(msg, "From", call->invite_from); + if (rc < 0) + return rc; + rc = out_msg_add_header(msg, "To", call->invite_to); + if (rc < 0) + return rc; + rc = out_msg_add_header(msg, "Call-ID", call->sip_call_id); + if (rc < 0) + return rc; + sprintf(cseq_str, "%u INVITE", ess->cseq_num); + rc = out_msg_add_header(msg, "CSeq", cseq_str); + if (rc < 0) + return rc; + return out_msg_add_header(msg, "Via", ess->via); +} + +static +fill_reinvite_resp_200(msg, call, ess) + struct sip_msg_out *msg; + struct call *call; + struct uas_parse_hdrs *ess; +{ + char contact_str[80]; + struct sdp_gen sdp; + int rc; + + start_response_out_msg(msg, "200 CONNECT"); + rc = fill_reinvite_resp(msg, call, ess); + if (rc < 0) + return rc; + sprintf(contact_str, "<sip:%s:%u;transport=udp>", + inet_ntoa(sip_bind_ip), sip_bind_port); + rc = out_msg_add_header(msg, "Contact", contact_str); + 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 = call->use_pcma ? SDP_CODEC_MASK_PCMA + : SDP_CODEC_MASK_PCMU; + sdp.session_id = (sdp.conn_port << 16) | call->sdp_addend; + sdp.owner_ip = sip_bind_ip; + return out_msg_finish_sdp(msg, &sdp); +} + void invite_existing_call(req, ess, sin, call) struct sip_pkt_rx *req; @@ -29,48 +96,40 @@ struct sip_msg_out resp; int rc; - if (ess->cseq_num != call->invite_cseq) { - start_response_out_msg(&resp, "501 Re-INVITE not supported"); - rc = add_resp_basic_headers(&resp, ess, req->req_method); + switch (call->sip_state) { + case SIP_STATE_INVITE_PROC: + start_response_out_msg(&resp, "100 Proceeding"); + rc = fill_reinvite_resp(&resp, call, ess); if (rc < 0) { - syslog(LOG_ERR, - "sending 501 Re-INVITE error: response length exceeded"); +msg_size_err: syslog(LOG_ERR, + "Call in%06u: msg size error on re-INVITE response", + call->in_tag_num); return; } out_msg_finish(&resp); sip_tx_packet(&resp, sin); return; - } - /* it's a retransmission, not a re-INVITE */ - switch (call->sip_state) { - case SIP_STATE_INVITE_PROC: - start_response_out_msg(&resp, "100 Proceeding"); - fill_invite_resp_from_call(&resp, call); - out_msg_finish(&resp); - sip_tx_packet(&resp, sin); - return; case SIP_STATE_RINGING: - start_response_out_msg(&resp, "180 Ringing"); - fill_invite_resp_from_call(&resp, call); - out_msg_finish(&resp); - sip_tx_packet(&resp, sin); - return; case SIP_STATE_RINGING_REL: start_response_out_msg(&resp, "180 Ringing"); - fill_invite_resp_from_call(&resp, call); - out_msg_add_header(&resp, "Require", "100rel"); - out_msg_add_header(&resp, "RSeq", "1"); + rc = fill_reinvite_resp(&resp, call, ess); + if (rc < 0) + goto msg_size_err; out_msg_finish(&resp); sip_tx_packet(&resp, sin); return; case SIP_STATE_INVITE_200: case SIP_STATE_CONNECTED: - fill_invite_200_resp(&resp, call); + rc = fill_reinvite_resp_200(&resp, call, ess); + if (rc < 0) + goto msg_size_err; sip_tx_packet(&resp, sin); return; case SIP_STATE_INVITE_ERR: start_response_out_msg(&resp, call->invite_fail); - fill_invite_resp_from_call(&resp, call); + rc = fill_reinvite_resp(&resp, call, ess); + if (rc < 0) + goto msg_size_err; out_msg_finish(&resp); sip_tx_packet(&resp, sin); return;