diff --git a/src/mode/mam.c b/src/mode/mam.c index a914623be658edead15261a7b1acee1eb106ac59..bb6968cee3e998ab6fbbe35fa074514815c2acce 100644 --- a/src/mode/mam.c +++ b/src/mode/mam.c @@ -51,11 +51,14 @@ #define FORWARD_NS "urn:xmpp:forward:0" #define DELAY_NS "urn:xmpp:delay" #define RSM_NS "http://jabber.org/protocol/rsm" +#define SID_NS "urn:xmpp:sid:0" #define MAM_DEFAULT_MAX 5 #define MAM_MAX_CAP 50 #define MAM_DEFAULT_TIMEOUT_SECONDS 300 #define MAM_POLL_PERIOD_MS 2000 +#define MAM_ARCHIVE_LOOKUP_TIMEOUT_SECONDS 15 +#define MAM_ARCHIVE_LOOKUP_POLL_MS 1000 typedef struct { char *with; @@ -79,17 +82,42 @@ typedef struct { bool done; } mam_run_t; +typedef struct { + xmppc_t *xmppc; + char *with; + char *message_id; + char *start; + char *queryid; + char *archive_id; + gint64 deadline_us; + bool done; + MamArchiveLookupCallback callback; + void *userdata; +} mam_archive_lookup_t; + +static mam_archive_lookup_t *mam_archive_lookup_active = NULL; + static void _mam_options_init(mam_options_t *options); static void _mam_options_free(mam_options_t *options); static bool _mam_parse_terms(xmppc_t *xmppc, int argc, char *argv[], mam_options_t *options, bool receive); static void _mam_start_request(xmppc_t *xmppc, mam_options_t *options, bool pretty, bool receive); static void _mam_send_request(mam_run_t *run); +static void _mam_send_query(xmppc_t *xmppc, mam_options_t *options, char **queryid, xmpp_handler finish_handler, void *userdata); static int _mam_finish(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); static int _mam_receive_poll(xmpp_conn_t *const conn, void *const userdata); static int _mam_receive_timeout(xmpp_conn_t *const conn, void *const userdata); static int _mam_display_message(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); static int _mam_display_pretty_message(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); static void _mam_disconnect_and_free(xmpp_conn_t *conn, mam_run_t *run, bool delete_id_handler); +static void _mam_send_archive_lookup_query(mam_archive_lookup_t *lookup); +static int _mam_archive_lookup_result_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); +static int _mam_archive_lookup_finished(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); +static int _mam_archive_lookup_poll(xmpp_conn_t *const conn, void *const userdata); +static int _mam_archive_lookup_timeout(xmpp_conn_t *const conn, void *const userdata); +static bool _mam_archive_lookup_result_matches(mam_archive_lookup_t *lookup, xmpp_stanza_t *result); +static bool _mam_has_origin_id(xmpp_stanza_t *message, const char *id); +static void _mam_archive_lookup_done(xmpp_conn_t *conn, mam_archive_lookup_t *lookup, bool delete_id_handler); +static void _mam_archive_lookup_free(mam_archive_lookup_t *lookup); static void _mam_add_field(xmpp_ctx_t *ctx, xmpp_stanza_t *x, const char *var, const char *value, const char *type); static void _mam_add_ids_field(xmpp_ctx_t *ctx, xmpp_stanza_t *x, const char *ids); static void _mam_add_text_child(xmpp_ctx_t *ctx, xmpp_stanza_t *parent, const char *name, const char *text); @@ -287,15 +315,18 @@ static void _mam_start_request(xmppc_t *xmppc, mam_options_t *options, bool pret } static void _mam_send_request(mam_run_t *run) { - xmppc_t *xmppc = run->xmppc; + _mam_send_query(run->xmppc, &run->options, &run->queryid, _mam_finish, run); +} + +static void _mam_send_query(xmppc_t *xmppc, mam_options_t *options, char **queryid, xmpp_handler finish_handler, void *userdata) { xmpp_ctx_t *ctx = xmppc->ctx; char max[16]; - g_snprintf(max, sizeof(max), "%d", run->options.max); + g_snprintf(max, sizeof(max), "%d", options->max); char* id = xmpp_uuid_gen(ctx); - g_free(run->queryid); - run->queryid = g_strdup(id); + g_free(*queryid); + *queryid = g_strdup(id); xmpp_stanza_t *iq = xmpp_iq_new(ctx, "set", id); xmpp_stanza_t *query = xmpp_stanza_new(ctx); @@ -311,33 +342,33 @@ static void _mam_send_request(mam_run_t *run) { _mam_add_field(ctx, x, "FORM_TYPE", MAM_NS, "hidden"); - if (run->options.with) { - _mam_add_field(ctx, x, "with", run->options.with, NULL); + if (options->with) { + _mam_add_field(ctx, x, "with", options->with, NULL); } - if (run->options.start) { - _mam_add_field(ctx, x, "start", run->options.start, NULL); + if (options->start) { + _mam_add_field(ctx, x, "start", options->start, NULL); } - if (run->options.end) { - _mam_add_field(ctx, x, "end", run->options.end, NULL); + if (options->end) { + _mam_add_field(ctx, x, "end", options->end, NULL); } - if (run->options.ids) { - _mam_add_ids_field(ctx, x, run->options.ids); + if (options->ids) { + _mam_add_ids_field(ctx, x, options->ids); } xmpp_stanza_t *set = xmpp_stanza_new(ctx); xmpp_stanza_set_name(set, "set"); xmpp_stanza_set_ns(set, RSM_NS); _mam_add_text_child(ctx, set, "max", max); - if (run->options.after_id) { - _mam_add_text_child(ctx, set, "after", run->options.after_id); + if (options->after_id) { + _mam_add_text_child(ctx, set, "after", options->after_id); } - if (run->options.before_id) { - _mam_add_text_child(ctx, set, "before", run->options.before_id); + if (options->before_id) { + _mam_add_text_child(ctx, set, "before", options->before_id); } xmpp_stanza_add_child(query, set); xmpp_stanza_add_child(iq,query); - xmpp_id_handler_add(xmppc->conn, _mam_finish, id, run); + xmpp_id_handler_add(xmppc->conn, finish_handler, id, userdata); xmpp_send(xmppc->conn,iq); xmpp_stanza_release(iq); @@ -417,6 +448,189 @@ static void _mam_disconnect_and_free(xmpp_conn_t *conn, mam_run_t *run, bool del xmpp_disconnect(conn); } +void mam_lookup_message_archive_id(xmppc_t *xmppc, const char *with, const char *message_id, MamArchiveLookupCallback callback, void *userdata) { + if (!with || !message_id) { + if (callback) { + callback(xmppc->conn, NULL, userdata); + } + return; + } + + if (mam_archive_lookup_active) { + logError(xmppc, "MAM archive lookup already active\n"); + if (callback) { + callback(xmppc->conn, NULL, userdata); + } + return; + } + + mam_archive_lookup_t *lookup = g_new0(mam_archive_lookup_t, 1); + lookup->xmppc = xmppc; + lookup->with = g_strdup(with); + lookup->message_id = g_strdup(message_id); + lookup->start = _mam_normalize_datetime("-30s"); + lookup->deadline_us = g_get_monotonic_time() + ((gint64)MAM_ARCHIVE_LOOKUP_TIMEOUT_SECONDS * G_USEC_PER_SEC); + lookup->callback = callback; + lookup->userdata = userdata; + mam_archive_lookup_active = lookup; + + xmpp_handler_add(xmppc->conn, _mam_archive_lookup_result_handler, NULL, "message", NULL, lookup); + xmpp_timed_handler_add(xmppc->conn, _mam_archive_lookup_timeout, MAM_ARCHIVE_LOOKUP_TIMEOUT_SECONDS * 1000, lookup); + _mam_send_archive_lookup_query(lookup); +} + +static void _mam_send_archive_lookup_query(mam_archive_lookup_t *lookup) { + mam_options_t options; + _mam_options_init(&options); + options.with = lookup->with; + options.start = lookup->start; + options.before_id = ""; + options.max = MAM_MAX_CAP; + + _mam_send_query(lookup->xmppc, &options, &lookup->queryid, _mam_archive_lookup_finished, lookup); +} + +static int _mam_archive_lookup_result_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata) { + mam_archive_lookup_t *lookup = (mam_archive_lookup_t *)userdata; + xmpp_stanza_t* result = xmpp_stanza_get_child_by_name(stanza,"result"); + + if (!lookup->done && result && _mam_archive_lookup_result_matches(lookup, result)) { + const char *archive_id = xmpp_stanza_get_attribute(result, "id"); + if (archive_id) { + g_free(lookup->archive_id); + lookup->archive_id = g_strdup(archive_id); + } + } + + return 1; +} + +static int _mam_archive_lookup_finished(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata) { + mam_archive_lookup_t *lookup = (mam_archive_lookup_t *)userdata; + const char *type = xmpp_stanza_get_type(stanza); + + if (lookup->done) { + return 0; + } + + if (lookup->archive_id) { + _mam_archive_lookup_done(conn, lookup, false); + return 0; + } + + if (type && strcmp(type, "error") == 0) { + logError(lookup->xmppc, "MAM archive lookup failed\n"); + _mam_archive_lookup_done(conn, lookup, false); + return 0; + } + + if (g_get_monotonic_time() < lookup->deadline_us) { + xmpp_timed_handler_add(conn, _mam_archive_lookup_poll, MAM_ARCHIVE_LOOKUP_POLL_MS, lookup); + } else { + logError(lookup->xmppc, "MAM archive lookup timed out\n"); + _mam_archive_lookup_done(conn, lookup, false); + } + + return 0; +} + +static int _mam_archive_lookup_poll(xmpp_conn_t *const conn, void *const userdata) { + mam_archive_lookup_t *lookup = (mam_archive_lookup_t *)userdata; + + if (lookup->done) { + return 0; + } + + if (g_get_monotonic_time() >= lookup->deadline_us) { + logError(lookup->xmppc, "MAM archive lookup timed out\n"); + _mam_archive_lookup_done(conn, lookup, false); + return 0; + } + + _mam_send_archive_lookup_query(lookup); + return 0; +} + +static int _mam_archive_lookup_timeout(xmpp_conn_t *const conn, void *const userdata) { + mam_archive_lookup_t *lookup = (mam_archive_lookup_t *)userdata; + + if (!lookup->done) { + logError(lookup->xmppc, "MAM archive lookup timed out\n"); + _mam_archive_lookup_done(conn, lookup, true); + } + + return 0; +} + +static bool _mam_archive_lookup_result_matches(mam_archive_lookup_t *lookup, xmpp_stanza_t *result) { + const char *ns = xmpp_stanza_get_ns(result); + if (!ns || strcmp(MAM_NS, ns) != 0) { + return false; + } + + const char *queryid = xmpp_stanza_get_attribute(result, "queryid"); + if (queryid && lookup->queryid && strcmp(queryid, lookup->queryid) != 0) { + return false; + } + + xmpp_stanza_t* forwarded = xmpp_stanza_get_child_by_ns(result, FORWARD_NS); + xmpp_stanza_t* message = forwarded ? xmpp_stanza_get_child_by_name(forwarded, "message") : NULL; + if (!message) { + return false; + } + + const char *archived_message_id = xmpp_stanza_get_id(message); + if (archived_message_id && strcmp(archived_message_id, lookup->message_id) == 0) { + return true; + } + + return _mam_has_origin_id(message, lookup->message_id); +} + +static bool _mam_has_origin_id(xmpp_stanza_t *message, const char *id) { + for (xmpp_stanza_t *child = xmpp_stanza_get_children(message); child; child = xmpp_stanza_get_next(child)) { + const char *name = xmpp_stanza_get_name(child); + const char *ns = xmpp_stanza_get_ns(child); + const char *origin_id = xmpp_stanza_get_attribute(child, "id"); + + if (name && ns && origin_id && strcmp(name, "origin-id") == 0 && strcmp(ns, SID_NS) == 0 && strcmp(origin_id, id) == 0) { + return true; + } + } + + return false; +} + +static void _mam_archive_lookup_done(xmpp_conn_t *conn, mam_archive_lookup_t *lookup, bool delete_id_handler) { + if (lookup->done) { + return; + } + + lookup->done = true; + xmpp_handler_delete(conn, _mam_archive_lookup_result_handler); + xmpp_timed_handler_delete(conn, _mam_archive_lookup_poll); + xmpp_timed_handler_delete(conn, _mam_archive_lookup_timeout); + if (delete_id_handler && lookup->queryid) { + xmpp_id_handler_delete(conn, _mam_archive_lookup_finished, lookup->queryid); + } + if (mam_archive_lookup_active == lookup) { + mam_archive_lookup_active = NULL; + } + if (lookup->callback) { + lookup->callback(conn, lookup->archive_id, lookup->userdata); + } + _mam_archive_lookup_free(lookup); +} + +static void _mam_archive_lookup_free(mam_archive_lookup_t *lookup) { + g_free(lookup->with); + g_free(lookup->message_id); + g_free(lookup->start); + g_free(lookup->queryid); + g_free(lookup->archive_id); + g_free(lookup); +} + static void _mam_add_field(xmpp_ctx_t *ctx, xmpp_stanza_t *x, const char *var, const char *value, const char *type) { xmpp_stanza_t* field = xmpp_stanza_new(ctx); xmpp_stanza_set_name(field,"field"); diff --git a/src/mode/mam.h b/src/mode/mam.h index 9e663fff5b648778703f5bd9d66f9e10cc4df557..0c81fbf454c6f70ec9413b56098ff97e9d70a761 100644 --- a/src/mode/mam.h +++ b/src/mode/mam.h @@ -45,6 +45,10 @@ #include "xmppc.h" +typedef void (*MamArchiveLookupCallback)(xmpp_conn_t *conn, const char *archive_id, void *userdata); + void mam_execute_command(xmppc_t *xmppc, int agrc, char *argv[]); +void mam_lookup_message_archive_id(xmppc_t *xmppc, const char *with, const char *message_id, MamArchiveLookupCallback callback, void *userdata); + #endif // XMPPC_MAM_H__ diff --git a/src/mode/message.c b/src/mode/message.c index 0c35c288c685de215437e2da4ec66081fc1d0f3e..83fdf39df2b4c1cf9f96527cce66e00b68517dae 100644 --- a/src/mode/message.c +++ b/src/mode/message.c @@ -41,45 +41,26 @@ */ #include "message.h" +#include "mam.h" #include "glib.h" #include "stdbool.h" #include "stdlib.h" #include "string.h" -#define MAM_NS "urn:xmpp:mam:2" -#define FORWARD_NS "urn:xmpp:forward:0" -#define RSM_NS "http://jabber.org/protocol/rsm" #define SID_NS "urn:xmpp:sid:0" -#define MESSAGE_ARCHIVE_LOOKUP_TIMEOUT_SECONDS 15 -#define MESSAGE_ARCHIVE_LOOKUP_POLL_MS 1000 - typedef struct { - xmppc_t *xmppc; char *to; char *message_id; - char *start; - char *queryid; char *archive_id; - gint64 deadline_us; bool done; -} message_archive_lookup_t; +} message_send_t; static void _message_send_text(xmppc_t *xmppc, char* to, char* message); -static void _message_lookup_archive_id(xmppc_t *xmppc, const char *to, const char *message_id); -static void _message_send_archive_query(message_archive_lookup_t *lookup); -static int _message_archive_result_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); -static int _message_archive_query_finished(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata); -static int _message_archive_query_poll(xmpp_conn_t *const conn, void *const userdata); -static int _message_archive_lookup_timeout(xmpp_conn_t *const conn, void *const userdata); -static bool _message_archive_result_matches(message_archive_lookup_t *lookup, xmpp_stanza_t *result); -static bool _message_has_origin_id(xmpp_stanza_t *message, const char *id); -static void _message_add_text_child(xmpp_ctx_t *ctx, xmpp_stanza_t *parent, const char *name, const char *text); -static void _message_add_field(xmpp_ctx_t *ctx, xmpp_stanza_t *x, const char *var, const char *value, const char *type); -static char *_message_lookup_start_time(void); -static void _message_finish_sent(xmpp_conn_t *conn, message_archive_lookup_t *lookup, bool delete_id_handler); -static void _message_archive_lookup_free(message_archive_lookup_t *lookup); -static void _message_print_sent(message_archive_lookup_t *lookup); +static void _message_archive_id_found(xmpp_conn_t *conn, const char *archive_id, void *userdata); +static void _message_finish_sent(xmpp_conn_t *conn, message_send_t *sent); +static void _message_send_free(message_send_t *sent); +static void _message_print_sent(message_send_t *sent); static void _message_print_escaped_attr(const char *text); void message_execute_command(xmppc_t *xmppc, int argc, char *argv[]) { @@ -106,8 +87,12 @@ void _message_send_text(xmppc_t *xmppc, char* to, char* text) { xmpp_stanza_add_child(message, origin); xmpp_stanza_release(origin); + message_send_t *sent = g_new0(message_send_t, 1); + sent->to = g_strdup(to); + sent->message_id = g_strdup(id); + xmpp_send(conn, message); - _message_lookup_archive_id(xmppc, to, id); + mam_lookup_message_archive_id(xmppc, to, id, _message_archive_id_found, sent); } else { xmpp_disconnect(conn); } @@ -115,233 +100,35 @@ void _message_send_text(xmppc_t *xmppc, char* to, char* text) { free(id); } -static void _message_lookup_archive_id(xmppc_t *xmppc, const char *to, const char *message_id) { - message_archive_lookup_t *lookup = g_new0(message_archive_lookup_t, 1); - lookup->xmppc = xmppc; - lookup->to = g_strdup(to); - lookup->message_id = g_strdup(message_id); - lookup->start = _message_lookup_start_time(); - lookup->deadline_us = g_get_monotonic_time() + ((gint64)MESSAGE_ARCHIVE_LOOKUP_TIMEOUT_SECONDS * G_USEC_PER_SEC); - - xmpp_handler_add(xmppc->conn, _message_archive_result_handler, NULL, "message", NULL, lookup); - xmpp_timed_handler_add(xmppc->conn, _message_archive_lookup_timeout, MESSAGE_ARCHIVE_LOOKUP_TIMEOUT_SECONDS * 1000, lookup); - _message_send_archive_query(lookup); -} - -static void _message_send_archive_query(message_archive_lookup_t *lookup) { - xmppc_t *xmppc = lookup->xmppc; - xmpp_ctx_t *ctx = xmppc->ctx; - char* id = xmpp_uuid_gen(ctx); - g_free(lookup->queryid); - lookup->queryid = g_strdup(id); - - xmpp_stanza_t *iq = xmpp_iq_new(ctx, "set", id); - xmpp_stanza_t *query = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(query, "query"); - xmpp_stanza_set_ns(query, MAM_NS); - xmpp_stanza_set_attribute(query, "queryid", id); - - xmpp_stanza_t* x = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(x,"x"); - xmpp_stanza_set_ns(x, "jabber:x:data"); - xmpp_stanza_set_type(x,"submit"); - xmpp_stanza_add_child(query,x); - - _message_add_field(ctx, x, "FORM_TYPE", MAM_NS, "hidden"); - _message_add_field(ctx, x, "with", lookup->to, NULL); - _message_add_field(ctx, x, "start", lookup->start, NULL); - - xmpp_stanza_t *set = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(set, "set"); - xmpp_stanza_set_ns(set, RSM_NS); - _message_add_text_child(ctx, set, "max", "50"); - _message_add_text_child(ctx, set, "before", ""); - xmpp_stanza_add_child(query, set); - - xmpp_stanza_add_child(iq, query); - xmpp_id_handler_add(xmppc->conn, _message_archive_query_finished, id, lookup); - xmpp_send(xmppc->conn, iq); - - xmpp_stanza_release(iq); - xmpp_stanza_release(query); - xmpp_stanza_release(x); - xmpp_stanza_release(set); - free(id); -} - -static int _message_archive_result_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata) { - message_archive_lookup_t *lookup = (message_archive_lookup_t *)userdata; - xmpp_stanza_t* result = xmpp_stanza_get_child_by_name(stanza,"result"); - - if (!lookup->done && result && _message_archive_result_matches(lookup, result)) { - const char *archive_id = xmpp_stanza_get_attribute(result, "id"); - if (archive_id) { - g_free(lookup->archive_id); - lookup->archive_id = g_strdup(archive_id); - } - } - - return 1; -} - -static int _message_archive_query_finished(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata) { - message_archive_lookup_t *lookup = (message_archive_lookup_t *)userdata; - const char *type = xmpp_stanza_get_type(stanza); - - if (lookup->done) { - return 0; - } - - if (lookup->archive_id) { - _message_finish_sent(conn, lookup, false); - return 0; - } - - if (type && strcmp(type, "error") == 0) { - logError(lookup->xmppc, "MAM archive lookup failed\n"); - _message_finish_sent(conn, lookup, false); - return 0; - } - - if (g_get_monotonic_time() < lookup->deadline_us) { - xmpp_timed_handler_add(conn, _message_archive_query_poll, MESSAGE_ARCHIVE_LOOKUP_POLL_MS, lookup); - } else { - logError(lookup->xmppc, "MAM archive lookup timed out\n"); - _message_finish_sent(conn, lookup, false); - } - - return 0; -} - -static int _message_archive_query_poll(xmpp_conn_t *const conn, void *const userdata) { - message_archive_lookup_t *lookup = (message_archive_lookup_t *)userdata; - - if (lookup->done) { - return 0; - } - - if (g_get_monotonic_time() >= lookup->deadline_us) { - logError(lookup->xmppc, "MAM archive lookup timed out\n"); - _message_finish_sent(conn, lookup, false); - return 0; - } - - _message_send_archive_query(lookup); - return 0; -} - -static int _message_archive_lookup_timeout(xmpp_conn_t *const conn, void *const userdata) { - message_archive_lookup_t *lookup = (message_archive_lookup_t *)userdata; +static void _message_archive_id_found(xmpp_conn_t *conn, const char *archive_id, void *userdata) { + message_send_t *sent = (message_send_t *)userdata; - if (!lookup->done) { - logError(lookup->xmppc, "MAM archive lookup timed out\n"); - _message_finish_sent(conn, lookup, true); + if (archive_id) { + sent->archive_id = g_strdup(archive_id); } - return 0; + _message_finish_sent(conn, sent); } -static bool _message_archive_result_matches(message_archive_lookup_t *lookup, xmpp_stanza_t *result) { - const char *ns = xmpp_stanza_get_ns(result); - if (!ns || strcmp(MAM_NS, ns) != 0) { - return false; - } - - const char *queryid = xmpp_stanza_get_attribute(result, "queryid"); - if (queryid && lookup->queryid && strcmp(queryid, lookup->queryid) != 0) { - return false; - } - - xmpp_stanza_t* forwarded = xmpp_stanza_get_child_by_ns(result, FORWARD_NS); - xmpp_stanza_t* message = forwarded ? xmpp_stanza_get_child_by_name(forwarded, "message") : NULL; - if (!message) { - return false; - } - - const char *message_id = xmpp_stanza_get_id(message); - if (message_id && strcmp(message_id, lookup->message_id) == 0) { - return true; - } - - return _message_has_origin_id(message, lookup->message_id); -} - -static bool _message_has_origin_id(xmpp_stanza_t *message, const char *id) { - for (xmpp_stanza_t *child = xmpp_stanza_get_children(message); child; child = xmpp_stanza_get_next(child)) { - const char *name = xmpp_stanza_get_name(child); - const char *ns = xmpp_stanza_get_ns(child); - const char *origin_id = xmpp_stanza_get_attribute(child, "id"); - - if (name && ns && origin_id && strcmp(name, "origin-id") == 0 && strcmp(ns, SID_NS) == 0 && strcmp(origin_id, id) == 0) { - return true; - } - } - - return false; -} - -static void _message_add_text_child(xmpp_ctx_t *ctx, xmpp_stanza_t *parent, const char *name, const char *text) { - xmpp_stanza_t *child = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(child, name); - - xmpp_stanza_t *body = xmpp_stanza_new(ctx); - xmpp_stanza_set_text(body, text ? text : ""); - xmpp_stanza_add_child(child, body); - xmpp_stanza_release(body); - - xmpp_stanza_add_child(parent, child); - xmpp_stanza_release(child); -} - -static void _message_add_field(xmpp_ctx_t *ctx, xmpp_stanza_t *x, const char *var, const char *value, const char *type) { - xmpp_stanza_t* field = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(field,"field"); - xmpp_stanza_set_attribute(field, "var", var); - if (type) { - xmpp_stanza_set_type(field, type); - } - - _message_add_text_child(ctx, field, "value", value); - xmpp_stanza_add_child(x, field); - xmpp_stanza_release(field); -} - -static char *_message_lookup_start_time(void) { - GDateTime *now = g_date_time_new_now_utc(); - GDateTime *then = g_date_time_add_seconds(now, -30); - char *formatted = g_date_time_format(then, "%Y-%m-%dT%H:%M:%SZ"); - g_date_time_unref(then); - g_date_time_unref(now); - return formatted; -} - -static void _message_finish_sent(xmpp_conn_t *conn, message_archive_lookup_t *lookup, bool delete_id_handler) { - if (lookup->done) { +static void _message_finish_sent(xmpp_conn_t *conn, message_send_t *sent) { + if (sent->done) { return; } - lookup->done = true; - _message_print_sent(lookup); - xmpp_handler_delete(conn, _message_archive_result_handler); - xmpp_timed_handler_delete(conn, _message_archive_query_poll); - xmpp_timed_handler_delete(conn, _message_archive_lookup_timeout); - if (delete_id_handler && lookup->queryid) { - xmpp_id_handler_delete(conn, _message_archive_query_finished, lookup->queryid); - } - _message_archive_lookup_free(lookup); + sent->done = true; + _message_print_sent(sent); + _message_send_free(sent); xmpp_disconnect(conn); } -static void _message_archive_lookup_free(message_archive_lookup_t *lookup) { - g_free(lookup->to); - g_free(lookup->message_id); - g_free(lookup->start); - g_free(lookup->queryid); - g_free(lookup->archive_id); - g_free(lookup); +static void _message_send_free(message_send_t *sent) { + g_free(sent->to); + g_free(sent->message_id); + g_free(sent->archive_id); + g_free(sent); } -static void _message_print_sent(message_archive_lookup_t *lookup) { +static void _message_print_sent(message_send_t *lookup) { printf("archive_id ? lookup->archive_id : ""); printf("\" message-id=\"");