]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_hep: Provide an option to pick the UUID type 14/2814/3
authorMatt Jordan <mjordan@digium.com>
Thu, 12 May 2016 01:17:15 +0000 (20:17 -0500)
committerMatt Jordan <mjordan@digium.com>
Fri, 13 May 2016 12:44:20 +0000 (07:44 -0500)
At one point in time, it seemed like a good idea to use the Asterisk
channel name as the HEP correlation UUID. In particular, it felt like
this would be a useful identifier to tie PJSIP messages and RTCP
messages together, along with whatever other data we may eventually send
to Homer. This also had the benefit of keeping the correlation UUID
channel technology agnostic.

In practice, it isn't as useful as hoped, for two reasons:
1) The first INVITE request received doesn't have a channel. As a
   result, there is always an 'odd message out', leading it to be
   potentially uncorrelated in Homer.
2) Other systems sending capture packets (Kamailio) use the SIP Call-ID.
   This causes RTCP information to be uncorrelated to the SIP message
   traffic seen by those capture nodes.

In order to support both (in case someone is trying to use res_hep_rtcp
with a non-PJSIP channel), this patch adds a new option, uuid_type, with
two valid values - 'call-id' and 'channel'. The uuid_type option is used
by a module to determine the preferred UUID type. When available, that
source of a correlation UUID is used; when not, the more readily available
source is used.

For res_hep_pjsip:
 - uuid_type = call-id: the module uses the SIP Call-ID header value
 - uuid_type = channel: the module uses the channel name if available,
                        falling back to SIP Call-ID if not
For res_hep_rtcp:
 - uuid_type = call-id: the module uses the SIP Call-ID header if the
                        channel type is PJSIP and we have a channel,
                        falling back to the Stasis event provided
                        channel name if not
 - uuid_type = channel: the module uses the channel name

ASTERISK-25352 #close

Change-Id: Ide67e59a52d9c806e3cc0a797ea1a4b88a00122c

CHANGES
configs/samples/hep.conf.sample
include/asterisk/res_hep.h
res/res_hep.c
res/res_hep.exports.in
res/res_hep_pjsip.c
res/res_hep_rtcp.c

diff --git a/CHANGES b/CHANGES
index 965b1b4beac0fef55a08290a1508095ee82a2318..5b38649536ecf043671af84c2da910f7da230997 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -26,6 +26,16 @@ res_pjsip
    into the "reg_server" field in the ps_contacts table to facilitate
    multi-server setups.
 
+res_hep
+------------------
+ * Added a new option, 'uuid_type', that sets the preferred source of the Homer
+   correlation UUID. The valid options are:
+   - call-id: Use the PJSIP SIP Call-ID header value
+   - channel: Use the Asterisk channel name
+   The default value is 'call-id'. In the event that a HEP module cannot find a
+   valid value using the specified 'uuid_type', the module may fallback to a
+   more readily available source for the correlation UUID.
+
 app_confbridge
 ------------------
  * Added a bridge profile option called regcontext that allows you to
index 40b17aa0e34e709229e358bf4a576f4967265c8c..6e409d151c0c2154a52b9eb4534c080520b2d5b8 100644 (file)
@@ -13,4 +13,8 @@ capture_password = foo             ; If specified, the authorization passsword
 capture_id = 1234                  ; A unique integer identifier for this
                                    ; server. This ID will be embedded sent
                                    ; with each packet from this server.
+uuid_type = call-id                ; Specify the preferred source for the Homer
+                                   ; correlation UUID. Valid options are:
+                                   ; - 'call-id' for the PJSIP SIP Call-ID
+                                   ; - 'channel' for the Asterisk channel name
 
index 8839fd60ab9aad62f29220330ee78538721337bf..bd0129eeadac0c0680e335554f62dbc9b89704f7 100644 (file)
@@ -49,6 +49,11 @@ enum hepv3_capture_type {
        HEPV3_CAPTURE_TYPE_IAX    = 0x10,
 };
 
