res_pjsip_transport_websocket: Fix security events and simplify implementation.
[asterisk/asterisk.git] / res / res_pjsip / location.c
index 8569e7a..14f5855 100644 (file)
@@ -26,9 +26,6 @@
 #include "asterisk/sorcery.h"
 #include "include/res_pjsip_private.h"
 
-#define CONTACT_TRANSPORTS_BUCKETS 7
-static struct ao2_container *contact_transports;
-
 /*! \brief Destructor for AOR */
 static void aor_destroy(void *obj)
 {
@@ -74,48 +71,6 @@ static void *contact_alloc(const char *name)
        return contact;
 }
 
-/*! \brief Callback function for finding a contact_transport by URI */
-static int contact_transport_find_by_uri(void *obj, void *arg, int flags)
-{
-       struct ast_sip_contact_transport *ct = obj;
-       const char *contact_uri = arg;
-
-       return (!strcmp(ct->uri, contact_uri)) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-/*! \brief Callback function for finding a contact_transport by transport */
-static int contact_transport_find_by_transport(void *obj, void *arg, int flags)
-{
-       struct ast_sip_contact_transport *ct = obj;
-       pjsip_transport *transport = arg;
-
-       return (ct->transport == transport) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-void ast_sip_location_add_contact_transport(struct ast_sip_contact_transport *ct)
-{
-       ao2_link(contact_transports, ct);
-
-       return;
-}
-
-void ast_sip_location_delete_contact_transport(struct ast_sip_contact_transport *ct)
-{
-       ao2_unlink(contact_transports, ct);
-
-       return;
-}
-
-struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_uri(const char *contact_uri)
-{
-       return ao2_callback(contact_transports, 0, contact_transport_find_by_uri, (void *)contact_uri);
-}
-
-struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_transport(pjsip_transport *transport)
-{
-       return ao2_callback(contact_transports, 0, contact_transport_find_by_transport, transport);
-}
-
 struct ast_sip_aor *ast_sip_location_retrieve_aor(const char *aor_name)
 {
        return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
@@ -300,6 +255,123 @@ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variab
        return 0;
 }
 
+int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
+{
+       char *copy, *name;
+
+       if (!on_aor || ast_strlen_zero(aors)) {
+               return 0;
+       }
+
+       copy = ast_strdupa(aors);
+       while ((name = strsep(&copy, ","))) {
+               RAII_VAR(struct ast_sip_aor *, aor,
+                        ast_sip_location_retrieve_aor(name), ao2_cleanup);
+
+               if (!aor) {
+                       continue;
+               }
+
+               if (on_aor(aor, arg, 0)) {
+                       return -1;
+               }
+       }
+       ast_free(copy);
+       return 0;
+}
+
+int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
+                            on_contact_t on_contact, void *arg)
+{
+       RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
+       struct ast_sip_contact *contact;
+       int num;
+       struct ao2_iterator i;
+
+       if (!on_contact ||
+           !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
+               return 0;
+       }
+
+       num = ao2_container_count(contacts);
+       i = ao2_iterator_init(contacts, 0);
+       while ((contact = ao2_iterator_next(&i))) {
+               int res = on_contact(aor, contact, --num == 0, arg);
+
+               ao2_ref(contact, -1);
+               if (res) {
+                       return -1;
+               }
+       }
+       ao2_iterator_destroy(&i);
+       return 0;
+}
+
+int ast_sip_contact_to_str(const struct ast_sip_aor *aor,
+                          const struct ast_sip_contact *contact,
+                          int last, void *arg)
+{
+       struct ast_str **buf = arg;
+
+       ast_str_append(buf, 0, "%s/%s",
+                      ast_sorcery_object_get_id(aor), contact->uri);
+
+       if (!last) {
+               ast_str_append(buf, 0, ",");
+       }
+
+       return 0;
+}
+
+static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
+{
+       return ast_sip_sorcery_object_to_ami(aor, buf);
+}
+
+static int format_ami_aor_handler(void *obj, void *arg, int flags)
+{
+       const struct ast_sip_aor *aor = obj;
+       struct ast_sip_ami *ami = arg;
+       const struct ast_sip_endpoint *endpoint = ami->arg;
+       RAII_VAR(struct ast_str *, buf,
+                ast_sip_create_ami_event("AorDetail", ami), ast_free);
+
+       int num;
+       RAII_VAR(struct ao2_container *, contacts,
+                ast_sip_location_retrieve_aor_contacts(aor), ao2_cleanup);
+
+       if (!buf) {
+               return -1;
+       }
+
+       sip_aor_to_ami(aor, &buf);
+       ast_str_append(&buf, 0, "Contacts: ");
+       ast_sip_for_each_contact(aor, ast_sip_contact_to_str, &buf);
+       ast_str_append(&buf, 0, "\r\n");
+
+       num = ao2_container_count(contacts);
+       ast_str_append(&buf, 0, "TotalContacts: %d\r\n", num);
+       ast_str_append(&buf, 0, "ContactsRegistered: %d\r\n",
+                      num - ao2_container_count(aor->permanent_contacts));
+       ast_str_append(&buf, 0, "EndpointName: %s\r\n",
+                      ast_sorcery_object_get_id(endpoint));
+
+       astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+       return 0;
+}
+
+static int format_ami_endpoint_aor(const struct ast_sip_endpoint *endpoint,
+                                  struct ast_sip_ami *ami)
+{
+       ami->arg = (void *)endpoint;
+       return ast_sip_for_each_aor(endpoint->aors,
+                                   format_ami_aor_handler, ami);
+}
+
+struct ast_sip_endpoint_formatter endpoint_aor_formatter = {
+       .format_ami = format_ami_endpoint_aor
+};
+
 /*! \brief Initialize sorcery with location support */
 int ast_sip_initialize_sorcery_location(struct ast_sorcery *sorcery)
 {
@@ -328,19 +400,7 @@ int ast_sip_initialize_sorcery_location(struct ast_sorcery *sorcery)
        ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, NULL, 0, 0);
        ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes));
 
+       ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
        return 0;
 }
 
-int ast_res_pjsip_init_contact_transports(void)
-{
-       if (contact_transports) {
-               ao2_t_ref(contact_transports, -1, "Remove old contact transports");
-       }
-
-       contact_transports = ao2_t_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CONTACT_TRANSPORTS_BUCKETS, NULL, NULL, "Create container for contact transports");
-       if (!contact_transports) {
-               return -1;
-       }
-
-       return 0;
-}