diff --git a/CHANGES b/CHANGES
index 328f08c8953ea47ee0df5eded3a5e277d1b8920f..6c7c4522fa169d1efb555a9a68d688544dfe0a75 100644
--- a/CHANGES
+++ b/CHANGES
@@ -252,6 +252,12 @@ res_pjsip
    will be used instead. The new SIP resolver provides NAPTR support, improved
    SRV support, and AAAA record support.
 
+res_pjsip_info_empty
+--------------------
+ * A new module that can respond to empty Content-Type INFO packets during call.
+   Some SBCs will terminate a call if their empty INFO packets are not responded
+   to within a predefined time.
+
 res_pjsip_outbound_registration
 -------------------------------
 * A new 'fatal_retry_interval' option has been added to outbound registration.
@@ -264,6 +270,7 @@ res_pjsip_outbound_publish
  * Added a new multi_user option that when set to 'yes' allows a given configuration
    to be used for multiple users.
 
+
 CEL Backends
 ------------------
 
diff --git a/res/res_pjsip_dtmf_info.c b/res/res_pjsip_dtmf_info.c
index 47ccd1ae5cd6cfc792ace3d3f0a5176b13408f28..e534f3e27edf0fa705e1741681356859a48d480f 100644
--- a/res/res_pjsip_dtmf_info.c
+++ b/res/res_pjsip_dtmf_info.c
@@ -103,13 +103,13 @@ static int dtmf_info_incoming_request(struct ast_sip_session *session, struct pj
 	if (!body || !body->len) {
 		/* need to return 200 OK on empty body */
 		send_response(session, rdata, 200);
-		return 0;
+		return 1;
 	}
 
 	res = body->print_body(body, buf, body->len);
 	if (res < 0) {
 		send_response(session, rdata, 500);
-		return 0;
+		return 1;
 	}
 	buf[res] = '\0';
 
@@ -150,11 +150,12 @@ static int dtmf_info_incoming_request(struct ast_sip_session *session, struct pj
 	}
 
 	send_response(session, rdata, event ? 200 : 500);
-	return event ? 0 : -1;
+	return 1;
 }
 
 static struct ast_sip_session_supplement dtmf_info_supplement = {
 	.method = "INFO",
+	.priority = AST_SIP_SUPPLEMENT_PRIORITY_FIRST,
 	.incoming_request = dtmf_info_incoming_request,
 };
 
diff --git a/res/res_pjsip_empty_info.c b/res/res_pjsip_empty_info.c
new file mode 100644
index 0000000000000000000000000000000000000000..09109ba2c3b3d2c49eff4e3d390dd92e6c0885fe
--- /dev/null
+++ b/res/res_pjsip_empty_info.c
@@ -0,0 +1,89 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2016, Digium, Inc.
+ *
+ * Bradley Latus <brad.latus@gmail.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*** MODULEINFO
+	<depend>pjproject</depend>
+	<depend>res_pjsip</depend>
+	<depend>res_pjsip_session</depend>
+	<support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_REGISTER_FILE()
+
+#include <pjsip.h>
+#include <pjsip_ua.h>
+
+#include "asterisk/res_pjsip.h"
+#include "asterisk/res_pjsip_session.h"
+#include "asterisk/module.h"
+
+static void send_response(struct ast_sip_session *session,
+		struct pjsip_rx_data *rdata, int code)
+{
+	pjsip_tx_data *tdata;
+	pjsip_dialog *dlg = session->inv_session->dlg;
+
+	if (pjsip_dlg_create_response(dlg, rdata, code, NULL, &tdata) == PJ_SUCCESS) {
+		struct pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
+		pjsip_dlg_send_response(dlg, tsx, tdata);
+	}
+}
+
+static int empty_info_incoming_request(struct ast_sip_session *session,
+		struct pjsip_rx_data *rdata)
+{
+	if (!rdata->msg_info.ctype) {
+		/* Need to return 200 OK on empty body */
+		/* Some SBCs use empty INFO as a KEEPALIVE */
+		send_response(session, rdata, 200);
+		return 1;
+	}
+
+	/* Let another module respond */
+	return 0;
+
+}
+
+static struct ast_sip_session_supplement empty_info_supplement = {
+	.method = "INFO",
+	.priority = AST_SIP_SUPPLEMENT_PRIORITY_LAST,
+	.incoming_request = empty_info_incoming_request,
+};
+
+static int load_module(void)
+{
+	CHECK_PJSIP_SESSION_MODULE_LOADED();
+
+	ast_sip_session_register_supplement(&empty_info_supplement);
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+	ast_sip_session_unregister_supplement(&empty_info_supplement);
+	return 0;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Empty INFO Support",
+	.support_level = AST_MODULE_SUPPORT_CORE,
+	.load = load_module,
+	.unload = unload_module,
+	.load_pri = AST_MODPRI_APP_DEPEND,
+);
diff --git a/res/res_pjsip_one_touch_record_info.c b/res/res_pjsip_one_touch_record_info.c
index 30dfcaabf87ef2862b45889acd161374cf0ced6b..2d53fd48ee0760cd4844c40cd715f283820c8e80 100644
--- a/res/res_pjsip_one_touch_record_info.c
+++ b/res/res_pjsip_one_touch_record_info.c
@@ -72,13 +72,13 @@ static int handle_incoming_request(struct ast_sip_session *session, struct pjsip
 
 	if (!session->channel) {
 		send_response(session, 481, rdata);
-		return 0;
+		return 1;
 	}
 
 	/* Is this endpoint configured with One Touch Recording? */
 	if (!session->endpoint->info.recording.enabled || ast_strlen_zero(feature)) {
 		send_response(session, 403, rdata);
-		return 0;
+		return 1;
 	}
 
 	ast_channel_lock(session->channel);
@@ -87,7 +87,7 @@ static int handle_incoming_request(struct ast_sip_session *session, struct pjsip
 
 	if (feature_res || ast_strlen_zero(feature_code)) {
 		send_response(session, 403, rdata);
-		return 0;
+		return 1;
 	}
 
 	for (digit = feature_code; *digit; ++digit) {
@@ -97,11 +97,12 @@ static int handle_incoming_request(struct ast_sip_session *session, struct pjsip
 
 	send_response(session, 200, rdata);
 
-	return 0;
+	return 1;
 }
 
 static struct ast_sip_session_supplement info_supplement = {
 	.method = "INFO",
+	.priority = AST_SIP_SUPPLEMENT_PRIORITY_FIRST,
 	.incoming_request = handle_incoming_request,
 };