conn: refactore connect functions

Common code is moved to a separated function.
This commit is contained in:
Dmitry Podgorny
2016-04-12 20:19:16 +00:00
parent 968cb7dcdf
commit b169c0a91e
2 changed files with 102 additions and 94 deletions

View File

@@ -131,6 +131,8 @@ struct _xmpp_handlist_t {
}; };
}; };
#define MAX_DOMAIN_LEN 256
#define SASL_MASK_PLAIN 0x01 #define SASL_MASK_PLAIN 0x01
#define SASL_MASK_DIGESTMD5 0x02 #define SASL_MASK_DIGESTMD5 0x02
#define SASL_MASK_ANONYMOUS 0x04 #define SASL_MASK_ANONYMOUS 0x04

View File

@@ -57,7 +57,15 @@ static void _handle_stream_end(char *name,
void * const userdata); void * const userdata);
static void _handle_stream_stanza(xmpp_stanza_t *stanza, static void _handle_stream_stanza(xmpp_stanza_t *stanza,
void * const userdata); void * const userdata);
static unsigned short _conn_default_port(xmpp_conn_t * const conn); static unsigned short _conn_default_port(xmpp_conn_t * const conn,
xmpp_conn_type_t type);
static int _conn_connect(xmpp_conn_t * const conn,
const char * const domain,
const char * const host,
unsigned short port,
xmpp_conn_type_t type,
xmpp_conn_handler callback,
void * const userdata);
/** Create a new Strophe connection object. /** Create a new Strophe connection object.
* *
@@ -124,7 +132,6 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
_handle_stream_stanza, _handle_stream_stanza,
conn); conn);
conn->reset_parser = 0; conn->reset_parser = 0;
conn_prepare_reset(conn, auth_handle_open);
conn->authenticated = 0; conn->authenticated = 0;
conn->conn_handler = NULL; conn->conn_handler = NULL;
@@ -433,66 +440,45 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void * const userdata) void * const userdata)
{ {
char domain[2048]; char *buf = NULL;
char *domain;
const char *host;
unsigned short port; unsigned short port;
const char *prefdomain = NULL; int found = 0;
int found; int rc;
if (conn->state != XMPP_STATE_DISCONNECTED) domain = xmpp_jid_domain(conn->ctx, conn->jid);
return -1; if (!domain) return -1;
if (conn->domain != NULL)
xmpp_free(conn->ctx, conn->domain);
conn->type = XMPP_CLIENT;
conn->secured = 0;
conn->tls_failed = 0;
conn->domain = xmpp_jid_domain(conn->ctx, conn->jid);
if (!conn->domain) return -1;
if (altdomain != NULL) { if (altdomain != NULL) {
xmpp_debug(conn->ctx, "xmpp", "Connecting via altdomain."); xmpp_debug(conn->ctx, "xmpp", "Connecting via altdomain.");
prefdomain = altdomain; host = altdomain;
port = altport ? altport : _conn_default_port(conn); port = altport ? altport : _conn_default_port(conn, XMPP_CLIENT);
} else { found = 1;
found = resolver_srv_lookup("xmpp-client", "tcp", conn->domain,
domain, sizeof(domain), &port); /* SSL tunneled connection on 5223 port is legacy and doesn't
if (!found) { * have an SRV record. */
xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed, " } else if (!conn->tls_legacy_ssl) {
"connecting via domain."); host = buf = xmpp_alloc(conn->ctx, MAX_DOMAIN_LEN);
prefdomain = conn->domain; if (buf != NULL) {
port = altport ? altport : _conn_default_port(conn); found = resolver_srv_lookup("xmpp-client", "tcp", domain,
} buf, MAX_DOMAIN_LEN, &port);
if (conn->tls_legacy_ssl) {
/* SSL tunneled connection on 5223 port is legacy and doesn't
* have an SRV record. Force port 5223 here unless altport is
* specified.
*/
port = altport ? altport : XMPP_PORT_CLIENT_LEGACY_SSL;
} }
} }
if (prefdomain != NULL) {
strncpy(domain, prefdomain, sizeof(domain)); if (!found) {
domain[sizeof(domain) - 1] = '\0'; xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed, "
"connecting via domain.");
host = domain;
port = altport ? altport : _conn_default_port(conn, XMPP_CLIENT);
} }
conn->sock = sock_connect(domain, port);
xmpp_debug(conn->ctx, "xmpp", "sock_connect to %s:%u returned %d",
domain, port, conn->sock);
if (conn->sock == -1) return -1;
/* setup handler */ rc = _conn_connect(conn, domain, host, port, XMPP_CLIENT,
conn->conn_handler = callback; callback, userdata);
conn->userdata = userdata; xmpp_free(conn->ctx, domain);
if (buf) xmpp_free(conn->ctx, buf);
/* FIXME: it could happen that the connect returns immediately as return rc;
* successful, though this is pretty unlikely. This would be a little
* hard to fix, since we'd have to detect and fire off the callback
* from within the event loop */
conn->state = XMPP_STATE_CONNECTING;
conn->timeout_stamp = time_stamp();
xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", domain);
return 0;
} }
/** Initiate a component connection to server. /** Initiate a component connection to server.
@@ -522,50 +508,22 @@ int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
unsigned short port, xmpp_conn_handler callback, unsigned short port, xmpp_conn_handler callback,
void * const userdata) void * const userdata)
{ {
unsigned short connectport;
if (conn->state != XMPP_STATE_DISCONNECTED)
return -1;
if (conn->domain != NULL)
xmpp_free(conn->ctx, conn->domain);
conn->type = XMPP_COMPONENT;
conn->secured = 0;
conn->tls_failed = 0;
/* JID serves as an identificator here and will be used as "to" attribute
of the stream */
conn->domain = xmpp_strdup(conn->ctx, conn->jid);
/* The server domain, jid and password MUST be specified. */ /* The server domain, jid and password MUST be specified. */
if (!(server && conn->jid && conn->pass)) return -1; if (!(server && conn->jid && conn->pass)) return -1;
connectport = port ? port : _conn_default_port(conn);
xmpp_debug(conn->ctx, "xmpp", "Connecting via %s", server);
conn->sock = sock_connect(server, connectport);
xmpp_debug(conn->ctx, "xmpp", "sock_connect to %s:%u returned %d",
server, connectport, conn->sock);
if (conn->sock == -1) return -1;
/* XEP-0114 does not support TLS */ /* XEP-0114 does not support TLS */
conn->tls_disabled = 1; xmpp_conn_disable_tls(conn);
if (!conn->tls_disabled) {
xmpp_error(conn->ctx, "conn", "Failed to disable TLS. "
"XEP-0114 does not support TLS");
return -1;
}
/* setup handler */ port = port ? port : _conn_default_port(conn, XMPP_COMPONENT);
conn->conn_handler = callback; /* JID serves as an identificator here and will be used as "to" attribute
conn->userdata = userdata; of the stream */
return _conn_connect(conn, conn->jid, server, port, XMPP_COMPONENT,
conn_prepare_reset(conn, auth_handle_component_open); callback, userdata);
/* FIXME: it could happen that the connect returns immediately as
* successful, though this is pretty unlikely. This would be a little
* hard to fix, since we'd have to detect and fire off the callback
* from within the event loop */
conn->state = XMPP_STATE_CONNECTING;
conn->timeout_stamp = time_stamp();
xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", server);
return 0;
} }
/** Cleanly disconnect the connection. /** Cleanly disconnect the connection.
@@ -996,15 +954,63 @@ static void _handle_stream_stanza(xmpp_stanza_t *stanza,
handler_fire_stanza(conn, stanza); handler_fire_stanza(conn, stanza);
} }
static unsigned short _conn_default_port(xmpp_conn_t * const conn) static unsigned short _conn_default_port(xmpp_conn_t * const conn,
xmpp_conn_type_t type)
{ {
switch (conn->type) { switch (type) {
case XMPP_CLIENT: case XMPP_CLIENT:
return conn->tls_legacy_ssl ? XMPP_PORT_CLIENT_LEGACY_SSL : return conn->tls_legacy_ssl ? XMPP_PORT_CLIENT_LEGACY_SSL :
XMPP_PORT_CLIENT; XMPP_PORT_CLIENT;
case XMPP_COMPONENT: case XMPP_COMPONENT:
return XMPP_PORT_COMPONENT; return XMPP_PORT_COMPONENT;
default: default:
return -1; return 0;
}; };
} }
static int _conn_connect(xmpp_conn_t * const conn,
const char * const domain,
const char * const host,
unsigned short port,
xmpp_conn_type_t type,
xmpp_conn_handler callback,
void * const userdata)
{
if (conn->state != XMPP_STATE_DISCONNECTED) return -1;
if (type != XMPP_CLIENT && type != XMPP_COMPONENT) return -1;
/* conn->stream_error must be released in order to support reconnect. */
if (conn->type != XMPP_UNKNOWN) return -1;
if (conn->domain != NULL)
xmpp_free(conn->ctx, conn->domain);
conn->type = type;
conn->secured = 0;
conn->tls_failed = 0;
conn->error = 0;
conn->domain = xmpp_strdup(conn->ctx, domain);
if (!conn->domain) return -1;
conn->sock = sock_connect(host, port);
xmpp_debug(conn->ctx, "xmpp", "sock_connect() to %s:%u returned %d",
host, port, conn->sock);
if (conn->sock == -1) return -1;
/* setup handler */
conn->conn_handler = callback;
conn->userdata = userdata;
conn_prepare_reset(conn, type == XMPP_CLIENT ? auth_handle_open :
auth_handle_component_open);
/* FIXME: it could happen that the connect returns immediately as
* successful, though this is pretty unlikely. This would be a little
* hard to fix, since we'd have to detect and fire off the callback
* from within the event loop */
conn->state = XMPP_STATE_CONNECTING;
conn->timeout_stamp = time_stamp();
xmpp_debug(conn->ctx, "xmpp", "Attempting to connect to %s", host);
return 0;
}