summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordefanor <defanor@uberspace.net>2021-09-24 17:04:49 +0300
committerdefanor <defanor@uberspace.net>2021-09-24 17:04:49 +0300
commit8021dfe24fc44c7a1adbcf8bd49c48e488e8ba2c (patch)
treef201b26dcf46f856a797ff52a9cbf1a09828d4d1
parent6fce0156861461cf35222b048e422db61898bb80 (diff)
Pass user-provided pointers to <iq> callback functions
-rw-r--r--src/rexmpp.c93
-rw-r--r--src/rexmpp.h6
-rw-r--r--src/rexmpp_console.c8
-rw-r--r--src/rexmpp_openpgp.c16
-rw-r--r--src/rexmpp_pubsub.c20
-rw-r--r--src/rexmpp_pubsub.h12
-rw-r--r--src/rexmpp_roster.c2
-rw-r--r--src/rexmpp_roster.h1
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);