[asterisk-commits] phsultan: branch phsultan/res_jabber-openssl r72434 - in /team/phsultan/res_j...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jun 28 05:54:01 CDT 2007
Author: phsultan
Date: Thu Jun 28 05:54:01 2007
New Revision: 72434
URL: http://svn.digium.com/view/asterisk?view=rev&rev=72434
Log:
We basically took the secured networking functions out of the iksemel
library by :
- rewriting the TLS initialization and uninitialization procedures;
- rewriting secured network functions (for sending/receiving data).
OpenSSL is used instead of GnuTLS in both cases, and all the XML
message parsing is still handled by the iksemel library.
Modified:
team/phsultan/res_jabber-openssl/include/asterisk/jabber.h
team/phsultan/res_jabber-openssl/res/res_jabber.c
Modified: team/phsultan/res_jabber-openssl/include/asterisk/jabber.h
URL: http://svn.digium.com/view/asterisk/team/phsultan/res_jabber-openssl/include/asterisk/jabber.h?view=diff&rev=72434&r1=72433&r2=72434
==============================================================================
--- team/phsultan/res_jabber-openssl/include/asterisk/jabber.h (original)
+++ team/phsultan/res_jabber-openssl/include/asterisk/jabber.h Thu Jun 28 05:54:01 2007
@@ -44,6 +44,19 @@
#ifndef _ASTERISK_JABBER_H
#define _ASTERISK_JABBER_H
+
+#ifdef HAVE_OPENSSL
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#define TRY_SECURE 2
+#define SECURE 4
+/* file is read by blocks with this size */
+#define NET_IO_BUF_SIZE 4096
+/* Return value for timeout connection expiration */
+#define IKS_NET_EXPIRED 12
+
+#endif /* HAVE_OPENSSL */
#include <iksemel.h>
#include "asterisk/astobj.h"
@@ -120,12 +133,19 @@
char serverhost[160];
char context[100];
char statusmessage[256];
+ char name_space[256];
char sid[10]; /* Session ID */
char mid[6]; /* Message ID */
iksid *jid;
iksparser *p;
iksfilter *f;
ikstack *stack;
+#ifdef HAVE_OPENSSL
+ SSL_CTX *ssl_context;
+ SSL *ssl_session;
+ SSL_METHOD *ssl_method;
+ unsigned int stream_flags;
+#endif /* HAVE_OPENSSL */
enum aji_state state;
int port;
int debug;
Modified: team/phsultan/res_jabber-openssl/res/res_jabber.c
URL: http://svn.digium.com/view/asterisk/team/phsultan/res_jabber-openssl/res/res_jabber.c?view=diff&rev=72434&r1=72433&r2=72434
==============================================================================
--- team/phsultan/res_jabber-openssl/res/res_jabber.c (original)
+++ team/phsultan/res_jabber-openssl/res/res_jabber.c Thu Jun 28 05:54:01 2007
@@ -23,14 +23,12 @@
* \extref Iksemel http://iksemel.jabberstudio.org/
*
* \todo If you unload this module, chan_gtalk/jingle will be dead. How do we handle that?
- * \todo If you have TLS, you can't unload this module. See bug #9738. This needs to be fixed,
- * but the bug is in the unmantained Iksemel library
*
*/
/*** MODULEINFO
<depend>iksemel</depend>
- <use>gnutls</use>
+ <use>openssl</use>
***/
#include "asterisk.h"
@@ -71,13 +69,21 @@
#endif
/*-- Forward declarations */
-static int aji_start_sasl(iksparser *prs, enum ikssasltype type, char *username, char *pass);
static int aji_highest_bit(int number);
static void aji_buddy_destroy(struct aji_buddy *obj);
static void aji_client_destroy(struct aji_client *obj);
static int aji_send_exec(struct ast_channel *chan, void *data);
static int aji_status_exec(struct ast_channel *chan, void *data);
+static int aji_is_secure(struct aji_client *client);
+static int aji_start_tls(struct aji_client *client);
+static int aji_tls_handshake(struct aji_client *client);
+static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout);
+static int aji_recv(struct aji_client *client, int timeout);
+static int aji_send_header(struct aji_client *client, const char *to);
+static int aji_send(struct aji_client *client, iks *x);
+static int aji_send_raw(struct aji_client *client, const char *xmlstr);
static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming);
+static int aji_start_sasl(struct aji_client *client, enum ikssasltype type, char *username, char *pass);
static int aji_act_hook(void *data, int type, iks *node);
static void aji_handle_iq(struct aji_client *client, iks *node);
static void aji_handle_message(struct aji_client *client, ikspak *pak);
@@ -179,7 +185,6 @@
/*! \brief Global flags, initialized to default values */
static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER };
-static int tls_initialized = FALSE;
/*!
* \brief Deletes the aji_client data structure.
@@ -474,6 +479,252 @@
return 0;
}
+/*!
+ * \brief Tests whether the connection is secured or not
+ * \return 0 if the connection is not secured
+ */
+static int aji_is_secure(struct aji_client *client)
+{
+#ifdef HAVE_OPENSSL
+ return client->stream_flags & SECURE;
+#else
+ return 0;
+#endif
+}
+
+
+/*!
+ * \brief Starts the TLS procedure
+ * \param client the configured XMPP client we use to connect to a XMPP server
+ * \return IKS_OK on success, an error code if sending failed, IKS_NET_TLSFAIL
+ * if OpenSSL is not installed
+ */
+static int aji_start_tls(struct aji_client *client)
+{
+ int ret;
+#ifndef HAVE_OPENSSL
+ return IKS_NET_TLSFAIL;
+#endif
+ /* This is sent not encrypted */
+ ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
+ if (ret)
+ return ret;
+ client->stream_flags |= TRY_SECURE;
+
+ return IKS_OK;
+}
+
+/*!
+ * \brief TLS handshake, OpenSSL initialization
+ * \param client the configured XMPP client we use to connect to a XMPP server
+ * \return IKS_OK on success, IKS_NET_TLSFAIL on failure
+ */
+static int aji_tls_handshake(struct aji_client *client)
+{
+ int ret;
+ int sock;
+
+#ifndef HAVE_OPENSSL
+ return IKS_NET_TLSFAIL;
+#endif
+
+ ast_debug(1, "Starting TLS handshake\n");
+
+ /* Load encryption, hashing algorithms and error strings */
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ /* Choose an SSL/TLS protocol version, create SSL_CTX */
+ client->ssl_method = SSLv3_method();
+ client->ssl_context = SSL_CTX_new(client->ssl_method);
+ if (!client->ssl_context)
+ return IKS_NET_TLSFAIL;
+
+ /* Create new SSL session */
+ client->ssl_session = SSL_new(client->ssl_context);
+ if (!client->ssl_session)
+ return IKS_NET_TLSFAIL;
+
+ /* Enforce TLS on our XMPP connection */
+ sock = iks_fd(client->p);
+ ret = SSL_set_fd(client->ssl_session, sock);
+ if (!ret)
+ return IKS_NET_TLSFAIL;
+
+ /* Perform SSL handshake */
+ ret = SSL_connect(client->ssl_session);
+ if (!ret)
+ return IKS_NET_TLSFAIL;
+
+ client->stream_flags &= (~TRY_SECURE);
+ client->stream_flags |= SECURE;
+
+ /* Sent over the established TLS connection */
+ ret = aji_send_header(client, client->jid->server);
+ if (ret != IKS_OK)
+ return IKS_NET_TLSFAIL;
+
+ ast_debug(1, "TLS started with server\n");
+
+ return IKS_OK;
+}
+
+/*!
+ * \brief Secured or unsecured IO socket receiving function
+ * \param client the configured XMPP client we use to connect to a XMPP server
+ * \param buffer the reception buffer
+ * \param buf_len the size of the buffer
+ * \param timeout the select timer
+ * \return the number of read bytes on success, 0 on timeout expiration,
+ * -1 on error
+ */
+static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout)
+{
+ int sock;
+ fd_set fds;
+ struct timeval tv, *tvptr = NULL;
+ int len, res;
+
+#ifdef HAVE_OPENSSL
+ if (aji_is_secure(client)) {
+ sock = SSL_get_fd(client->ssl_session);
+ if (sock < 0)
+ return -1;
+ } else
+#endif /* HAVE_OPENSSL */
+ sock = iks_fd(client->p);
+
+ memset(&tv, 0, sizeof(struct timeval));
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ tv.tv_sec = timeout;
+
+ /* NULL value for tvptr makes ast_select wait indefinitely */
+ tvptr = (timeout != -1) ? &tv : NULL;
+
+ /* ast_select emulates linux behaviour in terms of timeout handling */
+ res = ast_select(sock + 1, &fds, NULL, NULL, tvptr);
+ if (res > 0) {
+#ifdef HAVE_OPENSSL
+ if (aji_is_secure(client)) {
+ len = SSL_read(client->ssl_session, buffer, buf_len);
+ } else
+#endif /* HAVE_OPENSSL */
+ len = recv(sock, buffer, buf_len, 0);
+
+ if (len > 0) {
+ return len;
+ } else if (len <= 0) {
+ return -1;
+ }
+ }
+ return res;
+}
+
+/*!
+ * \brief Tries to receive data from the Jabber server
+ * \param client the configured XMPP client we use to connect to a XMPP server
+ * \param timeout the timeout value
+ * This function receives (encrypted or unencrypted) data from the XMPP server,
+ * and passes it to the parser.
+ * \return IKS_OK on success, IKS_NET_RWERR on IO error, IKS_NET_NOCONN, if no
+ * connection available, IKS_NET_EXPIRED on timeout expiration
+ */
+static int aji_recv (struct aji_client *client, int timeout)
+{
+ int len, ret;
+ char buf[NET_IO_BUF_SIZE -1];
+
+ memset(buf, 0, sizeof(buf));
+
+ while (1) {
+ len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 1, timeout);
+ if (len < 0) return IKS_NET_RWERR;
+ if (len == 0) return IKS_NET_EXPIRED;
+ buf[len] = '\0';
+
+ /* Log the message here, because iksemel's logHook is
+ unaccessible */
+ aji_log_hook(client, buf, len, 1);
+
+ ret = iks_parse(client->p, buf, len, 0);
+ if (ret != IKS_OK) {
+ return ret;
+ }
+ }
+ return IKS_OK;
+}
+
+/*!
+ * \brief Sends XMPP header to the server
+ * \param client the configured XMPP client we use to connect to a XMPP server
+ * \param to the target XMPP server
+ * \return IKS_OK on success, any other value on failure
+ */
+static int aji_send_header(struct aji_client *client, const char *to)
+{
+ char *msg;
+ int len, err;
+
+ len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1;
+ msg = iks_malloc(len);
+ if (!msg)
+ return IKS_NOMEM;
+ sprintf(msg, "<?xml version='1.0'?>"
+ "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='"
+ "%s' to='%s' version='1.0'>", client->name_space, to);
+ err = aji_send_raw(client, msg);
+ iks_free(msg);
+ if (err != IKS_OK)
+ return err;
+
+ return IKS_OK;
+}
+
+/*!
+ * \brief Wraps raw sending
+ * \param client the configured XMPP client we use to connect to a XMPP server
+ * \param x the XMPP packet to send
+ * \return IKS_OK on success, any other value on failure
+ */
+static int aji_send(struct aji_client *client, iks *x)
+{
+ return aji_send_raw(client, iks_string(iks_stack(x), x));
+}
+
+/*!
+ * \brief Sends an XML string over an XMPP connection
+ * \param client the configured XMPP client we use to connect to a XMPP server
+ * \param xmlstr the XML string to send
+ * The XML data is sent whether the connection is secured or not. In the
+ * latter case, we just call iks_send_raw().
+ * \return IKS_OK on success, any other value on failure
+ */
+static int aji_send_raw(struct aji_client *client, const char *xmlstr)
+{
+ int ret;
+#ifdef HAVE_OPENSSL
+ int len = strlen(xmlstr);
+
+ if (aji_is_secure(client)) {
+ ret = SSL_write(client->ssl_session, xmlstr, len);
+ if (ret) {
+ /* Log the message here, because iksemel's logHook is
+ unaccessible */
+ aji_log_hook(client, xmlstr, len, 0);
+ return IKS_OK;
+ }
+ }
+#endif
+ /* If needed, data will be sent unencrypted, and logHook will
+ be called inside iks_send_raw */
+ ret = iks_send_raw(client->p, xmlstr);
+ if (ret != IKS_OK)
+ return ret;
+
+ return IKS_OK;
+}
+
/*!
* \brief the debug loop.
* \param data void
@@ -505,7 +756,7 @@
/*!
* \brief A wrapper function for iks_start_sasl
- * \param prs the XML parser
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param type the SASL authentication type. Supported types are PLAIN and MD5
* \param username
* \param pass
@@ -515,12 +766,12 @@
* computed with iks_start_sasl().
* \return IKS_OK on success, IKSNET_NOTSUPP on failure.
*/
-static int aji_start_sasl(iksparser *prs, enum ikssasltype type, char *username, char *pass)
+static int aji_start_sasl(struct aji_client *client, enum ikssasltype type, char *username, char *pass)
{
iks *x = NULL;
if (type == IKS_STREAM_SASL_MD5)
- return iks_start_sasl(prs, type, username, pass);
+ return iks_start_sasl(client->p, type, username, pass);
x = iks_new("auth");
if (!x) {
@@ -537,7 +788,7 @@
sprintf(s, "%c%s%c%s", 0, username, 0, pass);
ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
iks_insert_cdata(x, base64, 0);
- iks_send(prs, x);
+ aji_send(client, x);
iks_delete(x);
if (base64)
free(base64);
@@ -577,12 +828,13 @@
if (!client->component) { /*client */
switch (type) {
case IKS_NODE_START:
- if (client->usetls && !iks_is_secure(client->p)) {
- if (iks_has_tls()) {
- iks_start_tls(client->p);
- tls_initialized = TRUE;
- } else
- ast_log(LOG_ERROR, "gnuTLS not installed. You need to recompile the Iksemel library with gnuTLS support\n");
+ if (client->usetls && !aji_is_secure(client)) {
+ if (aji_start_tls(client) == IKS_NET_TLSFAIL) {
+ ast_log(LOG_ERROR, "OpenSSL not installed. You need to install OpenSSL on this system\n");
+ ASTOBJ_UNREF(client, aji_client_destroy);
+ return IKS_HOOK;
+ }
+
break;
}
if (!client->usesasl) {
@@ -592,7 +844,7 @@
iks_insert_attrib(auth, "id", client->mid);
iks_insert_attrib(auth, "to", client->jid->server);
ast_aji_increment_mid(client->mid);
- iks_send(client->p, auth);
+ aji_send(client, auth);
iks_delete(auth);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
@@ -600,19 +852,25 @@
break;
case IKS_NODE_NORMAL:
+ if (client->stream_flags & TRY_SECURE) {
+ if (!strcmp("proceed", iks_name(node))) {
+ return aji_tls_handshake(client);
+ }
+ }
+
if (!strcmp("stream:features", iks_name(node))) {
features = iks_stream_features(node);
if (client->usesasl) {
- if (client->usetls && !iks_is_secure(client->p))
+ if (client->usetls && !aji_is_secure(client))
break;
if (client->authorized) {
if (features & IKS_STREAM_BIND) {
- iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
+ iks_filter_add_rule(client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
auth = iks_make_resource_bind(client->jid);
if (auth) {
iks_insert_attrib(auth, "id", client->mid);
ast_aji_increment_mid(client->mid);
- iks_send(client->p, auth);
+ aji_send(client, auth);
iks_delete(auth);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
@@ -625,7 +883,7 @@
if (auth) {
iks_insert_attrib(auth, "id", "auth");
ast_aji_increment_mid(client->mid);
- iks_send(client->p, auth);
+ aji_send(client, auth);
iks_delete(auth);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
@@ -638,7 +896,7 @@
break;
}
features = aji_highest_bit(features);
- ret = aji_start_sasl(client->p, features, client->jid->user, client->password);
+ ret = aji_start_sasl(client, features, client->jid->user, client->password);
if (ret != IKS_OK) {
ASTOBJ_UNREF(client, aji_client_destroy);
return IKS_HOOK;
@@ -650,7 +908,7 @@
ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
} else if (!strcmp("success", iks_name(node))) {
client->authorized = 1;
- iks_send_header(client->p, client->jid->server);
+ aji_send_header(client, client->jid->server);
}
break;
case IKS_NODE_ERROR:
@@ -675,12 +933,12 @@
handshake = NULL;
asprintf(&handshake, "<handshake>%s</handshake>", shasum);
if (handshake) {
- iks_send_raw(client->p, handshake);
+ aji_send_raw(client, handshake);
ast_free(handshake);
handshake = NULL;
}
client->state = AJI_CONNECTING;
- if(iks_recv(client->p,1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/
+ if(aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/
client->state = AJI_CONNECTED;
else
ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
@@ -756,7 +1014,7 @@
iks_insert_attrib(iq, "to", pak->from->full);
iks_insert_attrib(iq, "id", pak->id);
iks_insert_attrib(iq, "type", "result");
- iks_send(client->p, iq);
+ aji_send(client, iq);
iks_insert_attrib(presence, "from", client->jid->full);
iks_insert_attrib(presence, "to", pak->from->partial);
@@ -765,7 +1023,7 @@
iks_insert_attrib(presence, "type", "subscribe");
iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
iks_insert_node(presence, x);
- iks_send(client->p, presence);
+ aji_send(client, presence);
}
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
@@ -815,7 +1073,7 @@
iks_insert_node(iq, query);
iks_insert_node(iq, error);
iks_insert_node(error, notacceptable);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -842,7 +1100,7 @@
iks_insert_cdata(instructions, explain, 0);
iks_insert_node(iq, query);
iks_insert_node(query, instructions);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -886,7 +1144,7 @@
iks_insert_node(iq, query);
iks_insert_node(query, item);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -915,7 +1173,7 @@
iks_insert_node(iq, query);
iks_insert_node(query, confirm);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -942,7 +1200,7 @@
iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
iks_insert_node(iq, query);
iks_insert_node(query, feature);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -1003,7 +1261,7 @@
iks_insert_node(query, ident);
iks_insert_node(query, google);
iks_insert_node(query, disco);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else
ast_log(LOG_ERROR, "Out of Memory.\n");
if (iq)
@@ -1090,7 +1348,7 @@
iks_insert_node(query, version);
iks_insert_node(query, vcard);
iks_insert_node(query, search);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -1134,7 +1392,7 @@
iks_insert_attrib(confirm, "jid", client->user);
iks_insert_node(iq, query);
iks_insert_node(query, confirm);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -1161,7 +1419,7 @@
iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
iks_insert_node(iq, query);
iks_insert_node(query, feature);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -1179,7 +1437,7 @@
/*!
* \brief Handles \verbatim <iq> \endverbatim tags.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param node iks
* \return void.
*/
@@ -1190,7 +1448,7 @@
/*!
* \brief Handles presence packets.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param pak ikspak the node
*/
static void aji_handle_message(struct aji_client *client, ikspak *pak)
@@ -1230,7 +1488,7 @@
}
/*!
* \brief Check the presence info
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param pak ikspak
*/
static void aji_handle_presence(struct aji_client *client, ikspak *pak)
@@ -1376,7 +1634,7 @@
ast_aji_increment_mid(client->mid);
iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
iks_insert_node(iq, query);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
@@ -1424,7 +1682,7 @@
/*!
* \brief handles subscription requests.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param pak ikspak iksemel packet.
* \return void.
*/
@@ -1442,7 +1700,7 @@
iks_insert_attrib(presence, "id", pak->id);
iks_insert_cdata(status, "Asterisk has approved subscription", 0);
iks_insert_node(presence, status);
- iks_send(client->p, presence);
+ aji_send(client, presence);
} else
ast_log(LOG_ERROR, "Unable to allocate nodes\n");
if(presence)
@@ -1475,7 +1733,7 @@
/*!
* \brief sends messages.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param address
* \param message
* \return 1.
@@ -1488,7 +1746,7 @@
message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message);
if (message_packet) {
iks_insert_attrib(message_packet, "from", client->jid->full);
- res = iks_send(client->p, message_packet);
+ res = aji_send(client, message_packet);
} else {
ast_log(LOG_ERROR, "Out of memory.\n");
}
@@ -1501,7 +1759,7 @@
/*!
* \brief create a chatroom.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param room name of room
* \param server name of server
* \param topic topic for the room.
@@ -1517,7 +1775,7 @@
iks_insert_attrib(iq, "to", server);
iks_insert_attrib(iq, "id", client->mid);
ast_aji_increment_mid(client->mid);
- iks_send(client->p, iq);
+ aji_send(client, iq);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
return res;
@@ -1525,7 +1783,7 @@
/*!
* \brief join a chatroom.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param room room to join
* \return res.
*/
@@ -1539,10 +1797,10 @@
iks_insert_cdata(priority, "0", 1);
iks_insert_attrib(presence, "to", room);
iks_insert_node(presence, priority);
- res = iks_send(client->p, presence);
+ res = aji_send(client, presence);
iks_insert_cdata(priority, "5", 1);
iks_insert_attrib(presence, "to", room);
- res = iks_send(client->p, presence);
+ res = aji_send(client, presence);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
if (presence)
@@ -1554,7 +1812,7 @@
/*!
* \brief invite to a chatroom.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param user
* \param room
* \param message
@@ -1577,7 +1835,7 @@
iks_insert_attrib(namespace, "jid", room);
iks_insert_node(invite, body);
iks_insert_node(invite, namespace);
- res = iks_send(client->p, invite);
+ res = aji_send(client, invite);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
if (body)
@@ -1599,29 +1857,41 @@
{
struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
int res = IKS_HOOK;
+
+ while(res != IKS_OK) {
+ if(option_verbose > 3)
+ ast_verbose("JABBER: Connecting.\n");
+ res = aji_reconnect(client);
+ sleep(4);
+ }
+
do {
- if (res != IKS_OK) {
+ if (res == IKS_NET_RWERR || client->timeout == 0) {
while(res != IKS_OK) {
if(option_verbose > 3)
- ast_verbose("JABBER: reconnecting.\n");
+ ast_verbose("JABBER: Reconnecting.\n");
res = aji_reconnect(client);
sleep(4);
}
}
- res = iks_recv(client->p, 1);
-
+ res = aji_recv(client, 1);
+
if (client->state == AJI_DISCONNECTING) {
ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n");
pthread_exit(NULL);
}
- client->timeout--;
+
+ /* Decrease timeout if no data received */
+ if (res == IKS_NET_EXPIRED)
+ client->timeout--;
+
if (res == IKS_HOOK)
ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
else if (res == IKS_NET_TLSFAIL)
ast_log(LOG_WARNING, "JABBER: Failure in TLS.\n");
else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
- res = iks_send_raw(client->p, " ");
+ res = aji_send_raw(client, " ");
if(res == IKS_OK)
client->timeout = 50;
else
@@ -1679,7 +1949,7 @@
iks_insert_attrib(send, "id", client->mid);
ast_aji_increment_mid(client->mid);
iks_insert_attrib(send, "from", client->user);
- res = iks_send(client->p, send);
+ res = aji_send(client, send);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
@@ -1725,7 +1995,7 @@
iks_insert_node(regiq, regquery);
iks_insert_node(regquery, reguser);
iks_insert_node(regquery, regpass);
- res = iks_send(client->p, regiq);
+ res = aji_send(client, regiq);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
if (regiq)
@@ -1742,7 +2012,7 @@
*/
/*!
* \brief goes through roster and prunes users not needed in list, or adds them accordingly.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \return void.
*/
static void aji_pruneregister(struct aji_client *client)
@@ -1761,10 +2031,10 @@
/* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never
* be called at the same time */
if (ast_test_flag(iterator, AJI_AUTOPRUNE)) {
- res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
+ res = aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
"GoodBye your status is no longer needed by Asterisk the Open Source PBX"
" so I am no longer subscribing to your presence.\n"));
- res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
+ res = aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
"GoodBye you are no longer in the asterisk config file so I am removing"
" your access to my presence.\n"));
iks_insert_attrib(removeiq, "from", client->jid->full);
@@ -1772,9 +2042,9 @@
iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster");
iks_insert_attrib(removeitem, "jid", iterator->name);
iks_insert_attrib(removeitem, "subscription", "remove");
- res = iks_send(client->p, removeiq);
+ res = aji_send(client, removeiq);
} else if (ast_test_flag(iterator, AJI_AUTOREGISTER)) {
- res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name,
+ res = aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name,
"Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
ast_clear_flag(iterator, AJI_AUTOREGISTER);
}
@@ -1871,7 +2141,7 @@
}
/*!
* \brief reconnect to jabber server
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \return res.
*/
static int aji_reconnect(struct aji_client *client)
@@ -1892,7 +2162,7 @@
}
/*!
* \brief Get the roster of jabber users
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \return 1.
*/
static int aji_get_roster(struct aji_client *client)
@@ -1902,7 +2172,7 @@
if(roster) {
iks_insert_attrib(roster, "id", "roster");
aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage);
- iks_send(client->p, roster);
+ aji_send(client, roster);
}
if (roster)
iks_delete(roster);
@@ -1938,7 +2208,7 @@
/*!
* \brief prepares client for connect.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \return 1.
*/
static int aji_initialize(struct aji_client *client)
@@ -1952,14 +2222,14 @@
} else if (connected == IKS_NET_NODNS) {
ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, S_OR(client->serverhost, client->jid->server));
return IKS_HOOK;
- } else /* if (!connected) phsultan: check if this is needed! */
- iks_recv(client->p, 30);
+ }
+
return IKS_OK;
}
/*!
* \brief disconnect from jabber server.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \return 1.
*/
int ast_aji_disconnect(struct aji_client *client)
@@ -1967,6 +2237,13 @@
if (client) {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_3 "JABBER: Disconnecting\n");
+#ifdef HAVE_OPENSSL
+ if (client->stream_flags & SECURE) {
+ SSL_shutdown(client->ssl_session);
+ SSL_CTX_free(client->ssl_context);
+ SSL_free(client->ssl_session);
+ }
+#endif
iks_disconnect(client->p);
iks_parser_delete(client->p);
ASTOBJ_UNREF(client, aji_client_destroy);
@@ -1977,7 +2254,7 @@
/*!
* \brief set presence of client.
- * \param client aji_client
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \param to user send it to
* \param from user it came from
* \param level
@@ -2002,7 +2279,7 @@
iks_insert_attrib(cnode, "ext", "voice-v1");
iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
iks_insert_node(presence, cnode);
- res = iks_send(client->p, presence);
+ res = aji_send(client, presence);
} else
ast_log(LOG_ERROR, "Out of memory.\n");
if (cnode)
@@ -2243,7 +2520,9 @@
ASTOBJ_UNREF(client, aji_client_destroy);
return 1;
}
- client->p = iks_stream_new(((client->component) ? "jabber:component:accept" : "jabber:client"), client, aji_act_hook);
+
+ ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space));
+ client->p = iks_stream_new(client->name_space, client, aji_act_hook);
if (!client->p) {
ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name);
return 0;
@@ -2344,7 +2623,7 @@
/*!
* \brief creates buddy.
* \param label char.
- * \param client aji_client buddy to dump it into.
+ * \param client the configured XMPP client we use to connect to a XMPP server
* \return 1 on success, 0 on failure.
*/
static int aji_create_buddy(char *label, struct aji_client *client)
@@ -2509,16 +2788,6 @@
static int unload_module(void)
{
- /* Check if TLS is initialized. If that's the case, we can't unload this
- module due to a bug in the iksemel library that will cause a crash or
- a deadlock. We're trying to find a way to handle this, but in the meantime
- we will simply refuse to die...
- */
- if (tls_initialized) {
- ast_log(LOG_ERROR, "Module can't be unloaded due to a bug in the Iksemel library when using TLS.\n");
- return 1; /* You need a forced unload to get rid of this module */
- }
-
ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
ast_unregister_application(app_ajisend);
ast_unregister_application(app_ajistatus);
@@ -2526,7 +2795,7 @@
ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
ASTOBJ_RDLOCK(iterator);
- ast_debug(3, "JABBER: Releasing and disconneing client: %s\n", iterator->name);
+ ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name);
iterator->state = AJI_DISCONNECTING;
ast_aji_disconnect(iterator);
pthread_join(iterator->thread, NULL);
More information about the asterisk-commits
mailing list