Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4b05cf156 | ||
|
|
06da6d5125 | ||
|
|
1bcf77608d | ||
|
|
aab0cc3e3e | ||
|
|
822f95071a | ||
|
|
27f613bc84 | ||
|
|
af1ef3855b | ||
|
|
7ede9c6d03 | ||
|
|
20c6f225b9 | ||
|
|
5b204b0938 | ||
|
|
6e6093ee7b | ||
|
|
f12d43989f | ||
|
|
032e8ec89d | ||
|
|
d0644c5e95 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -34,7 +34,6 @@ examples/active
|
|||||||
examples/basic
|
examples/basic
|
||||||
examples/bot
|
examples/bot
|
||||||
examples/component
|
examples/component
|
||||||
examples/ext_auth
|
|
||||||
examples/roster
|
examples/roster
|
||||||
examples/uuid
|
examples/uuid
|
||||||
examples/vcard
|
examples/vcard
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
userdata
|
userdata
|
||||||
- System handlers are deleted on xmpp_conn_t reconnection. Old system
|
- System handlers are deleted on xmpp_conn_t reconnection. Old system
|
||||||
handlers could cause problems
|
handlers could cause problems
|
||||||
|
- Default timeout for xmpp_run() is increased from 1 millisecond to 1
|
||||||
|
second in order to reduce CPU consumption
|
||||||
|
- Reduced memory usage in expat module
|
||||||
- New functions:
|
- New functions:
|
||||||
- xmpp_ctx_set_timeout()
|
- xmpp_ctx_set_timeout()
|
||||||
- xmpp_sha1_digest()
|
- xmpp_sha1_digest()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ SSL_LIBS = @openssl_LIBS@
|
|||||||
|
|
||||||
RESOLV_LIBS = @RESOLV_LIBS@
|
RESOLV_LIBS = @RESOLV_LIBS@
|
||||||
|
|
||||||
STROPHE_FLAGS = -I$(top_srcdir) -Wall -Wextra -Werror -Wno-unused-parameter
|
STROPHE_FLAGS = -I$(top_srcdir) -Wall -Wextra -Wno-unused-parameter
|
||||||
STROPHE_LIBS = libstrophe.la
|
STROPHE_LIBS = libstrophe.la
|
||||||
|
|
||||||
## Main build targets
|
## Main build targets
|
||||||
@@ -98,7 +98,6 @@ noinst_PROGRAMS = \
|
|||||||
examples/basic \
|
examples/basic \
|
||||||
examples/bot \
|
examples/bot \
|
||||||
examples/component \
|
examples/component \
|
||||||
examples/ext_auth \
|
|
||||||
examples/roster \
|
examples/roster \
|
||||||
examples/uuid \
|
examples/uuid \
|
||||||
examples/vcard
|
examples/vcard
|
||||||
@@ -115,9 +114,6 @@ examples_bot_LDADD = $(STROPHE_LIBS)
|
|||||||
examples_component_SOURCES = examples/component.c
|
examples_component_SOURCES = examples/component.c
|
||||||
examples_component_CFLAGS = $(STROPHE_FLAGS)
|
examples_component_CFLAGS = $(STROPHE_FLAGS)
|
||||||
examples_component_LDADD = $(STROPHE_LIBS)
|
examples_component_LDADD = $(STROPHE_LIBS)
|
||||||
examples_ext_auth_SOURCES = examples/ext_auth.c
|
|
||||||
examples_ext_auth_CFLAGS = $(STROPHE_FLAGS)
|
|
||||||
examples_ext_auth_LDADD = $(STROPHE_LIBS)
|
|
||||||
examples_roster_SOURCES = examples/roster.c
|
examples_roster_SOURCES = examples/roster.c
|
||||||
examples_roster_CFLAGS = $(STROPHE_FLAGS)
|
examples_roster_CFLAGS = $(STROPHE_FLAGS)
|
||||||
examples_roster_LDADD = $(STROPHE_LIBS)
|
examples_roster_LDADD = $(STROPHE_LIBS)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libstrophe], [0.9.1], [jack@metajack.im])
|
AC_INIT([libstrophe], [0.9.2], [jack@metajack.im])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AM_INIT_AUTOMAKE([foreign])
|
AM_INIT_AUTOMAKE([foreign])
|
||||||
LT_INIT([dlopen])
|
LT_INIT([dlopen])
|
||||||
|
|||||||
@@ -1,290 +0,0 @@
|
|||||||
/* ext_auth.c
|
|
||||||
* strophe XMPP client library -- PLAIN mechanism example with a raw connection
|
|
||||||
*
|
|
||||||
* Copyright (C) 2016 Dmitry Podgorny <pasis.ua@gmail.com>
|
|
||||||
*
|
|
||||||
* This software is provided AS-IS with no warranty, either express
|
|
||||||
* or implied.
|
|
||||||
*
|
|
||||||
* This program is dual licensed under the MIT and GPLv3 licenses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <strophe.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
xmpp_ctx_t *ctx;
|
|
||||||
const char *jid;
|
|
||||||
const char *pass;
|
|
||||||
char *domain;
|
|
||||||
int authenticated;
|
|
||||||
} xmpp_auth_t;
|
|
||||||
|
|
||||||
#define FEATURES_TIMEOUT 5000 /* 5 seconds */
|
|
||||||
|
|
||||||
static int _handle_error(xmpp_conn_t * const conn,
|
|
||||||
xmpp_stanza_t * const stanza,
|
|
||||||
void * const userdata)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "DEBUG: received stream error\n");
|
|
||||||
xmpp_disconnect(conn);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _handle_proceedtls_default(xmpp_conn_t * const conn,
|
|
||||||
xmpp_stanza_t * const stanza,
|
|
||||||
void * const userdata)
|
|
||||||
{
|
|
||||||
xmpp_auth_t *auth = (xmpp_auth_t *)userdata;
|
|
||||||
const char *name = xmpp_stanza_get_name(stanza);
|
|
||||||
|
|
||||||
(void)auth;
|
|
||||||
if (strcmp(name, "proceed") == 0) {
|
|
||||||
if (xmpp_conn_tls_start(conn) == 0) {
|
|
||||||
xmpp_handler_delete(conn, _handle_error);
|
|
||||||
xmpp_conn_open_stream_default(conn);
|
|
||||||
} else {
|
|
||||||
/* failed tls spoils the connection, so disconnect */
|
|
||||||
xmpp_disconnect(conn);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
xmpp_disconnect(conn);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _plain_mechanim_exists(xmpp_ctx_t *ctx, xmpp_stanza_t *features)
|
|
||||||
{
|
|
||||||
xmpp_stanza_t *mechanisms;
|
|
||||||
xmpp_stanza_t *child;
|
|
||||||
char *text;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
mechanisms = xmpp_stanza_get_child_by_name(features, "mechanisms");
|
|
||||||
child = mechanisms ? xmpp_stanza_get_children(mechanisms) : NULL;
|
|
||||||
while (!found && mechanisms && child) {
|
|
||||||
/* TODO xmpp_stanza_get_name(child) is "mechanism" */
|
|
||||||
text = xmpp_stanza_get_text(child);
|
|
||||||
found = text && strcmp(text, "PLAIN") == 0;
|
|
||||||
xmpp_free(ctx, text);
|
|
||||||
child = xmpp_stanza_get_next(child);
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *_plain_mechanism_authdata(xmpp_auth_t *auth)
|
|
||||||
{
|
|
||||||
char *node, *b64;
|
|
||||||
unsigned char *msg;
|
|
||||||
size_t node_len, pass_len;
|
|
||||||
|
|
||||||
node = xmpp_jid_node(auth->ctx, auth->jid);
|
|
||||||
node_len = strlen(node);
|
|
||||||
pass_len = strlen(auth->pass);
|
|
||||||
msg = malloc(node_len + pass_len + 2);
|
|
||||||
msg[0] = '\0';
|
|
||||||
memcpy(msg + 1, node, node_len);
|
|
||||||
msg[node_len + 1] = '\0';
|
|
||||||
memcpy(msg + node_len + 2, auth->pass, pass_len);
|
|
||||||
b64 = xmpp_base64_encode(auth->ctx, msg, node_len + pass_len + 2);
|
|
||||||
|
|
||||||
free(msg);
|
|
||||||
xmpp_free(auth->ctx, node);
|
|
||||||
|
|
||||||
return b64;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _plain_mechanism_handle_result(xmpp_conn_t * const conn,
|
|
||||||
xmpp_stanza_t * const stanza,
|
|
||||||
void * const userdata)
|
|
||||||
{
|
|
||||||
xmpp_auth_t *auth = (xmpp_auth_t *)userdata;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
name = xmpp_stanza_get_name(stanza);
|
|
||||||
|
|
||||||
if (strcmp(name, "success") == 0) {
|
|
||||||
/* SASL PLAIN auth successful, we need to restart the stream */
|
|
||||||
fprintf(stderr, "DEBUG: SASL PLAIN auth successful\n");
|
|
||||||
auth->authenticated = 1;
|
|
||||||
xmpp_handler_delete(conn, _handle_error);
|
|
||||||
xmpp_conn_open_stream_default(conn);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "DEBUG: SASL authentication failed: %s\n", name);
|
|
||||||
xmpp_disconnect(conn);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _handle_missing_features(xmpp_conn_t * const conn,
|
|
||||||
void * const userdata)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "DEBUG: timeout\n");
|
|
||||||
xmpp_disconnect(conn);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _handle_features(xmpp_conn_t * const conn,
|
|
||||||
xmpp_stanza_t * const stanza,
|
|
||||||
void * const userdata)
|
|
||||||
{
|
|
||||||
xmpp_auth_t *auth = (xmpp_auth_t *)userdata;
|
|
||||||
xmpp_ctx_t *ctx = auth->ctx;
|
|
||||||
xmpp_stanza_t *plain, *child;
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
xmpp_timed_handler_delete(conn, _handle_missing_features);
|
|
||||||
|
|
||||||
if (auth->authenticated) {
|
|
||||||
/* after successful SASL authentication */
|
|
||||||
/* TODO bind, session and we'are done */
|
|
||||||
xmpp_disconnect(conn); /* XXX */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* secure connection if possible */
|
|
||||||
child = xmpp_stanza_get_child_by_name(stanza, "starttls");
|
|
||||||
if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_TLS) == 0)) {
|
|
||||||
child = xmpp_stanza_new(ctx);
|
|
||||||
xmpp_stanza_set_name(child, "starttls");
|
|
||||||
xmpp_stanza_set_ns(child, XMPP_NS_TLS);
|
|
||||||
xmpp_handler_add(conn, _handle_proceedtls_default,
|
|
||||||
XMPP_NS_TLS, NULL, NULL, userdata);
|
|
||||||
xmpp_send(conn, child);
|
|
||||||
xmpp_stanza_release(child);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if PLAIN mechanism is supported */
|
|
||||||
if (!_plain_mechanim_exists(ctx, stanza)) {
|
|
||||||
fprintf(stderr, "DEBUG: PLAIN mechanism is NOT supported\n");
|
|
||||||
xmpp_disconnect(conn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* perform authentication */
|
|
||||||
plain = xmpp_stanza_new(ctx);
|
|
||||||
xmpp_stanza_set_name(plain, "auth");
|
|
||||||
xmpp_stanza_set_ns(plain, XMPP_NS_SASL);
|
|
||||||
xmpp_stanza_set_attribute(plain, "mechanism", "PLAIN");
|
|
||||||
str = _plain_mechanism_authdata(auth);
|
|
||||||
child = xmpp_stanza_new(ctx);
|
|
||||||
xmpp_stanza_set_text(child, str);
|
|
||||||
xmpp_free(ctx, str);
|
|
||||||
xmpp_stanza_add_child(plain, child);
|
|
||||||
xmpp_stanza_release(child);
|
|
||||||
|
|
||||||
xmpp_handler_add(conn, _plain_mechanism_handle_result,
|
|
||||||
XMPP_NS_SASL, NULL, NULL, userdata);
|
|
||||||
xmpp_send(conn, plain);
|
|
||||||
xmpp_stanza_release(plain);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void conn_handler(xmpp_conn_t * const conn,
|
|
||||||
const xmpp_conn_event_t status,
|
|
||||||
const int error,
|
|
||||||
xmpp_stream_error_t * const stream_error,
|
|
||||||
void * const userdata)
|
|
||||||
{
|
|
||||||
xmpp_auth_t *auth = (xmpp_auth_t *)userdata;
|
|
||||||
xmpp_ctx_t *ctx = auth->ctx;
|
|
||||||
int secured;
|
|
||||||
|
|
||||||
if (status == XMPP_CONN_RAW_CONNECT) {
|
|
||||||
fprintf(stderr, "DEBUG: raw connection established\n");
|
|
||||||
xmpp_conn_open_stream_default(conn);
|
|
||||||
} else if (status == XMPP_CONN_CONNECT) {
|
|
||||||
fprintf(stderr, "DEBUG: stream opened\n");
|
|
||||||
secured = xmpp_conn_is_secured(conn);
|
|
||||||
fprintf(stderr, "DEBUG: connection is %s.\n",
|
|
||||||
secured ? "secured" : "NOT secured");
|
|
||||||
|
|
||||||
/* setup handler for stream:error */
|
|
||||||
xmpp_handler_add(conn, _handle_error, XMPP_NS_STREAMS,
|
|
||||||
"error", NULL, NULL);
|
|
||||||
|
|
||||||
/* setup handlers for incoming <stream:features> */
|
|
||||||
xmpp_handler_add(conn, _handle_features, XMPP_NS_STREAMS,
|
|
||||||
"features", NULL, auth);
|
|
||||||
xmpp_timed_handler_add(conn, _handle_missing_features,
|
|
||||||
FEATURES_TIMEOUT, NULL);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "DEBUG: disconnected\n");
|
|
||||||
xmpp_stop(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static xmpp_auth_t *xmpp_auth_new(void)
|
|
||||||
{
|
|
||||||
xmpp_auth_t *auth;
|
|
||||||
|
|
||||||
auth = malloc(sizeof(*auth));
|
|
||||||
if (auth != NULL) {
|
|
||||||
memset(auth, 0, sizeof(*auth));
|
|
||||||
}
|
|
||||||
return auth;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xmpp_auth_release(xmpp_auth_t *auth)
|
|
||||||
{
|
|
||||||
free(auth);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
xmpp_ctx_t *ctx;
|
|
||||||
xmpp_conn_t *conn;
|
|
||||||
xmpp_log_t *log;
|
|
||||||
xmpp_auth_t *auth;
|
|
||||||
const char *jid;
|
|
||||||
const char *pass;
|
|
||||||
const char *host = NULL;
|
|
||||||
|
|
||||||
if (argc < 3 || argc > 4) {
|
|
||||||
fprintf(stderr, "Usage: %s <jid> <pass> [<host>]\n", argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
jid = argv[1];
|
|
||||||
pass = argv[2];
|
|
||||||
if (argc > 3)
|
|
||||||
host = argv[3];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note, this example doesn't handle errors. Applications should check
|
|
||||||
* return values of non-void functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
xmpp_initialize();
|
|
||||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
|
|
||||||
ctx = xmpp_ctx_new(NULL, log);
|
|
||||||
conn = xmpp_conn_new(ctx);
|
|
||||||
|
|
||||||
xmpp_conn_set_jid(conn, jid);
|
|
||||||
|
|
||||||
/* private data */
|
|
||||||
auth = xmpp_auth_new();
|
|
||||||
auth->ctx = ctx;
|
|
||||||
auth->jid = jid;
|
|
||||||
auth->pass = pass;
|
|
||||||
auth->domain = xmpp_jid_domain(ctx, jid);
|
|
||||||
|
|
||||||
xmpp_connect_raw(conn, host, 0, conn_handler, auth);
|
|
||||||
xmpp_run(ctx);
|
|
||||||
|
|
||||||
/* release private data */
|
|
||||||
xmpp_auth_release(auth);
|
|
||||||
|
|
||||||
xmpp_conn_release(conn);
|
|
||||||
xmpp_ctx_free(ctx);
|
|
||||||
xmpp_shutdown();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -73,6 +73,15 @@ static int _conn_connect(xmpp_conn_t * const conn,
|
|||||||
xmpp_conn_handler callback,
|
xmpp_conn_handler callback,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
|
|
||||||
|
void xmpp_send_error(xmpp_conn_t * const conn, xmpp_error_type_t const type, char * const text)
|
||||||
|
{
|
||||||
|
xmpp_stanza_t *error = xmpp_error_new(conn->ctx, type, text);
|
||||||
|
|
||||||
|
xmpp_send(conn, error);
|
||||||
|
|
||||||
|
xmpp_stanza_release(error);
|
||||||
|
}
|
||||||
|
|
||||||
/** Create a new Strophe connection object.
|
/** Create a new Strophe connection object.
|
||||||
*
|
*
|
||||||
* @param ctx a Strophe context object
|
* @param ctx a Strophe context object
|
||||||
|
|||||||
26
src/crypto.c
26
src/crypto.c
@@ -61,7 +61,7 @@ static char *digest_to_string_alloc(xmpp_ctx_t *ctx, const uint8_t *digest)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute SHA1 message digest
|
/** Compute SHA1 message digest.
|
||||||
* Returns an allocated string which represents SHA1 message digest in
|
* Returns an allocated string which represents SHA1 message digest in
|
||||||
* hexadecimal notation. The string must be freed with xmpp_free().
|
* hexadecimal notation. The string must be freed with xmpp_free().
|
||||||
*
|
*
|
||||||
@@ -81,7 +81,7 @@ char *xmpp_sha1(xmpp_ctx_t *ctx, const unsigned char *data, size_t len)
|
|||||||
return digest_to_string_alloc(ctx, digest);
|
return digest_to_string_alloc(ctx, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute SHA1 message digest
|
/** Compute SHA1 message digest.
|
||||||
* Stores digest in user's buffer which must be at least XMPP_SHA1_DIGEST_SIZE
|
* Stores digest in user's buffer which must be at least XMPP_SHA1_DIGEST_SIZE
|
||||||
* bytes long.
|
* bytes long.
|
||||||
*
|
*
|
||||||
@@ -97,7 +97,7 @@ void xmpp_sha1_digest(const unsigned char *data, size_t len,
|
|||||||
crypto_SHA1((const uint8_t *)data, len, digest);
|
crypto_SHA1((const uint8_t *)data, len, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create new SHA1 object
|
/** Create new SHA1 object.
|
||||||
* SHA1 object is used to compute SHA1 digest of a buffer that is split
|
* SHA1 object is used to compute SHA1 digest of a buffer that is split
|
||||||
* in multiple chunks or provided in stream mode. A single buffer can be
|
* in multiple chunks or provided in stream mode. A single buffer can be
|
||||||
* processed by short functions xmpp_sha1() and xmpp_sha1_digest().
|
* processed by short functions xmpp_sha1() and xmpp_sha1_digest().
|
||||||
@@ -111,7 +111,7 @@ void xmpp_sha1_digest(const unsigned char *data, size_t len,
|
|||||||
* xmpp_sha1_free(sha1);
|
* xmpp_sha1_free(sha1);
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param ctx a Strophe context onject
|
* @param ctx a Strophe context object
|
||||||
*
|
*
|
||||||
* @return new SHA1 object
|
* @return new SHA1 object
|
||||||
*
|
*
|
||||||
@@ -130,7 +130,7 @@ xmpp_sha1_t *xmpp_sha1_new(xmpp_ctx_t *ctx)
|
|||||||
return sha1;
|
return sha1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Destroy SHA1 object
|
/** Destroy SHA1 object.
|
||||||
*
|
*
|
||||||
* @param sha1 a SHA1 object
|
* @param sha1 a SHA1 object
|
||||||
*
|
*
|
||||||
@@ -141,7 +141,7 @@ void xmpp_sha1_free(xmpp_sha1_t *sha1)
|
|||||||
xmpp_free(sha1->xmpp_ctx, sha1);
|
xmpp_free(sha1->xmpp_ctx, sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update SHA1 context with the next portion of data
|
/** Update SHA1 context with the next portion of data.
|
||||||
* Can be called repeatedly.
|
* Can be called repeatedly.
|
||||||
*
|
*
|
||||||
* @param sha1 a SHA1 object
|
* @param sha1 a SHA1 object
|
||||||
@@ -155,7 +155,7 @@ void xmpp_sha1_update(xmpp_sha1_t *sha1, const unsigned char *data, size_t len)
|
|||||||
crypto_SHA1_Update(&sha1->ctx, data, len);
|
crypto_SHA1_Update(&sha1->ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Finish SHA1 computation
|
/** Finish SHA1 computation.
|
||||||
* Don't call xmpp_sha1_update() after this function. Retrieve resulting
|
* Don't call xmpp_sha1_update() after this function. Retrieve resulting
|
||||||
* message digest with xmpp_sha1_to_string() or xmpp_sha1_to_digest().
|
* message digest with xmpp_sha1_to_string() or xmpp_sha1_to_digest().
|
||||||
*
|
*
|
||||||
@@ -168,7 +168,7 @@ void xmpp_sha1_final(xmpp_sha1_t *sha1)
|
|||||||
crypto_SHA1_Final(&sha1->ctx, sha1->digest);
|
crypto_SHA1_Final(&sha1->ctx, sha1->digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return message digest rendered as a string
|
/** Return message digest rendered as a string.
|
||||||
* Stores the string to a user's buffer and returns the buffer. Call this
|
* Stores the string to a user's buffer and returns the buffer. Call this
|
||||||
* function after xmpp_sha1_final().
|
* function after xmpp_sha1_final().
|
||||||
*
|
*
|
||||||
@@ -185,7 +185,7 @@ char *xmpp_sha1_to_string(xmpp_sha1_t *sha1, char *s, size_t slen)
|
|||||||
return digest_to_string(sha1->digest, s, slen);
|
return digest_to_string(sha1->digest, s, slen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return message digest rendered as a string
|
/** Return message digest rendered as a string.
|
||||||
* Returns an allocated string. Free the string using the Strophe context
|
* Returns an allocated string. Free the string using the Strophe context
|
||||||
* which is passed to xmpp_sha1_new(). Call this function after
|
* which is passed to xmpp_sha1_new(). Call this function after
|
||||||
* xmpp_sha1_final().
|
* xmpp_sha1_final().
|
||||||
@@ -201,7 +201,7 @@ char *xmpp_sha1_to_string_alloc(xmpp_sha1_t *sha1)
|
|||||||
return digest_to_string_alloc(sha1->xmpp_ctx, sha1->digest);
|
return digest_to_string_alloc(sha1->xmpp_ctx, sha1->digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Stores message digest to a user's buffer
|
/** Stores message digest to a user's buffer.
|
||||||
*
|
*
|
||||||
* @param sha1 a SHA1 object
|
* @param sha1 a SHA1 object
|
||||||
* @param digest output buffer of XMPP_SHA1_DIGEST_SIZE bytes
|
* @param digest output buffer of XMPP_SHA1_DIGEST_SIZE bytes
|
||||||
@@ -419,7 +419,7 @@ _base64_error:
|
|||||||
*outlen = 0;
|
*outlen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Base64 encoding routine
|
/** Base64 encoding routine.
|
||||||
* Returns an allocated string which must be freed with xmpp_free().
|
* Returns an allocated string which must be freed with xmpp_free().
|
||||||
*
|
*
|
||||||
* @param ctx a Strophe context
|
* @param ctx a Strophe context
|
||||||
@@ -435,7 +435,7 @@ char *xmpp_base64_encode(xmpp_ctx_t *ctx, const unsigned char *data, size_t len)
|
|||||||
return base64_encode(ctx, data, len);
|
return base64_encode(ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Base64 decoding routine
|
/** Base64 decoding routine.
|
||||||
* Returns an allocated string which must be freed with xmpp_free(). User
|
* Returns an allocated string which must be freed with xmpp_free(). User
|
||||||
* calls this function when the result must be a string. When decoded buffer
|
* calls this function when the result must be a string. When decoded buffer
|
||||||
* contains '\0' NULL is returned.
|
* contains '\0' NULL is returned.
|
||||||
@@ -471,7 +471,7 @@ char *xmpp_base64_decode_str(xmpp_ctx_t *ctx, const char *base64, size_t len)
|
|||||||
return (char *)buf;
|
return (char *)buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Base64 decoding routine
|
/** Base64 decoding routine.
|
||||||
* Returns an allocated buffer which must be freed with xmpp_free().
|
* Returns an allocated buffer which must be freed with xmpp_free().
|
||||||
*
|
*
|
||||||
* @param ctx a Strophe context
|
* @param ctx a Strophe context
|
||||||
|
|||||||
@@ -262,10 +262,8 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
|||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
ret = parser_feed(conn->parser, buf, ret);
|
ret = parser_feed(conn->parser, buf, ret);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
/* parse error, we need to shut down */
|
xmpp_debug(ctx, "xmpp", "parse error [%s]", buf);
|
||||||
/* FIXME */
|
xmpp_send_error(conn, XMPP_SE_INVALID_XML, "parse error");
|
||||||
xmpp_debug(ctx, "xmpp", "parse error, disconnecting");
|
|
||||||
conn_disconnect(conn);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (conn->tls) {
|
if (conn->tls) {
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ void hash_iter_release(hash_iterator_t *iter)
|
|||||||
|
|
||||||
iter->ref--;
|
iter->ref--;
|
||||||
|
|
||||||
if (iter->ref <= 0) {
|
if (iter->ref == 0) { // ref is unsigned!!!
|
||||||
hash_release(iter->table);
|
hash_release(iter->table);
|
||||||
xmpp_free(ctx, iter);
|
xmpp_free(ctx, iter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ void parser_free(parser_t *parser)
|
|||||||
{
|
{
|
||||||
if (parser->xmlctx)
|
if (parser->xmlctx)
|
||||||
xmlFreeParserCtxt(parser->xmlctx);
|
xmlFreeParserCtxt(parser->xmlctx);
|
||||||
|
if (parser->stanza)
|
||||||
|
xmpp_stanza_release(parser->stanza);
|
||||||
xmpp_free(parser->ctx, parser);
|
xmpp_free(parser->ctx, parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,18 +259,16 @@ int parser_reset(parser_t *parser)
|
|||||||
{
|
{
|
||||||
if (parser->xmlctx)
|
if (parser->xmlctx)
|
||||||
xmlFreeParserCtxt(parser->xmlctx);
|
xmlFreeParserCtxt(parser->xmlctx);
|
||||||
|
|
||||||
if (parser->stanza)
|
if (parser->stanza)
|
||||||
xmpp_stanza_release(parser->stanza);
|
xmpp_stanza_release(parser->stanza);
|
||||||
|
|
||||||
|
parser->stanza = NULL;
|
||||||
|
parser->depth = 0;
|
||||||
|
|
||||||
parser->xmlctx = xmlCreatePushParserCtxt(&parser->handlers,
|
parser->xmlctx = xmlCreatePushParserCtxt(&parser->handlers,
|
||||||
parser, NULL, 0, NULL);
|
parser, NULL, 0, NULL);
|
||||||
if (!parser->xmlctx) return 0;
|
|
||||||
|
|
||||||
parser->depth = 0;
|
return parser->xmlctx ? 1 : 0;
|
||||||
parser->stanza = NULL;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* feed a chunk of data to the parser */
|
/* feed a chunk of data to the parser */
|
||||||
|
|||||||
@@ -517,7 +517,7 @@ static int resolver_win32_srv_query(const char *fulldomain,
|
|||||||
unsigned char *buf, size_t len)
|
unsigned char *buf, size_t len)
|
||||||
{
|
{
|
||||||
int set = 0;
|
int set = 0;
|
||||||
int insize;
|
int insize = 0;
|
||||||
|
|
||||||
/* if dnsapi didn't work/isn't there, try querying the dns server manually */
|
/* if dnsapi didn't work/isn't there, try querying the dns server manually */
|
||||||
if (!set)
|
if (!set)
|
||||||
@@ -550,7 +550,7 @@ static int resolver_win32_srv_query(const char *fulldomain,
|
|||||||
char buffer[65535];
|
char buffer[65535];
|
||||||
|
|
||||||
len = 65535;
|
len = 65535;
|
||||||
fi = buffer;
|
fi = (FIXED_INFO *)buffer;
|
||||||
|
|
||||||
if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
|
if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -264,7 +264,8 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
|
|||||||
xmpp_rand_nonce(ctx->rand, cnonce, sizeof(cnonce));
|
xmpp_rand_nonce(ctx->rand, cnonce, sizeof(cnonce));
|
||||||
hash_add(table, "cnonce", xmpp_strdup(ctx, cnonce));
|
hash_add(table, "cnonce", xmpp_strdup(ctx, cnonce));
|
||||||
hash_add(table, "nc", xmpp_strdup(ctx, "00000001"));
|
hash_add(table, "nc", xmpp_strdup(ctx, "00000001"));
|
||||||
hash_add(table, "qop", xmpp_strdup(ctx, "auth"));
|
if (hash_get(table, "qop") == NULL)
|
||||||
|
hash_add(table, "qop", xmpp_strdup(ctx, "auth"));
|
||||||
value = xmpp_alloc(ctx, 5 + strlen(domain) + 1);
|
value = xmpp_alloc(ctx, 5 + strlen(domain) + 1);
|
||||||
memcpy(value, "xmpp/", 5);
|
memcpy(value, "xmpp/", 5);
|
||||||
memcpy(value+5, domain, strlen(domain));
|
memcpy(value+5, domain, strlen(domain));
|
||||||
|
|||||||
467
src/stanza.c
467
src/stanza.c
@@ -1,7 +1,7 @@
|
|||||||
/* stanza.c
|
/* stanza.c
|
||||||
** strophe XMPP client library -- XMPP stanza object and utilities
|
** strophe XMPP client library -- XMPP stanza object and utilities
|
||||||
**
|
**
|
||||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||||
**
|
**
|
||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
@@ -40,15 +40,15 @@ xmpp_stanza_t *xmpp_stanza_new(xmpp_ctx_t *ctx)
|
|||||||
|
|
||||||
stanza = xmpp_alloc(ctx, sizeof(xmpp_stanza_t));
|
stanza = xmpp_alloc(ctx, sizeof(xmpp_stanza_t));
|
||||||
if (stanza != NULL) {
|
if (stanza != NULL) {
|
||||||
stanza->ref = 1;
|
stanza->ref = 1;
|
||||||
stanza->ctx = ctx;
|
stanza->ctx = ctx;
|
||||||
stanza->type = XMPP_STANZA_UNKNOWN;
|
stanza->type = XMPP_STANZA_UNKNOWN;
|
||||||
stanza->prev = NULL;
|
stanza->prev = NULL;
|
||||||
stanza->next = NULL;
|
stanza->next = NULL;
|
||||||
stanza->children = NULL;
|
stanza->children = NULL;
|
||||||
stanza->parent = NULL;
|
stanza->parent = NULL;
|
||||||
stanza->data = NULL;
|
stanza->data = NULL;
|
||||||
stanza->attributes = NULL;
|
stanza->attributes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return stanza;
|
return stanza;
|
||||||
@@ -121,27 +121,27 @@ xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t * const stanza)
|
|||||||
copy->type = stanza->type;
|
copy->type = stanza->type;
|
||||||
|
|
||||||
if (stanza->data) {
|
if (stanza->data) {
|
||||||
copy->data = xmpp_strdup(stanza->ctx, stanza->data);
|
copy->data = xmpp_strdup(stanza->ctx, stanza->data);
|
||||||
if (!copy->data) goto copy_error;
|
if (!copy->data) goto copy_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stanza->attributes) {
|
if (stanza->attributes) {
|
||||||
if (_stanza_copy_attributes(copy, stanza) == -1)
|
if (_stanza_copy_attributes(copy, stanza) == -1)
|
||||||
goto copy_error;
|
goto copy_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
tail = copy->children;
|
tail = copy->children;
|
||||||
for (child = stanza->children; child; child = child->next) {
|
for (child = stanza->children; child; child = child->next) {
|
||||||
copychild = xmpp_stanza_copy(child);
|
copychild = xmpp_stanza_copy(child);
|
||||||
if (!copychild) goto copy_error;
|
if (!copychild) goto copy_error;
|
||||||
copychild->parent = copy;
|
copychild->parent = copy;
|
||||||
|
|
||||||
if (tail) {
|
if (tail) {
|
||||||
copychild->prev = tail;
|
copychild->prev = tail;
|
||||||
tail->next = copychild;
|
tail->next = copychild;
|
||||||
} else
|
} else
|
||||||
copy->children = copychild;
|
copy->children = copychild;
|
||||||
tail = copychild;
|
tail = copychild;
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
@@ -153,7 +153,7 @@ copy_error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Release a stanza object and all of its children.
|
/** Release a stanza object and all of its children.
|
||||||
* This function releases a stanza object and potentially all of its
|
* This function releases a stanza object and potentially all of its
|
||||||
* children, which may cause the object(s) to be freed.
|
* children, which may cause the object(s) to be freed.
|
||||||
*
|
*
|
||||||
* @param stanza a Strophe stanza object
|
* @param stanza a Strophe stanza object
|
||||||
@@ -169,20 +169,20 @@ int xmpp_stanza_release(xmpp_stanza_t * const stanza)
|
|||||||
|
|
||||||
/* release stanza */
|
/* release stanza */
|
||||||
if (stanza->ref > 1)
|
if (stanza->ref > 1)
|
||||||
stanza->ref--;
|
stanza->ref--;
|
||||||
else {
|
else {
|
||||||
/* release all children */
|
/* release all children */
|
||||||
child = stanza->children;
|
child = stanza->children;
|
||||||
while (child) {
|
while (child) {
|
||||||
tchild = child;
|
tchild = child;
|
||||||
child = child->next;
|
child = child->next;
|
||||||
xmpp_stanza_release(tchild);
|
xmpp_stanza_release(tchild);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stanza->attributes) hash_release(stanza->attributes);
|
if (stanza->attributes) hash_release(stanza->attributes);
|
||||||
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
|
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
|
||||||
xmpp_free(stanza->ctx, stanza);
|
xmpp_free(stanza->ctx, stanza);
|
||||||
released = 1;
|
released = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return released;
|
return released;
|
||||||
@@ -274,17 +274,17 @@ static char *_escape_xml(xmpp_ctx_t * const ctx, char *text)
|
|||||||
|
|
||||||
/* small helper function */
|
/* small helper function */
|
||||||
static void _render_update(int *written, const int length,
|
static void _render_update(int *written, const int length,
|
||||||
const int lastwrite,
|
const int lastwrite,
|
||||||
size_t *left, char **ptr)
|
size_t *left, char **ptr)
|
||||||
{
|
{
|
||||||
*written += lastwrite;
|
*written += lastwrite;
|
||||||
|
|
||||||
if (*written >= length) {
|
if (*written >= length) {
|
||||||
*left = 0;
|
*left = 0;
|
||||||
*ptr = NULL;
|
*ptr = NULL;
|
||||||
} else {
|
} else {
|
||||||
*left -= lastwrite;
|
*left -= lastwrite;
|
||||||
*ptr = &(*ptr)[lastwrite];
|
*ptr = &(*ptr)[lastwrite];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ static void _render_update(int *written, const int length,
|
|||||||
* and return values > buflen indicate buffer was not large enough
|
* and return values > buflen indicate buffer was not large enough
|
||||||
*/
|
*/
|
||||||
static int _render_stanza_recursive(xmpp_stanza_t *stanza,
|
static int _render_stanza_recursive(xmpp_stanza_t *stanza,
|
||||||
char * const buf, size_t const buflen)
|
char * const buf, size_t const buflen)
|
||||||
{
|
{
|
||||||
char *ptr = buf;
|
char *ptr = buf;
|
||||||
size_t left = buflen;
|
size_t left = buflen;
|
||||||
@@ -309,80 +309,80 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza,
|
|||||||
if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP;
|
if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP;
|
||||||
|
|
||||||
if (stanza->type == XMPP_STANZA_TEXT) {
|
if (stanza->type == XMPP_STANZA_TEXT) {
|
||||||
if (!stanza->data) return XMPP_EINVOP;
|
if (!stanza->data) return XMPP_EINVOP;
|
||||||
|
|
||||||
tmp = _escape_xml(stanza->ctx, stanza->data);
|
tmp = _escape_xml(stanza->ctx, stanza->data);
|
||||||
if (tmp == NULL) return XMPP_EMEM;
|
if (tmp == NULL) return XMPP_EMEM;
|
||||||
ret = xmpp_snprintf(ptr, left, "%s", tmp);
|
ret = xmpp_snprintf(ptr, left, "%s", tmp);
|
||||||
xmpp_free(stanza->ctx, tmp);
|
xmpp_free(stanza->ctx, tmp);
|
||||||
if (ret < 0) return XMPP_EMEM;
|
if (ret < 0) return XMPP_EMEM;
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
} else { /* stanza->type == XMPP_STANZA_TAG */
|
} else { /* stanza->type == XMPP_STANZA_TAG */
|
||||||
if (!stanza->data) return XMPP_EINVOP;
|
if (!stanza->data) return XMPP_EINVOP;
|
||||||
|
|
||||||
/* write beginning of tag and attributes */
|
/* write beginning of tag and attributes */
|
||||||
ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
|
ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
|
||||||
if (ret < 0) return XMPP_EMEM;
|
if (ret < 0) return XMPP_EMEM;
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
|
|
||||||
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
|
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
|
||||||
iter = hash_iter_new(stanza->attributes);
|
iter = hash_iter_new(stanza->attributes);
|
||||||
while ((key = hash_iter_next(iter))) {
|
while ((key = hash_iter_next(iter))) {
|
||||||
if (!strcmp(key, "xmlns")) {
|
if (!strcmp(key, "xmlns")) {
|
||||||
/* don't output namespace if parent stanza is the same */
|
/* don't output namespace if parent stanza is the same */
|
||||||
if (stanza->parent &&
|
if (stanza->parent &&
|
||||||
stanza->parent->attributes &&
|
stanza->parent->attributes &&
|
||||||
hash_get(stanza->parent->attributes, key) &&
|
hash_get(stanza->parent->attributes, key) &&
|
||||||
!strcmp((char*)hash_get(stanza->attributes, key),
|
!strcmp((char*)hash_get(stanza->attributes, key),
|
||||||
(char*)hash_get(stanza->parent->attributes, key)))
|
(char*)hash_get(stanza->parent->attributes, key)))
|
||||||
continue;
|
continue;
|
||||||
/* or if this is the stream namespace */
|
/* or if this is the stream namespace */
|
||||||
if (!stanza->parent &&
|
if (!stanza->parent &&
|
||||||
!strcmp((char*)hash_get(stanza->attributes, key),
|
!strcmp((char*)hash_get(stanza->attributes, key),
|
||||||
XMPP_NS_CLIENT))
|
XMPP_NS_CLIENT))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tmp = _escape_xml(stanza->ctx,
|
tmp = _escape_xml(stanza->ctx,
|
||||||
(char *)hash_get(stanza->attributes, key));
|
(char *)hash_get(stanza->attributes, key));
|
||||||
if (tmp == NULL) return XMPP_EMEM;
|
if (tmp == NULL) return XMPP_EMEM;
|
||||||
ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
|
ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
|
||||||
xmpp_free(stanza->ctx, tmp);
|
xmpp_free(stanza->ctx, tmp);
|
||||||
if (ret < 0) return XMPP_EMEM;
|
if (ret < 0) return XMPP_EMEM;
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
}
|
}
|
||||||
hash_iter_release(iter);
|
hash_iter_release(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stanza->children) {
|
if (!stanza->children) {
|
||||||
/* write end if singleton tag */
|
/* write end if singleton tag */
|
||||||
ret = xmpp_snprintf(ptr, left, "/>");
|
ret = xmpp_snprintf(ptr, left, "/>");
|
||||||
if (ret < 0) return XMPP_EMEM;
|
if (ret < 0) return XMPP_EMEM;
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
} else {
|
} else {
|
||||||
/* this stanza has child stanzas */
|
/* this stanza has child stanzas */
|
||||||
|
|
||||||
/* write end of start tag */
|
/* write end of start tag */
|
||||||
ret = xmpp_snprintf(ptr, left, ">");
|
ret = xmpp_snprintf(ptr, left, ">");
|
||||||
if (ret < 0) return XMPP_EMEM;
|
if (ret < 0) return XMPP_EMEM;
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
|
|
||||||
/* iterate and recurse over child stanzas */
|
|
||||||
child = stanza->children;
|
|
||||||
while (child) {
|
|
||||||
ret = _render_stanza_recursive(child, ptr, left);
|
|
||||||
if (ret < 0) return ret;
|
|
||||||
|
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
/* iterate and recurse over child stanzas */
|
||||||
|
child = stanza->children;
|
||||||
|
while (child) {
|
||||||
|
ret = _render_stanza_recursive(child, ptr, left);
|
||||||
|
if (ret < 0) return ret;
|
||||||
|
|
||||||
child = child->next;
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
}
|
|
||||||
|
|
||||||
/* write end tag */
|
child = child->next;
|
||||||
ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
|
}
|
||||||
if (ret < 0) return XMPP_EMEM;
|
|
||||||
|
/* write end tag */
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
|
||||||
}
|
if (ret < 0) return XMPP_EMEM;
|
||||||
|
|
||||||
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return written;
|
return written;
|
||||||
@@ -415,27 +415,27 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
|
|||||||
length = 1024;
|
length = 1024;
|
||||||
buffer = xmpp_alloc(stanza->ctx, length);
|
buffer = xmpp_alloc(stanza->ctx, length);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
*buf = NULL;
|
*buf = NULL;
|
||||||
*buflen = 0;
|
*buflen = 0;
|
||||||
return XMPP_EMEM;
|
return XMPP_EMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _render_stanza_recursive(stanza, buffer, length);
|
ret = _render_stanza_recursive(stanza, buffer, length);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) return ret;
|
||||||
|
|
||||||
if ((size_t)ret > length - 1) {
|
if ((size_t)ret > length - 1) {
|
||||||
tmp = xmpp_realloc(stanza->ctx, buffer, ret + 1);
|
tmp = xmpp_realloc(stanza->ctx, buffer, ret + 1);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
xmpp_free(stanza->ctx, buffer);
|
xmpp_free(stanza->ctx, buffer);
|
||||||
*buf = NULL;
|
*buf = NULL;
|
||||||
*buflen = 0;
|
*buflen = 0;
|
||||||
return XMPP_EMEM;
|
return XMPP_EMEM;
|
||||||
}
|
}
|
||||||
length = ret + 1;
|
length = ret + 1;
|
||||||
buffer = tmp;
|
buffer = tmp;
|
||||||
|
|
||||||
ret = _render_stanza_recursive(stanza, buffer, length);
|
ret = _render_stanza_recursive(stanza, buffer, length);
|
||||||
if ((size_t)ret > length - 1) return XMPP_EMEM;
|
if ((size_t)ret > length - 1) return XMPP_EMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[length - 1] = 0;
|
buffer[length - 1] = 0;
|
||||||
@@ -457,7 +457,7 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_set_name(xmpp_stanza_t *stanza,
|
int xmpp_stanza_set_name(xmpp_stanza_t *stanza,
|
||||||
const char * const name)
|
const char * const name)
|
||||||
{
|
{
|
||||||
if (stanza->type == XMPP_STANZA_TEXT) return XMPP_EINVOP;
|
if (stanza->type == XMPP_STANZA_TEXT) return XMPP_EINVOP;
|
||||||
|
|
||||||
@@ -496,7 +496,7 @@ const char *xmpp_stanza_get_name(xmpp_stanza_t * const stanza)
|
|||||||
int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza)
|
int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza)
|
||||||
{
|
{
|
||||||
if (stanza->attributes == NULL) {
|
if (stanza->attributes == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash_num_keys(stanza->attributes);
|
return hash_num_keys(stanza->attributes);
|
||||||
@@ -517,30 +517,30 @@ int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza)
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
|
int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
|
||||||
const char **attr, int attrlen)
|
const char **attr, int attrlen)
|
||||||
{
|
{
|
||||||
hash_iterator_t *iter;
|
hash_iterator_t *iter;
|
||||||
const char *key;
|
const char *key;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
if (stanza->attributes == NULL) {
|
if (stanza->attributes == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = hash_iter_new(stanza->attributes);
|
iter = hash_iter_new(stanza->attributes);
|
||||||
while ((key = hash_iter_next(iter)) != NULL && attrlen) {
|
while ((key = hash_iter_next(iter)) != NULL && attrlen) {
|
||||||
attr[num++] = key;
|
attr[num++] = key;
|
||||||
attrlen--;
|
attrlen--;
|
||||||
if (attrlen == 0) {
|
if (attrlen == 0) {
|
||||||
hash_iter_release(iter);
|
hash_iter_release(iter);
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
attr[num++] = hash_get(stanza->attributes, key);
|
attr[num++] = hash_get(stanza->attributes, key);
|
||||||
attrlen--;
|
attrlen--;
|
||||||
if (attrlen == 0) {
|
if (attrlen == 0) {
|
||||||
hash_iter_release(iter);
|
hash_iter_release(iter);
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_iter_release(iter);
|
hash_iter_release(iter);
|
||||||
@@ -558,8 +558,8 @@ int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
||||||
const char * const key,
|
const char * const key,
|
||||||
const char * const value)
|
const char * const value)
|
||||||
{
|
{
|
||||||
char *val;
|
char *val;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -567,8 +567,8 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
|||||||
if (stanza->type != XMPP_STANZA_TAG) return XMPP_EINVOP;
|
if (stanza->type != XMPP_STANZA_TAG) return XMPP_EINVOP;
|
||||||
|
|
||||||
if (!stanza->attributes) {
|
if (!stanza->attributes) {
|
||||||
stanza->attributes = hash_new(stanza->ctx, 8, xmpp_free);
|
stanza->attributes = hash_new(stanza->ctx, 8, xmpp_free);
|
||||||
if (!stanza->attributes) return XMPP_EMEM;
|
if (!stanza->attributes) return XMPP_EMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = xmpp_strdup(stanza->ctx, value);
|
val = xmpp_strdup(stanza->ctx, value);
|
||||||
@@ -598,7 +598,7 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_set_ns(xmpp_stanza_t * const stanza,
|
int xmpp_stanza_set_ns(xmpp_stanza_t * const stanza,
|
||||||
const char * const ns)
|
const char * const ns)
|
||||||
{
|
{
|
||||||
return xmpp_stanza_set_attribute(stanza, "xmlns", ns);
|
return xmpp_stanza_set_attribute(stanza, "xmlns", ns);
|
||||||
}
|
}
|
||||||
@@ -624,12 +624,12 @@ int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child)
|
|||||||
child->parent = stanza;
|
child->parent = stanza;
|
||||||
|
|
||||||
if (!stanza->children)
|
if (!stanza->children)
|
||||||
stanza->children = child;
|
stanza->children = child;
|
||||||
else {
|
else {
|
||||||
s = stanza->children;
|
s = stanza->children;
|
||||||
while (s->next) s = s->next;
|
while (s->next) s = s->next;
|
||||||
s->next = child;
|
s->next = child;
|
||||||
child->prev = s;
|
child->prev = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return XMPP_EOK;
|
return XMPP_EOK;
|
||||||
@@ -649,7 +649,7 @@ int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child)
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_set_text(xmpp_stanza_t *stanza,
|
int xmpp_stanza_set_text(xmpp_stanza_t *stanza,
|
||||||
const char * const text)
|
const char * const text)
|
||||||
{
|
{
|
||||||
if (stanza->type == XMPP_STANZA_TAG) return XMPP_EINVOP;
|
if (stanza->type == XMPP_STANZA_TAG) return XMPP_EINVOP;
|
||||||
|
|
||||||
@@ -676,8 +676,8 @@ int xmpp_stanza_set_text(xmpp_stanza_t *stanza,
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
|
int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
|
||||||
const char * const text,
|
const char * const text,
|
||||||
const size_t size)
|
const size_t size)
|
||||||
{
|
{
|
||||||
if (stanza->type == XMPP_STANZA_TAG) return XMPP_EINVOP;
|
if (stanza->type == XMPP_STANZA_TAG) return XMPP_EINVOP;
|
||||||
|
|
||||||
@@ -780,14 +780,14 @@ const char *xmpp_stanza_get_from(xmpp_stanza_t * const stanza)
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t * const stanza,
|
xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t * const stanza,
|
||||||
const char * const name)
|
const char * const name)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *child;
|
xmpp_stanza_t *child;
|
||||||
|
|
||||||
for (child = stanza->children; child; child = child->next) {
|
for (child = stanza->children; child; child = child->next) {
|
||||||
if (child->type == XMPP_STANZA_TAG &&
|
if (child->type == XMPP_STANZA_TAG &&
|
||||||
(strcmp(name, xmpp_stanza_get_name(child)) == 0))
|
(strcmp(name, xmpp_stanza_get_name(child)) == 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
@@ -806,14 +806,14 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t * const stanza,
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t * const stanza,
|
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t * const stanza,
|
||||||
const char * const ns)
|
const char * const ns)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *child;
|
xmpp_stanza_t *child;
|
||||||
|
|
||||||
for (child = stanza->children; child; child = child->next) {
|
for (child = stanza->children; child; child = child->next) {
|
||||||
if (xmpp_stanza_get_ns(child) &&
|
if (xmpp_stanza_get_ns(child) &&
|
||||||
strcmp(ns, xmpp_stanza_get_ns(child)) == 0)
|
strcmp(ns, xmpp_stanza_get_ns(child)) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
@@ -866,16 +866,16 @@ char *xmpp_stanza_get_text(xmpp_stanza_t * const stanza)
|
|||||||
char *text;
|
char *text;
|
||||||
|
|
||||||
if (stanza->type == XMPP_STANZA_TEXT) {
|
if (stanza->type == XMPP_STANZA_TEXT) {
|
||||||
if (stanza->data)
|
if (stanza->data)
|
||||||
return xmpp_strdup(stanza->ctx, stanza->data);
|
return xmpp_strdup(stanza->ctx, stanza->data);
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
for (child = stanza->children; child; child = child->next)
|
for (child = stanza->children; child; child = child->next)
|
||||||
if (child->type == XMPP_STANZA_TEXT)
|
if (child->type == XMPP_STANZA_TEXT)
|
||||||
len += strlen(child->data);
|
len += strlen(child->data);
|
||||||
|
|
||||||
if (len == 0) return NULL;
|
if (len == 0) return NULL;
|
||||||
|
|
||||||
@@ -884,11 +884,11 @@ char *xmpp_stanza_get_text(xmpp_stanza_t * const stanza)
|
|||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
for (child = stanza->children; child; child = child->next)
|
for (child = stanza->children; child; child = child->next)
|
||||||
if (child->type == XMPP_STANZA_TEXT) {
|
if (child->type == XMPP_STANZA_TEXT) {
|
||||||
clen = strlen(child->data);
|
clen = strlen(child->data);
|
||||||
memcpy(&text[len], child->data, clen);
|
memcpy(&text[len], child->data, clen);
|
||||||
len += clen;
|
len += clen;
|
||||||
}
|
}
|
||||||
|
|
||||||
text[len] = 0;
|
text[len] = 0;
|
||||||
|
|
||||||
@@ -911,7 +911,7 @@ char *xmpp_stanza_get_text(xmpp_stanza_t * const stanza)
|
|||||||
const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t * const stanza)
|
const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t * const stanza)
|
||||||
{
|
{
|
||||||
if (stanza->type == XMPP_STANZA_TEXT)
|
if (stanza->type == XMPP_STANZA_TEXT)
|
||||||
return stanza->data;
|
return stanza->data;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -928,7 +928,7 @@ const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t * const stanza)
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_set_id(xmpp_stanza_t * const stanza,
|
int xmpp_stanza_set_id(xmpp_stanza_t * const stanza,
|
||||||
const char * const id)
|
const char * const id)
|
||||||
{
|
{
|
||||||
return xmpp_stanza_set_attribute(stanza, "id", id);
|
return xmpp_stanza_set_attribute(stanza, "id", id);
|
||||||
}
|
}
|
||||||
@@ -945,7 +945,7 @@ int xmpp_stanza_set_id(xmpp_stanza_t * const stanza,
|
|||||||
* @ingroup Stanza
|
* @ingroup Stanza
|
||||||
*/
|
*/
|
||||||
int xmpp_stanza_set_type(xmpp_stanza_t * const stanza,
|
int xmpp_stanza_set_type(xmpp_stanza_t * const stanza,
|
||||||
const char * const type)
|
const char * const type)
|
||||||
{
|
{
|
||||||
return xmpp_stanza_set_attribute(stanza, "type", type);
|
return xmpp_stanza_set_attribute(stanza, "type", type);
|
||||||
}
|
}
|
||||||
@@ -1001,10 +1001,10 @@ const char *xmpp_stanza_get_attribute(xmpp_stanza_t * const stanza,
|
|||||||
const char * const name)
|
const char * const name)
|
||||||
{
|
{
|
||||||
if (stanza->type != XMPP_STANZA_TAG)
|
if (stanza->type != XMPP_STANZA_TAG)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!stanza->attributes)
|
if (!stanza->attributes)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return hash_get(stanza->attributes, name);
|
return hash_get(stanza->attributes, name);
|
||||||
}
|
}
|
||||||
@@ -1218,3 +1218,122 @@ xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx)
|
|||||||
{
|
{
|
||||||
return _stanza_new_with_attrs(ctx, "presence", NULL, NULL, NULL);
|
return _stanza_new_with_attrs(ctx, "presence", NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Create an <stream:error/> stanza object with given type and error text.
|
||||||
|
* The error text is optional and may be NULL.
|
||||||
|
*
|
||||||
|
* @param ctx a Strophe context object
|
||||||
|
* @param type enum of xmpp_error_type_t
|
||||||
|
* @param text content of a 'text'
|
||||||
|
*
|
||||||
|
* @return a new Strophe stanza object
|
||||||
|
*
|
||||||
|
* @todo Handle errors in this function
|
||||||
|
*
|
||||||
|
* @ingroup Stanza
|
||||||
|
*/
|
||||||
|
xmpp_stanza_t *xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t const type,
|
||||||
|
const char * const text)
|
||||||
|
{
|
||||||
|
xmpp_stanza_t *error = _stanza_new_with_attrs(ctx, "stream:error", NULL, NULL, NULL);
|
||||||
|
xmpp_stanza_t *error_type = xmpp_stanza_new(ctx);
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case XMPP_SE_BAD_FORMAT:
|
||||||
|
xmpp_stanza_set_name(error_type, "bad-format");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_BAD_NS_PREFIX:
|
||||||
|
xmpp_stanza_set_name(error_type, "bad-namespace-prefix");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_CONFLICT:
|
||||||
|
xmpp_stanza_set_name(error_type, "conflict");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_CONN_TIMEOUT:
|
||||||
|
xmpp_stanza_set_name(error_type, "connection-timeout");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_HOST_GONE:
|
||||||
|
xmpp_stanza_set_name(error_type, "host-gone");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_HOST_UNKNOWN:
|
||||||
|
xmpp_stanza_set_name(error_type, "host-unknown");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_IMPROPER_ADDR:
|
||||||
|
xmpp_stanza_set_name(error_type, "improper-addressing");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_INTERNAL_SERVER_ERROR:
|
||||||
|
xmpp_stanza_set_name(error_type, "internal-server-error");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_INVALID_FROM:
|
||||||
|
xmpp_stanza_set_name(error_type, "invalid-from");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_INVALID_ID:
|
||||||
|
xmpp_stanza_set_name(error_type, "invalid-id");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_INVALID_NS:
|
||||||
|
xmpp_stanza_set_name(error_type, "invalid-namespace");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_INVALID_XML:
|
||||||
|
xmpp_stanza_set_name(error_type, "invalid-xml");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_NOT_AUTHORIZED:
|
||||||
|
xmpp_stanza_set_name(error_type, "not-authorized");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_POLICY_VIOLATION:
|
||||||
|
xmpp_stanza_set_name(error_type, "policy-violation");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_REMOTE_CONN_FAILED:
|
||||||
|
xmpp_stanza_set_name(error_type, "remote-connection-failed");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_RESOURCE_CONSTRAINT:
|
||||||
|
xmpp_stanza_set_name(error_type, "resource-constraint");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_RESTRICTED_XML:
|
||||||
|
xmpp_stanza_set_name(error_type, "restricted-xml");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_SEE_OTHER_HOST:
|
||||||
|
xmpp_stanza_set_name(error_type, "see-other-host");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_SYSTEM_SHUTDOWN:
|
||||||
|
xmpp_stanza_set_name(error_type, "system-shutdown");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_UNDEFINED_CONDITION:
|
||||||
|
xmpp_stanza_set_name(error_type, "undefined-condition");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_UNSUPPORTED_ENCODING:
|
||||||
|
xmpp_stanza_set_name(error_type, "unsupported-encoding");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_UNSUPPORTED_STANZA_TYPE:
|
||||||
|
xmpp_stanza_set_name(error_type, "unsupported-stanza-type");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_UNSUPPORTED_VERSION:
|
||||||
|
xmpp_stanza_set_name(error_type, "unsupported-version");
|
||||||
|
break;
|
||||||
|
case XMPP_SE_XML_NOT_WELL_FORMED:
|
||||||
|
xmpp_stanza_set_name(error_type, "xml-not-well-formed");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
xmpp_stanza_set_name(error_type, "internal-server-error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_stanza_set_ns(error_type, XMPP_NS_STREAMS_IETF);
|
||||||
|
xmpp_stanza_add_child(error, error_type);
|
||||||
|
xmpp_stanza_release(error_type);
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
xmpp_stanza_t *error_text = xmpp_stanza_new(ctx);
|
||||||
|
xmpp_stanza_t *content = xmpp_stanza_new(ctx);
|
||||||
|
|
||||||
|
xmpp_stanza_set_name(error_text, "text");
|
||||||
|
xmpp_stanza_set_ns(error_text, XMPP_NS_STREAMS_IETF);
|
||||||
|
|
||||||
|
xmpp_stanza_set_text(content, text);
|
||||||
|
xmpp_stanza_add_child(error_text, content);
|
||||||
|
xmpp_stanza_release(content);
|
||||||
|
|
||||||
|
xmpp_stanza_add_child(error, error_text);
|
||||||
|
xmpp_stanza_release(error_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|||||||
@@ -209,6 +209,14 @@ int tls_stop(tls_t *tls)
|
|||||||
}
|
}
|
||||||
_tls_sock_wait(tls, error);
|
_tls_sock_wait(tls, error);
|
||||||
}
|
}
|
||||||
|
if (error == SSL_ERROR_SYSCALL && errno == 0) {
|
||||||
|
/*
|
||||||
|
* Handle special case when peer closes connection instead of
|
||||||
|
* proper shutdown.
|
||||||
|
*/
|
||||||
|
error = 0;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
_tls_set_error(tls, error);
|
_tls_set_error(tls, error);
|
||||||
|
|
||||||
return ret <= 0 ? 0 : 1;
|
return ret <= 0 ? 0 : 1;
|
||||||
@@ -260,6 +268,8 @@ static void _tls_sock_wait(tls_t *tls, int error)
|
|||||||
int nfds;
|
int nfds;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (error == SSL_ERROR_NONE) return;
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_ZERO(&wfds);
|
FD_ZERO(&wfds);
|
||||||
if (error == SSL_ERROR_WANT_READ)
|
if (error == SSL_ERROR_WANT_READ)
|
||||||
@@ -278,6 +288,7 @@ static void _tls_sock_wait(tls_t *tls, int error)
|
|||||||
static void _tls_set_error(tls_t *tls, int error)
|
static void _tls_set_error(tls_t *tls, int error)
|
||||||
{
|
{
|
||||||
if (error != 0 && !tls_is_recoverable(error)) {
|
if (error != 0 && !tls_is_recoverable(error)) {
|
||||||
|
xmpp_debug(tls->ctx, "tls", "error=%d errno=%d", error, errno);
|
||||||
_tls_log_error(tls->ctx);
|
_tls_log_error(tls->ctx);
|
||||||
}
|
}
|
||||||
tls->lasterror = error;
|
tls->lasterror = error;
|
||||||
|
|||||||
@@ -217,6 +217,7 @@ typedef void (*xmpp_conn_handler)(xmpp_conn_t * const conn,
|
|||||||
xmpp_stream_error_t * const stream_error,
|
xmpp_stream_error_t * const stream_error,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
|
|
||||||
|
void xmpp_send_error(xmpp_conn_t * const conn, xmpp_error_type_t const type, char * const text);
|
||||||
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx);
|
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx);
|
||||||
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t * const conn);
|
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t * const conn);
|
||||||
int xmpp_conn_release(xmpp_conn_t * const conn);
|
int xmpp_conn_release(xmpp_conn_t * const conn);
|
||||||
@@ -381,6 +382,8 @@ int xmpp_message_set_body(xmpp_stanza_t *msg, const char * const text);
|
|||||||
xmpp_stanza_t *xmpp_iq_new(xmpp_ctx_t *ctx, const char * const type,
|
xmpp_stanza_t *xmpp_iq_new(xmpp_ctx_t *ctx, const char * const type,
|
||||||
const char * const id);
|
const char * const id);
|
||||||
xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx);
|
xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx);
|
||||||
|
xmpp_stanza_t *xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t const type,
|
||||||
|
const char * const text);
|
||||||
|
|
||||||
/* jid */
|
/* jid */
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,16 @@
|
|||||||
|
|
||||||
#include "test.h" /* ARRAY_SIZE */
|
#include "test.h" /* ARRAY_SIZE */
|
||||||
|
|
||||||
|
/* strtok_s() has appeared in visual studio 2005.
|
||||||
|
Use own implementation for older versions. */
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# if (_MSC_VER >= 1400)
|
||||||
|
# define strtok_r strtok_s
|
||||||
|
# else
|
||||||
|
# define strtok_r xmpp_strtok_r
|
||||||
|
# endif
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
static int test_strtok_r(void)
|
static int test_strtok_r(void)
|
||||||
{
|
{
|
||||||
const char *test = "-abc-=-def--";
|
const char *test = "-abc-=-def--";
|
||||||
|
|||||||
Reference in New Issue
Block a user