From 120ac66df9021a122d6a7cb492002a685c137403 Mon Sep 17 00:00:00 2001 From: Mark Michelson <mmichelson@digium.com> Date: Thu, 1 May 2014 16:21:09 +0000 Subject: [PATCH] Make behavior of the PRESENCE_STATE 'e' option more consistent. When writing presence state, if 'e' is specified, then the presence state will be stored in the astdb encoded. However, consumers of presence state events or those that query for the presence state will be given decoded information. If base64 encoding is desired for consumers, then the information can be base64-encoded manually and the 'e' option can be omitted. closes issue ASTERISK-23671 Reported by Mark Michelson Review: https://reviewboard.asterisk.org/r/3482 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@413183 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- funcs/func_presencestate.c | 159 +++++++++++++++++++++++++++++++------ 1 file changed, 133 insertions(+), 26 deletions(-) diff --git a/funcs/func_presencestate.c b/funcs/func_presencestate.c index 8c916e891c..26b311d0e1 100644 --- a/funcs/func_presencestate.c +++ b/funcs/func_presencestate.c @@ -71,7 +71,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <optionlist> <option name="e"> <para>On Write - Use this option when the subtype and message provided are Base64 - encoded. On Read - Retrieves message/subtype in Base64 encoded form.</para> + encoded. The values will be stored encoded within Asterisk, but all consumers of + the presence state (e.g. the SIP presence event package) will receive decoded values.</para> + <para>On Read - Retrieves unencoded message/subtype in Base64 encoded form.</para> </option> </optionlist> </parameter> @@ -229,7 +231,18 @@ static int presence_write(struct ast_channel *chan, const char *cmd, char *data, ast_db_put(astdb_family, data, value); - ast_presence_state_changed_literal(state, subtype, message, tmp); + if (strchr(options, 'e')) { + /* Let's decode the values before sending them to stasis, yes? */ + char decoded_subtype[256] = { 0, }; + char decoded_message[256] = { 0, }; + + ast_base64decode((unsigned char *) decoded_subtype, subtype, sizeof(decoded_subtype) -1); + ast_base64decode((unsigned char *) decoded_message, message, sizeof(decoded_message) -1); + + ast_presence_state_changed_literal(state, decoded_subtype, decoded_message, tmp); + } else { + ast_presence_state_changed_literal(state, subtype, message, tmp); + } return 0; } @@ -643,12 +656,39 @@ AST_TEST_DEFINE(test_invalid_parse_data) return res; } +#define PRES_STATE "away" +#define PRES_SUBTYPE "down the hall" +#define PRES_MESSAGE "Quarterly financial meeting" + struct test_cb_data { struct ast_presence_state_message *presence_state; /* That's right. I'm using a semaphore */ sem_t sem; }; +static struct test_cb_data *test_cb_data_alloc(void) +{ + struct test_cb_data *cb_data = ast_calloc(1, sizeof(*cb_data)); + + if (!cb_data) { + return NULL; + } + + if (sem_init(&cb_data->sem, 0, 0)) { + ast_free(cb_data); + return NULL; + } + + return cb_data; +} + +static void test_cb_data_destroy(struct test_cb_data *cb_data) +{ + ao2_cleanup(cb_data->presence_state); + sem_destroy(&cb_data->sem); + ast_free(cb_data); +} + static void test_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg) { struct test_cb_data *cb_data = userdata; @@ -661,15 +701,48 @@ static void test_cb(void *userdata, struct stasis_subscription *sub, struct stas sem_post(&cb_data->sem); } -/* XXX This test could probably stand to be moved since - * it does not test func_presencestate but rather code in - * presencestate.h and presencestate.c. However, the convenience - * of presence_write() makes this a nice location for this test. - */ -AST_TEST_DEFINE(test_presence_state_change) +static enum ast_test_result_state presence_change_common(struct ast_test *test, + const char *state, const char *subtype, const char *message, const char *options, + char *out_state, size_t out_state_size, + char *out_subtype, size_t out_subtype_size, + char *out_message, size_t out_message_size) { + RAII_VAR(struct test_cb_data *, cb_data, test_cb_data_alloc(), test_cb_data_destroy); struct stasis_subscription *test_sub; - struct test_cb_data *cb_data; + char pres[1301]; + + if (!(test_sub = stasis_subscribe(ast_presence_state_topic_all(), test_cb, cb_data))) { + return AST_TEST_FAIL; + } + + if (ast_strlen_zero(options)) { + snprintf(pres, sizeof(pres), "%s,%s,%s", state, subtype, message); + } else { + snprintf(pres, sizeof(pres), "%s,%s,%s,%s", state, subtype, message, options); + } + + if (presence_write(NULL, "PRESENCESTATE", "CustomPresence:TestPresenceStateChange", pres)) { + test_sub = stasis_unsubscribe_and_join(test_sub); + return AST_TEST_FAIL; + } + + sem_wait(&cb_data->sem); + + ast_copy_string(out_state, ast_presence_state2str(cb_data->presence_state->state), out_state_size); + ast_copy_string(out_subtype, cb_data->presence_state->subtype, out_subtype_size); + ast_copy_string(out_message, cb_data->presence_state->message, out_message_size); + + test_sub = stasis_unsubscribe_and_join(test_sub); + ast_db_del("CustomPresence", "TestPresenceStateChange"); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(test_presence_state_change) +{ + char out_state[32]; + char out_subtype[32]; + char out_message[32]; switch (cmd) { case TEST_INIT: @@ -683,34 +756,66 @@ AST_TEST_DEFINE(test_presence_state_change) break; } - cb_data = ast_calloc(1, sizeof(*cb_data)); - if (!cb_data) { + if (presence_change_common(test, PRES_STATE, PRES_SUBTYPE, PRES_MESSAGE, NULL, + out_state, sizeof(out_state), + out_subtype, sizeof(out_subtype), + out_message, sizeof(out_message)) == AST_TEST_FAIL) { return AST_TEST_FAIL; } - if (!(test_sub = stasis_subscribe(ast_presence_state_topic_all(), test_cb, cb_data))) { + if (strcmp(out_state, PRES_STATE) || + strcmp(out_subtype, PRES_SUBTYPE) || + strcmp(out_message, PRES_MESSAGE)) { + ast_test_status_update(test, "Unexpected presence values, %s != %s, %s != %s, or %s != %s\n", + PRES_STATE, out_state, + PRES_SUBTYPE, out_subtype, + PRES_MESSAGE, out_message); return AST_TEST_FAIL; } - if (sem_init(&cb_data->sem, 0, 0)) { - return AST_TEST_FAIL; - } + return AST_TEST_PASS; +} - presence_write(NULL, "PRESENCESTATE", "CustomPresence:TestPresenceStateChange", "away,down the hall,Quarterly financial meeting"); - sem_wait(&cb_data->sem); - if (cb_data->presence_state->state != AST_PRESENCE_AWAY || - strcmp(cb_data->presence_state->provider, "CustomPresence:TestPresenceStateChange") || - strcmp(cb_data->presence_state->subtype, "down the hall") || - strcmp(cb_data->presence_state->message, "Quarterly financial meeting")) { - return AST_TEST_FAIL; +AST_TEST_DEFINE(test_presence_state_base64_encode) +{ + char out_state[32]; + char out_subtype[32]; + char out_message[32]; + char encoded_subtype[64]; + char encoded_message[64]; + + switch (cmd) { + case TEST_INIT: + info->name = "test_presence_state_base64_encode"; + info->category = "/funcs/func_presence/"; + info->summary = "presence state base64 encoding"; + info->description = + "Ensure that base64-encoded presence state is stored base64-encoded but\n" + "is presented to consumers decoded."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; } - test_sub = stasis_unsubscribe_and_join(test_sub); + ast_base64encode(encoded_subtype, (unsigned char *) PRES_SUBTYPE, strlen(PRES_SUBTYPE), sizeof(encoded_subtype) - 1); + ast_base64encode(encoded_message, (unsigned char *) PRES_MESSAGE, strlen(PRES_MESSAGE), sizeof(encoded_message) - 1); - ao2_cleanup(cb_data->presence_state); - ast_free((char *)cb_data); + if (presence_change_common(test, PRES_STATE, encoded_subtype, encoded_message, "e", + out_state, sizeof(out_state), + out_subtype, sizeof(out_subtype), + out_message, sizeof(out_message)) == AST_TEST_FAIL) { + return AST_TEST_FAIL; + } - ast_db_del("CustomPresence", "TestPresenceStateChange"); + if (strcmp(out_state, PRES_STATE) || + strcmp(out_subtype, PRES_SUBTYPE) || + strcmp(out_message, PRES_MESSAGE)) { + ast_test_status_update(test, "Unexpected presence values, %s != %s, %s != %s, or %s != %s\n", + PRES_STATE, out_state, + PRES_SUBTYPE, out_subtype, + PRES_MESSAGE, out_message); + return AST_TEST_FAIL; + } return AST_TEST_PASS; } @@ -728,6 +833,7 @@ static int unload_module(void) AST_TEST_UNREGISTER(test_valid_parse_data); AST_TEST_UNREGISTER(test_invalid_parse_data); AST_TEST_UNREGISTER(test_presence_state_change); + AST_TEST_UNREGISTER(test_presence_state_base64_encode); #endif return res; } @@ -767,6 +873,7 @@ static int load_module(void) AST_TEST_REGISTER(test_valid_parse_data); AST_TEST_REGISTER(test_invalid_parse_data); AST_TEST_REGISTER(test_presence_state_change); + AST_TEST_REGISTER(test_presence_state_base64_encode); #endif return res; -- GitLab