changeset 68:709b78a4ebf0

sip-in: implement retransmission of INVITE responses
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 18 Sep 2022 21:56:20 -0800
parents 15c9e1f8f756
children 8cf85edca543
files sip-in/Makefile sip-in/call_list.c sip-in/main.c sip-in/readconf.c sip-in/retrans.c
diffstat 5 files changed, 85 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/sip-in/Makefile	Sun Sep 18 16:55:01 2022 -0800
+++ b/sip-in/Makefile	Sun Sep 18 21:56:20 2022 -0800
@@ -2,8 +2,8 @@
 CFLAGS=	-O2
 PROG=	themwi-sip-in
 OBJS=	call_list.o call_setup.o disconnect.o invite.o main.o mgw_ops.o \
-	mgw_sock.o mncc_handle.o mncc_sock.o readconf.o sip_log.o sip_uas.o \
-	sip_udp.o
+	mgw_sock.o mncc_handle.o mncc_sock.o readconf.o retrans.o sip_log.o \
+	sip_uas.o sip_udp.o
 LIBS=	../libnumdb/libnumdb.a ../libsip/libsip.a ../libutil/libutil.a
 INSTBIN=/usr/local/bin
 
--- a/sip-in/call_list.c	Sun Sep 18 16:55:01 2022 -0800
+++ b/sip-in/call_list.c	Sun Sep 18 21:56:20 2022 -0800
@@ -52,3 +52,19 @@
 		}
 	}
 }
+
+void
+scan_call_list_for_timeouts(retrans)
+	int *retrans;
+{
+	struct call *call;
+
+	for (call = call_list; call; call = call->next) {
+		switch (call->sip_state) {
+		case SIP_STATE_INVITE_200:
+		case SIP_STATE_INVITE_ERR:
+			*retrans = 1;
+			break;
+		}
+	}
+}
--- a/sip-in/main.c	Sun Sep 18 16:55:01 2022 -0800
+++ b/sip-in/main.c	Sun Sep 18 21:56:20 2022 -0800
@@ -13,6 +13,8 @@
 #include <syslog.h>
 #include <unistd.h>
 
+extern unsigned cfg_retrans_timeout;
+
 extern int mgw_socket, sip_socket;
 extern int gsm_socket, gsm_is_connected;
 
@@ -30,7 +32,8 @@
 	char **argv;
 {
 	fd_set fds;
-	int rc;
+	int rc, need_retrans;
+	struct timeval timeout;
 
 	openlog("themwi-sip-in", 0, LOG_LOCAL5);
 	read_config_file();
@@ -59,7 +62,14 @@
 		FD_SET(sip_socket, &fds);
 		if (gsm_is_connected)
 			FD_SET(gsm_socket, &fds);
-		rc = select(max_fd+1, &fds, 0, 0, 0);
+		need_retrans = 0;
+		scan_call_list_for_timeouts(&need_retrans);
+		if (need_retrans) {
+			timeout.tv_sec = cfg_retrans_timeout / 1000;
+			timeout.tv_usec = (cfg_retrans_timeout % 1000) * 1000;
+			rc = select(max_fd+1, &fds, 0, 0, &timeout);
+		} else
+			rc = select(max_fd+1, &fds, 0, 0, 0);
 		if (rc < 0) {
 			if (errno == EINTR)
 				continue;
@@ -67,6 +77,10 @@
 			exit(1);
 		}
 		gettimeofday(&cur_event_time, 0);
+		if (rc == 0) {
+			run_periodic_retrans();
+			continue;
+		}
 		if (gsm_is_connected && FD_ISSET(gsm_socket, &fds))
 			gsm_socket_select();
 		if (FD_ISSET(sip_socket, &fds))
--- a/sip-in/readconf.c	Sun Sep 18 16:55:01 2022 -0800
+++ b/sip-in/readconf.c	Sun Sep 18 21:56:20 2022 -0800
@@ -17,6 +17,8 @@
 struct in_addr sip_bind_ip;
 unsigned sip_bind_port;
 int cfg_use_100rel;
+unsigned cfg_retrans_timeout = 500;
+unsigned cfg_retrans_count = 10;
 
 static char config_file_pathname[] = "/var/gsm/themwi-sip-in.cfg";
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sip-in/retrans.c	Sun Sep 18 21:56:20 2022 -0800
@@ -0,0 +1,49 @@
+/*
+ * In this module we handle retransmission of INVITE responses
+ * and BYE requests.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <syslog.h>
+#include "../libsip/out_msg.h"
+#include "call.h"
+
+extern unsigned cfg_retrans_count;
+extern struct call *call_list;
+
+void
+run_periodic_retrans()
+{
+	struct call *call;
+	struct sip_msg_out msg;
+
+	for (call = call_list; call; call = call->next) {
+		switch (call->sip_state) {
+		case SIP_STATE_INVITE_200:
+			if (call->sip_tx_count < cfg_retrans_count) {
+				fill_invite_200_resp(&msg, call);
+				sip_tx_packet(&msg, &call->udp_sin);
+				call->sip_tx_count++;
+			} else
+				/* error handling to be implemented */;
+			break;
+		case SIP_STATE_INVITE_ERR:
+			if (call->sip_tx_count < cfg_retrans_count) {
+				start_response_out_msg(&msg, call->invite_fail);
+				fill_invite_resp_from_call(&msg, call);
+				out_msg_finish(&msg);
+				sip_tx_packet(&msg, &call->udp_sin);
+				call->sip_tx_count++;
+			} else
+				/* error handling to be implemented */;
+			break;
+		}
+	}
+}