diff options
author | Mark Michelson <mmichelson@digium.com> | 2014-02-17 15:36:45 +0000 |
---|---|---|
committer | Mark Michelson <mmichelson@digium.com> | 2014-02-17 15:36:45 +0000 |
commit | ed66eefdf0f0974c5b403dff501108b122f230b2 (patch) | |
tree | 32ac4a90c07f5fb89c0dd57926270ae4c0bb2bb1 | |
parent | 438a7abc279bbcd6e0e770b72d5023555a86c7fd (diff) |
Store SIP User-Agent information in contacts.
When an endpoint sends a REGISTER request to Asterisk, we now will
associate the User-Agent header with all contacts that were bound in
that REGISTER request.
........
Merged revisions 408270 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@408272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | UPGRADE.txt | 8 | ||||
-rw-r--r-- | include/asterisk/res_pjsip.h | 5 | ||||
-rw-r--r-- | res/res_pjsip.c | 7 | ||||
-rw-r--r-- | res/res_pjsip/location.c | 8 | ||||
-rw-r--r-- | res/res_pjsip_registrar.c | 50 |
5 files changed, 66 insertions, 12 deletions
diff --git a/UPGRADE.txt b/UPGRADE.txt index 9712c49ea..b996f072c 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -20,6 +20,14 @@ === UPGRADE-11.txt -- Upgrade info for 10 to 11 === UPGRADE-12.txt -- Upgrade info for 11 to 12 =========================================================== +From 12.1.0 to 12.2.0: +PJSIP: + - The PJSIP registrar now stores the contents of the User-Agent header of incoming + REGISTER requests for each contact that is registered. If using realtime for + PJSIP contacts, this means that the schema has been updated to add a user_agent + column. An alembic revision has been added to facilitate this update. + +From 12.0.0 to 12.1.0: * The sound_place_into_conference sound used in Confbridge is now deprecated and is no longer functional since it has been broken since its inception and the fix involved using a different method to achieve the same goal. The diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 82f942ba1..80919c7d8 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -153,6 +153,8 @@ struct ast_sip_contact { AST_STRING_FIELD(outbound_proxy); /*! Path information to place in Route headers */ AST_STRING_FIELD(path); + /*! Content of the User-Agent header in REGISTER request */ + AST_STRING_FIELD(user_agent); ); /*! Absolute time that this contact is no longer valid after */ struct timeval expiration_time; @@ -905,12 +907,13 @@ struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_na * \param uri Full contact URI * \param expiration_time Optional expiration time of the contact * \param path_info Path information + * \param user_agent User-Agent header from REGISTER request * * \retval -1 failure * \retval 0 success */ int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, - struct timeval expiration_time, const char *path_info); + struct timeval expiration_time, const char *path_info, const char *user_agent); /*! * \brief Update a contact diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 3ad482dab..7406c2351 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -897,6 +897,13 @@ <configOption name="path"> <synopsis>Stored Path vector for use in Route headers on outgoing requests.</synopsis> </configOption> + <configOption name="user_agent"> + <synopsis>User-Agent header from registration.</synopsis> + <description><para> + The User-Agent is automatically stored based on data present in incoming SIP + REGISTER requests and is not intended to be configured manually. + </para></description> + </configOption> </configObject> <configObject name="aor"> <synopsis>The configuration for a location of an endpoint</synopsis> diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index fbc48fe9b..882628669 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -178,7 +178,8 @@ struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_na return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "contact", contact_name); } -int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info) +int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, + struct timeval expiration_time, const char *path_info, const char *user_agent) { char name[AST_UUID_STR_LEN]; RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup); @@ -201,6 +202,10 @@ int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struc ast_string_field_set(contact, outbound_proxy, aor->outbound_proxy); } + if (!ast_strlen_zero(user_agent)) { + ast_string_field_set(contact, user_agent, user_agent); + } + return ast_sorcery_create(ast_sip_get_sorcery(), contact); } @@ -665,6 +670,7 @@ int ast_sip_initialize_sorcery_location(void) ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400); ast_sorcery_object_field_register(sorcery, "contact", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, outbound_proxy)); + ast_sorcery_object_field_register(sorcery, "contact", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, user_agent)); ast_sorcery_object_field_register(sorcery, "aor", "type", "", OPT_NOOP_T, 0, 0); ast_sorcery_object_field_register(sorcery, "aor", "minimum_expiration", "60", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, minimum_expiration)); diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c index 7624472fc..5f020873b 100644 --- a/res/res_pjsip_registrar.c +++ b/res/res_pjsip_registrar.c @@ -170,9 +170,11 @@ static int registrar_delete_contact(void *obj, void *arg, int flags) ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact->uri, aor_name); ast_test_suite_event_notify("AOR_CONTACT_REMOVED", "Contact: %s\r\n" - "AOR: %s", + "AOR: %s\r\n" + "UserAgent: %s", contact->uri, - aor_name); + aor_name, + contact->user_agent); } return 0; @@ -407,6 +409,8 @@ static int registrar_validate_path(struct rx_task_data *task_data, struct ast_st static int rx_task(void *data) { + static const pj_str_t USER_AGENT = { "User-Agent", 10 }; + RAII_VAR(struct rx_task_data *, task_data, data, ao2_cleanup); RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup); @@ -418,6 +422,8 @@ static int rx_task(void *data) const char *aor_name = ast_sorcery_object_get_id(task_data->aor); RAII_VAR(struct ast_str *, path_str, NULL, ast_free); struct ast_sip_contact *response_contact; + char *user_agent = NULL; + pjsip_user_agent_hdr *user_agent_hdr; /* Retrieve the current contacts, we'll need to know whether to update or not */ contacts = ast_sip_location_retrieve_aor_contacts(task_data->aor); @@ -456,6 +462,13 @@ static int rx_task(void *data) return PJ_TRUE; } + user_agent_hdr = pjsip_msg_find_hdr_by_name(task_data->rdata->msg_info.msg, &USER_AGENT, NULL); + if (user_agent_hdr) { + size_t alloc_size = pj_strlen(&user_agent_hdr->hvalue) + 1; + user_agent = ast_alloca(alloc_size); + ast_copy_pj_str(user_agent, &user_agent_hdr->hvalue, alloc_size); + } + /* Iterate each provided Contact header and add, update, or delete */ while ((contact_hdr = pjsip_msg_find_hdr(task_data->rdata->msg_info.msg, PJSIP_H_CONTACT, contact_hdr ? contact_hdr->next : NULL))) { int expiration; @@ -485,17 +498,25 @@ static int rx_task(void *data) continue; } - ast_sip_location_add_contact(task_data->aor, contact_uri, ast_tvadd(ast_tvnow(), - ast_samp2tv(expiration, 1)), path_str ? ast_str_buffer(path_str) : NULL); + if (ast_sip_location_add_contact(task_data->aor, contact_uri, ast_tvadd(ast_tvnow(), + ast_samp2tv(expiration, 1)), path_str ? ast_str_buffer(path_str) : NULL, + user_agent)) { + ast_log(LOG_ERROR, "Unable to bind contact '%s' to AOR '%s'\n", + contact_uri, aor_name); + continue; + } + ast_verb(3, "Added contact '%s' to AOR '%s' with expiration of %d seconds\n", contact_uri, aor_name, expiration); ast_test_suite_event_notify("AOR_CONTACT_ADDED", "Contact: %s\r\n" "AOR: %s\r\n" - "Expiration: %d", + "Expiration: %d\r\n" + "UserAgent: %s", contact_uri, aor_name, - expiration); + expiration, + user_agent); } else if (expiration) { RAII_VAR(struct ast_sip_contact *, updated, ast_sorcery_copy(ast_sip_get_sorcery(), contact), ao2_cleanup); updated->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1)); @@ -504,6 +525,9 @@ static int rx_task(void *data) if (path_str) { ast_string_field_set(updated, path, ast_str_buffer(path_str)); } + if (user_agent) { + ast_string_field_set(updated, user_agent, user_agent); + } ast_sip_location_update_contact(updated); ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n", @@ -511,18 +535,24 @@ static int rx_task(void *data) ast_test_suite_event_notify("AOR_CONTACT_REFRESHED", "Contact: %s\r\n" "AOR: %s\r\n" - "Expiration: %d", + "Expiration: %d\r\n" + "UserAgent: %s", contact_uri, aor_name, - expiration); + expiration, + updated->user_agent); } else { + /* We want to report the user agent that was actually in the removed contact */ + user_agent = ast_strdupa(contact->user_agent); ast_sip_location_delete_contact(contact); ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact_uri, aor_name); ast_test_suite_event_notify("AOR_CONTACT_REMOVED", "Contact: %s\r\n" - "AOR: %s", + "AOR: %s\r\n" + "UserAgent: %s", contact_uri, - aor_name); + aor_name, + user_agent); } } |