Use one stanza handler per type (message, iq, presence)

Allows plugins to stop stanza processing
This commit is contained in:
James Booth
2016-03-28 01:25:48 +01:00
parent 8933d59b03
commit d39e48ba18
8 changed files with 457 additions and 638 deletions

View File

@@ -63,23 +63,20 @@
static Autocomplete sub_requests_ac;
#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_PRESENCE, type, ctx)
static int _presence_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
// regular handlers
static int _unavailable_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static int _subscribe_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static int _subscribed_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static int _unsubscribed_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static int _available_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static int _muc_user_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static int _presence_error_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
static void _presence_error_handler(xmpp_stanza_t *const stanza);
static void _unavailable_handler(xmpp_stanza_t *const stanza);
static void _subscribe_handler(xmpp_stanza_t *const stanza);
static void _subscribed_handler(xmpp_stanza_t *const stanza);
static void _unsubscribed_handler(xmpp_stanza_t *const stanza);
static void _muc_user_handler(xmpp_stanza_t *const stanza);
static void _available_handler(xmpp_stanza_t *const stanza);
void _send_caps_request(char *node, char *caps_key, char *id, char *from);
static void _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence);
static void _send_room_presence(xmpp_stanza_t *presence);
static void _send_presence_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza);
static void _send_iq_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza);
static gboolean _receive_presence_stanza(xmpp_stanza_t *const stanza);
static void _send_presence_stanza(xmpp_stanza_t *const stanza);
void
presence_sub_requests_init(void)
@@ -87,19 +84,57 @@ presence_sub_requests_init(void)
sub_requests_ac = autocomplete_new();
}
static int
_presence_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
{
log_debug("Presence stanza handler fired");
char *text;
size_t text_size;
xmpp_stanza_to_text(stanza, &text, &text_size);
gboolean cont = plugins_on_presence_stanza_receive(text);
if (!cont) {
return 1;
}
char *type = xmpp_stanza_get_type(stanza);
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
_presence_error_handler(stanza);
}
if (g_strcmp0(type, STANZA_TYPE_UNAVAILABLE) == 0) {
_unavailable_handler(stanza);
}
if (g_strcmp0(type, STANZA_TYPE_SUBSCRIBE) == 0) {
_subscribe_handler(stanza);
}
if (g_strcmp0(type, STANZA_TYPE_SUBSCRIBED) == 0) {
_subscribed_handler(stanza);
}
if (g_strcmp0(type, STANZA_TYPE_UNSUBSCRIBED) == 0) {
_unsubscribed_handler(stanza);
}
xmpp_stanza_t *mucuser = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (mucuser) {
_muc_user_handler(stanza);
}
_available_handler(stanza);
return 1;
}
void
presence_add_handlers(void)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
HANDLE(NULL, STANZA_TYPE_ERROR, _presence_error_handler);
HANDLE(STANZA_NS_MUC_USER, NULL, _muc_user_handler);
HANDLE(NULL, STANZA_TYPE_UNAVAILABLE, _unavailable_handler);
HANDLE(NULL, STANZA_TYPE_SUBSCRIBE, _subscribe_handler);
HANDLE(NULL, STANZA_TYPE_SUBSCRIBED, _subscribed_handler);
HANDLE(NULL, STANZA_TYPE_UNSUBSCRIBED, _unsubscribed_handler);
HANDLE(NULL, NULL, _available_handler);
xmpp_handler_add(conn, _presence_handler, NULL, STANZA_NAME_PRESENCE, NULL, ctx);
}
void
@@ -108,7 +143,6 @@ presence_subscription(const char *const jid, const jabber_subscr_t action)
assert(jid != NULL);
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_conn_t * const conn = connection_get_conn();
const char *type = NULL;
Jid *jidp = jid_create(jid);
@@ -140,7 +174,7 @@ presence_subscription(const char *const jid, const jabber_subscr_t action)
xmpp_stanza_set_name(presence, STANZA_NAME_PRESENCE);
xmpp_stanza_set_type(presence, type);
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, jidp->barejid);
_send_presence_stanza(conn, presence);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
jid_destroy(jidp);
@@ -214,7 +248,6 @@ presence_send(const resource_presence_t presence_type, const char *const msg, co
}
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_conn_t * const conn = connection_get_conn();
const int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), presence_type);
const char *show = stanza_get_presence_string_from_type(presence_type);
@@ -245,8 +278,8 @@ presence_send(const resource_presence_t presence_type, const char *const msg, co
stanza_attach_last_activity(ctx, presence, idle);
}
stanza_attach_caps(ctx, presence);
_send_presence_stanza(conn, presence);
_send_room_presence(conn, presence);
_send_presence_stanza(presence);
_send_room_presence(presence);
xmpp_stanza_release(presence);
// set last presence for account
@@ -261,7 +294,7 @@ presence_send(const resource_presence_t presence_type, const char *const msg, co
}
static void
_send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence)
_send_room_presence(xmpp_stanza_t *presence)
{
GList *rooms_p = muc_rooms();
GList *rooms = rooms_p;
@@ -275,7 +308,7 @@ _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence)
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid);
log_debug("Sending presence to room: %s", full_room_jid);
_send_presence_stanza(conn, presence);
_send_presence_stanza(presence);
free(full_room_jid);
}
@@ -294,7 +327,6 @@ presence_join_room(char *room, char *nick, char * passwd)
log_debug("Sending room join presence to: %s", jid->fulljid);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_conn_t *conn = connection_get_conn();
resource_presence_t presence_type =
accounts_get_last_presence(jabber_get_account_name());
const char *show = stanza_get_presence_string_from_type(presence_type);
@@ -308,7 +340,7 @@ presence_join_room(char *room, char *nick, char * passwd)
stanza_attach_priority(ctx, presence, pri);
stanza_attach_caps(ctx, presence);
_send_presence_stanza(conn, presence);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
jid_destroy(jid);
@@ -322,7 +354,6 @@ presence_change_room_nick(const char *const room, const char *const nick)
log_debug("Sending room nickname change to: %s, nick: %s", room, nick);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_conn_t *conn = connection_get_conn();
resource_presence_t presence_type =
accounts_get_last_presence(jabber_get_account_name());
const char *show = stanza_get_presence_string_from_type(presence_type);
@@ -338,7 +369,7 @@ presence_change_room_nick(const char *const room, const char *const nick)
stanza_attach_priority(ctx, presence, pri);
stanza_attach_caps(ctx, presence);
_send_presence_stanza(conn, presence);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
free(full_room_jid);
@@ -351,23 +382,18 @@ presence_leave_chat_room(const char *const room_jid)
log_debug("Sending room leave presence to: %s", room_jid);
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_conn_t *conn = connection_get_conn();
char *nick = muc_nick(room_jid);
if (nick) {
xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid,
nick);
_send_presence_stanza(conn, presence);
xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid, nick);
_send_presence_stanza(presence);
xmpp_stanza_release(presence);
}
}
static int
_presence_error_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza,
void *const userdata)
static void
_presence_error_handler(xmpp_stanza_t *const stanza)
{
log_debug("Presence stanza error handler fired");
char *id = xmpp_stanza_get_id(stanza);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
@@ -400,7 +426,7 @@ _presence_error_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza,
}
cons_show_error("Error joining room %s, reason: %s", fulljid->barejid, error_cond);
jid_destroy(fulljid);
return 1;
return;
}
// stanza_get_error never returns NULL
@@ -433,17 +459,12 @@ _presence_error_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza,
}
free(err_msg);
return 1;
}
static int
_unsubscribed_handler(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza, void *const userdata)
static void
_unsubscribed_handler(xmpp_stanza_t *const stanza)
{
log_debug("Presence stanza unsubscribed handler fired");
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
Jid *from_jid = jid_create(from);
log_debug("Unsubscribed presence handler fired for %s", from);
@@ -452,16 +473,11 @@ _unsubscribed_handler(xmpp_conn_t *const conn,
autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
return 1;
}
static int
_subscribed_handler(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza, void *const userdata)
static void
_subscribed_handler(xmpp_stanza_t *const stanza)
{
log_debug("Presence stanza subscribed handler fired");
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
Jid *from_jid = jid_create(from);
log_debug("Subscribed presence handler fired for %s", from);
@@ -470,40 +486,31 @@ _subscribed_handler(xmpp_conn_t *const conn,
autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
return 1;
}
static int
_subscribe_handler(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza, void *const userdata)
static void
_subscribe_handler(xmpp_stanza_t *const stanza)
{
log_debug("Presence stanza subscribe handler fired");
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
log_debug("Subscribe presence handler fired for %s", from);
Jid *from_jid = jid_create(from);
if (from_jid == NULL) {
return 1;
return;
}
sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE);
autocomplete_add(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
return 1;
}
static int
_unavailable_handler(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza, void *const userdata)
static void
_unavailable_handler(xmpp_stanza_t *const stanza)
{
log_debug("Presence stanza unavailale handler fired");
inp_nonblocking(TRUE);
xmpp_conn_t *conn = connection_get_conn();
const char *jid = xmpp_conn_get_jid(conn);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
log_debug("Unavailable presence handler fired for %s", from);
@@ -513,7 +520,7 @@ _unavailable_handler(xmpp_conn_t *const conn,
if (my_jid == NULL || from_jid == NULL) {
jid_destroy(my_jid);
jid_destroy(from_jid);
return 1;
return;
}
char *status_str = stanza_get_status(stanza, NULL);
@@ -535,8 +542,6 @@ _unavailable_handler(xmpp_conn_t *const conn,
free(status_str);
jid_destroy(my_jid);
jid_destroy(from_jid);
return 1;
}
static void
@@ -575,21 +580,14 @@ _handle_caps(char *jid, XMPPCaps *caps)
}
}
static int
_available_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
static void
_available_handler(xmpp_stanza_t *const stanza)
{
log_debug("Presence stanza available handler fired");
gboolean cont = _receive_presence_stanza(stanza);
if (!cont) {
return 1;
}
inp_nonblocking(TRUE);
// handler still fires if error
if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) {
return 1;
return;
}
// handler still fires if other types
@@ -597,12 +595,12 @@ _available_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *c
(g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBE) == 0) ||
(g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_SUBSCRIBED) == 0) ||
(g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNSUBSCRIBED) == 0)) {
return 1;
return;
}
// handler still fires for muc presence
if (stanza_is_muc_presence(stanza)) {
return 1;
return;
}
int err = 0;
@@ -622,12 +620,13 @@ _available_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *c
log_warning("Available presence handler fired, could not parse stanza.");
break;
}
return 1;
return;
} else {
char *jid = jid_fulljid_or_barejid(xmpp_presence->jid);
log_debug("Presence available handler fired for: %s", jid);
}
xmpp_conn_t *conn = connection_get_conn();
const char *my_jid_str = xmpp_conn_get_jid(conn);
Jid *my_jid = jid_create(my_jid_str);
@@ -656,22 +655,19 @@ _available_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *c
jid_destroy(my_jid);
stanza_free_presence(xmpp_presence);
return 1;
}
void
_send_caps_request(char *node, char *caps_key, char *id, char *from)
{
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_conn_t *conn = connection_get_conn();
if (node) {
log_debug("Node string: %s.", node);
if (!caps_contains(caps_key)) {
log_debug("Capabilities not cached for '%s', sending discovery IQ.", from);
xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, from, node);
_send_iq_stanza(conn, iq);
send_iq_stanza(iq);
xmpp_stanza_release(iq);
} else {
log_debug("Capabilities already cached, for %s", caps_key);
@@ -681,11 +677,9 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from)
}
}
static int
_muc_user_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
static void
_muc_user_handler(xmpp_stanza_t *const stanza)
{
log_debug("Presence stanza muc user handler fired");
inp_nonblocking(TRUE);
char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
@@ -693,14 +687,14 @@ _muc_user_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *co
// handler still fires if error
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
return 1;
return;
}
// invalid from attribute
Jid *from_jid = jid_create(from);
if (from_jid == NULL || from_jid->resourcepart == NULL) {
jid_destroy(from_jid);
return 1;
return;
}
char *room = from_jid->barejid;
@@ -832,17 +826,16 @@ _muc_user_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *co
free(show_str);
free(status_str);
jid_destroy(from_jid);
return 1;
}
static void
_send_presence_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza)
_send_presence_stanza(xmpp_stanza_t *const stanza)
{
char *text;
size_t text_size;
xmpp_stanza_to_text(stanza, &text, &text_size);
xmpp_conn_t *conn = connection_get_conn();
char *plugin_text = plugins_on_presence_stanza_send(text);
if (plugin_text) {
xmpp_send_raw_string(conn, "%s", plugin_text);
@@ -850,29 +843,3 @@ _send_presence_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza)
xmpp_send_raw_string(conn, "%s", text);
}
}
static void
_send_iq_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza)
{
char *text;
size_t text_size;
xmpp_stanza_to_text(stanza, &text, &text_size);
char *plugin_text = plugins_on_iq_stanza_send(text);
if (plugin_text) {
xmpp_send_raw_string(conn, "%s", plugin_text);
} else {
xmpp_send_raw_string(conn, "%s", text);
}
}
static gboolean
_receive_presence_stanza(xmpp_stanza_t *const stanza)
{
char *text;
size_t text_size;
xmpp_stanza_to_text(stanza, &text, &text_size);
return plugins_on_presence_stanza_receive(text);
}