diff sip-in/invite_resp.c @ 145:4b685a5d9bd4

sip-in code: split invite.c into 3 separate C modules
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 08 Oct 2022 19:31:05 -0800
parents sip-in/invite.c@c93c339271a7
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sip-in/invite_resp.c	Sat Oct 08 19:31:05 2022 -0800
@@ -0,0 +1,157 @@
+/*
+ * Here we implement SIP INVITE response generation.
+ */
+
+#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 "../include/gsm48_const.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;
+extern unsigned sip_linger_error;
+
+fill_invite_resp_from_call(msg, call)
+	struct sip_msg_out *msg;
+	struct call *call;
+{
+	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", call->invite_cseq);
+	rc = out_msg_add_header(msg, "CSeq", cseq_str);
+	if (rc < 0)
+		return rc;
+	return out_msg_add_header(msg, "Via", call->invite_via);
+}
+
+fill_invite_200_resp(msg, call)
+	struct sip_msg_out *msg;
+	struct call *call;
+{
+	char contact_str[80];
+	struct sdp_gen sdp;
+	int rc;
+
+	start_response_out_msg(msg, "200 CONNECT");
+	rc = fill_invite_resp_from_call(msg, call);
+	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
+signal_invite_ringing(call)
+	struct call *call;
+{
+	struct sip_msg_out resp;
+	int rc;
+
+	start_response_out_msg(&resp, "180 Ringing");
+	rc = fill_invite_resp_from_call(&resp, call);
+	if (rc < 0) {
+msg_size_err:	syslog(LOG_ERR, "INVITE 180 response length exceeded");
+		call->sip_state = SIP_STATE_MSG_SIZE_ERR;
+		call->overall_state = OVERALL_STATE_TEARDOWN;
+		disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
+				GSM48_CC_CAUSE_INTERWORKING);
+		disconnect_tmgw(call);
+		sip_mark_end_time(call, sip_linger_error);
+		return;
+	}
+	if (call->use_100rel) {
+		rc = out_msg_add_header(&resp, "Require", "100rel");
+		if (rc < 0)
+			goto msg_size_err;
+		rc = out_msg_add_header(&resp, "RSeq", "1");
+		if (rc < 0)
+			goto msg_size_err;
+	}
+	out_msg_finish(&resp);
+	sip_tx_packet(&resp, &call->udp_sin);
+	if (call->use_100rel) {
+		call->sip_state = SIP_STATE_RINGING_REL;
+		call->sip_tx_count = 1;
+	} else
+		call->sip_state = SIP_STATE_RINGING;
+}
+
+void
+signal_invite_200(call)
+	struct call *call;
+{
+	struct sip_msg_out resp;
+	int rc;
+
+	rc = fill_invite_200_resp(&resp, call);
+	if (rc < 0) {
+		syslog(LOG_ERR, "INVITE 200 response length exceeded");
+		call->sip_state = SIP_STATE_MSG_SIZE_ERR;
+		call->overall_state = OVERALL_STATE_TEARDOWN;
+		disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
+				GSM48_CC_CAUSE_INTERWORKING);
+		disconnect_tmgw(call);
+		sip_mark_end_time(call, sip_linger_error);
+		return;
+	}
+	sip_tx_packet(&resp, &call->udp_sin);
+	call->sip_state = SIP_STATE_INVITE_200;
+	call->sip_tx_count = 1;
+}
+
+void
+signal_invite_error(call)
+	struct call *call;
+{
+	struct sip_msg_out resp;
+	int rc;
+
+	start_response_out_msg(&resp, call->invite_fail);
+	rc = fill_invite_resp_from_call(&resp, call);
+	if (rc < 0) {
+		syslog(LOG_ERR, "INVITE late error response length exceeded");
+		call->sip_state = SIP_STATE_MSG_SIZE_ERR;
+		sip_mark_end_time(call, sip_linger_error);
+		transition_dead_sip(call);
+		return;
+	}
+	out_msg_finish(&resp);
+	sip_tx_packet(&resp, &call->udp_sin);
+	call->sip_state = SIP_STATE_INVITE_ERR;
+	call->sip_tx_count = 1;
+}