diff options
Diffstat (limited to 'src/xmpp/presence.c')
-rw-r--r-- | src/xmpp/presence.c | 213 |
1 files changed, 146 insertions, 67 deletions
diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c index f306712e..d8d89f12 100644 --- a/src/xmpp/presence.c +++ b/src/xmpp/presence.c @@ -39,11 +39,19 @@ static GHashTable *sub_requests; #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, +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 char* _handle_presence_caps(xmpp_stanza_t * const stanza); -static int _room_presence_handler(const char * const jid, - xmpp_stanza_t * const stanza); +static int _room_presence_handler(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata); void presence_init(void) @@ -56,7 +64,14 @@ presence_add_handlers(void) { xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); - HANDLE(NULL, NULL, _presence_handler); + + HANDLE(NULL, STANZA_TYPE_ERROR, connection_error_handler); + HANDLE(STANZA_NS_MUC_USER, NULL, _room_presence_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); } void @@ -215,86 +230,144 @@ presence_leave_chat_room(const char * const room_jid) xmpp_stanza_release(presence); } +static int +_unsubscribed_handler(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata) +{ + 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); + + prof_handle_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED); + g_hash_table_remove(sub_requests, 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) +{ + 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); + + prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED); + g_hash_table_remove(sub_requests, 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) +{ + char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); + Jid *from_jid = jid_create(from); + log_debug("subscribe presence handler fired for %s", from); + + prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE); + g_hash_table_insert(sub_requests, strdup(from_jid->barejid), strdup(from_jid->barejid)); + + jid_destroy(from_jid); + return 1; +} static int -_presence_handler(xmpp_conn_t * const conn, +_unavailable_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { const char *jid = xmpp_conn_get_jid(conn); char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); - char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); + log_debug("unavailable presence handler fired for %s", from); Jid *my_jid = jid_create(jid); Jid *from_jid = jid_create(from); - if ((type != NULL) && (strcmp(type, STANZA_TYPE_ERROR) == 0)) { - return connection_error_handler(stanza); + char *status_str; + xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS); + if (status != NULL) + status_str = xmpp_stanza_get_text(status); + else + status_str = NULL; + + if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { + prof_handle_contact_offline(from_jid->barejid, "offline", status_str); } - // handle chat room presence - if (muc_room_is_active(from_jid)) { - return _room_presence_handler(from_jid->str, stanza); + jid_destroy(my_jid); + jid_destroy(from_jid); - // handle regular presence - } else { - log_debug("Regular presence received from %s", from); - char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); - char *show_str, *status_str; - int idle_seconds = stanza_get_idle_time(stanza); - GDateTime *last_activity = NULL; + return 1; +} - if (idle_seconds > 0) { - GDateTime *now = g_date_time_new_now_local(); - last_activity = g_date_time_add_seconds(now, 0 - idle_seconds); - g_date_time_unref(now); - } +static int +_available_handler(xmpp_conn_t * const conn, + xmpp_stanza_t * const stanza, void * const userdata) +{ + // handler still fires if error + if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) { + return 1; + } - char *caps_key = _handle_presence_caps(stanza); + // handler still fires if other types + if ((g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_UNAVAILABLE) == 0) || + (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; + } - xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS); - if (status != NULL) - status_str = xmpp_stanza_get_text(status); - else - status_str = NULL; + const char *jid = xmpp_conn_get_jid(conn); + char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); + log_debug("available presence handler fired for %s", from); - if (type == NULL) { // available - xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW); - if (show != NULL) - show_str = xmpp_stanza_get_text(show); - else - show_str = "online"; + Jid *my_jid = jid_create(jid); + Jid *from_jid = jid_create(from); - if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { - prof_handle_contact_online(from_jid->barejid, show_str, status_str, last_activity, caps_key); - } - } else if (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0) { - if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { - prof_handle_contact_offline(from_jid->barejid, "offline", status_str); - } + char *show_str, *status_str; + char *caps_key = _handle_presence_caps(stanza); + int idle_seconds = stanza_get_idle_time(stanza); + GDateTime *last_activity = NULL; - if (last_activity != NULL) { - g_date_time_unref(last_activity); - } + if (idle_seconds > 0) { + GDateTime *now = g_date_time_new_now_local(); + last_activity = g_date_time_add_seconds(now, 0 - idle_seconds); + g_date_time_unref(now); + } - // subscriptions - } else if (strcmp(type, STANZA_TYPE_SUBSCRIBE) == 0) { - prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE); - g_hash_table_insert(sub_requests, strdup(from_jid->barejid), strdup(from_jid->barejid)); - } else if (strcmp(type, STANZA_TYPE_SUBSCRIBED) == 0) { - prof_handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED); - g_hash_table_remove(sub_requests, from_jid->barejid); - } else if (strcmp(type, STANZA_TYPE_UNSUBSCRIBED) == 0) { - prof_handle_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED); - g_hash_table_remove(sub_requests, from_jid->barejid); - } else { /* unknown type */ - log_debug("Received presence with unknown type '%s'", type); - } + xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW); + if (show != NULL) + show_str = xmpp_stanza_get_text(show); + else + show_str = "online"; + + xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS); + if (status != NULL) + status_str = xmpp_stanza_get_text(status); + else + status_str = NULL; + + if (strcmp(my_jid->barejid, from_jid->barejid) !=0) { + prof_handle_contact_online(from_jid->barejid, show_str, status_str, last_activity, caps_key); + } + + jid_destroy(my_jid); + jid_destroy(from_jid); + + if (last_activity != NULL) { + g_date_time_unref(last_activity); } return 1; } + static char * _handle_presence_caps(xmpp_stanza_t * const stanza) { @@ -387,16 +460,22 @@ _handle_presence_caps(xmpp_stanza_t * const stanza) } static int -_room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) +_room_presence_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, + void * const userdata) { - char *room = NULL; - char *nick = NULL; - - if (!parse_room_jid(jid, &room, &nick)) { - log_error("Could not parse room jid: %s", room); + // handler still fires if error + if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) { return 1; } + const char *jid = xmpp_conn_get_jid(conn); + char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); + Jid *my_jid = jid_create(jid); + Jid *from_jid = jid_create(from); + + char *room = from_jid->barejid; + char *nick = from_jid->resourcepart; + // handle self presence if (stanza_is_muc_self_presence(stanza, jabber_get_jid())) { char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); @@ -428,7 +507,7 @@ _room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) char *show_str, *status_str; char *caps_key = _handle_presence_caps(stanza); - log_debug("Room presence received from %s", jid); + log_debug("Room presence received from %s", from_jid->fulljid); xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS); if (status != NULL) { @@ -472,8 +551,8 @@ _room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) } } - free(room); - free(nick); + jid_destroy(my_jid); + jid_destroy(from_jid); return 1; } |