From 4d760694b21b317c36aed48a5025ace9dc561fd3 Mon Sep 17 00:00:00 2001
From: Joshua Colp <jcolp@digium.com>
Date: Mon, 9 Dec 2013 16:41:43 +0000
Subject: [PATCH] res_pjsip_nat: Add NAT module to session dialogs.

Due to the way pjproject internally works it was possible for the
NAT module to not be invoked on messages with-in a session dialog.
This means that the various parts of the message would not get rewritten
with the source IP address and port.

This change uses a session supplement to add the NAT module
to the dialog on the first incoming or outgoing INVITE.

(closes issue ASTERISK-22941)
Reported by: Leif Madsen
........

Merged revisions 403510 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403511 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 res/res_pjsip_nat.c | 50 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)

diff --git a/res/res_pjsip_nat.c b/res/res_pjsip_nat.c
index d045051076..9a3f500b94 100644
--- a/res/res_pjsip_nat.c
+++ b/res/res_pjsip_nat.c
@@ -28,10 +28,11 @@
 #include <pjsip_ua.h>
 
 #include "asterisk/res_pjsip.h"
+#include "asterisk/res_pjsip_session.h"
 #include "asterisk/module.h"
 #include "asterisk/acl.h"
 
-static pj_bool_t nat_on_rx_request(pjsip_rx_data *rdata)
+static pj_bool_t nat_on_rx_message(pjsip_rx_data *rdata)
 {
 	RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
 	pjsip_contact_hdr *contact;
@@ -213,23 +214,62 @@ static pjsip_module nat_module = {
 	.name = { "NAT", 3 },
 	.id = -1,
 	.priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 2,
-	.on_rx_request = nat_on_rx_request,
+	.on_rx_request = nat_on_rx_message,
+	.on_rx_response = nat_on_rx_message,
 	.on_tx_request = nat_on_tx_message,
 	.on_tx_response = nat_on_tx_message,
 };
 
-static int load_module(void)
+/*! \brief Function called when an INVITE goes out */
+static int nat_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 {
-	ast_sip_register_service(&nat_module);
-	return AST_MODULE_LOAD_SUCCESS;
+	if (session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
+		pjsip_dlg_add_usage(session->inv_session->dlg, &nat_module, NULL);
+	}
+
+	return 0;
 }
 
+/*! \brief Function called when an INVITE comes in */
+static void nat_outgoing_invite_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
+{
+	if (session->inv_session->state == PJSIP_INV_STATE_NULL) {
+		pjsip_dlg_add_usage(session->inv_session->dlg, &nat_module, NULL);
+	}
+}
+
+/*! \brief Supplement for adding NAT functionality to dialog */
+static struct ast_sip_session_supplement nat_supplement = {
+	.method = "INVITE",
+	.priority = AST_SIP_SESSION_SUPPLEMENT_PRIORITY_FIRST + 1,
+	.incoming_request = nat_incoming_invite_request,
+	.outgoing_request = nat_outgoing_invite_request,
+};
+
+
 static int unload_module(void)
 {
+	ast_sip_session_unregister_supplement(&nat_supplement);
 	ast_sip_unregister_service(&nat_module);
 	return 0;
 }
 
+static int load_module(void)
+{
+	if (ast_sip_register_service(&nat_module)) {
+		ast_log(LOG_ERROR, "Could not register NAT module for incoming and outgoing requests\n");
+		return AST_MODULE_LOAD_FAILURE;
+	}
+
+	if (ast_sip_session_register_supplement(&nat_supplement)) {
+		ast_log(LOG_ERROR, "Could not register NAT session supplement for incoming and outgoing INVITE requests\n");
+		unload_module();
+		return AST_MODULE_LOAD_FAILURE;
+	}
+
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP NAT Support",
 		.load = load_module,
 		.unload = unload_module,
-- 
GitLab