+enum hep_uuid_type {
+       HEP_UUID_TYPE_CALL_ID = 0,
+       HEP_UUID_TYPE_CHANNEL,
+};
+
 /*! \brief HEPv3 Capture Info */
 struct hepv3_capture_info {
        /*! The source address of the packet */
@@ -104,6 +109,15 @@ struct hepv3_capture_info *hepv3_create_capture_info(const void *payload, size_t
  */
 int hepv3_send_packet(struct hepv3_capture_info *capture_info);
 
+/*!
+ * \brief Get the preferred UUID type
+ *
+ * \since 13.10.0
+ *
+ * \retval The type of UUID the packet should use
+ */
+enum hep_uuid_type hepv3_get_uuid_type(void);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
index 69a8ab391549d2a27c4adf7eb851221cf1f81cbd..723b27df84e54b45ea49f8d4a07daee8237775e5 100644 (file)
                                                </enumlist>
                                        </description>
                                </configOption>
+                               <configOption name="uuid_type" default="call-id">
+                                       <synopsis>The preferred type of UUID to pass to Homer.</synopsis>
+                                       <description>
+                                               <enumlist>
+                                                       <enum name="call-id"><para>Use the PJSIP Call-Id</para></enum>
+                                                       <enum name="channel"><para>Use the Asterisk channel name</para></enum>
+                                               </enumlist>
+                                       </description>
+                               </configOption>
                                <configOption name="capture_address" default="192.168.1.1:9061">
                                        <synopsis>The address and port of the Homer server to send packets to.</synopsis>
                                </configOption>
@@ -231,6 +240,7 @@ struct hep_generic {
 struct hepv3_global_config {
        unsigned int enabled;                    /*!< Whether or not sending is enabled */
        unsigned int capture_id;                 /*!< Capture ID for this agent */
+       enum hep_uuid_type uuid_type;            /*!< The preferred type of the UUID */
        AST_DECLARE_STRING_FIELDS(
                AST_STRING_FIELD(capture_address);   /*!< Address to send to */
                AST_STRING_FIELD(capture_password);  /*!< Password for Homer server */
@@ -329,6 +339,25 @@ static void *module_config_alloc(void)
        return config;
 }
 
+/*! \brief Handler for the uuid_type attribute */
+static int uuid_type_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+       struct hepv3_global_config *global_config = obj;
+
+       if (strcasecmp(var->name, "uuid_type")) {
+               return -1;
+       }
+
+       if (!strcasecmp(var->value, "channel")) {
+               global_config->uuid_type = HEP_UUID_TYPE_CHANNEL;
+       } else if (!strcasecmp(var->value, "call-id")) {
+               global_config->uuid_type = HEP_UUID_TYPE_CALL_ID;
+       } else {
+               return -1;
+       }
+       return 0;
+}
+
 /*! \brief HEPv3 run-time data destructor */
 static void hepv3_data_dtor(void *obj)
 {
@@ -376,6 +405,13 @@ static void capture_info_dtor(void *obj)
        ast_free(info->payload);
 }
 
+enum hep_uuid_type hepv3_get_uuid_type(void)
+{
+       RAII_VAR(struct module_config *, config, ao2_global_obj_ref(global_config), ao2_cleanup);
+
+       return config->general->uuid_type;
+}
+
 struct hepv3_capture_info *hepv3_create_capture_info(const void *payload, size_t len)
 {
        struct hepv3_capture_info *info;
@@ -607,6 +643,7 @@ static int load_module(void)
        aco_option_register(&cfg_info, "capture_address", ACO_EXACT, global_options, DEFAULT_HEP_SERVER, OPT_STRINGFIELD_T, 0, STRFLDSET(struct hepv3_global_config, capture_address));
        aco_option_register(&cfg_info, "capture_password", ACO_EXACT, global_options, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct hepv3_global_config, capture_password));
        aco_option_register(&cfg_info, "capture_id", ACO_EXACT, global_options, "0", OPT_UINT_T, 0, STRFLDSET(struct hepv3_global_config, capture_id));
+       aco_option_register_custom(&cfg_info, "uuid_type", ACO_EXACT, global_options, "call-id", uuid_type_handler, 0);
 
        if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
                goto error;
index d09d3f40934b5d4a5104d36920731ccf01c9eb74..df0f2b4f7042573744aabdef3007261844376edc 100644 (file)
@@ -2,6 +2,7 @@
        global:
                LINKER_SYMBOL_PREFIX*hepv3_send_packet;
                LINKER_SYMBOL_PREFIX*hepv3_create_capture_info;
+               LINKER_SYMBOL_PREFIX*hepv3_get_uuid_type;
        local:
                *;
 };
index b5cf0b81e9e52f95bf6bc1a31a882d031adc21d5..caffd256398791eb369828821fffbc449a86f79e 100644 (file)
@@ -51,13 +51,18 @@ static char *assign_uuid(const pj_str_t *call_id, const pj_str_t *local_tag, con
        RAII_VAR(struct ast_sip_session *, session, NULL, ao2_cleanup);
        pjsip_dialog *dlg;
        char *uuid = NULL;
+       enum hep_uuid_type uuid_type = hepv3_get_uuid_type();
 
-       if ((dlg = pjsip_ua_find_dialog(call_id, local_tag, remote_tag, PJ_FALSE))
+       if ((uuid_type == HEP_UUID_TYPE_CHANNEL)
+               && (dlg = pjsip_ua_find_dialog(call_id, local_tag, remote_tag, PJ_FALSE))
            && (session = ast_sip_dialog_get_session(dlg))
            && (session->channel)) {
 
                uuid = ast_strdup(ast_channel_name(session->channel));
-       } else {
+       }
+
+       /* If we couldn't get the channel or we never wanted it, default to the call-id */
+       if (!uuid) {
 
                uuid = ast_malloc(pj_strlen(call_id) + 1);
                if (uuid) {
index 787512bbfe3d963fe45d172f70e6b9dd9ce6200e..49a92539f8ca517e18e901a5b9e8f4cdee3731bc 100644 (file)
@@ -36,6 +36,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/res_hep.h"
 #include "asterisk/module.h"
 #include "asterisk/netsock2.h"
+#include "asterisk/channel.h"
+#include "asterisk/pbx.h"
 #include "asterisk/stasis.h"
 #include "asterisk/rtp_engine.h"
 #include "asterisk/json.h"
@@ -43,6 +45,35 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 static struct stasis_subscription *stasis_rtp_subscription;
 
+static char *assign_uuid(struct ast_json *json_channel)
+{
+       const char *channel_name = ast_json_string_get(ast_json_object_get(json_channel, "name"));
+       enum hep_uuid_type uuid_type = hepv3_get_uuid_type();
+       char *uuid = NULL;
+
+       if (!channel_name) {
+               return NULL;
+       }
+
+       if (uuid_type == HEP_UUID_TYPE_CALL_ID && ast_begins_with(channel_name, "PJSIP")) {
+               struct ast_channel *chan = ast_channel_get_by_name(channel_name);
+               char buf[128];
+
+               if (chan && !ast_func_read(chan, "CHANNEL(pjsip,call-id)", buf, sizeof(buf))) {
+                       uuid = ast_strdup(buf);
+               }
+
+               ast_channel_cleanup(chan);
+       }
+
+       /* If we couldn't get the call-id or didn't want it, just use the channel name */
+       if (!uuid) {
+               uuid = ast_strdup(channel_name);
+       }
+
+       return uuid;
+}
+
 static void rtcp_message_handler(struct stasis_message *message)
 {
 
@@ -94,7 +125,7 @@ static void rtcp_message_handler(struct stasis_message *message)
        ast_sockaddr_parse(&capture_info->src_addr, ast_json_string_get(from), PARSE_PORT_REQUIRE);
        ast_sockaddr_parse(&capture_info->dst_addr, ast_json_string_get(to), PARSE_PORT_REQUIRE);
 
-       capture_info->uuid = ast_strdup(ast_json_string_get(ast_json_object_get(json_channel, "name")));
+       capture_info->uuid = assign_uuid(json_channel);
        if (!capture_info->uuid) {
                ao2_ref(capture_info, -1);
                return;