FreeCalypso > hg > themwi-system-sw
view sip-in/invite_dup.c @ 272:c78b8d6ce885
doc/Number-database: should be complete for now
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 26 Nov 2023 19:13:52 -0800 |
parents | 54c2f271380d |
children |
line wrap: on
line source
/* * Here we process SIP INVITE retransmissions and/or re-INVITEs * 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> #include <string.h> #include <strings.h> #include <syslog.h> #include "../libsip/parse.h" #include "../libsip/uas_basic.h" #include "../libsip/sdp.h" #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; struct uas_parse_hdrs *ess; struct sockaddr_in *sin; struct call *call; { struct sip_msg_out resp; int rc; 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) { 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; case SIP_STATE_RINGING: case SIP_STATE_RINGING_REL: start_response_out_msg(&resp, "180 Ringing"); 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: 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); rc = fill_reinvite_resp(&resp, call, ess); if (rc < 0) goto msg_size_err; out_msg_finish(&resp); sip_tx_packet(&resp, sin); return; default: /* silently discard */ return; } }