conn: implemented xmpp_connect_raw()

This function is similar to xmpp_connect_client(), but doesn't perform
authentication. Instead, it calls user's connection handler immediately
after establishing the connection. Hence, user can implement own
authendication or registration procedures.

Such a "raw" connection can be useful when user interaction is required
(e.g. Data Forms in XEP-0077, OAuth2).
This commit is contained in:
Dmitry Podgorny
2016-04-26 18:29:47 +00:00
parent 3869906357
commit dc56737b71
6 changed files with 130 additions and 22 deletions

View File

@@ -4,8 +4,14 @@
- Initial Android support
- Resolver returns all SRV records instead of one. Lookup is performed
according to RFC2052.
- xmpp_connect_raw() provides access to a xmpp_conn object just after
establishing TCP connection. This allows to implement in-band
registration or authentication mechanisms.
- New API:
- xmpp_uuid_gen()
- xmpp_connect_raw()
- xmpp_conn_raw_open_stream()
- xmpp_conn_raw_tls_start()
- xmpp_conn_get_flags()
- xmpp_conn_set_flags()
- xmpp_conn_set_keepalive()

View File

@@ -288,6 +288,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
xmpp_debug(conn->ctx, "xmpp", "proceeding with TLS");
if (conn_tls_start(conn) == 0) {
conn_prepare_reset(conn, auth_handle_open);
conn_open_stream(conn);
} else {
/* failed tls spoils the connection, so disconnect */
@@ -1235,3 +1236,16 @@ int _handle_missing_handshake(xmpp_conn_t * const conn, void * const userdata)
xmpp_disconnect(conn);
return 0;
}
void auth_handle_open_raw(xmpp_conn_t * const conn)
{
handler_reset_timed(conn, 0);
/* user handlers are not called before authentication is completed. */
conn->authenticated = 1;
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
}
void auth_handle_open_stub(xmpp_conn_t * const conn)
{
xmpp_warn(conn->ctx, "auth", "Stub callback is called.");
}

View File

