1 Commits

Author SHA1 Message Date
Dmitry Podgorny
b1698f7b5d WIP Initial server support 2017-07-15 21:38:38 +03:00
29 changed files with 731 additions and 591 deletions

1
.gitignore vendored
View File

@@ -35,6 +35,7 @@ examples/basic
examples/bot
examples/component
examples/roster
examples/server
examples/uuid
examples/vcard
test_stamp

View File

@@ -1,11 +1,11 @@
language: c
install:
- sudo apt-get update
- sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev
- sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev check
before_script:
- ./bootstrap.sh
script:
- ./configure ${CONFIGURE_OPT} CFLAGS="-Werror" && make && make check
- ./configure ${CONFIGURE_OPT} && make && make check-TESTS
env:
- CONFIGURE_OPT="--without-libxml2"
- CONFIGURE_OPT="--with-libxml2"

View File

@@ -1,12 +1,3 @@
0.9.3
- PLAIN mechanism is used only when no other mechanisms are supported
- Legacy authentication is disabled by default, can be enabled with
connection flag XMPP_CONN_FLAG_LEGACY_AUTH
- Session is not established if it is optional
- Fixed a bug causing a reused connection not to cleanup properly
- Improved debug logging in OpenSSL module
- Few memory leaks fixed
0.9.2
- OpenSSL tls module verifies certificate by default. Set flag
XMPP_CONN_FLAG_TRUST_TLS to ignore result of the verification
@@ -17,12 +8,7 @@
userdata
- System handlers are deleted on xmpp_conn_t reconnection. Old system
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:
- xmpp_error_new()
- xmpp_send_error()
- xmpp_ctx_set_timeout()
- xmpp_sha1_digest()

View File

@@ -1,6 +1,7 @@
AUTOMAKE_OPTIONS = subdir-objects
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = -g -Wall
PARSER_CFLAGS=@PARSER_CFLAGS@
PARSER_LIBS=@PARSER_LIBS@
@@ -10,7 +11,7 @@ SSL_LIBS = @openssl_LIBS@
RESOLV_LIBS = @RESOLV_LIBS@
STROPHE_FLAGS = -I$(top_srcdir) -Wall -Wextra -Wno-unused-parameter
STROPHE_FLAGS = -I$(top_srcdir) -Wall -Wextra -Werror -Wno-unused-parameter
STROPHE_LIBS = libstrophe.la
## Main build targets
@@ -35,6 +36,7 @@ libstrophe_la_SOURCES = \
src/resolver.c \
src/sasl.c \
src/scram.c \
src/server.c \
src/sha1.c \
src/snprintf.c \
src/sock.c \
@@ -98,6 +100,7 @@ noinst_PROGRAMS = \
examples/bot \
examples/component \
examples/roster \
examples/server \
examples/uuid \
examples/vcard
@@ -116,6 +119,9 @@ examples_component_LDADD = $(STROPHE_LIBS)
examples_roster_SOURCES = examples/roster.c
examples_roster_CFLAGS = $(STROPHE_FLAGS)
examples_roster_LDADD = $(STROPHE_LIBS)
examples_server_SOURCES = examples/server.c
examples_server_CFLAGS = $(STROPHE_FLAGS)
examples_server_LDADD = $(STROPHE_LIBS)
examples_uuid_SOURCES = examples/uuid.c
examples_uuid_CFLAGS = $(STROPHE_FLAGS)
examples_uuid_LDADD = $(STROPHE_LIBS)

View File

@@ -1,4 +1,4 @@
AC_INIT([libstrophe], [0.9.3], [jack@metajack.im])
AC_INIT([libstrophe], [0.9.1], [jack@metajack.im])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign])
LT_INIT([dlopen])

83
examples/server.c Normal file
View File

@@ -0,0 +1,83 @@
#include <stdio.h>
#include <string.h>
#include <strophe.h>
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
int message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
xmpp_stanza_t *success;
if (strcmp(xmpp_stanza_get_name(stanza), "auth") == 0) {
success = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(success, "success");
xmpp_stanza_set_ns(success, XMPP_NS_SASL);
xmpp_send(conn, success);
xmpp_stanza_release(success);
} else
xmpp_disconnect(conn);
return 1;
}
void server_handler(xmpp_server_t * const srv, xmpp_conn_t * const conn,
const xmpp_server_event_t event, const int error,
void * const userdata)
{
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
static char *attrs[] = {
"xmlns", XMPP_NS_CLIENT, "xmlns:stream", XMPP_NS_STREAMS,
"id", "0123456789", "from", "127.0.0.1", "version", "1.0",
"xml:lang", "en",
};
switch (event) {
case XMPP_SERVER_ACCEPT:
printf("Event XMPP_SERVER_ACCEPT\n");
break;
case XMPP_SERVER_OPEN_STREAM:
printf("Event XMPP_SERVER_OPEN_STREAM\n");
xmpp_handler_add(conn, message_handler, NULL, NULL, NULL, ctx);
xmpp_conn_open_stream(conn, attrs, ARRAY_SIZE(attrs));
xmpp_send_raw_string(conn,
"<stream:features>"
"<mechanisms xmlns=\"%s\"><mechanism>PLAIN</mechanism>"
"</mechanisms></stream:features>", XMPP_NS_SASL);
break;
case XMPP_SERVER_DISCONNECT:
printf("Event XMPP_SERVER_DISCONNECT\n");
xmpp_stop(ctx);
break;
default:
printf("Unknown event\n");
break;
}
}
int main()
{
xmpp_ctx_t *ctx;
xmpp_log_t *log;
xmpp_server_t *srv;
xmpp_initialize();
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
ctx = xmpp_ctx_new(NULL, log);
srv = xmpp_server_new(ctx);
xmpp_server_listen(srv, 0, server_handler, ctx);
xmpp_run(ctx);
xmpp_server_stop(srv);
xmpp_server_free(srv);
xmpp_ctx_free(ctx);
xmpp_shutdown();
return 0;
}

View File

@@ -44,6 +44,7 @@ LOCAL_SRC_FILES := \
../src/resolver.c \
../src/sasl.c \
../src/scram.c \
../src/server.c \
../src/sha1.c \
../src/snprintf.c \
../src/sock.c \
@@ -62,7 +63,7 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libexpat
LOCAL_CFLAGS := -DHAVE_MEMMOVE -DXML_DEV_URANDOM
LOCAL_CFLAGS := -DHAVE_MEMMOVE
#LOCAL_C_INCLUDES := \
# $(LOCAL_PATH)/expat

View File

@@ -1,2 +1,2 @@
APP_ABI := armeabi-v7a arm64-v8a
APP_ABI := armeabi armeabi-v7a mips x86
APP_PLATFORM := android-19

View File

