about summary refs log tree commit diff stats
path: root/src/xmpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmpp')
-rw-r--r--src/xmpp/bookmark.c7
-rw-r--r--src/xmpp/iq.c13
-rw-r--r--src/xmpp/message.c31
-rw-r--r--src/xmpp/omemo.c39
-rw-r--r--src/xmpp/stanza.c51
-rw-r--r--src/xmpp/stanza.h6
-rw-r--r--src/xmpp/xmpp.h1
7 files changed, 133 insertions, 15 deletions
diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c
index 65c3bd01..4e40e3ec 100644
--- a/src/xmpp/bookmark.c
+++ b/src/xmpp/bookmark.c
@@ -225,6 +225,13 @@ bookmark_remove(const char* jid)
     return TRUE;
 }
 
+Bookmark*
+bookmark_get_by_jid(const char* jid)
+{
+    Bookmark* bookmark = g_hash_table_lookup(bookmarks, jid);
+    return bookmark;
+}
+
 GList*
 bookmark_get_list(void)
 {
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index beecb97e..19b620e2 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -2308,6 +2308,8 @@ _disco_info_response_id_handler(xmpp_stanza_t* const stanza, void* const userdat
         GSList* features = NULL;
         while (child) {
             const char* stanza_name = xmpp_stanza_get_name(child);
+            const char* child_type = xmpp_stanza_get_type(child);
+
             if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) {
                 const char* var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR);
                 if (var) {
@@ -2315,10 +2317,9 @@ _disco_info_response_id_handler(xmpp_stanza_t* const stanza, void* const userdat
                 }
             } else if (g_strcmp0(stanza_name, STANZA_NAME_IDENTITY) == 0) {
                 const char* name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
-                const char* type = xmpp_stanza_get_type(child);
                 const char* category = xmpp_stanza_get_attribute(child, STANZA_ATTR_CATEGORY);
 
-                if (name || category || type) {
+                if (name || category || child_type) {
                     DiscoIdentity* identity = malloc(sizeof(struct disco_identity_t));
 
                     if (identity) {
@@ -2332,8 +2333,8 @@ _disco_info_response_id_handler(xmpp_stanza_t* const stanza, void* const userdat
                         } else {
                             identity->category = NULL;
                         }
-                        if (type) {
-                            identity->type = strdup(type);
+                        if (child_type) {
+                            identity->type = strdup(child_type);
                         } else {
                             identity->type = NULL;
                         }
@@ -2341,6 +2342,10 @@ _disco_info_response_id_handler(xmpp_stanza_t* const stanza, void* const userdat
                         identities = g_slist_append(identities, identity);
                     }
                 }
+            } else if (g_strcmp0(child_type, STANZA_TYPE_RESULT) == 0) {
+                GHashTable *adr = stanza_get_service_contact_addresses(connection_get_ctx(), child);
+                cons_show_disco_contact_information(adr);
+                g_hash_table_destroy(adr);
             }
 
             child = xmpp_stanza_get_next(child);
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index 4f093bcf..e14ae07d 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -93,6 +93,7 @@ static void _send_message_stanza(xmpp_stanza_t* const stanza);
 static gboolean _handle_mam(xmpp_stanza_t* const stanza);
 static void _handle_pubsub(xmpp_stanza_t* const stanza, xmpp_stanza_t* const event);
 static gboolean _handle_form(xmpp_stanza_t* const stanza);
+static gboolean _handle_jingle_message(xmpp_stanza_t* const stanza);
 
 #ifdef HAVE_LIBGPGME
 static xmpp_stanza_t* _openpgp_signcrypt(xmpp_ctx_t* ctx, const char* const to, const char* const text);
@@ -167,9 +168,14 @@ _message_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* con
         _handle_groupchat(stanza);
     } else if (type && g_strcmp0(type, STANZA_TYPE_HEADLINE) == 0) {
         _handle_headline(stanza);
-    } else if (type == NULL || g_strcmp0(type, STANZA_TYPE_CHAT) != 0 || g_strcmp0(type, STANZA_TYPE_NORMAL) != 0) {
+    } else if (type == NULL || g_strcmp0(type, STANZA_TYPE_CHAT) == 0 || g_strcmp0(type, STANZA_TYPE_NORMAL) == 0) {
         // type: chat, normal (==NULL)
 
+        // XEP-0353: Jingle Message Initiation
+        if (_handle_jingle_message(stanza)) {
+            return 1;
+        }
+
         // XEP-0045: Multi-User Chat 8.6 Voice Requests
         if (_handle_form(stanza)) {
             return 1;
@@ -624,6 +630,7 @@ message_send_chat_omemo(const char* const jid, uint32_t sid, GList* keys,
     xmpp_stanza_t* header = xmpp_stanza_new(ctx);
     xmpp_stanza_set_name(header, "header");
     char* sid_text = g_strdup_printf("%d", sid);
+    log_debug("[OMEMO] Sending from device sid %s", sid_text);
     xmpp_stanza_set_attribute(header, "sid", sid_text);
     g_free(sid_text);
 
@@ -634,6 +641,7 @@ message_send_chat_omemo(const char* const jid, uint32_t sid, GList* keys,
         xmpp_stanza_t* key_stanza = xmpp_stanza_new(ctx);
         xmpp_stanza_set_name(key_stanza, "key");
         char* rid = g_strdup_printf("%d", key->device_id);
+        log_debug("[OMEMO] Sending to device rid %s", rid == NULL ? "NULL" : rid );
         xmpp_stanza_set_attribute(key_stanza, "rid", rid);
         g_free(rid);
         if (key->prekey) {
@@ -1084,7 +1092,7 @@ _handle_groupchat(xmpp_stanza_t* const stanza)
 #endif
 
     if (!message->plain && !message->body) {
-        log_error("Message received without body for room: %s", from_jid->str);
+        log_info("Message received without body for room: %s", from_jid->str);
         goto out;
     } else if (!message->plain) {
         message->plain = strdup(message->body);
@@ -1242,7 +1250,7 @@ _handle_muc_private_message(xmpp_stanza_t* const stanza)
     message->body = xmpp_message_get_body(stanza);
 
     if (!message->plain && !message->body) {
-        log_error("Message received without body from: %s", message->from_jid->str);
+        log_info("Message received without body from: %s", message->from_jid->str);
         goto out;
     } else if (!message->plain) {
         message->plain = strdup(message->body);
@@ -1662,3 +1670,20 @@ message_request_voice(const char* const roomjid)
     _send_message_stanza(stanza);
     xmpp_stanza_release(stanza);
 }
+
+static gboolean
+_handle_jingle_message(xmpp_stanza_t* const stanza)
+{
+    xmpp_stanza_t* propose = xmpp_stanza_get_child_by_name_and_ns(stanza, STANZA_NAME_PROPOSE, STANZA_NS_JINGLE_MESSAGE);
+
+    if (propose) {
+        xmpp_stanza_t* description = xmpp_stanza_get_child_by_ns(propose, STANZA_NS_JINGLE_RTP);
+        if (description) {
+            const char* const from = xmpp_stanza_get_from(stanza);
+            cons_show("Ring ring: %s is trying to call you", from);
+            cons_alert(NULL);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c
index be81ba62..54cd12ad 100644
--- a/src/xmpp/omemo.c
+++ b/src/xmpp/omemo.c
@@ -51,6 +51,8 @@ static int _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const
 static int _omemo_bundle_publish_configure(xmpp_stanza_t* const stanza, void* const userdata);
 static int _omemo_bundle_publish_configure_result(xmpp_stanza_t* const stanza, void* const userdata);
 
+static int _omemo_device_list_publish_result(xmpp_stanza_t* const stanza, void* const userdata);
+
 void
 omemo_devicelist_subscribe(void)
 {
@@ -65,12 +67,14 @@ omemo_devicelist_publish(GList* device_list)
     xmpp_ctx_t* const ctx = connection_get_ctx();
     xmpp_stanza_t* iq = stanza_create_omemo_devicelist_publish(ctx, device_list);
 
-    log_info("[OMEMO] publish device list");
+    log_debug("[OMEMO] publish device list");
 
     if (connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) {
         stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open");
     }
 
+    iq_id_handler_add(xmpp_stanza_get_id(iq), _omemo_device_list_publish_result, NULL, NULL);
+
     iq_send_stanza(iq);
     xmpp_stanza_release(iq);
 }
@@ -81,7 +85,7 @@ omemo_devicelist_request(const char* const jid)
     xmpp_ctx_t* const ctx = connection_get_ctx();
     char* id = connection_create_stanza_id();
 
-    log_info("[OMEMO] request device list for jid: %s", jid);
+    log_debug("[OMEMO] request device list for jid: %s", jid);
 
     xmpp_stanza_t* iq = stanza_create_omemo_devicelist_request(ctx, id, jid);
     iq_id_handler_add(id, _omemo_receive_devicelist, NULL, NULL);
@@ -95,7 +99,7 @@ omemo_devicelist_request(const char* const jid)
 void
 omemo_bundle_publish(gboolean first)
 {
-    log_info("[OMEMO] publish own OMEMO bundle");
+    log_debug("[OMEMO] publish own OMEMO bundle");
     xmpp_ctx_t* const ctx = connection_get_ctx();
     unsigned char* identity_key = NULL;
     size_t identity_key_length;
@@ -144,7 +148,7 @@ omemo_bundle_request(const char* const jid, uint32_t device_id, ProfIqCallback f
     xmpp_ctx_t* const ctx = connection_get_ctx();
     char* id = connection_create_stanza_id();
 
-    log_info("[OMEMO] request omemo bundle (jid: %s, deivce: %d)", jid, device_id);
+    log_debug("[OMEMO] request omemo bundle (jid: %s, device: %d)", jid, device_id);
 
     xmpp_stanza_t* iq = stanza_create_omemo_bundle_request(ctx, id, jid, device_id);
     iq_id_handler_add(id, func, free_func, userdata);
@@ -164,6 +168,12 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t* const stanza, void* cons
     char* from = NULL;
 
     const char* from_attr = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+    log_debug("[OMEMO] omemo_start_device_session_handle_bundle: %s", from_attr);
+
+    const char* type = xmpp_stanza_get_type(stanza);
+    if ( g_strcmp0( type, "error") == 0 ) {
+        log_error("[OMEMO] Error to get key for a device from : %s", from_attr);
+    }
 
     if (!from_attr) {
         Jid* jid = jid_create(connection_get_fulljid());
@@ -193,6 +203,7 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t* const stanza, void* cons
     }
 
     uint32_t device_id = strtoul(++device_id_str, NULL, 10);
+    log_debug("[OMEMO] omemo_start_device_session_handle_bundle: %d", device_id);
 
     xmpp_stanza_t* item = xmpp_stanza_get_child_by_name(items, "item");
     if (!item) {
@@ -510,7 +521,7 @@ _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata)
     const char* type = xmpp_stanza_get_type(stanza);
 
     if (g_strcmp0(type, STANZA_TYPE_RESULT) == 0) {
-        log_info("[OMEMO] bundle published successfully");
+        log_debug("[OMEMO] bundle published successfully");
         return 0;
     }
 
@@ -519,12 +530,12 @@ _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata)
         return 0;
     }
 
-    log_info("[OMEMO] cannot publish bundle with open access model, trying to configure node");
+    log_debug("[OMEMO] cannot publish bundle with open access model, trying to configure node");
     xmpp_ctx_t* const ctx = connection_get_ctx();
     Jid* jid = jid_create(connection_get_fulljid());
     char* id = connection_create_stanza_id();
     char* node = g_strdup_printf("%s:%d", STANZA_NS_OMEMO_BUNDLES, omemo_device_id());
-    log_info("[OMEMO] node: %s", node);
+    log_debug("[OMEMO] node: %s", node);
 
     xmpp_stanza_t* iq = stanza_create_pubsub_configure_request(ctx, id, jid->barejid, node);
     g_free(node);
@@ -594,10 +605,22 @@ _omemo_bundle_publish_configure_result(xmpp_stanza_t* const stanza, void* const
         return 0;
     }
 
-    log_info("[OMEMO] node configured");
+    log_debug("[OMEMO] node configured");
 
     // Try to publish again
     omemo_bundle_publish(TRUE);
 
     return 0;
 }
+
+static int
+_omemo_device_list_publish_result(xmpp_stanza_t* const stanza, void* const userdata)
+{
+    const char* type = xmpp_stanza_get_type(stanza);
+    if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
+        cons_show_error("Unable to publish own OMEMO device list");
+        log_error("[OMEMO] Publishing device list failed");
+        return 0;
+    }
+    return 0;
+}
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 235a7dee..604d4003 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -2838,3 +2838,54 @@ stanza_create_muc_register_nick(xmpp_ctx_t* ctx, const char* const id, const cha
 
     return iq;
 }
+
+static void
+_contact_addresses_list_free(GSList* list)
+{
+    if (list) {
+        g_slist_free_full(list, g_free);
+    }
+}
+
+GHashTable*
+stanza_get_service_contact_addresses(xmpp_ctx_t* ctx, xmpp_stanza_t* stanza)
+{
+    GHashTable* addresses = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_contact_addresses_list_free);
+
+    xmpp_stanza_t* fields = xmpp_stanza_get_children(stanza);
+    while (fields) {
+        const char* child_name = xmpp_stanza_get_name(fields);
+        const char* child_type = xmpp_stanza_get_type(fields);
+
+        if (g_strcmp0(child_name, STANZA_NAME_FIELD) == 0 && g_strcmp0(child_type, STANZA_TYPE_LIST_MULTI) == 0) {
+            // extract key (eg 'admin-addresses')
+            const char* var = xmpp_stanza_get_attribute(fields, STANZA_ATTR_VAR );
+
+            // extract values (a list of contact addresses eg mailto:xmpp@shakespeare.lit, xmpp:admins@shakespeare.lit)
+            xmpp_stanza_t* values = xmpp_stanza_get_children(fields);
+            GSList* val_list = NULL;
+            while (values) {
+                const char* value_name = xmpp_stanza_get_name(values);
+                if (value_name && (g_strcmp0(value_name, STANZA_NAME_VALUE) == 0)) {
+                    char* value_text = xmpp_stanza_get_text(values);
+                    if (value_text) {
+                        val_list = g_slist_append(val_list, g_strdup(value_text));
+
+                        xmpp_free(ctx, value_text);
+                    }
+                }
+
+                values = xmpp_stanza_get_next(values);
+            }
+
+            // add to list
+            if (g_slist_length(val_list) > 0) {
+                g_hash_table_insert(addresses, g_strdup(var), val_list);
+            }
+        }
+
+        fields = xmpp_stanza_get_next(fields);
+    }
+
+    return addresses;
+}
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 06b2815a..aeddf6a2 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -121,6 +121,7 @@
 #define STANZA_NAME_LAST             "last"
 #define STANZA_NAME_AFTER            "after"
 #define STANZA_NAME_USERNAME         "username"
+#define STANZA_NAME_PROPOSE          "propose"
 
 // error conditions
 #define STANZA_NAME_BAD_REQUEST             "bad-request"
@@ -161,6 +162,7 @@
 #define STANZA_TYPE_SUBMIT       "submit"
 #define STANZA_TYPE_CANCEL       "cancel"
 #define STANZA_TYPE_MODIFY       "modify"
+#define STANZA_TYPE_LIST_MULTI   "list-multi"
 
 #define STANZA_ATTR_TO             "to"
 #define STANZA_ATTR_FROM           "from"
@@ -238,6 +240,8 @@
 #define STANZA_NS_RSM                     "http://jabber.org/protocol/rsm"
 #define STANZA_NS_REGISTER                "jabber:iq:register"
 #define STANZA_NS_VOICEREQUEST            "http://jabber.org/protocol/muc#request"
+#define STANZA_NS_JINGLE_MESSAGE          "urn:xmpp:jingle-message:0"
+#define STANZA_NS_JINGLE_RTP              "urn:xmpp:jingle:apps:rtp:1"
 
 #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
 
@@ -385,6 +389,8 @@ char* stanza_get_muc_destroy_reason(xmpp_stanza_t* stanza);
 const char* stanza_get_actor(xmpp_stanza_t* stanza);
 char* stanza_get_reason(xmpp_stanza_t* stanza);
 
+GHashTable* stanza_get_service_contact_addresses(xmpp_ctx_t* ctx, xmpp_stanza_t* stanza);
+
 Resource* stanza_resource_from_presence(XMPPPresence* presence);
 XMPPPresence* stanza_parse_presence(xmpp_stanza_t* stanza, int* err);
 void stanza_free_presence(XMPPPresence* presence);
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 4229ddae..003c3e07 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -274,6 +274,7 @@ gboolean bookmark_update(const char* jid, const char* nick, const char* password
 gboolean bookmark_remove(const char* jid);
 gboolean bookmark_join(const char* jid);
 GList* bookmark_get_list(void);
+Bookmark* bookmark_get_by_jid(const char* jid);
 char* bookmark_find(const char* const search_str, gboolean previous, void* context);
 void bookmark_autocomplete_reset(void);
 gboolean bookmark_exists(const char* const room);