From 8021dfe24fc44c7a1adbcf8bd49c48e488e8ba2c Mon Sep 17 00:00:00 2001 From: defanor Date: Fri, 24 Sep 2021 17:04:49 +0300 Subject: Pass user-provided pointers to callback functions --- src/rexmpp.c | 93 ++++++++++++++++++++++++++++------------------------ src/rexmpp.h | 6 +++- src/rexmpp_console.c | 8 +++-- src/rexmpp_openpgp.c | 16 ++++++--- src/rexmpp_pubsub.c | 20 ++++++----- src/rexmpp_pubsub.h | 12 ++++--- src/rexmpp_roster.c | 2 ++ src/rexmpp_roster.h | 1 + 8 files changed, 97 insertions(+), 61 deletions(-) diff --git a/src/rexmpp.c b/src/rexmpp.c index f2c0f9b..bf396ca 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -559,6 +559,18 @@ void rexmpp_cleanup (rexmpp_t *s) { s->ping_requested = 0; } +void rexmpp_iq_finish (rexmpp_t *s, + rexmpp_iq_t *iq, + int success, + xmlNodePtr response) +{ + if (iq->cb != NULL) { + iq->cb(s, iq->cb_data, iq->request, response, success); + } + xmlFreeNode(iq->request); + free(iq); +} + /* Frees the things that persist through reconnects. */ void rexmpp_done (rexmpp_t *s) { rexmpp_cleanup(s); @@ -599,9 +611,9 @@ void rexmpp_done (rexmpp_t *s) { } while (s->active_iq != NULL) { rexmpp_iq_t *next = s->active_iq->next; - xmlFreeNode(s->active_iq->request); - free(s->active_iq); + rexmpp_iq_t *iq = s->active_iq; s->active_iq = next; + rexmpp_iq_finish(s, iq, 0, NULL); } } @@ -969,7 +981,8 @@ rexmpp_err_t rexmpp_iq_new (rexmpp_t *s, const char *type, const char *to, xmlNodePtr payload, - rexmpp_iq_callback_t cb) + rexmpp_iq_callback_t cb, + void *cb_data) { unsigned int i; rexmpp_iq_t *prev = NULL, *last = s->active_iq; @@ -981,11 +994,7 @@ rexmpp_err_t rexmpp_iq_new (rexmpp_t *s, rexmpp_log(s, LOG_WARNING, "The IQ queue limit is reached, giving up on the oldest IQ."); prev->next = NULL; - if (last->cb != NULL) { - last->cb(s, last->request, NULL, 0); - } - xmlFreeNode(last->request); - free(last); + rexmpp_iq_finish(s, last, 0, NULL); } xmlNodePtr iq_stanza = rexmpp_xml_add_id(s, xmlNewNode(NULL, "iq")); @@ -1001,6 +1010,7 @@ rexmpp_err_t rexmpp_iq_new (rexmpp_t *s, rexmpp_iq_t *iq = malloc(sizeof(rexmpp_iq_t)); iq->request = xmlCopyNode(iq_stanza, 1); iq->cb = cb; + iq->cb_data = cb_data; iq->next = s->active_iq; s->active_iq = iq; return rexmpp_send(s, iq_stanza); @@ -1363,10 +1373,12 @@ void rexmpp_sm_handle_ack (rexmpp_t *s, xmlNodePtr elem) { } void rexmpp_carbons_enabled (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)req; /* The request is always the same. */ (void)response; /* Only checking whether it's a success. */ if (success) { @@ -1379,10 +1391,12 @@ void rexmpp_carbons_enabled (rexmpp_t *s, } void rexmpp_pong (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)req; (void)response; (void)success; @@ -1390,10 +1404,12 @@ void rexmpp_pong (rexmpp_t *s, } void rexmpp_iq_discovery_info (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)req; if (! success) { rexmpp_log(s, LOG_ERR, "Failed to discover features"); @@ -1416,7 +1432,7 @@ void rexmpp_iq_discovery_info (rexmpp_t *s, xmlNewNs(carbons_enable, "urn:xmpp:carbons:2", NULL); s->carbons_state = REXMPP_CARBONS_NEGOTIATION; rexmpp_iq_new(s, "set", NULL, carbons_enable, - rexmpp_carbons_enabled); + rexmpp_carbons_enabled, NULL); } free(var); } @@ -1432,7 +1448,7 @@ void rexmpp_stream_is_ready(rexmpp_t *s) { xmlNodePtr disco_query = xmlNewNode(NULL, "query"); xmlNewNs(disco_query, "http://jabber.org/protocol/disco#info", NULL); rexmpp_iq_new(s, "get", s->initial_jid.domain, - disco_query, rexmpp_iq_discovery_info); + disco_query, rexmpp_iq_discovery_info, NULL); } if (s->manage_roster) { if (s->roster_cache_file != NULL) { @@ -1446,7 +1462,7 @@ void rexmpp_stream_is_ready(rexmpp_t *s) { xmlNewProp(roster_query, "ver", ""); } rexmpp_iq_new(s, "get", NULL, - roster_query, rexmpp_iq_roster_get); + roster_query, rexmpp_iq_roster_get, NULL); } xmlNodePtr presence = rexmpp_xml_add_id(s, xmlNewNode(NULL, "presence")); char *caps_hash = rexmpp_capabilities_hash(s, rexmpp_disco_info(s)); @@ -1464,7 +1480,13 @@ void rexmpp_stream_is_ready(rexmpp_t *s) { /* Resource binding, https://tools.ietf.org/html/rfc6120#section-7 */ -void rexmpp_bound (rexmpp_t *s, xmlNodePtr req, xmlNodePtr response, int success) { +void rexmpp_bound (rexmpp_t *s, + void *ptr, + xmlNodePtr req, + xmlNodePtr response, + int success) +{ + (void)ptr; (void)req; if (! success) { /* todo: reconnect here? */ @@ -1506,7 +1528,7 @@ rexmpp_err_t rexmpp_stream_bind (rexmpp_t *s) { s->stream_state = REXMPP_STREAM_BIND; xmlNodePtr bind_cmd = xmlNewNode(NULL, "bind"); xmlNewNs(bind_cmd, "urn:ietf:params:xml:ns:xmpp-bind", NULL); - return rexmpp_iq_new(s, "set", NULL, bind_cmd, rexmpp_bound); + return rexmpp_iq_new(s, "set", NULL, bind_cmd, rexmpp_bound, NULL); } rexmpp_err_t rexmpp_process_element (rexmpp_t *s, xmlNodePtr elem) { @@ -1643,12 +1665,13 @@ rexmpp_err_t rexmpp_process_element (rexmpp_t *s, xmlNodePtr elem) { /* IQ responses. */ if (strcmp(type, "result") == 0 || strcmp(type, "error") == 0) { char *id = xmlGetProp(elem, "id"); - rexmpp_iq_t *req = s->active_iq; + rexmpp_iq_t *req = s->active_iq, *prev_req = NULL; int found = 0; while (req != NULL && found == 0) { char *req_id = xmlGetProp(req->request, "id"); char *req_to = xmlGetProp(req->request, "to"); char *rep_from = xmlGetProp(elem, "from"); + rexmpp_iq_t *req_next = req->next; int id_matches = (strcmp(id, req_id) == 0); int jid_matches = 0; if (rep_from == NULL) { @@ -1658,33 +1681,18 @@ rexmpp_err_t rexmpp_process_element (rexmpp_t *s, xmlNodePtr elem) { } if (id_matches && jid_matches) { found = 1; - if (req->cb != NULL) { - char *iq_type = xmlGetProp(elem, "type"); - int success = 0; - if (strcmp(type, "result") == 0) { - success = 1; - } - free(iq_type); - req->cb(s, req->request, elem, success); + int success = 0; + if (strcmp(type, "result") == 0) { + success = 1; } - /* Remove the callback from the list, but keep in mind that - it could have added more entries. */ - if (s->active_iq == req) { - s->active_iq = req->next; + /* Remove the callback from the list. */ + if (prev_req == NULL) { + s->active_iq = req_next; } else { - rexmpp_iq_t *prev_req = s->active_iq; - for (prev_req = s->active_iq; - prev_req != NULL; - prev_req = prev_req->next) - { - if (prev_req->next == req) { - prev_req->next = req->next; - break; - } - } + prev_req->next = req_next; } - xmlFreeNode(req->request); - free(req); + /* Finish and free the IQ request structure. */ + rexmpp_iq_finish(s, req, success, elem); } if (req_to != NULL) { free(req_to); @@ -1693,7 +1701,8 @@ rexmpp_err_t rexmpp_process_element (rexmpp_t *s, xmlNodePtr elem) { free(rep_from); } free(req_id); - req = req->next; + prev_req = req; + req = req_next; } free(id); } @@ -2062,9 +2071,9 @@ rexmpp_err_t rexmpp_process_element (rexmpp_t *s, xmlNodePtr elem) { while (s->active_iq != NULL) { /* todo: check that those are not queued for resending? */ rexmpp_iq_t *next = s->active_iq->next; - xmlFreeNode(s->active_iq->request); - free(s->active_iq); + rexmpp_iq_t *iq = s->active_iq; s->active_iq = next; + rexmpp_iq_finish(s, iq, 0, NULL); } xmlNodePtr child = rexmpp_xml_find_child(s->stream_features, @@ -2339,7 +2348,7 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { xmlNodePtr ping_cmd = xmlNewNode(NULL, "ping"); xmlNewNs(ping_cmd, "urn:xmpp:ping", NULL); rexmpp_iq_new(s, "get", s->initial_jid.domain, - ping_cmd, rexmpp_pong); + ping_cmd, rexmpp_pong, NULL); } else { rexmpp_log(s, LOG_WARNING, "Ping timeout, reconnecting."); rexmpp_cleanup(s); diff --git a/src/rexmpp.h b/src/rexmpp.h index dd9d22b..5e40d30 100644 --- a/src/rexmpp.h +++ b/src/rexmpp.h @@ -38,6 +38,7 @@ typedef struct rexmpp rexmpp_t; inspect those and react. */ typedef void (*rexmpp_iq_callback_t) (rexmpp_t *s, + void *cb_data, xmlNodePtr request, xmlNodePtr response, int success); @@ -51,6 +52,8 @@ struct rexmpp_iq xmlNodePtr request; /** @brief A callback to call on reply. */ rexmpp_iq_callback_t cb; + /** @brief User-supplied data, to pass to a callback function. */ + void *cb_data; /** @brief Next pending IQ. */ rexmpp_iq_t *next; }; @@ -424,7 +427,8 @@ rexmpp_err_t rexmpp_iq_new (rexmpp_t *s, const char *type, const char *to, xmlNodePtr payload, - rexmpp_iq_callback_t cb); + rexmpp_iq_callback_t cb, + void *cb_data); /** @brief Determines the maximum time to wait before the next diff --git a/src/rexmpp_console.c b/src/rexmpp_console.c index 5476f0b..82086a7 100644 --- a/src/rexmpp_console.c +++ b/src/rexmpp_console.c @@ -207,10 +207,12 @@ void rexmpp_console_on_recv (rexmpp_t *s, xmlNodePtr node) { void rexmpp_console_roster_deleted (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)response; xmlNodePtr item = rexmpp_xml_find_child(rexmpp_xml_find_child(req, @@ -227,10 +229,12 @@ void rexmpp_console_roster_deleted (rexmpp_t *s, } void rexmpp_console_roster_added (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)response; xmlNodePtr item = rexmpp_xml_find_child(rexmpp_xml_find_child(req, @@ -482,7 +486,7 @@ void rexmpp_console_feed (rexmpp_t *s, char *str, ssize_t str_len) { delete_query->ns = xmlNewNs(delete_query, "jabber:iq:roster", NULL); xmlAddChild(delete_query, delete_item); rexmpp_iq_new(s, "set", NULL, delete_query, - rexmpp_console_roster_deleted); + rexmpp_console_roster_deleted, NULL); } else if (! strcmp(word, "add")) { word = strtok_r(NULL, " ", &words_save_ptr); if (word == NULL) { @@ -495,7 +499,7 @@ void rexmpp_console_feed (rexmpp_t *s, char *str, ssize_t str_len) { delete_query->ns = xmlNewNs(delete_query, "jabber:iq:roster", NULL); xmlAddChild(delete_query, delete_item); rexmpp_iq_new(s, "set", NULL, delete_query, - rexmpp_console_roster_added); + rexmpp_console_roster_added, NULL); } } diff --git a/src/rexmpp_openpgp.c b/src/rexmpp_openpgp.c index 84b7537..3e71169 100644 --- a/src/rexmpp_openpgp.c +++ b/src/rexmpp_openpgp.c @@ -59,10 +59,12 @@ Possible future improvements: #ifdef HAVE_GPGME void rexmpp_pgp_fp_reply (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)req; /* Not of interest. */ if (! success) { rexmpp_log(s, LOG_WARNING, "Failed to retrieve an OpenpPGP key"); @@ -168,7 +170,7 @@ rexmpp_openpgp_check_keys (rexmpp_t *s, snprintf(key_node, 72, "urn:xmpp:openpgp:0:public-keys:%s", fingerprint); xmlNewProp(fp_req_items, "node", key_node); xmlAddChild(fp_req, fp_req_items); - rexmpp_iq_new(s, "get", jid, fp_req, rexmpp_pgp_fp_reply); + rexmpp_iq_new(s, "get", jid, fp_req, rexmpp_pgp_fp_reply, NULL); } else if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { rexmpp_log(s, LOG_WARNING, "OpenPGP error when looking for a key: %s", @@ -258,10 +260,12 @@ rexmpp_openpgp_remove_key_from_list (rexmpp_t *s, } void rexmpp_pgp_key_publish_list_iq (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)req; (void)response; if (! success) { @@ -276,14 +280,16 @@ void rexmpp_pgp_key_fp_list_upload (rexmpp_t *s, xmlNodePtr metadata) { xmlNewNs(keylist, "urn:xmpp:openpgp:0", NULL); xmlAddChild(keylist, metadata); rexmpp_pubsub_item_publish(s, NULL, "urn:xmpp:openpgp:0:public-keys", - NULL, keylist, rexmpp_pgp_key_publish_list_iq); + NULL, keylist, rexmpp_pgp_key_publish_list_iq, NULL); } void rexmpp_pgp_key_delete_iq (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)response; if (! success) { rexmpp_log(s, LOG_WARNING, "Failed to delete an OpenpPGP key"); @@ -298,10 +304,12 @@ void rexmpp_pgp_key_delete_iq (rexmpp_t *s, } void rexmpp_pgp_key_publish_iq (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)response; if (! success) { rexmpp_log(s, LOG_WARNING, "Failed to publish an OpenpPGP key"); @@ -340,7 +348,7 @@ void rexmpp_openpgp_retract_key (rexmpp_t *s, const char *fp) { } char node_str[72]; snprintf(node_str, 72, "urn:xmpp:openpgp:0:public-keys:%s", fp); - rexmpp_pubsub_node_delete(s, NULL, node_str, rexmpp_pgp_key_delete_iq); + rexmpp_pubsub_node_delete(s, NULL, node_str, rexmpp_pgp_key_delete_iq, NULL); } rexmpp_err_t rexmpp_openpgp_publish_key (rexmpp_t *s, const char *fp) { @@ -391,7 +399,7 @@ rexmpp_err_t rexmpp_openpgp_publish_key (rexmpp_t *s, const char *fp) { char node_str[72]; snprintf(node_str, 72, "urn:xmpp:openpgp:0:public-keys:%s", fp); rexmpp_pubsub_item_publish(s, NULL, node_str, time_str, - pubkey, rexmpp_pgp_key_publish_iq); + pubkey, rexmpp_pgp_key_publish_iq, NULL); return REXMPP_SUCCESS; } diff --git a/src/rexmpp_pubsub.c b/src/rexmpp_pubsub.c index 6ed3f75..145a352 100644 --- a/src/rexmpp_pubsub.c +++ b/src/rexmpp_pubsub.c @@ -14,7 +14,8 @@ rexmpp_pubsub_iq (rexmpp_t *s, const char *pubsub_namespace, const char *service_jid, xmlNodePtr payload, - rexmpp_iq_callback_t callback) + rexmpp_iq_callback_t callback, + void *cb_data) { xmlNodePtr pubsub = xmlNewNode(NULL, "pubsub"); if (pubsub_namespace == NULL) { @@ -25,7 +26,7 @@ rexmpp_pubsub_iq (rexmpp_t *s, xmlAddChild(pubsub, payload); - rexmpp_iq_new(s, iq_type, service_jid, pubsub, callback); + rexmpp_iq_new(s, iq_type, service_jid, pubsub, callback, cb_data); } void @@ -34,7 +35,8 @@ rexmpp_pubsub_item_publish (rexmpp_t *s, const char *node, const char *item_id, xmlNodePtr payload, - rexmpp_iq_callback_t callback) + rexmpp_iq_callback_t callback, + void *cb_data) { xmlNodePtr item = xmlNewNode(NULL, "item"); xmlNewNs(item, "http://jabber.org/protocol/pubsub", NULL); @@ -48,7 +50,7 @@ rexmpp_pubsub_item_publish (rexmpp_t *s, xmlNewProp(publish, "node", node); xmlAddChild(publish, item); - rexmpp_pubsub_iq(s, "set", NULL, service_jid, publish, callback); + rexmpp_pubsub_iq(s, "set", NULL, service_jid, publish, callback, cb_data); } void @@ -56,7 +58,8 @@ rexmpp_pubsub_item_retract (rexmpp_t *s, const char *service_jid, const char *node, const char *item_id, - rexmpp_iq_callback_t callback) + rexmpp_iq_callback_t callback, + void *cb_data) { xmlNodePtr item = xmlNewNode(NULL, "item"); xmlNewNs(item, "http://jabber.org/protocol/pubsub", NULL); @@ -69,19 +72,20 @@ rexmpp_pubsub_item_retract (rexmpp_t *s, xmlNewProp(retract, "node", node); xmlAddChild(retract, item); - rexmpp_pubsub_iq(s, "set", NULL, service_jid, retract, callback); + rexmpp_pubsub_iq(s, "set", NULL, service_jid, retract, callback, cb_data); } void rexmpp_pubsub_node_delete (rexmpp_t *s, const char *service_jid, const char *node, - rexmpp_iq_callback_t callback) + rexmpp_iq_callback_t callback, + void *cb_data) { xmlNodePtr delete = xmlNewNode(NULL, "delete"); xmlNewNs(delete, "http://jabber.org/protocol/pubsub#owner", NULL); xmlNewProp(delete, "node", node); rexmpp_pubsub_iq(s, "set", "http://jabber.org/protocol/pubsub#owner", - service_jid, delete, callback); + service_jid, delete, callback, cb_data); } diff --git a/src/rexmpp_pubsub.h b/src/rexmpp_pubsub.h index 1c36fc2..b5a7c3e 100644 --- a/src/rexmpp_pubsub.h +++ b/src/rexmpp_pubsub.h @@ -12,7 +12,8 @@ rexmpp_pubsub_iq (rexmpp_t *s, const char *pubsub_namespace, const char *service_jid, xmlNodePtr payload, - rexmpp_iq_callback_t callback); + rexmpp_iq_callback_t callback, + void *cb_data); void rexmpp_pubsub_item_publish (rexmpp_t *s, @@ -20,17 +21,20 @@ rexmpp_pubsub_item_publish (rexmpp_t *s, const char *node, const char *item_id, xmlNodePtr payload, - rexmpp_iq_callback_t callback); + rexmpp_iq_callback_t callback, + void *cb_data); void rexmpp_pubsub_item_retract (rexmpp_t *s, const char *service_jid, const char *node, const char *item_id, - rexmpp_iq_callback_t callback); + rexmpp_iq_callback_t callback, + void *cb_data); void rexmpp_pubsub_node_delete (rexmpp_t *s, const char *service_jid, const char *node, - rexmpp_iq_callback_t callback); + rexmpp_iq_callback_t callback, + void *cb_data); diff --git a/src/rexmpp_roster.c b/src/rexmpp_roster.c index 5012282..63a52b9 100644 --- a/src/rexmpp_roster.c +++ b/src/rexmpp_roster.c @@ -138,10 +138,12 @@ void rexmpp_roster_cache_write (rexmpp_t *s) { } void rexmpp_iq_roster_get (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success) { + (void)ptr; (void)req; /* Nothing interesting in the request. */ if (! success) { rexmpp_log(s, LOG_ERR, "Roster loading failed."); diff --git a/src/rexmpp_roster.h b/src/rexmpp_roster.h index d9e41fd..1fa9183 100644 --- a/src/rexmpp_roster.h +++ b/src/rexmpp_roster.h @@ -15,6 +15,7 @@ void rexmpp_roster_set (rexmpp_t *s, xmlNodePtr query); void rexmpp_roster_cache_read (rexmpp_t *s); void rexmpp_roster_cache_write (rexmpp_t *s); void rexmpp_iq_roster_get (rexmpp_t *s, + void *ptr, xmlNodePtr req, xmlNodePtr response, int success); -- cgit v1.2.3