@@ -61,7 +61,6 @@
#endif
static void _auth(xmpp_conn_t * const conn);
static void _auth_legacy(xmpp_conn_t *conn);
static void _handle_open_sasl(xmpp_conn_t * const conn);
static void _handle_open_tls(xmpp_conn_t * const conn);
@@ -70,6 +69,11 @@ static int _handle_component_hs_response(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza,
void * const userdata);
static int _handle_missing_legacy(xmpp_conn_t * const conn,
void * const userdata);
static int _handle_legacy(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza,
void * const userdata);
static int _handle_features_sasl(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza,
void * const userdata);
@@ -215,7 +219,6 @@ static int _handle_features(xmpp_conn_t * const conn,
void * const userdata)
{
xmpp_stanza_t *child, *mech;
const char *ns;
char *text;
/* remove the handler that detects missing stream:features */
@@ -225,10 +228,8 @@ static int _handle_features(xmpp_conn_t * const conn,
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 (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_TLS) == 0))
conn->tls_support = 1;
} else {
conn->tls_support = 0;
}
@@ -236,15 +237,11 @@ static int _handle_features(xmpp_conn_t * const conn,
/* 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) {
if (child && (strcmp(xmpp_stanza_get_ns(child), 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, "DIGEST-MD5") == 0)
@@ -259,10 +256,6 @@ static int _handle_features(xmpp_conn_t * const conn,
}
}
/* Disable PLAIN when other secure mechanisms are supported */
if (conn->sasl_support & ~(SASL_MASK_PLAIN | SASL_MASK_ANONYMOUS))
conn->sasl_support &= ~SASL_MASK_PLAIN;
_auth(conn);
return 0;
@@ -557,11 +550,9 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t * const conn,
*/
static void _auth(xmpp_conn_t * const conn)
{
xmpp_stanza_t *auth;
xmpp_stanza_t *authdata;
char *authid;
xmpp_stanza_t *auth, *authdata, *query, *child, *iq;
char *str, *authid;
char *scram_init;
char *str;
int anonjid;
/* if there is no node in conn->jid, we assume anonymous connect */
@@ -728,12 +719,105 @@ static void _auth(xmpp_conn_t * const conn)
/* SASL PLAIN was tried */
conn->sasl_support &= ~SASL_MASK_PLAIN;
} else if (conn->type == XMPP_CLIENT && conn->auth_legacy_enabled) {
/* legacy client authentication */
_auth_legacy(conn);
} else {
xmpp_error(conn->ctx, "auth", "Cannot authenticate with known methods");
xmpp_disconnect(conn);
} else if (conn->type == XMPP_CLIENT) {
/* legacy client authentication */
iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_auth1");
if (!iq) {
disconnect_mem_error(conn);
return;
}
query = xmpp_stanza_new(conn->ctx);
if (!query) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
xmpp_stanza_set_name(query, "query");
xmpp_stanza_set_ns(query, XMPP_NS_AUTH);
xmpp_stanza_add_child(iq, query);
xmpp_stanza_release(query);
child = xmpp_stanza_new(conn->ctx);
if (!child) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
xmpp_stanza_set_name(child, "username");
xmpp_stanza_add_child(query, child);
xmpp_stanza_release(child);
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
str = xmpp_jid_node(conn->ctx, conn->jid);
xmpp_stanza_set_text(authdata, str);
xmpp_free(conn->ctx, str);
xmpp_stanza_add_child(child, authdata);
xmpp_stanza_release(authdata);
child = xmpp_stanza_new(conn->ctx);
if (!child) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
xmpp_stanza_set_name(child, "password");
xmpp_stanza_add_child(query, child);
xmpp_stanza_release(child);
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
xmpp_stanza_set_text(authdata, conn->pass);
xmpp_stanza_add_child(child, authdata);
xmpp_stanza_release(authdata);
child = xmpp_stanza_new(conn->ctx);
if (!child) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
xmpp_stanza_set_name(child, "resource");
xmpp_stanza_add_child(query, child);
xmpp_stanza_release(child);
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
str = xmpp_jid_resource(conn->ctx, conn->jid);
if (str) {
xmpp_stanza_set_text(authdata, str);
xmpp_free(conn->ctx, str);
} else {
xmpp_stanza_release(authdata);
xmpp_stanza_release(iq);
xmpp_error(conn->ctx, "auth",
"Cannot authenticate without resource");
xmpp_disconnect(conn);
return;
}
xmpp_stanza_add_child(child, authdata);
xmpp_stanza_release(authdata);
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
handler_add_timed(conn, _handle_missing_legacy,
LEGACY_TIMEOUT, NULL);
xmpp_send(conn, iq);
xmpp_stanza_release(iq);
}
}
@@ -787,8 +871,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza,
void * const userdata)
{
xmpp_stanza_t *bind, *session, *iq, *res, *text, *opt;
const char *ns;
xmpp_stanza_t *bind, *session, *iq, *res, *text;
char *resource;
/* remove missing features handler */
@@ -797,21 +880,16 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
/* we are expecting <bind/> and <session/> since this is a
XMPP style connection */
/* check whether resource binding is required */
bind = xmpp_stanza_get_child_by_name(stanza, "bind");
if (bind) {
ns = xmpp_stanza_get_ns(bind);
conn->bind_required = ns != NULL && strcmp(ns, XMPP_NS_BIND) == 0;
if (bind && strcmp(xmpp_stanza_get_ns(bind), XMPP_NS_BIND) == 0) {
/* resource binding is required */
conn->bind_required = 1;
}
/* check whether session establishment is required */
session = xmpp_stanza_get_child_by_name(stanza, "session");
if (session) {
ns = xmpp_stanza_get_ns(session);
opt = xmpp_stanza_get_child_by_name(session, "optional");
if (!opt)
conn->session_required = ns != NULL &&
strcmp(ns, XMPP_NS_SESSION) == 0;
if (session && strcmp(xmpp_stanza_get_ns(session), XMPP_NS_SESSION) == 0) {
/* session establishment required */
conn->session_required = 1;
}
/* if bind is required, go ahead and start it */
@@ -1014,15 +1092,6 @@ static int _handle_missing_session(xmpp_conn_t * const conn,
return 0;
}
static int _handle_missing_legacy(xmpp_conn_t * const conn,
void * const userdata)
{
xmpp_error(conn->ctx, "xmpp", "Server did not reply to legacy "\
"authentication request.");
xmpp_disconnect(conn);
return 0;
}
static int _handle_legacy(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza,
void * const userdata)
@@ -1059,97 +1128,13 @@ static int _handle_legacy(xmpp_conn_t * const conn,
return 0;
}
static void _auth_legacy(xmpp_conn_t *conn)
static int _handle_missing_legacy(xmpp_conn_t * const conn,
void * const userdata)
{
xmpp_stanza_t *iq;
xmpp_stanza_t *authdata;
xmpp_stanza_t *query;
xmpp_stanza_t *child;
char *str;
xmpp_debug(conn->ctx, "auth", "Legacy authentication request");
iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_auth1");
if (!iq)
goto err;
query = xmpp_stanza_new(conn->ctx);
if (!query)
goto err_free;
xmpp_stanza_set_name(query, "query");
xmpp_stanza_set_ns(query, XMPP_NS_AUTH);
xmpp_stanza_add_child(iq, query);
xmpp_stanza_release(query);
child = xmpp_stanza_new(conn->ctx);
if (!child)
goto err_free;
xmpp_stanza_set_name(child, "username");
xmpp_stanza_add_child(query, child);
xmpp_stanza_release(child);
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata)
goto err_free;
str = xmpp_jid_node(conn->ctx, conn->jid);
if (!str) {
xmpp_stanza_release(authdata);
goto err_free;
}
xmpp_stanza_set_text(authdata, str);
xmpp_free(conn->ctx, str);
xmpp_stanza_add_child(child, authdata);
xmpp_stanza_release(authdata);
child = xmpp_stanza_new(conn->ctx);
if (!child)
goto err_free;
xmpp_stanza_set_name(child, "password");
xmpp_stanza_add_child(query, child);
xmpp_stanza_release(child);
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata)
goto err_free;
xmpp_stanza_set_text(authdata, conn->pass);
xmpp_stanza_add_child(child, authdata);
xmpp_stanza_release(authdata);
child = xmpp_stanza_new(conn->ctx);
if (!child)
goto err_free;
xmpp_stanza_set_name(child, "resource");
xmpp_stanza_add_child(query, child);
xmpp_stanza_release(child);
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata)
goto err_free;
str = xmpp_jid_resource(conn->ctx, conn->jid);
if (str) {
xmpp_stanza_set_text(authdata, str);
xmpp_free(conn->ctx, str);
} else {
xmpp_stanza_release(authdata);
xmpp_stanza_release(iq);
xmpp_error(conn->ctx, "auth", "Cannot authenticate without resource");
xmpp_disconnect(conn);
return;
}
xmpp_stanza_add_child(child, authdata);
xmpp_stanza_release(authdata);
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
handler_add_timed(conn, _handle_missing_legacy, LEGACY_TIMEOUT, NULL);
xmpp_send(conn, iq);
xmpp_stanza_release(iq);
return;
err_free:
xmpp_stanza_release(iq);
err:
disconnect_mem_error(conn);
xmpp_error(conn->ctx, "xmpp", "Server did not reply to legacy "\
"authentication request.");
xmpp_disconnect(conn);
return 0;
}
void auth_handle_component_open(xmpp_conn_t * const conn)

