[Asterisk-code-review] res/res pjsip sip message: added sip message event notifier (asterisk[master])

sungtae kim asteriskteam at digium.com
Mon Nov 26 18:33:03 CST 2018


sungtae kim has uploaded this change for review. ( https://gerrit.asterisk.org/10715


Change subject: res/res_pjsip_sip_message: added sip message event notifier
......................................................................

res/res_pjsip_sip_message: added sip message event notifier

This module is sending an event messages for a given channel's SIP
messages.

ASTERISK-28183

Change-Id: I1dedcc678265ebb74d35e7a2f58bc4b5084bcfe1
---
A res/res_pjsip_sip_message.c
1 file changed, 464 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/15/10715/1

diff --git a/res/res_pjsip_sip_message.c b/res/res_pjsip_sip_message.c
new file mode 100644
index 0000000..7ec7337
--- /dev/null
+++ b/res/res_pjsip_sip_message.c
@@ -0,0 +1,464 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2018, Sungtae Kim
+ *
+ * Sungtae Kim <pchero21 at 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>
+	<support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include <stdbool.h>
+#include <pjlib.h>
+#include <pjsip.h>
+#include <pjsua.h>
+
+#include "asterisk/astobj2.h"
+#include "asterisk/module.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_app.h"
+#include "asterisk/logger.h"
+#include "asterisk/res_pjsip.h"
+#include "asterisk/res_pjsip_session.h"
+#include "res_pjsip/include/res_pjsip_private.h"
+
+#define DEF_MESSAGE_NAME	"ChannelSipMessage"
+
+static int incoming_request_handler(struct ast_sip_session* session, pjsip_rx_data* rdata);
+static void incoming_response_handler(struct ast_sip_session* session, pjsip_rx_data* rdata);
+static void outgoing_request_handler(struct ast_sip_session* session, pjsip_tx_data* tdata);
+static void outgoing_response_handler(struct ast_sip_session* session, pjsip_tx_data* tdata);
+
+static void incoming_msg_handler(const char* direction, struct ast_sip_session* session, pjsip_rx_data* rdata);
+static void outgoing_msg_handler(const char* direction, struct ast_sip_session* session, pjsip_tx_data* tdata);
+
+static void publish_event(struct ast_sip_session* session, struct ast_json *j_evt);
+
+static char* get_rx_request_method(pjsip_rx_data* rdata);
+static char* get_tx_request_method(pjsip_tx_data* tdata);
+
+static struct stasis_message_type *pjsip_sip_message_type(void);
+
+static struct ast_json *sip_message_to_json(
+	struct stasis_message *message,
+	const struct stasis_message_sanitizer *sanitize);
+
+static struct ast_json *blob_to_json(
+	struct stasis_message *message,
+	const char *type,
+	const struct stasis_message_sanitizer *sanitize);
+
+
+static struct ast_sip_session_supplement supp_sip_in_req = {
+		.priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 1,
+		.incoming_request = incoming_request_handler,
+};
+
+static struct ast_sip_session_supplement supp_sip_in_res = {
+		.priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 1,
+		.incoming_response = incoming_response_handler,
+};
+
+static struct ast_sip_session_supplement supp_sip_out_req = {
+		.priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 1,
+		.outgoing_request = outgoing_request_handler,
+};
+
+static struct ast_sip_session_supplement supp_sip_out_res = {
+		.priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 1,
+		.outgoing_response = outgoing_response_handler,
+};
+
+
+STASIS_MESSAGE_TYPE_DEFN(pjsip_sip_message_type,
+	.to_json = sip_message_to_json,
+	);
+
+
+static struct ast_json *sip_message_to_json(
+	struct stasis_message *message,
+	const struct stasis_message_sanitizer *sanitize)
+{
+	return blob_to_json(message, DEF_MESSAGE_NAME, sanitize);
+}
+
+static struct ast_json *blob_to_json(
+	struct stasis_message *message,
+	const char *type,
+	const struct stasis_message_sanitizer *sanitize)
+{
+	struct ast_json *to_json;
+	struct ast_channel_blob *channel_blob = stasis_message_data(message);
+	struct ast_json *blob = channel_blob->blob;
+	const struct timeval *tv = stasis_message_timestamp(message);
+	int res = 0;
+
+	to_json = ast_json_copy(blob);
+	if (!to_json) {
+		return NULL;
+	}
+
+	res |= ast_json_object_set(to_json, "type", ast_json_string_create(type));
+	res |= ast_json_object_set(to_json, "timestamp",
+		ast_json_timeval(*tv, NULL));
+
+	if (res != 0) {
+		ast_json_unref(to_json);
+		return NULL;
+	}
+
+	return to_json;
+}
+
+/*!
+ * outgoing request sip message handler
+ * \param session
+ * \param tdata
+ */
+static void outgoing_request_handler(struct ast_sip_session *session, pjsip_tx_data *tdata)
+{
+	if ((!session) || (!tdata)) {
+		ast_log(LOG_WARNING, "Wrong input parameters.\n");
+		return;
+	}
+
+	/* check message type. */
+	if (tdata->msg->type != PJSIP_REQUEST_MSG) {
+		ast_log(LOG_ERROR, "Wrong message type. It should not reach to here.\n");
+		return;
+	}
+
+	outgoing_msg_handler("outgoing request", session, tdata);
+
+	return;
+}
+
+/*!
+ * outgoing response sip message handler
+ * \param session
+ * \param tdata
+ */
+static void outgoing_response_handler(struct ast_sip_session *session, pjsip_tx_data *tdata)
+{
+	if ((!session) || (!tdata)) {
+		ast_log(LOG_WARNING, "Wrong input parameters.\n");
+		return;
+	}
+
+	/* check message type. */
+	if (tdata->msg->type != PJSIP_RESPONSE_MSG) {
+		ast_log(LOG_ERROR, "Wrong message type. It should not reach to here.\n");
+		return;
+	}
+
+	outgoing_msg_handler("outgoing response", session, tdata);
+
+	return;
+}
+
+/*!
+ * incoming request sip message handler
+ * \param session
+ * \param tdata
+ */
+static int incoming_request_handler(struct ast_sip_session *session, pjsip_rx_data *rdata)
+{
+	if ((session == NULL) || (rdata == NULL)) {
+		ast_log(LOG_WARNING, "Wrong input parameters.\n");
+		return 0;
+	}
+
+	/* check message type. */
+	if (rdata->msg_info.msg->type != PJSIP_REQUEST_MSG) {
+		ast_log(LOG_ERROR, "Wrong message type. It should not reach to here.\n");
+		return 0;
+	}
+
+	incoming_msg_handler("incoming request", session, rdata);
+
+	return 0;
+}
+
+/*!
+ * incoming response sip message handler
+ * \param session
+ * \param tdata
+ */
+static void incoming_response_handler(struct ast_sip_session* session, pjsip_rx_data* rdata)
+{
+	if ((session == NULL) || (rdata == NULL)) {
+		ast_log(LOG_WARNING, "Wrong input parameters.\n");
+		return;
+	}
+
+	/* check message type. */
+	if (rdata->msg_info.msg->type != PJSIP_RESPONSE_MSG) {
+		ast_log(LOG_ERROR, "Wrong message type. It should not reach to here.\n");
+		return;
+	}
+
+	incoming_msg_handler("incoming response", session, rdata);
+
+	return;
+}
+
+static void incoming_msg_handler(const char* direction, struct ast_sip_session* session, pjsip_rx_data* rdata)
+{
+	struct ast_channel_snapshot *snapshot;
+	struct ast_json *j_chan;
+	struct ast_json* j_data;
+	char* method;
+
+	if ((!direction) || (!session) || (!rdata)) {
+		ast_log(LOG_WARNING, "Wrong input parameters.\n");
+		return;
+	}
+
+	/* for the BYE response, the channel already removed it. */
+	/* and if no channel, doesn't go futher */
+	if (!session->channel) {
+		return;
+	}
+
+	/* get method */
+	method = get_rx_request_method(rdata);
+	if (method == NULL) {
+		ast_log(LOG_ERROR, "Could not get requested method name.\n");
+		return;
+	}
+
+	/* create channel info */
+	snapshot = ast_channel_snapshot_create(session->channel);
+	if (!snapshot) {
+		ast_free(method);
+		return;
+	}
+	j_chan = ast_channel_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+	ao2_cleanup(snapshot);
+
+	/* create data */
+	j_data = ast_json_pack("{s:s, s:s, s:s, s:o}",
+			"direction",			direction,
+			"method",				method,
+			"raw",					rdata->msg_info.msg_buf,
+			"channel",				j_chan
+			);
+	ast_free(method);
+
+	/* publish message */
+	publish_event(session, j_data);
+	ast_json_unref(j_data);
+
+	return;
+}
+
+static void outgoing_msg_handler(const char *direction, struct ast_sip_session *session, pjsip_tx_data *tdata)
+{
+	int ret;
+	struct ast_channel_snapshot *snapshot;
+	struct ast_json *j_chan;
+	struct ast_json *j_msg;
+	char *method;
+
+	if ((!direction) || (!session) || (!tdata)) {
+		ast_log(LOG_WARNING, "Wrong input parameters.\n");
+		return;
+	}
+
+	/* check channel */
+	if (!session->channel) {
+		return;
+	}
+
+	/* encode tx data*/
+	ret = pjsip_tx_data_encode(tdata);
+	if (ret != PJ_SUCCESS) {
+		return;
+	}
+
+	/* get method */
+	method = get_tx_request_method(tdata);
+	if (method == NULL) {
+		ast_log(LOG_ERROR, "Could not get request method name.\n");
+		return;
+	}
+
+	/* create channel info */
+	snapshot = ast_channel_snapshot_create(session->channel);
+	j_chan = ast_channel_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+	ao2_cleanup(snapshot);
+
+	/* create message */
+	j_msg = ast_json_pack("{s:s, s:s, s:s, s:o}",
+			"direction",			direction,
+			"method",				method,
+			"raw",					tdata->buf.start,
+			"channel",				j_chan
+			);
+	ast_free(method);
+
+	/* publish message */
+	publish_event(session, j_msg);
+	ast_json_unref(j_msg);
+
+	return;
+}
+
+
+/*!
+ * \brief Convenience function to publish an \ref ast_foo message to the
+ * \ref foo_topic.
+ */
+static void publish_event(struct ast_sip_session* session, struct ast_json *j_evt)
+{
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+
+	if ((!session) || (!session->channel) || (!j_evt)) {
+		ast_log(LOG_WARNING, "Wrong input parameter.\n");
+		return;
+	}
+
+	/* send message */
+	ast_channel_lock(session->channel);
+	ast_channel_publish_blob(session->channel, pjsip_sip_message_type(), j_evt);
+	ast_channel_unlock(session->channel);
+
+	return;
+}
+
+/**
+ * Returns given received sip message's requested method name.\n
+ * The return string should be freed after use.
+ * \param rdata
+ * \return
+ */
+static char* get_rx_request_method(pjsip_rx_data* rdata)
+{
+	char *res;
+	const pjsip_cseq_hdr *cseq;
+
+	if (rdata == NULL) {
+		ast_log(LOG_WARNING, "Wrong input parameter.\n");
+		return NULL;
+	}
+
+	if(rdata->msg_info.msg == NULL) {
+		ast_log(LOG_ERROR, "Could not get message info.\n");
+		return NULL;
+	}
+
+	cseq = (const pjsip_cseq_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CSEQ, NULL);
+	if (cseq == NULL) {
+		ast_log(LOG_WARNING, "Could not get cseq info.\n");
+		return NULL;
+	}
+
+	ast_copy_pj_str2(&res, &cseq->method.name);
+
+	return res;
+}
+
+/**
+ * Returns given received sip message's requested method name.\n
+ * The return string should be freed after use.
+ * \param rdata
+ * \return
+ */
+static char* get_tx_request_method(pjsip_tx_data* tdata)
+{
+	char *res;
+	const pjsip_cseq_hdr *cseq;
+
+	if (tdata == NULL) {
+		ast_log(LOG_WARNING, "Wrong input parameter.\n");
+		return NULL;
+	}
+
+	if(tdata->msg == NULL) {
+		ast_log(LOG_ERROR, "Could not get message info.\n");
+		return NULL;
+	}
+
+	cseq = (const pjsip_cseq_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
+	if (cseq == NULL) {
+		ast_log(LOG_WARNING, "Could not get cseq info.\n");
+		return NULL;
+	}
+
+	ast_copy_pj_str2(&res, &cseq->method.name);
+
+	return res;
+}
+
+
+static bool init(void)
+{
+	int ret;
+
+	ret = STASIS_MESSAGE_TYPE_INIT(pjsip_sip_message_type);
+	if(ret != 0) {
+		return false;
+	}
+
+	/* register callbacks */
+	ast_sip_session_register_supplement(&supp_sip_in_req);
+	ast_sip_session_register_supplement(&supp_sip_in_res);
+	ast_sip_session_register_supplement(&supp_sip_out_req);
+	ast_sip_session_register_supplement(&supp_sip_out_res);
+
+	ast_log(LOG_DEBUG, "Completed init.\n");
+
+	return true;
+}
+
+static void terminate(void)
+{
+	STASIS_MESSAGE_TYPE_CLEANUP(pjsip_sip_message_type);
+
+	return;
+}
+
+static int load_module(void)
+{
+	int ret;
+
+	ret = init();
+	if (ret != true) {
+		terminate();
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+	terminate();
+
+	return 0;
+}
+
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP SIP Message Support",
+	.support_level = AST_MODULE_SUPPORT_CORE,
+	.load = load_module,
+	.unload = unload_module,
+	.load_pri = AST_MODPRI_APP_DEPEND,
+	.requires = "res_pjsip,res_pjsip_session",
+);

-- 
To view, visit https://gerrit.asterisk.org/10715
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1dedcc678265ebb74d35e7a2f58bc4b5084bcfe1
Gerrit-Change-Number: 10715
Gerrit-PatchSet: 1
Gerrit-Owner: sungtae kim <pchero21 at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181126/9f98d6ee/attachment-0001.html>


More information about the asterisk-code-review mailing list