comparison sip-in/invite_dup.c @ 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
comparison
equal deleted inserted replaced
145:4b685a5d9bd4 146:54c2f271380d
1 /* 1 /*
2 * Here we process SIP INVITE retransmissions and/or re-INVITEs 2 * Here we process SIP INVITE retransmissions and/or re-INVITEs
3 * for existing calls. 3 * for existing calls. Our new approach is that we shall generate
4 * the same stateless response without caring if it's a retransmission
5 * or a re-INVITE, using CSeq and Via from the (re-)INVITE packet
6 * we are responding to. Our previous approach was to reject all
7 * re-INVITE requests, but it turns out that we have to support them
8 * in order to satisfy BulkVS and other calling servers that use
9 * session timers.
4 */ 10 */
5 11
6 #include <sys/types.h> 12 #include <sys/types.h>
7 #include <sys/socket.h> 13 #include <sys/socket.h>
8 #include <sys/time.h> 14 #include <sys/time.h>
9 #include <netinet/in.h> 15 #include <netinet/in.h>
16 #include <arpa/inet.h>
10 #include <stdio.h> 17 #include <stdio.h>
11 #include <stdint.h> 18 #include <stdint.h>
12 #include <stdlib.h> 19 #include <stdlib.h>
13 #include <string.h> 20 #include <string.h>
14 #include <strings.h> 21 #include <strings.h>
17 #include "../libsip/uas_basic.h" 24 #include "../libsip/uas_basic.h"
18 #include "../libsip/sdp.h" 25 #include "../libsip/sdp.h"
19 #include "../libsip/out_msg.h" 26 #include "../libsip/out_msg.h"
20 #include "call.h" 27 #include "call.h"
21 28
29 extern struct in_addr sip_bind_ip;
30 extern unsigned sip_bind_port;
31
32 static
33 fill_reinvite_resp(msg, call, ess)
34 struct sip_msg_out *msg;
35 struct call *call;
36 struct uas_parse_hdrs *ess;
37 {
38 char cseq_str[32];
39 int rc;
40
41 rc = out_msg_add_header(msg, "From", call->invite_from);
42 if (rc < 0)
43 return rc;
44 rc = out_msg_add_header(msg, "To", call->invite_to);
45 if (rc < 0)
46 return rc;
47 rc = out_msg_add_header(msg, "Call-ID", call->sip_call_id);
48 if (rc < 0)
49 return rc;
50 sprintf(cseq_str, "%u INVITE", ess->cseq_num);
51 rc = out_msg_add_header(msg, "CSeq", cseq_str);
52 if (rc < 0)
53 return rc;
54 return out_msg_add_header(msg, "Via", ess->via);
55 }
56
57 static
58 fill_reinvite_resp_200(msg, call, ess)
59 struct sip_msg_out *msg;
60 struct call *call;
61 struct uas_parse_hdrs *ess;
62 {
63 char contact_str[80];
64 struct sdp_gen sdp;
65 int rc;
66
67 start_response_out_msg(msg, "200 CONNECT");
68 rc = fill_reinvite_resp(msg, call, ess);
69 if (rc < 0)
70 return rc;
71 sprintf(contact_str, "<sip:%s:%u;transport=udp>",
72 inet_ntoa(sip_bind_ip), sip_bind_port);
73 rc = out_msg_add_header(msg, "Contact", contact_str);
74 if (rc < 0)
75 return rc;
76 rc = out_msg_add_header(msg, "Content-Type", "application/sdp");
77 if (rc < 0)
78 return rc;
79 bzero(&sdp, sizeof sdp);
80 sdp.conn_ip = call->pstn_rtp_local.sin_addr;
81 sdp.conn_port = ntohs(call->pstn_rtp_local.sin_port);
82 sdp.codec_mask = call->use_pcma ? SDP_CODEC_MASK_PCMA
83 : SDP_CODEC_MASK_PCMU;
84 sdp.session_id = (sdp.conn_port << 16) | call->sdp_addend;
85 sdp.owner_ip = sip_bind_ip;
86 return out_msg_finish_sdp(msg, &sdp);
87 }
88
22 void 89 void
23 invite_existing_call(req, ess, sin, call) 90 invite_existing_call(req, ess, sin, call)
24 struct sip_pkt_rx *req; 91 struct sip_pkt_rx *req;
25 struct uas_parse_hdrs *ess; 92 struct uas_parse_hdrs *ess;
26 struct sockaddr_in *sin; 93 struct sockaddr_in *sin;
27 struct call *call; 94 struct call *call;
28 { 95 {
29 struct sip_msg_out resp; 96 struct sip_msg_out resp;
30 int rc; 97 int rc;
31 98
32 if (ess->cseq_num != call->invite_cseq) { 99 switch (call->sip_state) {
33 start_response_out_msg(&resp, "501 Re-INVITE not supported"); 100 case SIP_STATE_INVITE_PROC:
34 rc = add_resp_basic_headers(&resp, ess, req->req_method); 101 start_response_out_msg(&resp, "100 Proceeding");
102 rc = fill_reinvite_resp(&resp, call, ess);
35 if (rc < 0) { 103 if (rc < 0) {
36 syslog(LOG_ERR, 104 msg_size_err: syslog(LOG_ERR,
37 "sending 501 Re-INVITE error: response length exceeded"); 105 "Call in%06u: msg size error on re-INVITE response",
106 call->in_tag_num);
38 return; 107 return;
39 } 108 }
40 out_msg_finish(&resp); 109 out_msg_finish(&resp);
41 sip_tx_packet(&resp, sin); 110 sip_tx_packet(&resp, sin);
42 return; 111 return;
43 }
44 /* it's a retransmission, not a re-INVITE */
45 switch (call->sip_state) {
46 case SIP_STATE_INVITE_PROC:
47 start_response_out_msg(&resp, "100 Proceeding");
48 fill_invite_resp_from_call(&resp, call);
49 out_msg_finish(&resp);
50 sip_tx_packet(&resp, sin);
51 return;
52 case SIP_STATE_RINGING: 112 case SIP_STATE_RINGING:
53 start_response_out_msg(&resp, "180 Ringing");
54 fill_invite_resp_from_call(&resp, call);
55 out_msg_finish(&resp);
56 sip_tx_packet(&resp, sin);
57 return;
58 case SIP_STATE_RINGING_REL: 113 case SIP_STATE_RINGING_REL:
59 start_response_out_msg(&resp, "180 Ringing"); 114 start_response_out_msg(&resp, "180 Ringing");
60 fill_invite_resp_from_call(&resp, call); 115 rc = fill_reinvite_resp(&resp, call, ess);
61 out_msg_add_header(&resp, "Require", "100rel"); 116 if (rc < 0)
62 out_msg_add_header(&resp, "RSeq", "1"); 117 goto msg_size_err;
63 out_msg_finish(&resp); 118 out_msg_finish(&resp);
64 sip_tx_packet(&resp, sin); 119 sip_tx_packet(&resp, sin);
65 return; 120 return;
66 case SIP_STATE_INVITE_200: 121 case SIP_STATE_INVITE_200:
67 case SIP_STATE_CONNECTED: 122 case SIP_STATE_CONNECTED:
68 fill_invite_200_resp(&resp, call); 123 rc = fill_reinvite_resp_200(&resp, call, ess);
124 if (rc < 0)
125 goto msg_size_err;
69 sip_tx_packet(&resp, sin); 126 sip_tx_packet(&resp, sin);
70 return; 127 return;
71 case SIP_STATE_INVITE_ERR: 128 case SIP_STATE_INVITE_ERR:
72 start_response_out_msg(&resp, call->invite_fail); 129 start_response_out_msg(&resp, call->invite_fail);
73 fill_invite_resp_from_call(&resp, call); 130 rc = fill_reinvite_resp(&resp, call, ess);
131 if (rc < 0)
132 goto msg_size_err;
74 out_msg_finish(&resp); 133 out_msg_finish(&resp);
75 sip_tx_packet(&resp, sin); 134 sip_tx_packet(&resp, sin);
76 return; 135 return;
77 default: 136 default:
78 /* silently discard */ 137 /* silently discard */