View File

@@ -43,6 +43,11 @@ typedef struct _xmpp_connlist_t {
struct _xmpp_connlist_t *next;
} xmpp_connlist_t;
typedef struct _xmpp_serverlist_t {
xmpp_server_t *server;
struct _xmpp_serverlist_t *next;
} xmpp_serverlist_t;
struct _xmpp_ctx_t {
const xmpp_mem_t *mem;
const xmpp_log_t *log;
@@ -50,6 +55,7 @@ struct _xmpp_ctx_t {
xmpp_rand_t *rand;
xmpp_loop_status_t loop_status;
xmpp_connlist_t *connlist;
xmpp_serverlist_t *serverlist;
unsigned long timeout;
};
@@ -172,7 +178,6 @@ struct _xmpp_conn_t {
int tls_failed; /* set when tls fails, so we don't try again */
int sasl_support; /* if true, field is a bitfield of supported
mechanisms */
int auth_legacy_enabled;
int secured; /* set when stream is secured with TLS */
/* if server returns <bind/> or <session/> we must do them */
@@ -226,6 +231,24 @@ int conn_tls_start(xmpp_conn_t * const conn);
void conn_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler);
void conn_parser_reset(xmpp_conn_t * const conn);
typedef enum {
XMPP_STATE_STOPPED,
XMPP_STATE_LISTENING
} xmpp_server_state_t;
struct _xmpp_server_t {
xmpp_ctx_t *ctx;
xmpp_server_state_t state;
sock_t sock;
unsigned short port;
xmpp_server_handler callback;
void *userdata;
/* incomming connections list */
};
void server_accept(xmpp_server_t * const srv);
void server_handle_open(xmpp_conn_t * const conn);
typedef enum {
XMPP_STANZA_UNKNOWN,

View File

@@ -73,15 +73,6 @@ static int _conn_connect(xmpp_conn_t * const conn,
xmpp_conn_handler callback,
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.
*
* @param ctx a Strophe context object
@@ -140,7 +131,6 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
conn->tls_trust = 0;
conn->tls_failed = 0;
conn->sasl_support = 0;
conn->auth_legacy_enabled = 0;
conn->secured = 0;
conn->bind_required = 0;
@@ -635,14 +625,15 @@ int xmpp_conn_open_stream(xmpp_conn_t * const conn, char **attributes,
{
char *tag;
if (!conn->is_raw)
if (!conn->is_raw && conn->type != XMPP_INCOMING)
return XMPP_EINVOP;
tag = _conn_build_stream_tag(conn, attributes, attributes_len);
if (!tag)
return XMPP_EMEM;
conn_prepare_reset(conn, auth_handle_open_raw);
if (conn->type != XMPP_INCOMING)
conn_prepare_reset(conn, auth_handle_open_raw);
xmpp_send_raw_string(conn, "<?xml version=\"1.0\"?>%s", tag);
xmpp_free(conn->ctx, tag);
@@ -714,7 +705,7 @@ void conn_parser_reset(xmpp_conn_t * const conn)
/** Initiate termination of the connection to the XMPP server.
* This function starts the disconnection sequence by sending
* </stream:stream> to the XMPP server. This function will do nothing
* if the connection state is different from CONNECTING or CONNECTED.
* if the connection state is CONNECTING or CONNECTED.
*
* @param conn a Strophe connection object
*
@@ -756,10 +747,10 @@ void xmpp_send_raw_string(xmpp_conn_t * const conn,
char *bigbuf;
va_start(ap, fmt);
len = xmpp_vsnprintf(buf, sizeof(buf), fmt, ap);
len = xmpp_vsnprintf(buf, 1024, fmt, ap);
va_end(ap);
if (len >= sizeof(buf)) {
if (len >= 1024) {
/* we need more space for this data, so we allocate a big
* enough buffer and print to that */
len++; /* account for trailing \0 */
@@ -780,6 +771,7 @@ void xmpp_send_raw_string(xmpp_conn_t * const conn,
xmpp_free(conn->ctx, bigbuf);
} else {
xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
xmpp_send_raw(conn, buf, len);
}
}
@@ -844,9 +836,10 @@ void xmpp_send(xmpp_conn_t * const conn,
{
char *buf;
size_t len;
int ret;
if (conn->state == XMPP_STATE_CONNECTED) {
if (xmpp_stanza_to_text(stanza, &buf, &len) == 0) {
if ((ret = xmpp_stanza_to_text(stanza, &buf, &len)) == 0) {
xmpp_send_raw(conn, buf, len);
xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
xmpp_free(conn->ctx, buf);
@@ -921,8 +914,7 @@ long xmpp_conn_get_flags(const xmpp_conn_t * const conn)
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_LEGACY_AUTH * conn->auth_legacy_enabled;;
XMPP_CONN_FLAG_TRUST_TLS * conn->tls_trust;
return flags;
}
@@ -940,7 +932,6 @@ long xmpp_conn_get_flags(const xmpp_conn_t * const conn)
* - XMPP_CONN_FLAG_MANDATORY_TLS
* - XMPP_CONN_FLAG_LEGACY_SSL
* - XMPP_CONN_FLAG_TRUST_TLS
* - XMPP_CONN_FLAG_LEGACY_AUTH
*
* @param conn a Strophe connection object
* @param flags ORed connection flags
@@ -967,7 +958,6 @@ int xmpp_conn_set_flags(xmpp_conn_t * const conn, long flags)
conn->tls_mandatory = (flags & XMPP_CONN_FLAG_MANDATORY_TLS) ? 1 : 0;
conn->tls_legacy_ssl = (flags & XMPP_CONN_FLAG_LEGACY_SSL) ? 1 : 0;
conn->tls_trust = (flags & XMPP_CONN_FLAG_TRUST_TLS) ? 1 : 0;
conn->auth_legacy_enabled = (flags & XMPP_CONN_FLAG_LEGACY_AUTH) ? 1 : 0;
return 0;
}
@@ -1213,9 +1203,6 @@ static void _conn_reset(xmpp_conn_t * const conn)
xmpp_free(ctx, tsq->data);
xmpp_free(ctx, tsq);
}
conn->send_queue_head = NULL;
conn->send_queue_tail = NULL;
conn->send_queue_len = 0;
if (conn->stream_error) {
xmpp_stanza_release(conn->stream_error->stanza);

View File

@@ -61,7 +61,7 @@ static char *digest_to_string_alloc(xmpp_ctx_t *ctx, const uint8_t *digest)
return s;
}
/** Compute SHA1 message digest.
/** Compute SHA1 message digest
* Returns an allocated string which represents SHA1 message digest in
* 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);
}
/** Compute SHA1 message digest.
/** Compute SHA1 message digest
* Stores digest in user's buffer which must be at least XMPP_SHA1_DIGEST_SIZE
* 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);
}
/** Create new SHA1 object.
/** Create new SHA1 object
* 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
* 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);
* @endcode
*
* @param ctx a Strophe context object
* @param ctx a Strophe context onject
*
* @return new SHA1 object
*
@@ -130,7 +130,7 @@ xmpp_sha1_t *xmpp_sha1_new(xmpp_ctx_t *ctx)
return sha1;
}
/** Destroy SHA1 object.
/** Destroy 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);
}
/** Update SHA1 context with the next portion of data.
/** Update SHA1 context with the next portion of data
* Can be called repeatedly.
*
* @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);
}
/** Finish SHA1 computation.
/** Finish SHA1 computation
* Don't call xmpp_sha1_update() after this function. Retrieve resulting
* 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);
}
/** 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
* 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 message digest rendered as a string.
/** 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().
@@ -201,7 +201,7 @@ char *xmpp_sha1_to_string_alloc(xmpp_sha1_t *sha1)
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 digest output buffer of XMPP_SHA1_DIGEST_SIZE bytes
@@ -419,7 +419,7 @@ _base64_error:
*outlen = 0;
}
/** Base64 encoding routine.
/** Base64 encoding routine
* Returns an allocated string which must be freed with xmpp_free().
*
* @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);
}
/** Base64 decoding routine.
/** Base64 decoding routine
* 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
* 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;
}
/** Base64 decoding routine.
/** Base64 decoding routine
* Returns an allocated buffer which must be freed with xmpp_free().
*
* @param ctx a Strophe context

View File

@@ -415,6 +415,7 @@ xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t * const mem,
ctx->log = log;
ctx->connlist = NULL;
ctx->serverlist = NULL;
ctx->loop_status = XMPP_LOOP_NOTSTARTED;
ctx->rand = xmpp_rand_new(ctx);
ctx->timeout = EVENT_LOOP_DEFAULT_TIMEOUT;

View File

@@ -67,7 +67,9 @@
void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
{
xmpp_connlist_t *connitem;
xmpp_serverlist_t *serveritem;
xmpp_conn_t *conn;
xmpp_server_t *srv;
fd_set rfds, wfds;
sock_t max = 0;
int ret;
@@ -206,6 +208,23 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
connitem = connitem->next;
}
serveritem = ctx->serverlist;
while (serveritem) {
srv = serveritem->server;
switch (srv->state) {
case XMPP_STATE_LISTENING:
FD_SET(srv->sock, &rfds);
if (srv->sock > max) max = srv->sock;
break;
case XMPP_STATE_STOPPED:
/* do nothing */
default:
break;
}
serveritem = serveritem->next;
}
/* check for events */
if (max > 0)
ret = select(max + 1, &rfds, &wfds, NULL, &tv);
@@ -262,8 +281,10 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
if (ret > 0) {
ret = parser_feed(conn->parser, buf, ret);
if (!ret) {
xmpp_debug(ctx, "xmpp", "parse error [%s]", buf);
xmpp_send_error(conn, XMPP_SE_INVALID_XML, "parse error");
/* parse error, we need to shut down */
/* FIXME */
xmpp_debug(ctx, "xmpp", "parse error, disconnecting");
conn_disconnect(conn);
}
} else {
if (conn->tls) {
@@ -291,6 +312,24 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
connitem = connitem->next;
}
serveritem = ctx->serverlist;
while (serveritem) {
srv = serveritem->server;
switch (srv->state) {
case XMPP_STATE_LISTENING:
if (FD_ISSET(srv->sock, &rfds)) {
server_accept(srv);
}
break;
case XMPP_STATE_STOPPED:
/* do nothing */
default:
break;
}
serveritem = serveritem->next;
}
/* fire any ready handlers */
handler_fire_timed(ctx);
}

View File

@@ -163,8 +163,6 @@ int hash_add(hash_t *table, const char * const key, void *data)
entry->next = table->entries[table_index];
table->entries[table_index] = entry;
table->num_keys++;
} else {
if (table->free) table->free(ctx, entry->value);
}
entry->value = data;
@@ -243,7 +241,7 @@ void hash_iter_release(hash_iterator_t *iter)
iter->ref--;
if (iter->ref == 0) { // ref is unsigned!!!
if (iter->ref <= 0) {
hash_release(iter->table);
xmpp_free(ctx, iter);
}

View File

@@ -137,7 +137,7 @@ static void _start_element(void *userdata,
if (parser->depth == 0) {
/* notify the owner */
if (parser->startcb)
parser->startcb(name, (char **)attrs,
parser->startcb((char *)name, (char **)attrs,
parser->userdata);
} else {
/* build stanzas at depth 1 */

View File

@@ -249,8 +249,6 @@ void parser_free(parser_t *parser)
{
if (parser->xmlctx)
xmlFreeParserCtxt(parser->xmlctx);
if (parser->stanza)
xmpp_stanza_release(parser->stanza);
xmpp_free(parser->ctx, parser);
}
@@ -259,16 +257,18 @@ int parser_reset(parser_t *parser)
{
if (parser->xmlctx)
xmlFreeParserCtxt(parser->xmlctx);
if (parser->stanza)
xmpp_stanza_release(parser->stanza);
parser->stanza = NULL;
parser->depth = 0;
parser->xmlctx = xmlCreatePushParserCtxt(&parser->handlers,
parser, NULL, 0, NULL);
if (!parser->xmlctx) return 0;
return parser->xmlctx ? 1 : 0;
parser->depth = 0;
parser->stanza = NULL;
return 1;
}
/* feed a chunk of data to the parser */

View File

@@ -127,11 +127,9 @@ static void Hash_DRBG_Instantiate(Hash_DRBG_CTX *ctx,
assert(entropy_input_len <= ENTROPY_MAX);
assert(nonce_len <= NONCE_MAX);
assert(nonce != NULL || nonce_len == 0);
memcpy(seed_material, entropy_input, entropy_input_len);
if (nonce != NULL)
memcpy(seed_material + entropy_input_len, nonce, nonce_len);
memcpy(seed_material + entropy_input_len, nonce, nonce_len);
Hash_df(seed_material, entropy_input_len + nonce_len, seed, seedlen);
seed0[0] = 0;

View File

@@ -36,7 +36,7 @@ xmpp_rand_t *xmpp_rand_new(xmpp_ctx_t *ctx);
*/
void xmpp_rand_free(xmpp_ctx_t *ctx, xmpp_rand_t *rand);
/** Generate random integer.
/** Generate random integer
* Analogue of rand(3).
*
* @ingroup Random

View File

@@ -517,7 +517,7 @@ static int resolver_win32_srv_query(const char *fulldomain,
unsigned char *buf, size_t len)
{
int set = 0;
int insize = 0;
int insize;
/* if dnsapi didn't work/isn't there, try querying the dns server manually */
if (!set)
@@ -550,7 +550,7 @@ static int resolver_win32_srv_query(const char *fulldomain,
char buffer[65535];
len = 65535;
fi = (FIXED_INFO *)buffer;
fi = buffer;
if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
{

View File

@@ -264,8 +264,7 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
xmpp_rand_nonce(ctx->rand, cnonce, sizeof(cnonce));
hash_add(table, "cnonce", xmpp_strdup(ctx, cnonce));
hash_add(table, "nc", xmpp_strdup(ctx, "00000001"));
if (hash_get(table, "qop") == NULL)
hash_add(table, "qop", xmpp_strdup(ctx, "auth"));
hash_add(table, "qop", xmpp_strdup(ctx, "auth"));
value = xmpp_alloc(ctx, 5 + strlen(domain) + 1);
memcpy(value, "xmpp/", 5);
memcpy(value+5, domain, strlen(domain));

162
src/server.c Normal file
View File

@@ -0,0 +1,162 @@
/* server.c
* strophe XMPP client library -- server object functions
*
* 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.
*/
/** @file
* Server management.
*/
/** @defgroup Server Server management
*/
#include <string.h>
#include "common.h"
#include "strophe.h"
static xmpp_server_t *conn2srv(xmpp_conn_t *conn);
static void _server_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_server_t *xmpp_server_new(xmpp_ctx_t * const ctx)
{
xmpp_server_t *srv;
xmpp_serverlist_t *item;
srv = xmpp_alloc(ctx, sizeof(*srv));
item = xmpp_alloc(ctx, sizeof(*item));
if (srv == NULL || item == NULL) {
xmpp_error(ctx, "xmpp", "Failed to allocate memory.");
xmpp_free(ctx, srv);
xmpp_free(ctx, item);
srv = NULL;
item = NULL;
}
if (srv != NULL) {
memset(srv, 0, sizeof(*srv));
srv->state = XMPP_STATE_STOPPED;
srv->ctx = ctx;
srv->sock = -1;
item->server = srv;
item->next = ctx->serverlist;
ctx->serverlist = item;
}
return srv;
}
void xmpp_server_free(xmpp_server_t * const srv)
{
xmpp_ctx_t *ctx = srv->ctx;
xmpp_serverlist_t *item, *prev = NULL;
item = ctx->serverlist;
while (item != NULL) {
if (item->server == srv) {
if (prev == NULL) ctx->serverlist = item->next;
if (prev != NULL) prev->next = item->next;
xmpp_free(ctx, item);
}
prev = item;
item = item->next;
}
xmpp_free(ctx, srv);
}
int xmpp_server_listen(xmpp_server_t * const srv, unsigned short port,
xmpp_server_handler callback, void * const userdata)
{
int rc = 0;
if (port == 0) port = XMPP_PORT_CLIENT;
srv->callback = callback;
srv->userdata = userdata;
srv->port = port;
srv->sock = sock_listen(port);
if (srv->sock >= 0) {
srv->state = XMPP_STATE_LISTENING;
xmpp_debug(srv->ctx, "xmpp", "Listening on port %u.", port);
} else
rc = XMPP_EINT;
return rc;
}
void xmpp_server_stop(xmpp_server_t * const srv)
{
srv->state = XMPP_STATE_STOPPED;
sock_stop_listen(srv->sock);
xmpp_debug(srv->ctx, "xmpp", "Server stopped on %u.", srv->port);
}
void server_accept(xmpp_server_t * const srv)
{
xmpp_conn_t *conn;
sock_t fd;
fd = sock_accept(srv->sock);
if (fd >= 0) {
xmpp_debug(srv->ctx, "xmpp", "New incoming connection on port %u.",
srv->port);
conn = xmpp_conn_new(srv->ctx);
conn->type = XMPP_INCOMING;
conn->state = XMPP_STATE_CONNECTED;
conn->sock = fd;
conn->conn_handler = _server_conn_handler;
conn->userdata = (void *)srv;
conn->authenticated = 1; /* don't ignore handlers */
conn_prepare_reset(conn, server_handle_open);
srv->callback(srv, conn, XMPP_SERVER_ACCEPT, 0, srv->userdata);
}
}
void server_handle_open(xmpp_conn_t * const conn)
{
xmpp_server_t *srv = conn2srv(conn);
/* XXX need to reset parser and re-open stream after authentication */
srv->callback(srv, conn, XMPP_SERVER_OPEN_STREAM, 0, srv->userdata);
}
static xmpp_server_t *conn2srv(xmpp_conn_t *conn)
{
xmpp_server_t *srv;
/* XXX dirty hack */
if (conn->ctx->serverlist != NULL)
srv = conn->ctx->serverlist->server;
else
srv = NULL;
return srv;
}
static void _server_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_server_t *srv = (xmpp_server_t *)userdata;
if (status == XMPP_CONN_DISCONNECT) {
/* remove conn from the list */
/* XXX when client sends </stream> first, server should close stream too */
srv->callback(srv, conn, XMPP_SERVER_DISCONNECT, error, srv->userdata);
}
}

View File

@@ -109,6 +109,43 @@ sock_t sock_connect(const char * const host, const unsigned short port)
return sock;
}
sock_t sock_listen(const unsigned short port)
{
struct sockaddr_in addr;
sock_t sock;
int rc;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) return -1;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
rc = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (rc == 0) {
rc = listen(sock, 100);
sock_set_nonblocking(sock);
}
if (rc != 0) close(sock);
return rc == 0 ? sock : -1;
}
int sock_stop_listen(const sock_t sock)
{
return sock_close(sock);
}
sock_t sock_accept(const sock_t sock)
{
sock_t fd;
fd = accept(sock, NULL, NULL);
return fd;
}
int sock_set_keepalive(const sock_t sock, int timeout, int interval)
{
int ret;

View File

@@ -32,6 +32,9 @@ int sock_error(void);
sock_t sock_connect(const char * const host, const unsigned short port);
int sock_close(const sock_t sock);
sock_t sock_listen(const unsigned short port);
int sock_stop_listen(const sock_t sock);
sock_t sock_accept(const sock_t sock);
int sock_set_blocking(const sock_t sock);
int sock_set_nonblocking(const sock_t sock);

View File

@@ -1,7 +1,7 @@
/* stanza.c
** 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
** or implied.
@@ -40,15 +40,15 @@ xmpp_stanza_t *xmpp_stanza_new(xmpp_ctx_t *ctx)
stanza = xmpp_alloc(ctx, sizeof(xmpp_stanza_t));
if (stanza != NULL) {
stanza->ref = 1;
stanza->ctx = ctx;
stanza->type = XMPP_STANZA_UNKNOWN;
stanza->prev = NULL;
stanza->next = NULL;
stanza->children = NULL;
stanza->parent = NULL;
stanza->data = NULL;
stanza->attributes = NULL;
stanza->ref = 1;
stanza->ctx = ctx;
stanza->type = XMPP_STANZA_UNKNOWN;
stanza->prev = NULL;
stanza->next = NULL;
stanza->children = NULL;
stanza->parent = NULL;
stanza->data = NULL;
stanza->attributes = NULL;
}
return stanza;
@@ -121,27 +121,27 @@ xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t * const stanza)
copy->type = stanza->type;
if (stanza->data) {
copy->data = xmpp_strdup(stanza->ctx, stanza->data);
if (!copy->data) goto copy_error;
copy->data = xmpp_strdup(stanza->ctx, stanza->data);
if (!copy->data) goto copy_error;
}
if (stanza->attributes) {
if (_stanza_copy_attributes(copy, stanza) == -1)
if (_stanza_copy_attributes(copy, stanza) == -1)
goto copy_error;
}
tail = copy->children;
for (child = stanza->children; child; child = child->next) {
copychild = xmpp_stanza_copy(child);
if (!copychild) goto copy_error;
copychild->parent = copy;
copychild = xmpp_stanza_copy(child);
if (!copychild) goto copy_error;
copychild->parent = copy;
if (tail) {
copychild->prev = tail;
tail->next = copychild;
} else
copy->children = copychild;
tail = copychild;
if (tail) {
copychild->prev = tail;
tail->next = copychild;
} else
copy->children = copychild;
tail = copychild;
}
return copy;
@@ -153,7 +153,7 @@ copy_error:
}
/** 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.
*
* @param stanza a Strophe stanza object
@@ -169,20 +169,20 @@ int xmpp_stanza_release(xmpp_stanza_t * const stanza)
/* release stanza */
if (stanza->ref > 1)
stanza->ref--;
stanza->ref--;
else {
/* release all children */
child = stanza->children;
while (child) {
tchild = child;
child = child->next;
xmpp_stanza_release(tchild);
}
/* release all children */
child = stanza->children;
while (child) {
tchild = child;
child = child->next;
xmpp_stanza_release(tchild);
}
if (stanza->attributes) hash_release(stanza->attributes);
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
xmpp_free(stanza->ctx, stanza);
released = 1;
if (stanza->attributes) hash_release(stanza->attributes);
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
xmpp_free(stanza->ctx, stanza);
released = 1;
}
return released;
@@ -274,17 +274,17 @@ static char *_escape_xml(xmpp_ctx_t * const ctx, char *text)
/* small helper function */
static void _render_update(int *written, const int length,
const int lastwrite,
size_t *left, char **ptr)
const int lastwrite,
size_t *left, char **ptr)
{
*written += lastwrite;
if (*written >= length) {
*left = 0;
*ptr = NULL;
*left = 0;
*ptr = NULL;
} else {
*left -= lastwrite;
*ptr = &(*ptr)[lastwrite];
*left -= 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
*/
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;
size_t left = buflen;
@@ -309,86 +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_TEXT) {
if (!stanza->data) return XMPP_EINVOP;
if (!stanza->data) return XMPP_EINVOP;
tmp = _escape_xml(stanza->ctx, stanza->data);
if (tmp == NULL) return XMPP_EMEM;
ret = xmpp_snprintf(ptr, left, "%s", tmp);
xmpp_free(stanza->ctx, tmp);
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
tmp = _escape_xml(stanza->ctx, stanza->data);
if (tmp == NULL) return XMPP_EMEM;
ret = xmpp_snprintf(ptr, left, "%s", tmp);
xmpp_free(stanza->ctx, tmp);
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
} else { /* stanza->type == XMPP_STANZA_TAG */
if (!stanza->data) return XMPP_EINVOP;
if (!stanza->data) return XMPP_EINVOP;
/* write beginning of tag and attributes */
ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
/* write beginning of tag and attributes */
ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
iter = hash_iter_new(stanza->attributes);
while ((key = hash_iter_next(iter))) {
if (!strcmp(key, "xmlns")) {
/* don't output namespace if parent stanza is the same */
if (stanza->parent &&
stanza->parent->attributes &&
hash_get(stanza->parent->attributes, key) &&
!strcmp((char*)hash_get(stanza->attributes, key),
(char*)hash_get(stanza->parent->attributes, key)))
continue;
/* or if this is the stream namespace */
if (!stanza->parent &&
!strcmp((char*)hash_get(stanza->attributes, key),
XMPP_NS_CLIENT))
continue;
}
tmp = _escape_xml(stanza->ctx,
(char *)hash_get(stanza->attributes, key));
if (tmp == NULL) {
hash_iter_release(iter);
return XMPP_EMEM;
}
ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
xmpp_free(stanza->ctx, tmp);
if (ret < 0) {
hash_iter_release(iter);
return XMPP_EMEM;
}
_render_update(&written, buflen, ret, &left, &ptr);
}
hash_iter_release(iter);
}
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
iter = hash_iter_new(stanza->attributes);
while ((key = hash_iter_next(iter))) {
if (!strcmp(key, "xmlns")) {
/* don't output namespace if parent stanza is the same */
if (stanza->parent &&
stanza->parent->attributes &&
hash_get(stanza->parent->attributes, key) &&
!strcmp((char*)hash_get(stanza->attributes, key),
(char*)hash_get(stanza->parent->attributes, key)))
continue;
/* or if this is the stream namespace */
if (!stanza->parent &&
!strcmp((char*)hash_get(stanza->attributes, key),
XMPP_NS_CLIENT))
continue;
}
tmp = _escape_xml(stanza->ctx,
(char *)hash_get(stanza->attributes, key));
if (tmp == NULL) return XMPP_EMEM;
ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
xmpp_free(stanza->ctx, tmp);
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
}
hash_iter_release(iter);
}
if (!stanza->children) {
/* write end if singleton tag */
ret = xmpp_snprintf(ptr, left, "/>");
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
} else {
/* this stanza has child stanzas */
if (!stanza->children) {
/* write end if singleton tag */
ret = xmpp_snprintf(ptr, left, "/>");
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
} else {
/* this stanza has child stanzas */
/* write end of start tag */
ret = xmpp_snprintf(ptr, left, ">");
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
/* write end of start tag */
ret = xmpp_snprintf(ptr, left, ">");
if (ret < 0) return XMPP_EMEM;
_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;
/* 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);
_render_update(&written, buflen, ret, &left, &ptr);
child = child->next;
}
child = child->next;
}
/* write end tag */
ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
}
/* write end tag */
ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
if (ret < 0) return XMPP_EMEM;
_render_update(&written, buflen, ret, &left, &ptr);
}
}
return written;
@@ -421,37 +415,27 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
length = 1024;
buffer = xmpp_alloc(stanza->ctx, length);
if (!buffer) {
*buf = NULL;
*buflen = 0;
return XMPP_EMEM;
*buf = NULL;
*buflen = 0;
return XMPP_EMEM;
}
ret = _render_stanza_recursive(stanza, buffer, length);
if (ret < 0) {
xmpp_free(stanza->ctx, buffer);
*buf = NULL;
*buflen = 0;
return ret;
}
if (ret < 0) return ret;
if ((size_t)ret > length - 1) {
tmp = xmpp_realloc(stanza->ctx, buffer, ret + 1);
if (!tmp) {
xmpp_free(stanza->ctx, buffer);
*buf = NULL;
*buflen = 0;
return XMPP_EMEM;
}
length = ret + 1;
buffer = tmp;
tmp = xmpp_realloc(stanza->ctx, buffer, ret + 1);
if (!tmp) {
xmpp_free(stanza->ctx, buffer);
*buf = NULL;
*buflen = 0;
return XMPP_EMEM;
}
length = ret + 1;
buffer = tmp;
ret = _render_stanza_recursive(stanza, buffer, length);
if ((size_t)ret > length - 1) {
xmpp_free(stanza->ctx, buffer);
*buf = NULL;
*buflen = 0;
return XMPP_EMEM;
}
ret = _render_stanza_recursive(stanza, buffer, length);
if ((size_t)ret > length - 1) return XMPP_EMEM;
}
buffer[length - 1] = 0;
@@ -473,7 +457,7 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
* @ingroup 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;
@@ -512,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)
{
if (stanza->attributes == NULL) {
return 0;
return 0;
}
return hash_num_keys(stanza->attributes);
@@ -533,30 +517,30 @@ int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza)
* @ingroup 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;
const char *key;
int num = 0;
if (stanza->attributes == NULL) {
return 0;
return 0;
}
iter = hash_iter_new(stanza->attributes);
while ((key = hash_iter_next(iter)) != NULL && attrlen) {
attr[num++] = key;
attrlen--;
if (attrlen == 0) {
hash_iter_release(iter);
return num;
}
attr[num++] = hash_get(stanza->attributes, key);
attrlen--;
if (attrlen == 0) {
hash_iter_release(iter);
return num;
}
attr[num++] = key;
attrlen--;
if (attrlen == 0) {
hash_iter_release(iter);
return num;
}
attr[num++] = hash_get(stanza->attributes, key);
attrlen--;
if (attrlen == 0) {
hash_iter_release(iter);
return num;
}
}
hash_iter_release(iter);
@@ -574,8 +558,8 @@ int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
* @ingroup Stanza
*/
int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
const char * const key,
const char * const value)
const char * const key,
const char * const value)
{
char *val;
int rc;
@@ -583,12 +567,13 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
if (stanza->type != XMPP_STANZA_TAG) return XMPP_EINVOP;
if (!stanza->attributes) {
stanza->attributes = hash_new(stanza->ctx, 8, xmpp_free);
if (!stanza->attributes) return XMPP_EMEM;
stanza->attributes = hash_new(stanza->ctx, 8, xmpp_free);
if (!stanza->attributes) return XMPP_EMEM;
}
val = xmpp_strdup(stanza->ctx, value);
if (!val) {
hash_release(stanza->attributes);
return XMPP_EMEM;
}
@@ -613,7 +598,7 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
* @ingroup 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);
}
@@ -639,12 +624,12 @@ int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child)
child->parent = stanza;
if (!stanza->children)
stanza->children = child;
stanza->children = child;
else {
s = stanza->children;
while (s->next) s = s->next;
s->next = child;
child->prev = s;
s = stanza->children;
while (s->next) s = s->next;
s->next = child;
child->prev = s;
}
return XMPP_EOK;
@@ -664,7 +649,7 @@ int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child)
* @ingroup 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;
@@ -691,8 +676,8 @@ int xmpp_stanza_set_text(xmpp_stanza_t *stanza,
* @ingroup Stanza
*/
int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
const char * const text,
const size_t size)
const char * const text,
const size_t size)
{
if (stanza->type == XMPP_STANZA_TAG) return XMPP_EINVOP;
@@ -795,14 +780,14 @@ const char *xmpp_stanza_get_from(xmpp_stanza_t * const stanza)
* @ingroup 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;
for (child = stanza->children; child; child = child->next) {
if (child->type == XMPP_STANZA_TAG &&
(strcmp(name, xmpp_stanza_get_name(child)) == 0))
break;
if (child->type == XMPP_STANZA_TAG &&
(strcmp(name, xmpp_stanza_get_name(child)) == 0))
break;
}
return child;
@@ -821,15 +806,14 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t * const stanza,
* @ingroup 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;
const char *child_ns;
for (child = stanza->children; child; child = child->next) {
child_ns = xmpp_stanza_get_ns(child);
if (child_ns && strcmp(ns, child_ns) == 0)
break;
if (xmpp_stanza_get_ns(child) &&
strcmp(ns, xmpp_stanza_get_ns(child)) == 0)
break;
}
return child;
@@ -882,16 +866,16 @@ char *xmpp_stanza_get_text(xmpp_stanza_t * const stanza)
char *text;
if (stanza->type == XMPP_STANZA_TEXT) {
if (stanza->data)
return xmpp_strdup(stanza->ctx, stanza->data);
else
return NULL;
if (stanza->data)
return xmpp_strdup(stanza->ctx, stanza->data);
else
return NULL;
}
len = 0;
for (child = stanza->children; child; child = child->next)
if (child->type == XMPP_STANZA_TEXT)
len += strlen(child->data);
if (child->type == XMPP_STANZA_TEXT)
len += strlen(child->data);
if (len == 0) return NULL;
@@ -900,11 +884,11 @@ char *xmpp_stanza_get_text(xmpp_stanza_t * const stanza)
len = 0;
for (child = stanza->children; child; child = child->next)
if (child->type == XMPP_STANZA_TEXT) {
clen = strlen(child->data);
memcpy(&text[len], child->data, clen);
len += clen;
}
if (child->type == XMPP_STANZA_TEXT) {
clen = strlen(child->data);
memcpy(&text[len], child->data, clen);
len += clen;
}
text[len] = 0;
@@ -927,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)
{
if (stanza->type == XMPP_STANZA_TEXT)
return stanza->data;
return stanza->data;
return NULL;
}
@@ -944,7 +928,7 @@ const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t * const stanza)
* @ingroup 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);
}
@@ -961,7 +945,7 @@ int xmpp_stanza_set_id(xmpp_stanza_t * const stanza,
* @ingroup 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);
}
@@ -1017,10 +1001,10 @@ const char *xmpp_stanza_get_attribute(xmpp_stanza_t * const stanza,
const char * const name)
{
if (stanza->type != XMPP_STANZA_TAG)
return NULL;
return NULL;
if (!stanza->attributes)
return NULL;
return NULL;
return hash_get(stanza->attributes, name);
}
@@ -1234,122 +1218,3 @@ xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx)
{
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;
}

