view sip-manual-out/uac.c @ 124:7e04d28fae8b

sip-in: default use-100rel to no BulkVS servers act badly when we send a reliable 180 Ringing response to an incoming call, even though they advertise 100rel support in the Supported header in the INVITE packet, and we probably won't be implementing 100rel for outbound because doing per-the-spec PRACK as a UAC is just too burdensome. Therefore, we need to consider 100rel extension as not-really-supported in themwi-system-sw.
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 01 Oct 2022 15:54:50 -0800
parents a36b731bfef9
children 6ac96217c442
line wrap: on
line source

/*
 * Here we implement processing of SIP responses to the requests we sent out.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "../libsip/parse.h"
#include "../libsip/resp_ident.h"
#include "../libsip/out_msg.h"

#define	MAX_TO_TAG	63

extern char *get_single_header();
extern char *extract_to_tag();

extern struct in_addr sip_bind_ip;
extern unsigned sip_bind_port;
extern char call_id[], from_uri[], to_uri[];
extern unsigned max_forwards;

char to_tag[MAX_TO_TAG+1];

add_req_boilerplate(msg, cseq, add_to_tag)
	struct sip_msg_out *msg;
	char *cseq;
{
	char strbuf[256];
	int rc;

	sprintf(strbuf, "SIP/2.0/UDP %s:%u",
		inet_ntoa(sip_bind_ip), sip_bind_port);
	rc = out_msg_add_header(msg, "Via", strbuf);
	if (rc < 0)
		return rc;
	rc = out_msg_add_header(msg, "From", from_uri);
	if (rc < 0)
		return rc;
	if (add_to_tag && to_tag[0]) {
		sprintf(strbuf, "<%s>;tag=%s", to_uri, to_tag);
		rc = out_msg_add_header(msg, "To", strbuf);
	} else
		rc = out_msg_add_header(msg, "To", to_uri);
	if (rc < 0)
		return rc;
	rc = out_msg_add_header(msg, "Call-ID", call_id);
	if (rc < 0)
		return rc;
	rc = out_msg_add_header(msg, "CSeq", cseq);
	if (rc < 0)
		return rc;
	sprintf(strbuf, "%u", max_forwards);
	return out_msg_add_header(msg, "Max-Forwards", strbuf);
}

add_contact_header(msg)
	struct sip_msg_out *msg;
{
	char strbuf[80];

	sprintf(strbuf, "<sip:%s:%u;transport=udp>",
		inet_ntoa(sip_bind_ip), sip_bind_port);
	return out_msg_add_header(msg, "Contact", strbuf);
}

static void
send_ack(sin)
	struct sockaddr_in *sin;
{
	struct sip_msg_out msg;
	int rc;

	rc = start_request_out_msg(&msg, "ACK", to_uri);
	if (rc < 0) {
msg_size_err:	fprintf(stderr, "composing ACK message: size error\n");
		return;
	}
	rc = add_req_boilerplate(&msg, "1 ACK", 1);
	if (rc < 0)
		goto msg_size_err;
	out_msg_finish(&msg);
	sip_tx_packet(&msg, sin);
}

static void
handle_invite_response(msg, sin)
	struct sip_pkt_rx *msg;
	struct sockaddr_in *sin;
{
	char *tag;

	printf("Response to INVITE: %s\n", msg->status_str);
	tag = extract_to_tag(msg, to_uri);
	if (tag) {
		printf("To tag: %s\n", tag);
		if (strlen(tag) <= MAX_TO_TAG)
			strcpy(to_tag, tag);
		else
			printf("To tag exceeds length limit!\n");
	}
	if (msg->status_code >= 200) {
		printf("Sending ACK\n");
		send_ack(sin);
	}
}

void
process_sip_response(msg, sin)
	struct sip_pkt_rx *msg;
	struct sockaddr_in *sin;
{
	struct sip_resp_ident rid;
	int rc;

	rc = sip_resp_extract_ident(msg, &rid);
	if (rc < 0) {
		printf("SIP %03u response: bad or missing %s header\n",
			msg->status_code, rid.error_field);
		return;
	}
	if (strcmp(rid.call_id, call_id)) {
		printf("Got SIP response with wrong Call-ID\n");
		return;
	}
	if (rid.cseq_num == 1 && !strcmp(rid.cseq_method, "INVITE"))
		handle_invite_response(msg, sin);
	else if (rid.cseq_num == 1 && !strcmp(rid.cseq_method, "CANCEL"))
		printf("Response to CANCEL: %s\n", msg->status_str);
	else if (rid.cseq_num == 2 && !strcmp(rid.cseq_method, "BYE"))
		printf("Response to BYE: %s\n", msg->status_str);
	else
		printf("Got SIP resp for our Call-ID with unknown CSeq %u %s\n",
			rid.cseq_num, rid.cseq_method);
}