view sip-in/retrans.c @ 197:73bbe7da45cd

add LICENSE
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 26 Mar 2023 15:29:48 -0800
parents bf3b19bf57e9
children
line wrap: on
line source

/*
 * In this module we handle retransmission of INVITE responses
 * and BYE requests.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.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/out_msg.h"
#include "call.h"

extern unsigned cfg_retrans_count;
extern unsigned sip_linger_error;
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_RINGING_REL:
			if (call->sip_tx_count < cfg_retrans_count) {
				start_response_out_msg(&msg, "180 Ringing");
				fill_invite_resp_from_call(&msg, call);
				out_msg_add_header(&msg, "Require", "100rel");
				out_msg_add_header(&msg, "RSeq", "1");
				out_msg_finish(&msg);
				sip_tx_packet(&msg, &call->udp_sin);
				call->sip_tx_count++;
			} else {
				syslog(LOG_ERR,
					"Call in%06u: 100rel retrans timeout",
					call->in_tag_num);
				call->overall_state = OVERALL_STATE_TEARDOWN;
				disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
						GSM48_CC_CAUSE_INTERWORKING);
				disconnect_tmgw(call);
				strcpy(call->invite_fail,
					"504 100rel retransmissions exhausted");
				signal_invite_error(call);
			}
			break;
		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 {
				syslog(LOG_ERR,
					"Call in%06u: 200 retrans timeout",
					call->in_tag_num);
				call->overall_state = OVERALL_STATE_TEARDOWN;
				disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
						GSM48_CC_CAUSE_INTERWORKING);
				disconnect_tmgw(call);
				initiate_bye(call);
			}
			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 {
				syslog(LOG_ERR,
				"Call in%06u: late error retrans timeout",
					call->in_tag_num);
				call->sip_state = SIP_STATE_ENDED;
				sip_mark_end_time(call, sip_linger_error);
				transition_dead_sip(call);
			}
			break;
		case SIP_STATE_BYE_SENT:
			if (call->sip_tx_count < cfg_retrans_count) {
				fill_bye_out_msg(&msg, call);
				sip_tx_packet(&msg, &call->udp_sin);
				call->sip_tx_count++;
			} else {
				syslog(LOG_ERR,
					"Call in%06u: BYE-out retrans timeout",
					call->in_tag_num);
				call->sip_state = SIP_STATE_ENDED;
				sip_mark_end_time(call, sip_linger_error);
				transition_dead_sip(call);
			}
			break;
		}
	}
}