View File

@@ -48,7 +48,6 @@ enum {
static void _tls_sock_wait(tls_t *tls, int error);
static void _tls_set_error(tls_t *tls, int error);
static void _tls_log_error(xmpp_ctx_t *ctx);
static void _tls_dump_cert_info(tls_t *tls);
void tls_initialize(void)
{
@@ -189,7 +188,6 @@ int tls_start(tls_t *tls)
x509_res = SSL_get_verify_result(tls->ssl);
xmpp_debug(tls->ctx, "tls", "Certificate verification %s",
x509_res == X509_V_OK ? "passed" : "FAILED");
_tls_dump_cert_info(tls);
_tls_set_error(tls, error);
return ret <= 0 ? 0 : 1;
@@ -201,11 +199,6 @@ int tls_stop(tls_t *tls)
int error;
int ret;
/* According to OpenSSL.org, we must not call SSL_shutdown(3)
if a previous fatal error has occurred on a connection. */
if (tls->lasterror == SSL_ERROR_SYSCALL || tls->lasterror == SSL_ERROR_SSL)
return 1;
while (1) {
++retries;
ret = SSL_shutdown(tls->ssl);
@@ -216,14 +209,6 @@ int tls_stop(tls_t *tls)
}
_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);
return ret <= 0 ? 0 : 1;
@@ -275,8 +260,6 @@ static void _tls_sock_wait(tls_t *tls, int error)
int nfds;
int ret;
if (error == SSL_ERROR_NONE) return;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
if (error == SSL_ERROR_WANT_READ)
@@ -295,7 +278,6 @@ static void _tls_sock_wait(tls_t *tls, int error)
static void _tls_set_error(tls_t *tls, int 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->lasterror = error;
@@ -314,26 +296,3 @@ static void _tls_log_error(xmpp_ctx_t *ctx)
}
} while (e != 0);
}
static void _tls_dump_cert_info(tls_t *tls)
{
X509 *cert;
char *name;
cert = SSL_get_peer_certificate(tls->ssl);
if (cert == NULL)
xmpp_debug(tls->ctx, "tls", "Certificate was not presented by peer");
else {
name = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
if (name != NULL) {
xmpp_debug(tls->ctx, "tls", "Subject=%s", name);
OPENSSL_free(name);
}
name = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
if (name != NULL) {
xmpp_debug(tls->ctx, "tls", "Issuer=%s", name);
OPENSSL_free(name);
}
X509_free(cert);
}
}

