From 10760238b3c7f35c3be0aee91dc1d91c671fde21 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Mon, 12 Jul 2021 18:43:06 +0200 Subject: [PATCH] add xmpp_conn_send_queue_drop_element() Signed-off-by: Steffen Jaeckel --- ChangeLog | 1 + src/conn.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- strophe.h | 7 +++++ 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5994aed..bb320ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ - Add support for password-protected TLS key & PKCS#12/PFX files - New API: - xmpp_conn_send_queue_len() + - xmpp_conn_send_queue_drop_element() - xmpp_conn_get_keyfile() - xmpp_conn_set_password_callback() - xmpp_conn_set_password_retries() diff --git a/src/conn.c b/src/conn.c index a6884c6..c00d9a4 100644 --- a/src/conn.c +++ b/src/conn.c @@ -100,6 +100,7 @@ static void _conn_sm_handle_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *stanza); static unsigned short _conn_default_port(xmpp_conn_t *conn, xmpp_conn_type_t type); +static char *_queue_element_free(xmpp_ctx_t *ctx, xmpp_send_queue_t *e); static void _conn_reset(xmpp_conn_t *conn); static int _conn_connect(xmpp_conn_t *conn, const char *domain, @@ -1266,6 +1267,77 @@ int xmpp_conn_send_queue_len(const xmpp_conn_t *conn) return conn->send_queue_user_len; } +/** Drop an element of the send queue. + * This can be used to manage the send queue in case a server + * isn't fast enough in processing the elements you're trying + * to send. + * + * @param conn a Strophe connection object + * @param which the element that shall be removed + * + * @ingroup Connections + */ +char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn, + xmpp_queue_element_t which) +{ + xmpp_send_queue_t *t, *p; + xmpp_send_queue_owner_t owner; + char *ret; + /* empty queue */ + if (!conn->send_queue_head) + return NULL; + /* one element in queue */ + if (conn->send_queue_head == conn->send_queue_tail) { + if (conn->send_queue_head->written) + return NULL; + + t = conn->send_queue_head; + conn->send_queue_head = conn->send_queue_tail = NULL; + owner = t->owner; + ret = _queue_element_free(conn->ctx, t); + conn->send_queue_len--; + if (owner == XMPP_QUEUE_USER) + conn->send_queue_user_len--; + return ret; + } + switch (which) { + case XMPP_QUEUE_OLDEST: + /* head is already sent out partially */ + if (conn->send_queue_head->written) { + t = conn->send_queue_head->next; + /* there are no more elements in the queue */ + if (!t) + return NULL; + conn->send_queue_head->next = t->next; + } else { + t = conn->send_queue_head; + conn->send_queue_head = t->next; + } + owner = t->owner; + ret = _queue_element_free(conn->ctx, t); + conn->send_queue_len--; + if (owner == XMPP_QUEUE_USER) + conn->send_queue_user_len--; + return ret; + case XMPP_QUEUE_YOUNGEST: + t = conn->send_queue_head; + do { + p = t; + t = t->next; + } while (t != conn->send_queue_tail); + conn->send_queue_tail = p; + owner = t->owner; + ret = _queue_element_free(conn->ctx, t); + conn->send_queue_len--; + if (owner == XMPP_QUEUE_USER) + conn->send_queue_user_len--; + return ret; + default: + strophe_error(conn->ctx, "conn", "Unknown queue element %d", which); + return NULL; + } +} + /* timed handler for cleanup if normal disconnect procedure takes too long */ static int _disconnect_cleanup(xmpp_conn_t *conn, void *userdata) { @@ -1516,6 +1588,16 @@ static unsigned short _conn_default_port(xmpp_conn_t *conn, }; } +static char *_queue_element_free(xmpp_ctx_t *ctx, xmpp_send_queue_t *e) +{ + char *ret = e->data; + strophe_debug_verbose(2, ctx, "conn", "Q_FREE: %p", e); + memset(e, 0, sizeof(*e)); + strophe_free(ctx, e); + strophe_debug_verbose(3, ctx, "conn", "Q_CONTENT: %s", ret); + return ret; +} + static void _conn_reset(xmpp_conn_t *conn) { xmpp_ctx_t *ctx = conn->ctx; @@ -1531,8 +1613,7 @@ static void _conn_reset(xmpp_conn_t *conn) while (sq) { tsq = sq; sq = sq->next; - strophe_free(ctx, tsq->data); - strophe_free(ctx, tsq); + strophe_free(ctx, _queue_element_free(ctx, tsq)); } conn->send_queue_head = NULL; conn->send_queue_tail = NULL; diff --git a/strophe.h b/strophe.h index 8aac69f..20239d3 100644 --- a/strophe.h +++ b/strophe.h @@ -385,6 +385,13 @@ int xmpp_conn_is_connected(xmpp_conn_t *conn); int xmpp_conn_is_disconnected(xmpp_conn_t *conn); int xmpp_conn_send_queue_len(const xmpp_conn_t *conn); +typedef enum { + XMPP_QUEUE_OLDEST = -1, + XMPP_QUEUE_YOUNGEST = -2, +} xmpp_queue_element_t; +char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn, + xmpp_queue_element_t which); + int xmpp_connect_client(xmpp_conn_t *conn, const char *altdomain, unsigned short altport,