Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1698f7b5d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,6 +35,7 @@ examples/basic
|
|||||||
examples/bot
|
examples/bot
|
||||||
examples/component
|
examples/component
|
||||||
examples/roster
|
examples/roster
|
||||||
|
examples/server
|
||||||
examples/uuid
|
examples/uuid
|
||||||
examples/vcard
|
examples/vcard
|
||||||
test_stamp
|
test_stamp
|
||||||
|
|||||||
@@ -8,9 +8,6 @@
|
|||||||
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 -Wno-unused-parameter
|
STROPHE_FLAGS = -I$(top_srcdir) -Wall -Wextra -Werror -Wno-unused-parameter
|
||||||
STROPHE_LIBS = libstrophe.la
|
STROPHE_LIBS = libstrophe.la
|
||||||
|
|
||||||
## Main build targets
|
## Main build targets
|
||||||
@@ -36,6 +36,7 @@ libstrophe_la_SOURCES = \
|
|||||||
src/resolver.c \
|
src/resolver.c \
|
||||||
src/sasl.c \
|
src/sasl.c \
|
||||||
src/scram.c \
|
src/scram.c \
|
||||||
|
src/server.c \
|
||||||
src/sha1.c \
|
src/sha1.c \
|
||||||
src/snprintf.c \
|
src/snprintf.c \
|
||||||
src/sock.c \
|
src/sock.c \
|
||||||
@@ -99,6 +100,7 @@ noinst_PROGRAMS = \
|
|||||||
examples/bot \
|
examples/bot \
|
||||||
examples/component \
|
examples/component \
|
||||||
examples/roster \
|
examples/roster \
|
||||||
|
examples/server \
|
||||||
examples/uuid \
|
examples/uuid \
|
||||||
examples/vcard
|
examples/vcard
|
||||||
|
|
||||||
@@ -117,6 +119,9 @@ examples_component_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)
|
||||||
|
examples_server_SOURCES = examples/server.c
|
||||||
|
examples_server_CFLAGS = $(STROPHE_FLAGS)
|
||||||
|
examples_server_LDADD = $(STROPHE_LIBS)
|
||||||
examples_uuid_SOURCES = examples/uuid.c
|
examples_uuid_SOURCES = examples/uuid.c
|
||||||
examples_uuid_CFLAGS = $(STROPHE_FLAGS)
|
examples_uuid_CFLAGS = $(STROPHE_FLAGS)
|
||||||
examples_uuid_LDADD = $(STROPHE_LIBS)
|
examples_uuid_LDADD = $(STROPHE_LIBS)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libstrophe], [0.9.2], [jack@metajack.im])
|
AC_INIT([libstrophe], [0.9.1], [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])
|
||||||
|
|||||||
83
examples/server.c
Normal file
83
examples/server.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -44,6 +44,7 @@ LOCAL_SRC_FILES := \
|
|||||||
../src/resolver.c \
|
../src/resolver.c \
|
||||||
../src/sasl.c \
|
../src/sasl.c \
|
||||||
../src/scram.c \
|
../src/scram.c \
|
||||||
|
../src/server.c \
|
||||||
../src/sha1.c \
|
../src/sha1.c \
|
||||||
../src/snprintf.c \
|
../src/snprintf.c \
|
||||||
../src/sock.c \
|
../src/sock.c \
|
||||||
|
|||||||
24
src/common.h
24
src/common.h
@@ -43,6 +43,11 @@ typedef struct _xmpp_connlist_t {
|
|||||||
struct _xmpp_connlist_t *next;
|
struct _xmpp_connlist_t *next;
|
||||||
} xmpp_connlist_t;
|
} xmpp_connlist_t;
|
||||||
|
|
||||||
|
typedef struct _xmpp_serverlist_t {
|
||||||
|
xmpp_server_t *server;
|
||||||
|
struct _xmpp_serverlist_t *next;
|
||||||
|
} xmpp_serverlist_t;
|
||||||
|
|
||||||
struct _xmpp_ctx_t {
|
struct _xmpp_ctx_t {
|
||||||
const xmpp_mem_t *mem;
|
const xmpp_mem_t *mem;
|
||||||
const xmpp_log_t *log;
|
const xmpp_log_t *log;
|
||||||
@@ -50,6 +55,7 @@ struct _xmpp_ctx_t {
|
|||||||
xmpp_rand_t *rand;
|
xmpp_rand_t *rand;
|
||||||
xmpp_loop_status_t loop_status;
|
xmpp_loop_status_t loop_status;
|
||||||
xmpp_connlist_t *connlist;
|
xmpp_connlist_t *connlist;
|
||||||
|
xmpp_serverlist_t *serverlist;
|
||||||
|
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
};
|
};
|
||||||
@@ -225,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_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler);
|
||||||
void conn_parser_reset(xmpp_conn_t * const conn);
|
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 {
|
typedef enum {
|
||||||
XMPP_STANZA_UNKNOWN,
|
XMPP_STANZA_UNKNOWN,
|
||||||
|
|||||||
14
src/conn.c
14
src/conn.c
@@ -73,15 +73,6 @@ 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
|
||||||
@@ -634,14 +625,15 @@ int xmpp_conn_open_stream(xmpp_conn_t * const conn, char **attributes,
|
|||||||
{
|
{
|
||||||
char *tag;
|
char *tag;
|
||||||
|
|
||||||
if (!conn->is_raw)
|
if (!conn->is_raw && conn->type != XMPP_INCOMING)
|
||||||
return XMPP_EINVOP;
|
return XMPP_EINVOP;
|
||||||
|
|
||||||
tag = _conn_build_stream_tag(conn, attributes, attributes_len);
|
tag = _conn_build_stream_tag(conn, attributes, attributes_len);
|
||||||
if (!tag)
|
if (!tag)
|
||||||
return XMPP_EMEM;
|
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_send_raw_string(conn, "<?xml version=\"1.0\"?>%s", tag);
|
||||||
xmpp_free(conn->ctx, tag);
|
xmpp_free(conn->ctx, tag);
|
||||||
|
|
||||||
|
|||||||
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 object
|
* @param ctx a Strophe context onject
|
||||||
*
|
*
|
||||||
* @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
|
||||||
|
|||||||
@@ -415,6 +415,7 @@ xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t * const mem,
|
|||||||
ctx->log = log;
|
ctx->log = log;
|
||||||
|
|
||||||
ctx->connlist = NULL;
|
ctx->connlist = NULL;
|
||||||
|
ctx->serverlist = NULL;
|
||||||
ctx->loop_status = XMPP_LOOP_NOTSTARTED;
|
ctx->loop_status = XMPP_LOOP_NOTSTARTED;
|
||||||
ctx->rand = xmpp_rand_new(ctx);
|
ctx->rand = xmpp_rand_new(ctx);
|
||||||
ctx->timeout = EVENT_LOOP_DEFAULT_TIMEOUT;
|
ctx->timeout = EVENT_LOOP_DEFAULT_TIMEOUT;
|
||||||
|
|||||||
43
src/event.c
43
src/event.c
@@ -67,7 +67,9 @@
|
|||||||
void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
||||||
{
|
{
|
||||||
xmpp_connlist_t *connitem;
|
xmpp_connlist_t *connitem;
|
||||||
|
xmpp_serverlist_t *serveritem;
|
||||||
xmpp_conn_t *conn;
|
xmpp_conn_t *conn;
|
||||||
|
xmpp_server_t *srv;
|
||||||
fd_set rfds, wfds;
|
fd_set rfds, wfds;
|
||||||
sock_t max = 0;
|
sock_t max = 0;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -206,6 +208,23 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
|||||||
connitem = connitem->next;
|
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 */
|
/* check for events */
|
||||||
if (max > 0)
|
if (max > 0)
|
||||||
ret = select(max + 1, &rfds, &wfds, NULL, &tv);
|
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) {
|
if (ret > 0) {
|
||||||
ret = parser_feed(conn->parser, buf, ret);
|
ret = parser_feed(conn->parser, buf, ret);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
xmpp_debug(ctx, "xmpp", "parse error [%s]", buf);
|
/* parse error, we need to shut down */
|
||||||
xmpp_send_error(conn, XMPP_SE_INVALID_XML, "parse error");
|
/* FIXME */
|
||||||
|
xmpp_debug(ctx, "xmpp", "parse error, disconnecting");
|
||||||
|
conn_disconnect(conn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (conn->tls) {
|
if (conn->tls) {
|
||||||
@@ -291,6 +312,24 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
|||||||
connitem = connitem->next;
|
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 */
|
/* fire any ready handlers */
|
||||||
handler_fire_timed(ctx);
|
handler_fire_timed(ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ void hash_iter_release(hash_iterator_t *iter)
|
|||||||
|
|
||||||
iter->ref--;
|
iter->ref--;
|
||||||
|
|
||||||
if (iter->ref == 0) { // ref is unsigned!!!
|
if (iter->ref <= 0) {
|
||||||
hash_release(iter->table);
|
hash_release(iter->table);
|
||||||
xmpp_free(ctx, iter);
|
xmpp_free(ctx, iter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,8 +249,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,16 +257,18 @@ 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;
|
||||||
|
|
||||||
return parser->xmlctx ? 1 : 0;
|
parser->depth = 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 = 0;
|
int insize;
|
||||||
|
|
||||||
/* 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 = (FIXED_INFO *)buffer;
|
fi = buffer;
|
||||||
|
|
||||||
if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
|
if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -264,8 +264,7 @@ 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"));
|
||||||
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);
|
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));
|
||||||
|
|||||||
162
src/server.c
Normal file
162
src/server.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/sock.c
37
src/sock.c
@@ -109,6 +109,43 @@ sock_t sock_connect(const char * const host, const unsigned short port)
|
|||||||
return sock;
|
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 sock_set_keepalive(const sock_t sock, int timeout, int interval)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ int sock_error(void);
|
|||||||
|
|
||||||
sock_t sock_connect(const char * const host, const unsigned short port);
|
sock_t sock_connect(const char * const host, const unsigned short port);
|
||||||
int sock_close(const sock_t sock);
|
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_blocking(const sock_t sock);
|
||||||
int sock_set_nonblocking(const sock_t sock);
|
int sock_set_nonblocking(const sock_t sock);
|
||||||
|
|||||||
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;
|
||||||
|
|
||||||
/* iterate and recurse over child stanzas */
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
child = stanza->children;
|
|
||||||
while (child) {
|
|
||||||
ret = _render_stanza_recursive(child, ptr, left);
|
|
||||||
if (ret < 0) return ret;
|
|
||||||
|
|
||||||
_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;
|
||||||
/* write end tag */
|
|
||||||
ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
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,122 +1218,3 @@ 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,14 +209,6 @@ 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;
|
||||||
@@ -268,8 +260,6 @@ 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)
|
||||||
@@ -288,7 +278,6 @@ 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;
|
||||||
|
|||||||
32
strophe.h
32
strophe.h
@@ -139,7 +139,8 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
XMPP_UNKNOWN,
|
XMPP_UNKNOWN,
|
||||||
XMPP_CLIENT,
|
XMPP_CLIENT,
|
||||||
XMPP_COMPONENT
|
XMPP_COMPONENT,
|
||||||
|
XMPP_INCOMING
|
||||||
} xmpp_conn_type_t;
|
} xmpp_conn_type_t;
|
||||||
|
|
||||||
typedef void (*xmpp_log_handler)(void * const userdata,
|
typedef void (*xmpp_log_handler)(void * const userdata,
|
||||||
@@ -211,13 +212,12 @@ typedef struct {
|
|||||||
xmpp_stanza_t *stanza;
|
xmpp_stanza_t *stanza;
|
||||||
} xmpp_stream_error_t;
|
} 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 xmpp_conn_event_t event,
|
||||||
const int error,
|
const int error,
|
||||||
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);
|
||||||
@@ -264,6 +264,30 @@ void xmpp_send_raw_string(xmpp_conn_t * const conn,
|
|||||||
void xmpp_send_raw(xmpp_conn_t * const conn,
|
void xmpp_send_raw(xmpp_conn_t * const conn,
|
||||||
const char * const data, const size_t len);
|
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 */
|
/* handlers */
|
||||||
|
|
||||||
@@ -382,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,
|
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,16 +20,6 @@
|
|||||||
|
|
||||||
#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