diff options
Diffstat (limited to 'src/xmpp')
-rw-r--r-- | src/xmpp/bookmark.c | 7 | ||||
-rw-r--r-- | src/xmpp/iq.c | 13 | ||||
-rw-r--r-- | src/xmpp/message.c | 31 | ||||
-rw-r--r-- | src/xmpp/omemo.c | 39 | ||||
-rw-r--r-- | src/xmpp/stanza.c | 51 | ||||
-rw-r--r-- | src/xmpp/stanza.h | 6 | ||||
-rw-r--r-- | src/xmpp/xmpp.h | 1 |
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); |