First version of XEP-0138 support
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
This commit is contained in:
166
src/auth.c
166
src/auth.c
@@ -62,6 +62,7 @@
|
||||
|
||||
static void _auth(xmpp_conn_t *conn);
|
||||
static void _auth_legacy(xmpp_conn_t *conn);
|
||||
static void _handle_open_compress(xmpp_conn_t *conn);
|
||||
static void _handle_open_sasl(xmpp_conn_t *conn);
|
||||
static void _handle_open_tls(xmpp_conn_t *conn);
|
||||
|
||||
@@ -72,6 +73,9 @@ static int _handle_component_hs_response(xmpp_conn_t *conn,
|
||||
|
||||
static int
|
||||
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata);
|
||||
static int _handle_features_compress(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata);
|
||||
static int
|
||||
_handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata);
|
||||
static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
|
||||
@@ -207,10 +211,61 @@ static int _handle_missing_features(xmpp_conn_t *conn, void *userdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef void (*text_handler)(xmpp_conn_t *conn, const char *text);
|
||||
static void _foreach_child(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *parent,
|
||||
const char *name,
|
||||
text_handler hndl)
|
||||
{
|
||||
xmpp_stanza_t *children;
|
||||
for (children = xmpp_stanza_get_children(parent); children;
|
||||
children = xmpp_stanza_get_next(children)) {
|
||||
const char *child_name = xmpp_stanza_get_name(children);
|
||||
if (child_name && strcmp(child_name, name) == 0) {
|
||||
char *text = xmpp_stanza_get_text(children);
|
||||
if (text == NULL)
|
||||
continue;
|
||||
|
||||
hndl(conn, text);
|
||||
|
||||
strophe_free(conn->ctx, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _handle_sasl_children(xmpp_conn_t *conn, const char *text)
|
||||
{
|
||||
if (strcasecmp(text, "PLAIN") == 0) {
|
||||
conn->sasl_support |= SASL_MASK_PLAIN;
|
||||
} else if (strcasecmp(text, "EXTERNAL") == 0 &&
|
||||
(conn->tls_client_cert || conn->tls_client_key)) {
|
||||
conn->sasl_support |= SASL_MASK_EXTERNAL;
|
||||
} else if (strcasecmp(text, "DIGEST-MD5") == 0) {
|
||||
conn->sasl_support |= SASL_MASK_DIGESTMD5;
|
||||
} else if (strcasecmp(text, "ANONYMOUS") == 0) {
|
||||
conn->sasl_support |= SASL_MASK_ANONYMOUS;
|
||||
} else {
|
||||
size_t n;
|
||||
for (n = 0; n < scram_algs_num; ++n) {
|
||||
if (strcasecmp(text, scram_algs[n]->scram_name) == 0) {
|
||||
conn->sasl_support |= scram_algs[n]->mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _handle_compression_children(xmpp_conn_t *conn, const char *text)
|
||||
{
|
||||
if (strcasecmp(text, "zlib") == 0) {
|
||||
conn->compression_supported = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
{
|
||||
xmpp_stanza_t *child, *mech;
|
||||
xmpp_stanza_t *child, *children;
|
||||
const char *ns;
|
||||
char *text;
|
||||
|
||||
@@ -222,10 +277,9 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
/* check for TLS */
|
||||
if (!conn->secured) {
|
||||
if (!conn->tls_disabled) {
|
||||
child = xmpp_stanza_get_child_by_name(stanza, "starttls");
|
||||
if (child) {
|
||||
ns = xmpp_stanza_get_ns(child);
|
||||
conn->tls_support = ns != NULL && strcmp(ns, XMPP_NS_TLS) == 0;
|
||||
if (xmpp_stanza_get_child_by_name_and_ns(stanza, "starttls",
|
||||
XMPP_NS_TLS)) {
|
||||
conn->tls_support = 1;
|
||||
}
|
||||
} else {
|
||||
conn->tls_support = 0;
|
||||
@@ -233,45 +287,23 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
}
|
||||
|
||||
/* check for SASL */
|
||||
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
|
||||
ns = child ? xmpp_stanza_get_ns(child) : NULL;
|
||||
if (child && ns && strcmp(ns, XMPP_NS_SASL) == 0) {
|
||||
for (mech = xmpp_stanza_get_children(child); mech;
|
||||
mech = xmpp_stanza_get_next(mech)) {
|
||||
if (xmpp_stanza_get_name(mech) &&
|
||||
strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) {
|
||||
text = xmpp_stanza_get_text(mech);
|
||||
if (text == NULL)
|
||||
continue;
|
||||
|
||||
if (strcasecmp(text, "PLAIN") == 0) {
|
||||
conn->sasl_support |= SASL_MASK_PLAIN;
|
||||
} else if (strcasecmp(text, "EXTERNAL") == 0 &&
|
||||
(conn->tls_client_cert || conn->tls_client_key)) {
|
||||
conn->sasl_support |= SASL_MASK_EXTERNAL;
|
||||
} else if (strcasecmp(text, "DIGEST-MD5") == 0) {
|
||||
conn->sasl_support |= SASL_MASK_DIGESTMD5;
|
||||
} else if (strcasecmp(text, "ANONYMOUS") == 0) {
|
||||
conn->sasl_support |= SASL_MASK_ANONYMOUS;
|
||||
} else {
|
||||
size_t n;
|
||||
for (n = 0; n < scram_algs_num; ++n) {
|
||||
if (strcasecmp(text, scram_algs[n]->scram_name) == 0) {
|
||||
conn->sasl_support |= scram_algs[n]->mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strophe_free(conn->ctx, text);
|
||||
}
|
||||
}
|
||||
child = xmpp_stanza_get_child_by_name_and_ns(stanza, "mechanisms",
|
||||
XMPP_NS_SASL);
|
||||
if (child) {
|
||||
_foreach_child(conn, child, "mechanism", _handle_sasl_children);
|
||||
}
|
||||
|
||||
/* Disable PLAIN when other secure mechanisms are supported */
|
||||
if (conn->sasl_support & ~(SASL_MASK_PLAIN | SASL_MASK_ANONYMOUS))
|
||||
conn->sasl_support &= ~SASL_MASK_PLAIN;
|
||||
|
||||
/* check for compression */
|
||||
child = xmpp_stanza_get_child_by_name_and_ns(stanza, "compression",
|
||||
XMPP_NS_COMPRESSION);
|
||||
if (conn->compression_allowed && child) {
|
||||
_foreach_child(conn, child, "method", _handle_compression_children);
|
||||
}
|
||||
|
||||
_auth(conn);
|
||||
|
||||
return 0;
|
||||
@@ -339,7 +371,9 @@ _handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
(char *)userdata);
|
||||
|
||||
/* reset parser */
|
||||
conn_prepare_reset(conn, _handle_open_sasl);
|
||||
conn_prepare_reset(conn, conn->compression_allowed
|
||||
? _handle_open_compress
|
||||
: _handle_open_sasl);
|
||||
|
||||
/* send stream tag */
|
||||
conn_open_stream(conn);
|
||||
@@ -950,6 +984,17 @@ static void _handle_open_sasl(xmpp_conn_t *conn)
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* called when stream:stream tag received after compression has been enabled */
|
||||
static void _handle_open_compress(xmpp_conn_t *conn)
|
||||
{
|
||||
strophe_debug(conn->ctx, "xmpp", "Reopened stream successfully.");
|
||||
|
||||
/* setup stream:features handlers */
|
||||
handler_add(conn, _handle_features_compress, XMPP_NS_STREAMS, "features",
|
||||
NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_features, FEATURES_TIMEOUT, NULL);
|
||||
}
|
||||
|
||||
static int _do_bind(xmpp_conn_t *conn, xmpp_stanza_t *bind)
|
||||
{
|
||||
xmpp_stanza_t *iq, *res, *text;
|
||||
@@ -1007,6 +1052,49 @@ static int _do_bind(xmpp_conn_t *conn, xmpp_stanza_t *bind)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _handle_compress_result(xmpp_conn_t *const conn,
|
||||
xmpp_stanza_t *const stanza,
|
||||
void *const userdata)
|
||||
{
|
||||
const char *name = xmpp_stanza_get_name(stanza);
|
||||
|
||||
if (!name)
|
||||
return 0;
|
||||
if (strcmp(name, "compressed") == 0) {
|
||||
/* Stream compression enabled, we need to restart the stream */
|
||||
strophe_debug(conn->ctx, "xmpp", "Stream compression enabled");
|
||||
|
||||
/* reset parser */
|
||||
conn_prepare_reset(conn, _handle_open_sasl);
|
||||
|
||||
/* make compression effective */
|
||||
conn->compress = 1;
|
||||
|
||||
/* send stream tag */
|
||||
conn_open_stream(conn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _handle_features_compress(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata)
|
||||
{
|
||||
const char *compress = "<compress xmlns='" XMPP_NS_COMPRESSION
|
||||
"'><method>zlib</method></compress>";
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
/* remove missing features handler */
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_features);
|
||||
|
||||
send_raw(conn, compress, strlen(compress), XMPP_QUEUE_STROPHE, NULL);
|
||||
handler_add(conn, _handle_compress_result, XMPP_NS_COMPRESSION, NULL, NULL,
|
||||
NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "strophe.h"
|
||||
#include "ostypes.h"
|
||||
@@ -255,6 +256,13 @@ struct _xmpp_conn_t {
|
||||
int sm_disable;
|
||||
xmpp_sm_state_t *sm_state;
|
||||
|
||||
int compression_allowed, compression_supported;
|
||||
int compress, compression_dont_flush;
|
||||
struct zlib_compression {
|
||||
void *buffer, *buffer_end;
|
||||
z_stream stream;
|
||||
} compression, decompression;
|
||||
|
||||
char *lang;
|
||||
char *domain;
|
||||
char *jid;
|
||||
|
||||
36
src/conn.c
36
src/conn.c
@@ -1106,12 +1106,15 @@ long xmpp_conn_get_flags(const xmpp_conn_t *conn)
|
||||
{
|
||||
long flags;
|
||||
|
||||
flags = XMPP_CONN_FLAG_DISABLE_TLS * conn->tls_disabled |
|
||||
XMPP_CONN_FLAG_MANDATORY_TLS * conn->tls_mandatory |
|
||||
XMPP_CONN_FLAG_LEGACY_SSL * conn->tls_legacy_ssl |
|
||||
XMPP_CONN_FLAG_TRUST_TLS * conn->tls_trust |
|
||||
XMPP_CONN_FLAG_DISABLE_SM * conn->sm_disable |
|
||||
XMPP_CONN_FLAG_LEGACY_AUTH * conn->auth_legacy_enabled;
|
||||
flags =
|
||||
XMPP_CONN_FLAG_DISABLE_TLS * conn->tls_disabled |
|
||||
XMPP_CONN_FLAG_MANDATORY_TLS * conn->tls_mandatory |
|
||||
XMPP_CONN_FLAG_LEGACY_SSL * conn->tls_legacy_ssl |
|
||||
XMPP_CONN_FLAG_TRUST_TLS * conn->tls_trust |
|
||||
XMPP_CONN_FLAG_DISABLE_SM * conn->sm_disable |
|
||||
XMPP_CONN_FLAG_ENABLE_COMPRESSION * conn->compression_allowed |
|
||||
XMPP_CONN_FLAG_COMPRESSION_DONT_FLUSH * conn->compression_dont_flush |
|
||||
XMPP_CONN_FLAG_LEGACY_AUTH * conn->auth_legacy_enabled;
|
||||
|
||||
return flags;
|
||||
}
|
||||
@@ -1160,6 +1163,19 @@ int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags)
|
||||
conn->tls_trust = (flags & XMPP_CONN_FLAG_TRUST_TLS) ? 1 : 0;
|
||||
conn->auth_legacy_enabled = (flags & XMPP_CONN_FLAG_LEGACY_AUTH) ? 1 : 0;
|
||||
conn->sm_disable = (flags & XMPP_CONN_FLAG_DISABLE_SM) ? 1 : 0;
|
||||
conn->compression_allowed =
|
||||
(flags & XMPP_CONN_FLAG_ENABLE_COMPRESSION) ? 1 : 0;
|
||||
conn->compression_dont_flush =
|
||||
(flags & XMPP_CONN_FLAG_COMPRESSION_DONT_FLUSH) ? 1 : 0;
|
||||
flags &= ~(XMPP_CONN_FLAG_DISABLE_TLS | XMPP_CONN_FLAG_MANDATORY_TLS |
|
||||
XMPP_CONN_FLAG_LEGACY_SSL | XMPP_CONN_FLAG_TRUST_TLS |
|
||||
XMPP_CONN_FLAG_LEGACY_AUTH | XMPP_CONN_FLAG_DISABLE_SM |
|
||||
XMPP_CONN_FLAG_ENABLE_COMPRESSION |
|
||||
XMPP_CONN_FLAG_COMPRESSION_DONT_FLUSH);
|
||||
if (flags) {
|
||||
strophe_error(conn->ctx, "conn", "Flags 0x%04lx unknown", flags);
|
||||
return XMPP_EINVOP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1752,6 +1768,14 @@ static void _conn_reset(xmpp_conn_t *conn)
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->compression.buffer) {
|
||||
deflateEnd(&conn->compression.stream);
|
||||
strophe_free_and_null(ctx, conn->compression.buffer);
|
||||
}
|
||||
if (conn->decompression.buffer) {
|
||||
inflateEnd(&conn->decompression.stream);
|
||||
strophe_free_and_null(ctx, conn->decompression.buffer);
|
||||
}
|
||||
/* free queued */
|
||||
sq = conn->send_queue_head;
|
||||
while (sq) {
|
||||
|
||||
222
src/event.c
222
src/event.c
@@ -75,6 +75,202 @@ static int _connect_next(xmpp_conn_t *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_conn_write_to_network(xmpp_conn_t *conn, const void *buff, size_t len)
|
||||
{
|
||||
int ret;
|
||||
if (conn->tls) {
|
||||
ret = tls_write(conn->tls, buff, len);
|
||||
if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls)))
|
||||
conn->error = tls_error(conn->tls);
|
||||
} else {
|
||||
ret = sock_write(conn->sock, buff, len);
|
||||
if (ret < 0 && !sock_is_recoverable(sock_error()))
|
||||
conn->error = sock_error();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _try_compressed_write_to_network(xmpp_conn_t *conn, int force)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t len =
|
||||
conn->compression.stream.next_out - (Bytef *)conn->compression.buffer;
|
||||
int buffer_full =
|
||||
conn->compression.stream.next_out == conn->compression.buffer_end;
|
||||
if ((buffer_full || force) && len) {
|
||||
ret = _conn_write_to_network(conn, conn->compression.buffer, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
// print_hex(xmpp_base64_encode(conn->ctx,
|
||||
// conn->compression.buffer, len),
|
||||
// conn->compression.buffer, len);
|
||||
char *b = xmpp_base64_encode(conn->ctx, conn->compression.buffer, len);
|
||||
printf("Sent: %s\n", b);
|
||||
xmpp_free(conn->ctx, b);
|
||||
|
||||
conn->compression.stream.next_out = conn->compression.buffer;
|
||||
conn->compression.stream.avail_out = STROPHE_MESSAGE_BUFFER_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _conn_compress(xmpp_conn_t *conn, void *buff, size_t len, int flush)
|
||||
{
|
||||
int ret;
|
||||
void *buff_end = buff + len;
|
||||
conn->compression.stream.next_in = buff;
|
||||
conn->compression.stream.avail_in = len;
|
||||
do {
|
||||
ret = _try_compressed_write_to_network(conn, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = deflate(&conn->compression.stream, flush);
|
||||
if (ret == Z_STREAM_END) {
|
||||
break;
|
||||
}
|
||||
if (flush && ret == Z_BUF_ERROR) {
|
||||
break;
|
||||
}
|
||||
if (ret != Z_OK) {
|
||||
strophe_error(conn->ctx, "zlib", "deflate error %d", ret);
|
||||
conn->error = EBADFD;
|
||||
conn_disconnect(conn);
|
||||
return ret;
|
||||
}
|
||||
ret = conn->compression.stream.next_in - (const Bytef *)buff;
|
||||
} while (conn->compression.stream.next_in < (const Bytef *)buff_end);
|
||||
if (flush) {
|
||||
ret = _try_compressed_write_to_network(conn, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *_zlib_alloc(void *opaque, unsigned int items, unsigned int size)
|
||||
{
|
||||
size_t sz = items * size;
|
||||
if (sz < items || sz < size)
|
||||
return NULL;
|
||||
return strophe_alloc(opaque, sz);
|
||||
}
|
||||
|
||||
static void _init_zlib_compression(xmpp_ctx_t *ctx, struct zlib_compression *s)
|
||||
{
|
||||
s->buffer = strophe_alloc(ctx, STROPHE_MESSAGE_BUFFER_SIZE);
|
||||
s->buffer_end = s->buffer + STROPHE_MESSAGE_BUFFER_SIZE;
|
||||
|
||||
s->stream.opaque = ctx;
|
||||
s->stream.zalloc = _zlib_alloc;
|
||||
s->stream.zfree = (free_func)strophe_free;
|
||||
}
|
||||
|
||||
static int _conn_write(xmpp_conn_t *conn, void *buff, size_t len)
|
||||
{
|
||||
if (conn->compress) {
|
||||
if (conn->compression.buffer == NULL) {
|
||||
_init_zlib_compression(conn->ctx, &conn->compression);
|
||||
|
||||
conn->compression.stream.next_out = conn->compression.buffer;
|
||||
conn->compression.stream.avail_out = STROPHE_MESSAGE_BUFFER_SIZE;
|
||||
int err =
|
||||
deflateInit(&conn->compression.stream, Z_DEFAULT_COMPRESSION);
|
||||
if (err != Z_OK) {
|
||||
strophe_free_and_null(conn->ctx, conn->compression.buffer);
|
||||
conn->error = EBADFD;
|
||||
conn_disconnect(conn);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return _conn_compress(conn, buff, len, Z_NO_FLUSH);
|
||||
} else {
|
||||
return _conn_write_to_network(conn, buff, len);
|
||||
}
|
||||
}
|
||||
|
||||
static int _conn_read_from_network(xmpp_conn_t *conn, void *buff, size_t len)
|
||||
{
|
||||
if (conn->tls) {
|
||||
return tls_read(conn->tls, buff, len);
|
||||
} else {
|
||||
return sock_read(conn->sock, buff, len);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_conn_decompress(xmpp_conn_t *conn, size_t c_len, void *buff, size_t len)
|
||||
{
|
||||
if (conn->decompression.stream.next_in == NULL) {
|
||||
conn->decompression.stream.next_in = conn->decompression.buffer;
|
||||
conn->decompression.buffer_end =
|
||||
conn->decompression.stream.next_in + c_len;
|
||||
conn->decompression.stream.avail_in = c_len;
|
||||
} else if (c_len) {
|
||||
strophe_error(conn->ctx, "zlib",
|
||||
"_conn_decompress() called with c_len=%zu", c_len);
|
||||
}
|
||||
conn->decompression.stream.next_out = buff;
|
||||
conn->decompression.stream.avail_out = len;
|
||||
int ret = inflate(&conn->decompression.stream, Z_SYNC_FLUSH);
|
||||
switch (ret) {
|
||||
case Z_STREAM_END:
|
||||
case Z_OK:
|
||||
if (conn->decompression.buffer_end ==
|
||||
conn->decompression.stream.next_in)
|
||||
conn->decompression.stream.next_in = NULL;
|
||||
/* -fallthrough */
|
||||
return conn->decompression.stream.next_out - (Bytef *)buff;
|
||||
case Z_BUF_ERROR:
|
||||
break;
|
||||
default:
|
||||
strophe_error(conn->ctx, "zlib", "inflate error %d", ret);
|
||||
conn->error = EBADFD;
|
||||
conn_disconnect(conn);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _conn_read(xmpp_conn_t *conn, void *buff, size_t len)
|
||||
{
|
||||
void *dbuff = buff;
|
||||
size_t dlen = len;
|
||||
if (conn->compress) {
|
||||
if (conn->decompression.buffer == NULL) {
|
||||
_init_zlib_compression(conn->ctx, &conn->decompression);
|
||||
|
||||
int err = inflateInit(&conn->decompression.stream);
|
||||
if (err != Z_OK) {
|
||||
strophe_free_and_null(conn->ctx, conn->decompression.buffer);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (conn->decompression.stream.next_in != NULL) {
|
||||
return _conn_decompress(conn, 0, buff, len);
|
||||
}
|
||||
dbuff = conn->decompression.buffer;
|
||||
dlen = STROPHE_MESSAGE_BUFFER_SIZE;
|
||||
}
|
||||
int ret = _conn_read_from_network(conn, dbuff, dlen);
|
||||
if (ret > 0 && conn->compress) {
|
||||
char *b = xmpp_base64_encode(conn->ctx, dbuff, ret);
|
||||
printf("Read: %s\n", b);
|
||||
xmpp_free(conn->ctx, b);
|
||||
return _conn_decompress(conn, ret, buff, len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _conn_pending(xmpp_conn_t *conn)
|
||||
{
|
||||
return (conn->compress && conn->decompression.stream.next_in != NULL) ||
|
||||
(conn->tls && tls_pending(conn->tls));
|
||||
}
|
||||
|
||||
/** Run the event loop once.
|
||||
* This function will run send any data that has been queued by
|
||||
* xmpp_send and related functions and run through the Strophe even
|
||||
@@ -136,15 +332,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
|
||||
while (sq) {
|
||||
towrite = sq->len - sq->written;
|
||||
|
||||
if (conn->tls) {
|
||||
ret = tls_write(conn->tls, &sq->data[sq->written], towrite);
|
||||
if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls)))
|
||||
conn->error = tls_error(conn->tls);
|
||||
} else {
|
||||
ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
|
||||
if (ret < 0 && !sock_is_recoverable(sock_error()))
|
||||
conn->error = sock_error();
|
||||
}
|
||||
ret = _conn_write(conn, &sq->data[sq->written], towrite);
|
||||
if (ret > 0 && ret < towrite)
|
||||
sq->written += ret; /* not all data could be sent now */
|
||||
sq->wip = 1;
|
||||
@@ -181,6 +369,11 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
|
||||
if (!sq)
|
||||
conn->send_queue_tail = NULL;
|
||||
}
|
||||
if (conn->compress) {
|
||||
_conn_compress(conn, conn->compression.buffer, 0,
|
||||
conn->compression_dont_flush ? Z_SYNC_FLUSH
|
||||
: Z_FULL_FLUSH);
|
||||
}
|
||||
|
||||
/* tear down connection on error */
|
||||
if (conn->error) {
|
||||
@@ -309,14 +502,9 @@ next_item:
|
||||
|
||||
break;
|
||||
case XMPP_STATE_CONNECTED:
|
||||
if (FD_ISSET(conn->sock, &rfds) ||
|
||||
(conn->tls && tls_pending(conn->tls))) {
|
||||
if (conn->tls) {
|
||||
ret = tls_read(conn->tls, buf, STROPHE_MESSAGE_BUFFER_SIZE);
|
||||
} else {
|
||||
ret =
|
||||
sock_read(conn->sock, buf, STROPHE_MESSAGE_BUFFER_SIZE);
|
||||
}
|
||||
if (FD_ISSET(conn->sock, &rfds) || _conn_pending(conn)) {
|
||||
|
||||
ret = _conn_read(conn, buf, STROPHE_MESSAGE_BUFFER_SIZE);
|
||||
|
||||
if (ret > 0) {
|
||||
ret = parser_feed(conn->parser, buf, ret);
|
||||
|
||||
Reference in New Issue
Block a user