WIP XEP-0198: implement stream management
Stream management is enabled when server supports it. There is no option to disable it.
This commit is contained in:
51
src/auth.c
51
src/auth.c
@@ -99,6 +99,9 @@ static int _handle_session(xmpp_conn_t * const conn,
|
|||||||
void * const userdata);
|
void * const userdata);
|
||||||
static int _handle_missing_session(xmpp_conn_t * const conn,
|
static int _handle_missing_session(xmpp_conn_t * const conn,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
|
static int _handle_sm(xmpp_conn_t * const conn,
|
||||||
|
xmpp_stanza_t * const stanza,
|
||||||
|
void * const userdata);
|
||||||
static int _handle_missing_handshake(xmpp_conn_t * const conn,
|
static int _handle_missing_handshake(xmpp_conn_t * const conn,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
|
|
||||||
@@ -814,6 +817,12 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
|
|||||||
strcmp(ns, XMPP_NS_SESSION) == 0;
|
strcmp(ns, XMPP_NS_SESSION) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opt = xmpp_stanza_get_child_by_ns(stanza, XMPP_NS_SM);
|
||||||
|
if (opt && strcmp(xmpp_stanza_get_name(opt), "sm") == 0) {
|
||||||
|
/* stream management supported */
|
||||||
|
conn->sm_support = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* if bind is required, go ahead and start it */
|
/* if bind is required, go ahead and start it */
|
||||||
if (conn->bind_required) {
|
if (conn->bind_required) {
|
||||||
/* bind resource */
|
/* bind resource */
|
||||||
@@ -902,7 +911,7 @@ static int _handle_bind(xmpp_conn_t * const conn,
|
|||||||
void * const userdata)
|
void * const userdata)
|
||||||
{
|
{
|
||||||
const char *type;
|
const char *type;
|
||||||
xmpp_stanza_t *iq, *session;
|
xmpp_stanza_t *iq, *enable, *session, *binding, *jid_stanza;
|
||||||
|
|
||||||
/* delete missing bind handler */
|
/* delete missing bind handler */
|
||||||
xmpp_timed_handler_delete(conn, _handle_missing_bind);
|
xmpp_timed_handler_delete(conn, _handle_missing_bind);
|
||||||
@@ -913,12 +922,11 @@ static int _handle_bind(xmpp_conn_t * const conn,
|
|||||||
xmpp_error(conn->ctx, "xmpp", "Binding failed.");
|
xmpp_error(conn->ctx, "xmpp", "Binding failed.");
|
||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
} else if (type && strcmp(type, "result") == 0) {
|
} else if (type && strcmp(type, "result") == 0) {
|
||||||
xmpp_stanza_t *binding = xmpp_stanza_get_child_by_name(stanza, "bind");
|
binding = xmpp_stanza_get_child_by_name(stanza, "bind");
|
||||||
xmpp_debug(conn->ctx, "xmpp", "Bind successful.");
|
xmpp_debug(conn->ctx, "xmpp", "Bind successful.");
|
||||||
|
|
||||||
if (binding) {
|
if (binding) {
|
||||||
xmpp_stanza_t *jid_stanza = xmpp_stanza_get_child_by_name(binding,
|
jid_stanza = xmpp_stanza_get_child_by_name(binding, "jid");
|
||||||
"jid");
|
|
||||||
if (jid_stanza) {
|
if (jid_stanza) {
|
||||||
conn->bound_jid = xmpp_stanza_get_text(jid_stanza);
|
conn->bound_jid = xmpp_stanza_get_text(jid_stanza);
|
||||||
}
|
}
|
||||||
@@ -954,7 +962,23 @@ static int _handle_bind(xmpp_conn_t * const conn,
|
|||||||
/* send session establishment request */
|
/* send session establishment request */
|
||||||
xmpp_send(conn, iq);
|
xmpp_send(conn, iq);
|
||||||
xmpp_stanza_release(iq);
|
xmpp_stanza_release(iq);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (conn->sm_support) {
|
||||||
|
enable = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!enable) {
|
||||||
|
disconnect_mem_error(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
xmpp_stanza_set_name(enable, "enable");
|
||||||
|
xmpp_stanza_set_ns(enable, XMPP_NS_SM);
|
||||||
|
handler_add(conn, _handle_sm, XMPP_NS_SM, NULL, NULL, NULL);
|
||||||
|
xmpp_send(conn, enable);
|
||||||
|
xmpp_stanza_release(enable);
|
||||||
|
conn->sm_sent_nr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conn->session_required) {
|
||||||
conn->authenticated = 1;
|
conn->authenticated = 1;
|
||||||
|
|
||||||
/* call connection handler */
|
/* call connection handler */
|
||||||
@@ -1023,6 +1047,23 @@ static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _handle_sm(xmpp_conn_t * const conn,
|
||||||
|
xmpp_stanza_t * const stanza,
|
||||||
|
void * const userdata)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
name = xmpp_stanza_get_name(stanza);
|
||||||
|
if (name && strcmp(name, "enabled") == 0) {
|
||||||
|
conn->sm_enabled = 1;
|
||||||
|
conn->sm_handled_nr = 0;
|
||||||
|
} else {
|
||||||
|
conn->sm_enabled = 0;
|
||||||
|
xmpp_warn(conn->ctx, "auth", "Stream management failed.");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _handle_legacy(xmpp_conn_t * const conn,
|
static int _handle_legacy(xmpp_conn_t * const conn,
|
||||||
xmpp_stanza_t * const stanza,
|
xmpp_stanza_t * const stanza,
|
||||||
void * const userdata)
|
void * const userdata)
|
||||||
|
|||||||
@@ -178,6 +178,10 @@ struct _xmpp_conn_t {
|
|||||||
/* if server returns <bind/> or <session/> we must do them */
|
/* if server returns <bind/> or <session/> we must do them */
|
||||||
int bind_required;
|
int bind_required;
|
||||||
int session_required;
|
int session_required;
|
||||||
|
int sm_support;
|
||||||
|
int sm_enabled;
|
||||||
|
uint32_t sm_handled_nr;
|
||||||
|
uint32_t sm_sent_nr;
|
||||||
|
|
||||||
char *lang;
|
char *lang;
|
||||||
char *domain;
|
char *domain;
|
||||||
|
|||||||
38
src/conn.c
38
src/conn.c
@@ -62,6 +62,8 @@ 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 void _conn_sm_handle_stanza(xmpp_conn_t * const conn,
|
||||||
|
xmpp_stanza_t *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);
|
xmpp_conn_type_t type);
|
||||||
static void _conn_reset(xmpp_conn_t * const conn);
|
static void _conn_reset(xmpp_conn_t * const conn);
|
||||||
@@ -145,6 +147,10 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
|
|||||||
|
|
||||||
conn->bind_required = 0;
|
conn->bind_required = 0;
|
||||||
conn->session_required = 0;
|
conn->session_required = 0;
|
||||||
|
conn->sm_support = 0;
|
||||||
|
conn->sm_enabled = 0;
|
||||||
|
conn->sm_handled_nr = 0;
|
||||||
|
conn->sm_sent_nr = 0;
|
||||||
|
|
||||||
conn->parser = parser_new(conn->ctx,
|
conn->parser = parser_new(conn->ctx,
|
||||||
_handle_stream_start,
|
_handle_stream_start,
|
||||||
@@ -1216,6 +1222,36 @@ static void _handle_stream_stanza(xmpp_stanza_t *stanza,
|
|||||||
}
|
}
|
||||||
|
|
||||||
handler_fire_stanza(conn, stanza);
|
handler_fire_stanza(conn, stanza);
|
||||||
|
if (conn->sm_enabled)
|
||||||
|
_conn_sm_handle_stanza(conn, stanza);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XEP-0198 stream management */
|
||||||
|
static void _conn_sm_handle_stanza(xmpp_conn_t * const conn,
|
||||||
|
xmpp_stanza_t *stanza)
|
||||||
|
{
|
||||||
|
xmpp_stanza_t *a;
|
||||||
|
const char *name;
|
||||||
|
const char *ns;
|
||||||
|
char h[11];
|
||||||
|
|
||||||
|
ns = xmpp_stanza_get_ns(stanza);
|
||||||
|
if (ns && strcmp(ns, XMPP_NS_SM) != 0)
|
||||||
|
++conn->sm_handled_nr;
|
||||||
|
else {
|
||||||
|
name = xmpp_stanza_get_name(stanza);
|
||||||
|
if (name && strcmp(name, "r") == 0) {
|
||||||
|
a = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!a)
|
||||||
|
return; /* XXX */
|
||||||
|
xmpp_stanza_set_name(a, "a");
|
||||||
|
xmpp_stanza_set_ns(a, XMPP_NS_SM);
|
||||||
|
xmpp_snprintf(h, sizeof(h), "%u", conn->sm_handled_nr);
|
||||||
|
xmpp_stanza_set_attribute(a, "h", h);
|
||||||
|
xmpp_send(conn, a);
|
||||||
|
xmpp_stanza_release(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned short _conn_default_port(xmpp_conn_t * const conn,
|
static unsigned short _conn_default_port(xmpp_conn_t * const conn,
|
||||||
@@ -1274,6 +1310,8 @@ static void _conn_reset(xmpp_conn_t * const conn)
|
|||||||
conn->error = 0;
|
conn->error = 0;
|
||||||
|
|
||||||
conn->tls_support = 0;
|
conn->tls_support = 0;
|
||||||
|
conn->sm_support = 0;
|
||||||
|
conn->sm_enabled = 0;
|
||||||
conn->bind_required = 0;
|
conn->bind_required = 0;
|
||||||
conn->session_required = 0;
|
conn->session_required = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ extern "C" {
|
|||||||
* Namespace definition for 'jabber:iq:register'.
|
* Namespace definition for 'jabber:iq:register'.
|
||||||
*/
|
*/
|
||||||
#define XMPP_NS_REGISTER "jabber:iq:register"
|
#define XMPP_NS_REGISTER "jabber:iq:register"
|
||||||
|
/** @def XMPP_NS_SM
|
||||||
|
* Namespace definition for Stream Management.
|
||||||
|
*/
|
||||||
|
#define XMPP_NS_SM "urn:xmpp:sm:3"
|
||||||
|
|
||||||
/* error defines */
|
/* error defines */
|
||||||
/** @def XMPP_EOK
|
/** @def XMPP_EOK
|
||||||
|
|||||||
Reference in New Issue
Block a user