View File

@@ -139,7 +139,8 @@ typedef enum {
typedef enum {
XMPP_UNKNOWN,
XMPP_CLIENT,
XMPP_COMPONENT
XMPP_COMPONENT,
XMPP_INCOMING
} xmpp_conn_type_t;
typedef void (*xmpp_log_handler)(void * const userdata,
@@ -169,10 +170,6 @@ typedef struct _xmpp_stanza_t xmpp_stanza_t;
* Trust server's certificate even if it is invalid.
*/
#define XMPP_CONN_FLAG_TRUST_TLS (1UL << 3)
/** @def XMPP_CONN_FLAG_LEGACY_AUTH
* Enable legacy authentication support.
*/
#define XMPP_CONN_FLAG_LEGACY_AUTH (1UL << 4)
/* connect callback */
typedef enum {
@@ -215,13 +212,12 @@ typedef struct {
xmpp_stanza_t *stanza;
} xmpp_stream_error_t;
typedef void (*xmpp_conn_handler)(xmpp_conn_t * const conn,
typedef void (*xmpp_conn_handler)(xmpp_conn_t * const conn,
const xmpp_conn_event_t event,
const int error,
xmpp_stream_error_t * const stream_error,
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_clone(xmpp_conn_t * const conn);
int xmpp_conn_release(xmpp_conn_t * const conn);
@@ -268,6 +264,30 @@ void xmpp_send_raw_string(xmpp_conn_t * const conn,
void xmpp_send_raw(xmpp_conn_t * const conn,
const char * const data, const size_t len);
/* server */
/* opaque server object */
typedef struct _xmpp_server_t xmpp_server_t;
/* server callback */
typedef enum {
XMPP_SERVER_ACCEPT,
XMPP_SERVER_OPEN_STREAM,
XMPP_SERVER_DISCONNECT,
XMPP_SERVER_FAIL
} xmpp_server_event_t;
typedef void (*xmpp_server_handler)(xmpp_server_t * const srv,
xmpp_conn_t * const conn,
const xmpp_server_event_t event,
const int error,
void * const userdata);
xmpp_server_t *xmpp_server_new(xmpp_ctx_t * const ctx);
void xmpp_server_free(xmpp_server_t * const srv);
int xmpp_server_listen(xmpp_server_t * const srv, unsigned short port,
xmpp_server_handler callback, void * const userdata);
void xmpp_server_stop(xmpp_server_t * const srv);
/* handlers */
@@ -386,8 +406,6 @@ 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,
const char * const id);
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 */

View File

@@ -16,19 +16,18 @@
#include "strophe.h"
#include "common.h"
#include "hash.h"
#include "test.h"
#define TABLESIZE 100
#define TESTSIZE 500
/* static test data */
const int nkeys = 5;
const char *keys[] = {
"foo", "bar", "baz", "quux", "xyzzy"
};
const char *values[] = {
"wuzzle", "mug", "canonical", "rosebud", "lottery"
};
const int nkeys = ARRAY_SIZE(keys);
int main(int argc, char **argv)
{
@@ -59,7 +58,7 @@ int main(int argc, char **argv)
}
/* allocate a hash table */
table = hash_new(ctx, TABLESIZE, xmpp_free);
table = hash_new(ctx, TABLESIZE, NULL);
if (table == NULL) {
/* table allocation failed! */
return 1;
@@ -67,7 +66,7 @@ int main(int argc, char **argv)
/* test insertion */
for (i = 0; i < nkeys; i++) {
err = hash_add(table, keys[i], xmpp_strdup(ctx, values[i]));
err = hash_add(table, keys[i], (void*)values[i]);
if (err) return err;
}
@@ -79,7 +78,7 @@ int main(int argc, char **argv)
/* test replacing old values */
for (i = 0; i < nkeys; i++) {
err = hash_add(table, keys[0], xmpp_strdup(ctx, values[i]));
err = hash_add(table, keys[0], (void*)values[i]);
if (err) return err;
if (hash_num_keys(table) != nkeys) return 1;
result = hash_get(table, keys[0]);
@@ -87,7 +86,7 @@ int main(int argc, char **argv)
if (strcmp(result, values[i]) != 0) return 1;
}
/* restore value for the 1st key */
hash_add(table, keys[0], xmpp_strdup(ctx, values[0]));
hash_add(table, keys[0], (void*)values[0]);
/* test cloning */
clone = hash_clone(table);

View File

@@ -20,16 +20,6 @@
#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)
{
const char *test = "-abc-=-def--";