diff --git a/src/auth.c b/src/auth.c index 21ff896..fcc57ad 100644 --- a/src/auth.c +++ b/src/auth.c @@ -397,7 +397,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn, handler_add(conn, _handle_digestmd5_rspauth, XMPP_NS_SASL, NULL, NULL, NULL); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); } else { @@ -431,7 +431,7 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t *conn, } xmpp_stanza_set_name(auth, "response"); xmpp_stanza_set_ns(auth, XMPP_NS_SASL); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); } else { return _handle_sasl_result(conn, stanza, "DIGEST-MD5"); @@ -494,7 +494,7 @@ static int _handle_scram_challenge(xmpp_conn_t *conn, xmpp_stanza_add_child(auth, authdata); xmpp_stanza_release(authdata); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); rc = 1; /* Keep handler */ @@ -624,7 +624,7 @@ static void _auth(xmpp_conn_t *conn) handler_add(conn, _handle_proceedtls_default, XMPP_NS_TLS, NULL, NULL, NULL); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); /* TLS was tried, unset flag */ @@ -652,7 +652,7 @@ static void _auth(xmpp_conn_t *conn) handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL, "ANONYMOUS"); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); /* SASL ANONYMOUS was tried, unset flag */ @@ -695,7 +695,7 @@ static void _auth(xmpp_conn_t *conn) handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL, "EXTERNAL"); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); /* SASL EXTERNAL was tried, unset flag */ @@ -760,7 +760,7 @@ static void _auth(xmpp_conn_t *conn) handler_add(conn, _handle_scram_challenge, XMPP_NS_SASL, NULL, NULL, (void *)scram_ctx); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); /* SASL SCRAM-SHA-1 was tried, unset flag */ @@ -775,7 +775,7 @@ static void _auth(xmpp_conn_t *conn) handler_add(conn, _handle_digestmd5_challenge, XMPP_NS_SASL, NULL, NULL, NULL); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); /* SASL DIGEST-MD5 was tried, unset flag */ @@ -811,7 +811,7 @@ static void _auth(xmpp_conn_t *conn) handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL, "PLAIN"); - xmpp_send(conn, auth); + send_stanza(conn, auth, XMPP_QUEUE_STROPHE); xmpp_stanza_release(auth); /* SASL PLAIN was tried */ @@ -978,7 +978,7 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_release(bind); /* send bind request */ - xmpp_send(conn, iq); + send_stanza(conn, iq, XMPP_QUEUE_STROPHE); xmpp_stanza_release(iq); } else { /* can't bind, disconnect */ @@ -1057,7 +1057,7 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_release(session); /* send session establishment request */ - xmpp_send(conn, iq); + send_stanza(conn, iq, XMPP_QUEUE_STROPHE); xmpp_stanza_release(iq); } @@ -1070,7 +1070,7 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_set_name(enable, "enable"); xmpp_stanza_set_ns(enable, XMPP_NS_SM); handler_add(conn, _handle_sm, XMPP_NS_SM, NULL, NULL, NULL); - xmpp_send(conn, enable); + send_stanza(conn, enable, XMPP_QUEUE_SM_STROPHE); xmpp_stanza_release(enable); conn->sm_sent_nr = 0; } @@ -1284,7 +1284,7 @@ static void _auth_legacy(xmpp_conn_t *conn) handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL); handler_add_timed(conn, _handle_missing_legacy, LEGACY_TIMEOUT, NULL); - xmpp_send(conn, iq); + send_stanza(conn, iq, XMPP_QUEUE_STROPHE); xmpp_stanza_release(iq); return; @@ -1347,8 +1347,8 @@ int _handle_component_auth(xmpp_conn_t *conn) strlen(digest)); /* Send the digest to the server */ - xmpp_send_raw_string(conn, "%s", - XMPP_NS_COMPONENT, digest); + send_raw_string(conn, "%s", + XMPP_NS_COMPONENT, digest); strophe_debug(conn->ctx, "auth", "Sent component handshake to the server."); strophe_free(conn->ctx, digest); diff --git a/src/common.h b/src/common.h index 76d75e6..5723484 100644 --- a/src/common.h +++ b/src/common.h @@ -128,11 +128,19 @@ typedef enum { XMPP_STATE_CONNECTED } xmpp_conn_state_t; +typedef enum { + XMPP_QUEUE_STROPHE = 0x1, + XMPP_QUEUE_USER = 0x2, + XMPP_QUEUE_SM = 0x800, + XMPP_QUEUE_SM_STROPHE = XMPP_QUEUE_SM | XMPP_QUEUE_STROPHE, +} xmpp_send_queue_owner_t; + typedef struct _xmpp_send_queue_t xmpp_send_queue_t; struct _xmpp_send_queue_t { char *data; size_t len; size_t written; + xmpp_send_queue_owner_t owner; xmpp_send_queue_t *next; }; @@ -220,6 +228,7 @@ struct _xmpp_conn_t { int blocking_send; int send_queue_max; int send_queue_len; + int send_queue_user_len; xmpp_send_queue_t *send_queue_head; xmpp_send_queue_t *send_queue_tail; @@ -308,4 +317,17 @@ void auth_handle_component_open(xmpp_conn_t *conn); void auth_handle_open_raw(xmpp_conn_t *conn); void auth_handle_open_stub(xmpp_conn_t *conn); +/* send functions */ +void send_raw(xmpp_conn_t *conn, + const char *data, + size_t len, + xmpp_send_queue_owner_t owner); +/* this is a bit special as it will always mark the sent string as + * owned by libstrophe + */ +void send_raw_string(xmpp_conn_t *conn, const char *fmt, ...); +void send_stanza(xmpp_conn_t *conn, + xmpp_stanza_t *stanza, + xmpp_send_queue_owner_t owner); + #endif /* __LIBSTROPHE_COMMON_H__ */ diff --git a/src/conn.c b/src/conn.c index b8fbae2..b099819 100644 --- a/src/conn.c +++ b/src/conn.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "strophe.h" @@ -106,13 +108,20 @@ static int _conn_connect(xmpp_conn_t *conn, xmpp_conn_type_t type, xmpp_conn_handler callback, void *userdata); -static int _send_raw(xmpp_conn_t *conn, char *data, size_t len); +static void _send_valist(xmpp_conn_t *conn, + const char *fmt, + va_list ap, + xmpp_send_queue_owner_t owner); +static int _send_raw(xmpp_conn_t *conn, + char *data, + size_t len, + xmpp_send_queue_owner_t owner); void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text) { xmpp_stanza_t *error = xmpp_error_new(conn->ctx, type, text); - xmpp_send(conn, error); + send_stanza(conn, error, XMPP_QUEUE_STROPHE); xmpp_stanza_release(error); } @@ -152,6 +161,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx) conn->blocking_send = 0; conn->send_queue_max = DEFAULT_SEND_QUEUE_MAX; conn->send_queue_len = 0; + conn->send_queue_user_len = 0; conn->send_queue_head = NULL; conn->send_queue_tail = NULL; @@ -985,7 +995,7 @@ void xmpp_disconnect(xmpp_conn_t *conn) return; /* close the stream */ - xmpp_send_raw_string(conn, ""); + send_raw_string(conn, ""); /* setup timed handler in case disconnect takes too long */ handler_add_timed(conn, _disconnect_cleanup, DISCONNECT_TIMEOUT, NULL); @@ -1007,37 +1017,13 @@ void xmpp_disconnect(xmpp_conn_t *conn) void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...) { va_list ap; - size_t len; - char buf[1024]; /* small buffer for common case */ - char *bigbuf; if (conn->state != XMPP_STATE_CONNECTED) return; va_start(ap, fmt); - len = strophe_vsnprintf(buf, sizeof(buf), fmt, ap); + _send_valist(conn, fmt, ap, XMPP_QUEUE_USER); va_end(ap); - - if (len >= sizeof(buf)) { - /* we need more space for this data, so we allocate a big - * enough buffer and print to that */ - len++; /* account for trailing \0 */ - bigbuf = strophe_alloc(conn->ctx, len); - if (!bigbuf) { - strophe_debug(conn->ctx, "xmpp", - "Could not allocate memory for send_raw_string"); - return; - } - va_start(ap, fmt); - strophe_vsnprintf(bigbuf, len, fmt, ap); - va_end(ap); - - /* len - 1 so we don't send trailing \0 */ - _send_raw(conn, bigbuf, len - 1); - } else { - /* go through xmpp_send_raw() which does the strdup() for us */ - xmpp_send_raw(conn, buf, len); - } } /** Send raw bytes to the XMPP server. @@ -1054,18 +1040,7 @@ void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...) */ void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len) { - char *d; - - if (conn->state != XMPP_STATE_CONNECTED) - return; - - d = strophe_strndup(conn->ctx, data, len); - if (!d) { - strophe_error(conn->ctx, "conn", "Failed to strndup"); - return; - } - - _send_raw(conn, d, len); + send_raw(conn, data, len, XMPP_QUEUE_USER); } /** Send an XML stanza to the XMPP server. @@ -1079,18 +1054,7 @@ void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len) */ void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza) { - char *buf = NULL; - size_t len; - - if (conn->state != XMPP_STATE_CONNECTED) - return; - - if (xmpp_stanza_to_text(stanza, &buf, &len) != 0) { - strophe_error(conn->ctx, "conn", "Failed to stanza_to_text"); - return; - } - - _send_raw(conn, buf, len); + send_stanza(conn, stanza, XMPP_QUEUE_USER); } /** Send the opening <stream:stream> tag to the server. @@ -1355,7 +1319,7 @@ static int _conn_open_stream_with_attributes(xmpp_conn_t *conn, if (!tag) return XMPP_EMEM; - xmpp_send_raw_string(conn, "%s", tag); + send_raw_string(conn, "%s", tag); strophe_free(conn->ctx, tag); return XMPP_EOK; @@ -1518,7 +1482,7 @@ static void _conn_sm_handle_stanza(xmpp_conn_t *const conn, xmpp_stanza_set_ns(a, XMPP_NS_SM); strophe_snprintf(h, sizeof(h), "%u", conn->sm_handled_nr); xmpp_stanza_set_attribute(a, "h", h); - xmpp_send(conn, a); + send_stanza(conn, a, XMPP_QUEUE_SM_STROPHE); xmpp_stanza_release(a); } } @@ -1559,6 +1523,7 @@ static void _conn_reset(xmpp_conn_t *conn) conn->send_queue_head = NULL; conn->send_queue_tail = NULL; conn->send_queue_len = 0; + conn->send_queue_user_len = 0; if (conn->stream_error) { xmpp_stanza_release(conn->stream_error->stanza); @@ -1642,9 +1607,101 @@ static int _conn_connect(xmpp_conn_t *conn, return 0; } -static int _send_raw(xmpp_conn_t *conn, char *data, size_t len) +void send_raw(xmpp_conn_t *conn, + const char *data, + size_t len, + xmpp_send_queue_owner_t owner) +{ + char *d; + + if (conn->state != XMPP_STATE_CONNECTED) + return; + + d = strophe_strndup(conn->ctx, data, len); + if (!d) { + strophe_error(conn->ctx, "conn", "Failed to strndup"); + return; + } + + _send_raw(conn, d, len, owner); +} + +static void _send_valist(xmpp_conn_t *conn, + const char *fmt, + va_list ap, + xmpp_send_queue_owner_t owner) +{ + va_list apdup; + size_t len; + char buf[1024]; /* small buffer for common case */ + char *bigbuf; + + if (conn->state != XMPP_STATE_CONNECTED) + return; + + va_copy(apdup, ap); + len = strophe_vsnprintf(buf, sizeof(buf), fmt, apdup); + va_end(apdup); + + if (len >= sizeof(buf)) { + /* we need more space for this data, so we allocate a big + * enough buffer and print to that */ + len++; /* account for trailing \0 */ + bigbuf = strophe_alloc(conn->ctx, len); + if (!bigbuf) { + strophe_debug(conn->ctx, "xmpp", + "Could not allocate memory for send_raw_string"); + return; + } + va_copy(apdup, ap); + strophe_vsnprintf(bigbuf, len, fmt, apdup); + va_end(apdup); + + /* len - 1 so we don't send trailing \0 */ + _send_raw(conn, bigbuf, len - 1, owner); + } else { + /* go through send_raw() which does the strdup() for us */ + send_raw(conn, buf, len, owner); + } +} + +void send_raw_string(xmpp_conn_t *conn, const char *fmt, ...) +{ + va_list ap; + + if (conn->state != XMPP_STATE_CONNECTED) + return; + + va_start(ap, fmt); + _send_valist(conn, fmt, ap, XMPP_QUEUE_SM_STROPHE); + va_end(ap); +} + +void send_stanza(xmpp_conn_t *conn, + xmpp_stanza_t *stanza, + xmpp_send_queue_owner_t owner) +{ + char *buf = NULL; + size_t len; + + if (conn->state != XMPP_STATE_CONNECTED) + return; + + if (xmpp_stanza_to_text(stanza, &buf, &len) != 0) { + strophe_error(conn->ctx, "conn", "Failed to stanza_to_text"); + return; + } + + _send_raw(conn, buf, len, owner); +} + +static int _send_raw(xmpp_conn_t *conn, + char *data, + size_t len, + xmpp_send_queue_owner_t owner) { xmpp_send_queue_t *item; + const char *req_ack = ""; /* create send queue item for queue */ item = strophe_alloc(conn->ctx, sizeof(xmpp_send_queue_t)); @@ -1658,8 +1715,8 @@ static int _send_raw(xmpp_conn_t *conn, char *data, size_t len) item->len = len; item->next = NULL; item->written = 0; + item->owner = owner; - /* add item to the send queue */ if (!conn->send_queue_tail) { /* first item, set head and tail */ conn->send_queue_head = item; @@ -1670,8 +1727,9 @@ static int _send_raw(xmpp_conn_t *conn, char *data, size_t len) conn->send_queue_tail = item; } conn->send_queue_len++; - strophe_debug_verbose(2, conn->ctx, "conn", "QUEUED: %s", data); - strophe_debug_verbose(1, conn->ctx, "conn", "Added queue element: %p", - item); + if (owner == XMPP_QUEUE_USER) + conn->send_queue_user_len++; + strophe_debug_verbose(3, conn->ctx, "conn", "QUEUED: %s", data); + strophe_debug_verbose(1, conn->ctx, "conn", "Q_ADD: %p", item); return XMPP_EOK; } diff --git a/src/crypto.c b/src/crypto.c index 60c3371..7e6af39 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -22,11 +22,11 @@ #include #include /* memset, memcpy */ -#include "common.h" /* xmpp_alloc */ +#include "common.h" /* strophe_alloc */ #include "ostypes.h" /* uint8_t, size_t */ #include "sha1.h" #include "snprintf.h" /* xmpp_snprintf */ -#include "strophe.h" /* xmpp_ctx_t, xmpp_free */ +#include "strophe.h" /* xmpp_ctx_t, strophe_free */ struct _xmpp_sha1_t { xmpp_ctx_t *xmpp_ctx; @@ -187,9 +187,9 @@ char *xmpp_sha1_to_string(xmpp_sha1_t *sha1, char *s, size_t slen) } /** Return message digest rendered as a string. - * Returns an allocated string. Free the string using the Strophe context - * which is passed to xmpp_sha1_new(). Call this function after - * xmpp_sha1_final(). + * Returns an allocated string. Free the string by calling xmpp_free() using + * the Strophe context which is passed to xmpp_sha1_new(). Call this function + * after xmpp_sha1_final(). * * @param sha1 a SHA1 object * diff --git a/src/ctx.c b/src/ctx.c index 703a6d2..4bcc926 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -255,8 +255,8 @@ void *strophe_realloc(const xmpp_ctx_t *ctx, void *p, size_t size) * Write a log message to the logger for the context for the specified * level and area. This function takes a printf-style format string and a * variable argument list (in va_list) format. This function is not meant - * to be called directly, but is used via xmpp_error, xmpp_warn, xmpp_info, - * and xmpp_debug. + * to be called directly, but is used via strophe_error, strophe_warn, + * strophe_info, and strophe_debug. * * @param ctx a Strophe context object * @param level the level at which to log diff --git a/src/event.c b/src/event.c index 30e4856..3bf4a73 100644 --- a/src/event.c +++ b/src/event.c @@ -142,6 +142,8 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout) tsq = sq; sq = sq->next; conn->send_queue_len--; + if (tsq->owner & XMPP_QUEUE_USER) + conn->send_queue_user_len--; strophe_free(ctx, tsq); /* pop the top item */ diff --git a/src/rand.c b/src/rand.c index 58de330..061e85e 100644 --- a/src/rand.c +++ b/src/rand.c @@ -32,7 +32,7 @@ #endif #endif -#include "common.h" /* xmpp_alloc, xmpp_free */ +#include "common.h" /* strophe_alloc, strophe_free */ #include "ostypes.h" /* uint8_t, uint32_t, size_t */ #ifndef USE_GETRANDOM diff --git a/src/stanza.c b/src/stanza.c index ef33b6b..24e6fe8 100644 --- a/src/stanza.c +++ b/src/stanza.c @@ -1509,7 +1509,7 @@ xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx) * The error text is optional and may be NULL. * * @param ctx a Strophe context object - * @param type enum of xmpp_error_type_t + * @param type enum of strophe_error_type_t * @param text content of a 'text' * * @return a new Strophe stanza object