[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