From 4bf2473ac4ee2f37523745c643f8b09163aa8937 Mon Sep 17 00:00:00 2001 From: Moritz Fain <moritz@fain.io> Date: Tue, 26 Apr 2022 00:40:49 +0200 Subject: [PATCH] ari: expose channel driver's unique id to ARI channel resource This change exposes the channel driver's unique id (i.e. the Call-ID for chan_sip/chan_pjsip based channels) to ARI channel resources as `protocol_id`. ASTERISK-30027 Reported by: Moritz Fain Tested by: Moritz Fain Change-Id: I7cc6e7a9d29efe74bc27811d788dac20fe559b87 --- channels/chan_pjsip.c | 2 +- .../ari_add_pvt_id_to_channel_resource.txt | 7 +++++++ include/asterisk/stasis_channels.h | 1 + main/channel_internal_api.c | 3 +++ main/stasis_channels.c | 11 ++++++++--- res/ari/ari_model_validators.c | 16 ++++++++++++++++ res/ari/ari_model_validators.h | 1 + rest-api/api-docs/channels.json | 5 +++++ tests/test_stasis_channels.c | 3 ++- 9 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 doc/CHANGES-staging/ari_add_pvt_id_to_channel_resource.txt diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index b70b210cec..7c6b301080 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -1273,7 +1273,7 @@ static const char *chan_pjsip_get_uniqueid(struct ast_channel *ast) struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast); char *uniqueid = ast_threadstorage_get(&uniqueid_threadbuf, UNIQUEID_BUFSIZE); - if (!uniqueid) { + if (!channel || !uniqueid) { return ""; } diff --git a/doc/CHANGES-staging/ari_add_pvt_id_to_channel_resource.txt b/doc/CHANGES-staging/ari_add_pvt_id_to_channel_resource.txt new file mode 100644 index 0000000000..a4f008f967 --- /dev/null +++ b/doc/CHANGES-staging/ari_add_pvt_id_to_channel_resource.txt @@ -0,0 +1,7 @@ +Subject: ari +Subject: stasis_channels + +Expose channel driver's unique id (which is the Call-ID for SIP/PJSIP) +to ARI channel resources as 'protocol_id'. + +ASTERISK-30027 diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h index 80c79ebd2e..73771864a6 100644 --- a/include/asterisk/stasis_channels.h +++ b/include/asterisk/stasis_channels.h @@ -112,6 +112,7 @@ struct ast_channel_snapshot_base { ); struct timeval creationtime; /*!< The time of channel creation */ int tech_properties; /*!< Properties of the channel's technology */ + AST_STRING_FIELD_EXTENDED(protocol_id); /*!< Channel driver protocol id (i.e. Call-ID for chan_sip/chan_pjsip) */ }; /*! diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 131faae452..123f61aebd 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -587,6 +587,9 @@ void *ast_channel_tech_pvt(const struct ast_channel *chan) void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value) { chan->tech_pvt = value; + if (value != NULL) { + ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE); + } } void *ast_channel_timingdata(const struct ast_channel *chan) { diff --git a/main/stasis_channels.c b/main/stasis_channels.c index 8becf96f89..d373f6a5ef 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -273,7 +273,7 @@ static struct ast_channel_snapshot_base *channel_snapshot_base_create(struct ast return NULL; } - if (ast_string_field_init(snapshot, 256)) { + if (ast_string_field_init(snapshot, 256) || ast_string_field_init_extended(snapshot, protocol_id)) { ao2_ref(snapshot, -1); return NULL; } @@ -288,6 +288,10 @@ static struct ast_channel_snapshot_base *channel_snapshot_base_create(struct ast snapshot->creationtime = ast_channel_creationtime(chan); snapshot->tech_properties = ast_channel_tech(chan)->properties; + if (ast_channel_tech(chan)->get_pvt_uniqueid) { + ast_string_field_set(snapshot, protocol_id, ast_channel_tech(chan)->get_pvt_uniqueid(chan)); + } + return snapshot; } @@ -1266,14 +1270,15 @@ struct ast_json *ast_channel_snapshot_to_json( } json_chan = ast_json_pack( - /* Broken up into groups of three for readability */ - "{ s: s, s: s, s: s," + /* Broken up into groups for readability */ + "{ s: s, s: s, s: s, s: s," " s: o, s: o, s: s," " s: o, s: o, s: s }", /* First line */ "id", snapshot->base->uniqueid, "name", snapshot->base->name, "state", ast_state2str(snapshot->state), + "protocol_id", snapshot->base->protocol_id, /* Second line */ "caller", ast_json_name_number( snapshot->caller->name, snapshot->caller->number), diff --git a/res/ari/ari_model_validators.c b/res/ari/ari_model_validators.c index 0bbbb195e2..fffb87a162 100644 --- a/res/ari/ari_model_validators.c +++ b/res/ari/ari_model_validators.c @@ -1043,6 +1043,7 @@ int ast_ari_validate_channel(struct ast_json *json) int has_id = 0; int has_language = 0; int has_name = 0; + int has_protocol_id = 0; int has_state = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { @@ -1135,6 +1136,16 @@ int ast_ari_validate_channel(struct ast_json *json) res = 0; } } else + if (strcmp("protocol_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_protocol_id = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI Channel field protocol_id failed validation\n"); + res = 0; + } + } else if (strcmp("state", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_state = 1; @@ -1193,6 +1204,11 @@ int ast_ari_validate_channel(struct ast_json *json) res = 0; } + if (!has_protocol_id) { + ast_log(LOG_ERROR, "ARI Channel missing required field protocol_id\n"); + res = 0; + } + if (!has_state) { ast_log(LOG_ERROR, "ARI Channel missing required field state\n"); res = 0; diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h index 583cba33a4..64f167c07c 100644 --- a/res/ari/ari_model_validators.h +++ b/res/ari/ari_model_validators.h @@ -1353,6 +1353,7 @@ ari_validator ast_ari_validate_application_fn(void); * - id: string (required) * - language: string (required) * - name: string (required) + * - protocol_id: string (required) * - state: string (required) * Dialed * DialplanCEP diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json index 04d1577337..269976dfa4 100644 --- a/rest-api/api-docs/channels.json +++ b/rest-api/api-docs/channels.json @@ -2126,6 +2126,11 @@ "type": "string", "description": "Unique identifier of the channel.\n\nThis is the same as the Uniqueid field in AMI." }, + "protocol_id": { + "required": true, + "type": "string", + "description": "Protocol id from underlying channel driver (i.e. Call-ID for chan_sip/chan_pjsip; will be empty if not applicable or not implemented by driver)." + }, "name": { "required": true, "type": "string", diff --git a/tests/test_stasis_channels.c b/tests/test_stasis_channels.c index d4a05b206f..5ea9dd807c 100644 --- a/tests/test_stasis_channels.c +++ b/tests/test_stasis_channels.c @@ -273,7 +273,7 @@ AST_TEST_DEFINE(channel_snapshot_json) ast_test_validate(test, NULL != snapshot); actual = ast_channel_snapshot_to_json(snapshot, NULL); - expected = ast_json_pack("{ s: s, s: s, s: s, s: s," + expected = ast_json_pack("{ s: s, s: s, s: s, s: s, s: s," " s: { s: s, s: s, s: i, s: s, s: s }," " s: { s: s, s: s }," " s: { s: s, s: s }," @@ -284,6 +284,7 @@ AST_TEST_DEFINE(channel_snapshot_json) "state", "Down", "accountcode", "acctcode", "id", ast_channel_uniqueid(chan), + "protocol_id", "", "dialplan", "context", "context", "exten", "exten", -- GitLab