@@ -150,6 +150,7 @@ struct _xmpp_conn_t {
unsigned int ref;
xmpp_ctx_t *ctx;
xmpp_conn_type_t type;
int is_raw;
xmpp_conn_state_t state;
uint64_t timeout_stamp;
@@ -215,6 +216,7 @@ struct _xmpp_conn_t {
void conn_disconnect(xmpp_conn_t * const conn);
void conn_disconnect_clean(xmpp_conn_t * const conn);
void conn_established(xmpp_conn_t * const conn);
void conn_open_stream(xmpp_conn_t * const conn);
int conn_tls_start(xmpp_conn_t * const conn);
void conn_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler);
@@ -269,5 +271,7 @@ void disconnect_mem_error(xmpp_conn_t * const conn);
/* auth functions */
void auth_handle_open(xmpp_conn_t * const conn);
void auth_handle_component_open(xmpp_conn_t * const conn);
void auth_handle_open_raw(xmpp_conn_t * const conn);
void auth_handle_open_stub(xmpp_conn_t * const conn);
#endif /* __LIBSTROPHE_COMMON_H__ */

View File

@@ -118,6 +118,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
conn->stream_id = NULL;
conn->bound_jid = NULL;
conn->is_raw = 0;
conn->tls_support = 0;
conn->tls_disabled = 0;
conn->tls_mandatory = 0;
@@ -520,6 +521,87 @@ int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
callback, userdata);
}
/** Initiate a raw connection to the XMPP server.
* Arguments and behaviour of the function are similar to
* xmpp_connect_client(), but it skips authentication process. Instead,
* the user's callback is called with event XMPP_CONN_RAW_CONNECT as soon
* as tcp connection is established.
*
* This function doesn't use password nor node part of a jid. Therefore,
* the only required configuration is a domain (or full jid) passed via
* xmpp_conn_set_jid().
*
* Next step should be xmpp_conn_raw_open_stream(). In case of legacy SSL,
* user might want to call xmpp_conn_raw_tls_start() before opening the
* stream.
*
* @see xmpp_connect_client()
*
* @return XMPP_EOK (0) on success a number less than 0 on failure
*
* @ingroup Connections
*/
int xmpp_connect_raw(xmpp_conn_t * const conn,
const char * const altdomain,
unsigned short altport,
xmpp_conn_handler callback,
void * const userdata)
{
conn->is_raw = 1;
return xmpp_connect_client(conn, altdomain, altport, callback, userdata);
}
/* Called when tcp connection is established. */
void conn_established(xmpp_conn_t * const conn)
{
if (conn->tls_legacy_ssl && !conn->is_raw) {
xmpp_debug(conn->ctx, "xmpp", "using legacy SSL connection");
if (conn_tls_start(conn) != 0) {
conn_disconnect(conn);
return;
}
}
if (conn->is_raw) {
handler_reset_timed(conn, 0);
/* we skip authentication for a "raw" connection, but the event loop
ignores user's handlers when conn->authenticated is not set. */
conn->authenticated = 1;
conn->conn_handler(conn, XMPP_CONN_RAW_CONNECT, 0, NULL, conn->userdata);
} else {
/* send stream init */
conn_open_stream(conn);
}
}
/** Send an opening stream tag.
* User's connection handler is called with event XMPP_CONN_CONNECT when
* server replies with its opening tag.
*
* @return XMPP_EOK (0) on success a number less than 0 on failure
*
* @ingroup Connections
*/
int xmpp_conn_raw_open_stream(xmpp_conn_t * const conn)
{
if (!conn->is_raw)
return XMPP_EINVOP;
conn_prepare_reset(conn, auth_handle_open_raw);
conn_open_stream(conn);
return XMPP_EOK;
}
/** Start synchronous TLS handshake with the server.
*
* @return XMPP_EOK (0) on success a number less than 0 on failure
*/
int xmpp_conn_raw_tls_start(xmpp_conn_t * const conn)
{
return conn_tls_start(conn);
}
/** Cleanly disconnect the connection.
* This function is only called by the stream parser when </stream:stream>
* is received, and it not intended to be called by code outside of Strophe.
@@ -756,27 +838,27 @@ int conn_tls_start(xmpp_conn_t * const conn)
if (conn->tls_disabled) {
conn->tls = NULL;
rc = -ENOSYS;
rc = XMPP_EINVOP;
} else {
conn->tls = tls_new(conn->ctx, conn->sock);
rc = conn->tls == NULL ? -ENOMEM : 0;
rc = conn->tls == NULL ? XMPP_EMEM : 0;
}
if (conn->tls != NULL) {
if (tls_start(conn->tls)) {
conn->secured = 1;
conn_prepare_reset(conn, auth_handle_open);
} else {
rc = tls_error(conn->tls);
conn->error = rc;
rc = XMPP_EINT;
conn->error = tls_error(conn->tls);
tls_free(conn->tls);
conn->tls = NULL;
conn->tls_failed = 1;
}
}
if (rc != 0)
xmpp_debug(conn->ctx, "conn", "Couldn't start TLS! error %d", rc);
if (rc != 0) {
xmpp_debug(conn->ctx, "conn", "Couldn't start TLS! "
"error %d tls_error %d", rc, conn->error);
}
return rc;
}
@@ -1030,6 +1112,8 @@ static int _conn_connect(xmpp_conn_t * const conn,
xmpp_conn_handler callback,
void * const userdata)
{
xmpp_open_handler open_handler;
if (conn->state != XMPP_STATE_DISCONNECTED) return -1;
if (type != XMPP_CLIENT && type != XMPP_COMPONENT) return -1;
@@ -1050,8 +1134,10 @@ static int _conn_connect(xmpp_conn_t * const conn,
conn->conn_handler = callback;
conn->userdata = userdata;
conn_prepare_reset(conn, type == XMPP_CLIENT ? auth_handle_open :
auth_handle_component_open);
open_handler = conn->is_raw ? auth_handle_open_stub :
type == XMPP_CLIENT ? auth_handle_open :
auth_handle_component_open;
conn_prepare_reset(conn, open_handler);
/* FIXME: it could happen that the connect returns immediately as
* successful, though this is pretty unlikely. This would be a little

View File

@@ -267,18 +267,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
conn->state = XMPP_STATE_CONNECTED;
xmpp_debug(ctx, "xmpp", "connection successful");
if (conn->tls_legacy_ssl) {
xmpp_debug(ctx, "xmpp", "using legacy SSL connection");
ret = conn_tls_start(conn);
if (ret != 0) {
conn_disconnect(conn);
break;
}
}
/* send stream init */
conn_open_stream(conn);
conn_established(conn);
}
break;

View File

@@ -169,6 +169,7 @@ typedef struct _xmpp_stanza_t xmpp_stanza_t;
/* connect callback */
typedef enum {
XMPP_CONN_CONNECT,
XMPP_CONN_RAW_CONNECT,
XMPP_CONN_DISCONNECT,
XMPP_CONN_FAIL
} xmpp_conn_event_t;
@@ -238,6 +239,14 @@ int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
unsigned short port, xmpp_conn_handler callback,
void * const userdata);
int xmpp_connect_raw(xmpp_conn_t * const conn,
const char * const altdomain,
unsigned short altport,
xmpp_conn_handler callback,
void * const userdata);
int xmpp_conn_raw_open_stream(xmpp_conn_t * const conn);
int xmpp_conn_raw_tls_start(xmpp_conn_t * const conn);
void xmpp_disconnect(xmpp_conn_t * const conn);
void xmpp_send(xmpp_conn_t * const conn,