Skip to content

Commit 164c6ed

Browse files
committed
Make DNS operations non-blocking when using c-ares
Previously the connection and reconnection process would block the event loop waiting on DNS results. Without c-ares this is still the case here, but when c-ares is used this is now a non-blocking operation which progresses during normal xmpp_run_once calls along with everything else in the system.
1 parent f8cda0f commit 164c6ed

File tree

6 files changed

+271
-171
lines changed

6 files changed

+271
-171
lines changed

src/conn.c

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ static void _conn_sm_handle_stanza(xmpp_conn_t *const conn,
103103
static unsigned short _conn_default_port(xmpp_conn_t *conn,
104104
xmpp_conn_type_t type);
105105
static void _conn_reset(xmpp_conn_t *conn);
106-
static int _conn_connect(xmpp_conn_t *conn,
107-
const char *domain,
108-
xmpp_conn_type_t type,
109-
xmpp_conn_handler callback,
110-
void *userdata);
106+
static int _conn_preconnect(xmpp_conn_t *conn,
107+
char *domain,
108+
xmpp_conn_type_t type,
109+
xmpp_conn_handler callback,
110+
void *userdata);
111111
static void _send_valist(xmpp_conn_t *conn,
112112
const char *fmt,
113113
va_list ap,
@@ -709,14 +709,14 @@ int xmpp_connect_client(xmpp_conn_t *conn,
709709

710710
if (conn->xsock)
711711
sock_free(conn->xsock);
712-
conn->xsock = sock_new(conn, domain, altdomain, altport);
713-
if (!conn->xsock)
714-
goto err_mem;
715712

716-
rc = _conn_connect(conn, domain, XMPP_CLIENT, callback, userdata);
717-
strophe_free(conn->ctx, domain);
713+
/* domain ownership transfers to conn */
714+
if ((rc =
715+
_conn_preconnect(conn, domain, XMPP_CLIENT, callback, userdata))) {
716+
return rc;
717+
}
718718

719-
return rc;
719+
return sock_new(conn, domain, altdomain, altport);
720720

721721
err_mem:
722722
strophe_free(conn->ctx, domain);
@@ -752,6 +752,7 @@ int xmpp_connect_component(xmpp_conn_t *conn,
752752
xmpp_conn_handler callback,
753753
void *userdata)
754754
{
755+
int rc;
755756
/* The server domain, jid and password MUST be specified. */
756757
if (!(server && conn->jid && conn->pass))
757758
return XMPP_EINVOP;
@@ -769,13 +770,15 @@ int xmpp_connect_component(xmpp_conn_t *conn,
769770
port = port ? port : _conn_default_port(conn, XMPP_COMPONENT);
770771
if (conn->xsock)
771772
sock_free(conn->xsock);
772-
conn->xsock = sock_new(conn, NULL, server, port);
773-
if (!conn->xsock)
774-
return XMPP_EMEM;
775773

776774
/* JID serves as an identifier here and will be used as "to" attribute
777775
of the stream */
778-
return _conn_connect(conn, conn->jid, XMPP_COMPONENT, callback, userdata);
776+
if ((rc = _conn_preconnect(conn, strophe_strdup(conn->ctx, conn->jid),
777+
XMPP_COMPONENT, callback, userdata))) {
778+
return rc;
779+
}
780+
781+
return sock_new(conn, NULL, server, port);
779782
}
780783

781784
/** Initiate a raw connection to the XMPP server.
@@ -2170,11 +2173,11 @@ static void _conn_reset(xmpp_conn_t *conn)
21702173
handler_system_delete_all(conn);
21712174
}
21722175

2173-
static int _conn_connect(xmpp_conn_t *conn,
2174-
const char *domain,
2175-
xmpp_conn_type_t type,
2176-
xmpp_conn_handler callback,
2177-
void *userdata)
2176+
static int _conn_preconnect(xmpp_conn_t *conn,
2177+
char *domain,
2178+
xmpp_conn_type_t type,
2179+
xmpp_conn_handler callback,
2180+
void *userdata)
21782181
{
21792182
xmpp_open_handler open_handler;
21802183

@@ -2186,14 +2189,10 @@ static int _conn_connect(xmpp_conn_t *conn,
21862189
_conn_reset(conn);
21872190

21882191
conn->type = type;
2189-
conn->domain = strophe_strdup(conn->ctx, domain);
2192+
conn->domain = domain;
21902193
if (!conn->domain)
21912194
return XMPP_EMEM;
21922195

2193-
conn->sock = sock_connect(conn->xsock);
2194-
if (conn->sock == INVALID_SOCKET)
2195-
return XMPP_EINT;
2196-
21972196
/* setup handler */
21982197
conn->conn_handler = callback;
21992198
conn->userdata = userdata;
@@ -2208,6 +2207,7 @@ static int _conn_connect(xmpp_conn_t *conn,
22082207
* hard to fix, since we'd have to detect and fire off the callback
22092208
* from within the event loop */
22102209

2210+
conn->sock = INVALID_SOCKET;
22112211
conn->state = XMPP_STATE_CONNECTING;
22122212
conn->timeout_stamp = time_stamp();
22132213

src/event.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,19 @@
5757
#include "strophe.h"
5858
#include "common.h"
5959
#include "parser.h"
60+
#include "resolver.h"
6061

6162
#ifndef STROPHE_MESSAGE_BUFFER_SIZE
6263
/** Max buffer size for receiving messages. */
6364
#define STROPHE_MESSAGE_BUFFER_SIZE 4096
6465
#endif
6566

66-
static int _connect_next(xmpp_conn_t *conn)
67+
static void _connect_next(xmpp_conn_t *conn)
6768
{
6869
sock_close(conn->sock);
69-
conn->sock = sock_connect(conn->xsock);
70-
if (conn->sock == INVALID_SOCKET)
71-
return -1;
72-
70+
conn->sock = INVALID_SOCKET;
7371
conn->timeout_stamp = time_stamp();
74-
75-
return 0;
72+
sock_connect(conn->xsock);
7673
}
7774

7875
/** Run the event loop once.
@@ -220,17 +217,14 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
220217

221218
/* make sure the timeout hasn't expired */
222219
if (time_elapsed(conn->timeout_stamp, time_stamp()) <=
223-
conn->connect_timeout)
224-
FD_SET(conn->sock, &wfds);
225-
else {
220+
conn->connect_timeout) {
221+
if (conn->sock != INVALID_SOCKET)
222+
FD_SET(conn->sock, &wfds);
223+
} else {
226224
strophe_info(ctx, "xmpp", "Connection attempt timed out.");
227-
ret = _connect_next(conn);
228-
if (ret != 0) {
229-
conn->error = ETIMEDOUT;
230-
conn_disconnect(conn);
231-
} else {
225+
_connect_next(conn);
226+
if (conn->sock != INVALID_SOCKET)
232227
FD_SET(conn->sock, &wfds);
233-
}
234228
}
235229
break;
236230
case XMPP_STATE_CONNECTED:
@@ -254,6 +248,15 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
254248
connitem = connitem->next;
255249
}
256250

251+
#ifdef HAVE_CARES
252+
if (ares_chan) {
253+
int ares_max = ares_fds(ares_chan, &rfds, &wfds);
254+
if (ares_max > max)
255+
max = ares_max;
256+
ares_timeout(ares_chan, &tv, &tv);
257+
}
258+
#endif
259+
257260
/* check for events */
258261
if (max > 0)
259262
ret = select(max + 1, &rfds, &wfds, NULL, &tv);
@@ -275,6 +278,11 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
275278
if (ret == 0 && tls_read_bytes == 0)
276279
return;
277280

281+
#ifdef HAVE_CARES
282+
if (ares_chan)
283+
ares_process(ares_chan, &rfds, &wfds);
284+
#endif
285+
278286
/* process events */
279287
connitem = ctx->connlist;
280288
while (connitem) {
@@ -292,11 +300,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
292300
/* connection failed */
293301
strophe_debug(ctx, "xmpp", "connection failed, error %d",
294302
ret);
295-
ret = _connect_next(conn);
296-
if (ret != 0) {
297-
conn->error = ret;
298-
conn_disconnect(conn);
299-
}
303+
_connect_next(conn);
300304
break;
301305
}
302306

0 commit comments

Comments
 (0)