static void query_unread_mails_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; WockyPorter *porter = WOCKY_PORTER (source_object); WockyStanza *reply = wocky_porter_send_iq_finish (porter, res, &error); GabbleConnection *conn = GABBLE_CONNECTION (user_data); if (reply == NULL || wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL)) { DEBUG ("Failed retreive unread emails information: %s", error->message); g_error_free (error); } else if (conn->mail_priv->interested) { WockyNode *node = wocky_node_get_child ( wocky_stanza_get_top_node (reply), "mailbox"); DEBUG ("Got unread mail details"); if (node != NULL) store_unread_mails (conn, node); } /* else we no longer care about unread mail, so ignore it */ tp_clear_object (&reply); return_from_request_inbox_url (conn); }
/* Signals incoming delivery receipts. http://xmpp.org/extensions/xep-0184.html */ static gboolean im_factory_receipt_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabbleImFactory *self = GABBLE_IM_FACTORY (user_data); WockyNode *received; const gchar *from, *received_id; GabbleIMChannel *channel; received = wocky_node_get_child_ns (wocky_stanza_get_top_node (message), "received", NS_RECEIPTS); g_return_val_if_fail (received != NULL, FALSE); received_id = wocky_node_get_attribute (received, "id"); if (received_id == NULL) { STANZA_DEBUG (message, "but *what* did you receive?!"); return TRUE; } from = wocky_stanza_get_from (message); channel = get_channel_for_incoming_message (self, from, FALSE); if (channel == NULL) { DEBUG ("no existing channel with '%s'; ignoring receipt", from); return TRUE; } gabble_im_channel_receive_receipt (channel, received_id); return TRUE; }
/* initial XMPP stream setup, up to sending features stanza */ static WockyStanza * feature_stanza (TestConnectorServer *self) { TestConnectorServerPrivate *priv = self->priv; XmppProblem problem = priv->problem.connector->xmpp; const gchar *name = NULL; WockyStanza *feat = NULL; WockyNode *node = NULL; DEBUG (""); if (problem & XMPP_PROBLEM_OTHER_HOST) return error_stanza ("host-unknown", "some sort of DNS error", TRUE); name = (problem & XMPP_PROBLEM_FEATURES) ? "badger" : "features"; feat = wocky_stanza_new (name, WOCKY_XMPP_NS_STREAM); node = wocky_stanza_get_top_node (feat); DEBUG ("constructing <%s...>... stanza", name); if (priv->problem.sasl != SERVER_PROBLEM_NO_SASL) { if (priv->sasl == NULL) priv->sasl = test_sasl_auth_server_new (NULL, priv->mech, priv->user, priv->pass, NULL, priv->problem.sasl, FALSE); test_sasl_auth_server_set_mechs (G_OBJECT (priv->sasl), feat); } if (problem & XMPP_PROBLEM_OLD_AUTH_FEATURE) wocky_node_add_child_ns (node, "auth", WOCKY_JABBER_NS_AUTH_FEATURE); if (!(problem & XMPP_PROBLEM_NO_TLS) && !priv->tls_started) wocky_node_add_child_ns (node, "starttls", WOCKY_XMPP_NS_TLS); return feat; }
/* resume control after the sasl auth server is done: */ static void after_auth (GObject *source, GAsyncResult *res, gpointer data) { GError *error = NULL; WockyStanza *feat = NULL; WockyNode *node = NULL; TestSaslAuthServer *tsas = TEST_SASL_AUTH_SERVER (source); TestConnectorServer *tcs = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = tcs->priv; WockyXmppConnection *conn = priv->conn; DEBUG ("Auth finished: %d", priv->outstanding); if (!test_sasl_auth_server_auth_finish (tsas, res, &error)) { g_object_unref (priv->sasl); priv->sasl = NULL; if (server_dec_outstanding (tcs)) return; server_enc_outstanding (tcs); wocky_xmpp_connection_send_close_async (conn, priv->cancellable, xmpp_close, data); return; } priv->used_mech = g_strdup (test_sasl_auth_server_get_selected_mech (priv->sasl)); g_object_unref (priv->sasl); priv->sasl = NULL; if (server_dec_outstanding (tcs)) return; feat = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_FEATURES, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, NULL); node = wocky_stanza_get_top_node (feat); if (!(priv->problem.connector->xmpp & XMPP_PROBLEM_NO_SESSION)) wocky_node_add_child_ns (node, "session", WOCKY_XMPP_NS_SESSION); if (!(priv->problem.connector->xmpp & XMPP_PROBLEM_CANNOT_BIND)) wocky_node_add_child_ns (node, "bind", WOCKY_XMPP_NS_BIND); priv->state = SERVER_STATE_FEATURES_SENT; server_enc_outstanding (tcs); wocky_xmpp_connection_send_stanza_async (conn, feat, priv->cancellable, xmpp_init, data); g_object_unref (feat); }
/* * gabble_bytestream_multiple_accept * * Implements gabble_bytestream_iface_accept on GabbleBytestreamIface */ static void gabble_bytestream_multiple_accept (GabbleBytestreamIface *iface, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (iface); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); WockyStanza *msg; WockyNode *si; GList *all_methods; gchar *current_method; /* We cannot just call the accept method of the active bytestream because * the result stanza is different if we are using si-multiple */ if (priv->state != GABBLE_BYTESTREAM_STATE_LOCAL_PENDING) { /* The stream was previoulsy or automatically accepted */ return; } g_return_if_fail (priv->active_bytestream != NULL); all_methods = g_list_copy (priv->fallback_stream_methods); g_object_get (priv->active_bytestream, "protocol", ¤t_method, NULL); all_methods = g_list_prepend (all_methods, current_method); msg = gabble_bytestream_factory_make_multi_accept_iq (priv->peer_jid, priv->stream_init_id, all_methods); g_free (current_method); g_list_free (all_methods); si = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si != NULL); if (func != NULL) { /* let the caller add his profile specific data */ func (si, user_data); } if (_gabble_connection_send (priv->conn, msg, NULL)) { DEBUG ("stream %s with %s is now accepted", priv->stream_id, priv->peer_jid); g_object_set (priv->active_bytestream, "state", GABBLE_BYTESTREAM_STATE_ACCEPTED, NULL); } g_object_unref (msg); }
static gboolean im_factory_own_message_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleImFactory *self = GABBLE_IM_FACTORY (user_data); WockyNode *own_message, *body; const gchar *to; gboolean sent_locally; GabbleIMChannel *chan; /* Our stanza filter should guarantee that these are present. */ own_message = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "own-message"); g_return_val_if_fail (own_message != NULL, FALSE); body = wocky_node_get_child (own_message, "body"); g_return_val_if_fail (body != NULL, FALSE); to = wocky_node_get_attribute (own_message, "to"); if (to == NULL) { DEBUG ("own-message missing to='' attribute; ignoring"); return FALSE; } /* If self='true', the message was sent by the local user on this machine, * rather than by the local user on some other machine. We don't really have * a good way to show this in Messages. Also we don't get told the id='' of * the original message, which is annoying. */ sent_locally = !tp_strdiff ("true", wocky_node_get_attribute (own_message, "self")); DEBUG ("this report is for a message to '%s', sent %s", to, sent_locally ? "locally" : "remotely"); /* Don't create a channel for the sole purpose of reporting an own-message. * This is consistent with not creating a channel to report send errors * (given that both are delivery reports). */ chan = get_channel_for_incoming_message (self, to, FALSE); if (chan != NULL) _gabble_im_channel_report_delivery (chan, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, 0, NULL, body->content, GABBLE_TEXT_CHANNEL_SEND_NO_ERROR, TP_DELIVERY_STATUS_ACCEPTED); else DEBUG ("no channel for '%s'; not spawning one just for the delivery report", to); wocky_porter_acknowledge_iq (porter, stanza, NULL); return TRUE; }
GibberFileTransfer * gibber_file_transfer_new_from_stanza (WockyStanza *stanza, WockyPorter *porter, WockyContact *contact, GError **error) { const gchar *from; from = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "from"); return gibber_file_transfer_new_from_stanza_with_from (stanza, porter, contact, from, error); }
static gboolean received_stanza_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GibberFileTransfer *self = user_data; const gchar *id; id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); if (id != NULL && strcmp (id, self->id) == 0) { GIBBER_FILE_TRANSFER_GET_CLASS (self)->received_stanza (self, stanza); return TRUE; } return FALSE; }
/* error stanza */ static WockyStanza * error_stanza (const gchar *cond, const gchar *msg, gboolean extended) { WockyStanza *error = wocky_stanza_new ("error", WOCKY_XMPP_NS_STREAM); WockyNode *node = wocky_stanza_get_top_node (error); wocky_node_add_child_ns (node, cond, WOCKY_XMPP_NS_STREAMS); if ((msg != NULL) && (*msg != '\0')) wocky_node_add_child_with_content_ns (node, "text", msg, WOCKY_XMPP_NS_STREAMS); if (extended) wocky_node_add_child_with_content_ns (node, "something", "blah", "urn:ietf:a:namespace:I:made:up"); return error; }
static void iq_set_bind_XMPP_BIND (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; BindProblem problems = priv->problem.connector->bind; BindProblem bp = BIND_PROBLEM_NONE; DEBUG(""); if ((bp = problems & BIND_PROBLEM_INVALID) || (bp = problems & BIND_PROBLEM_DENIED) || (bp = problems & BIND_PROBLEM_CONFLICT) || (bp = problems & BIND_PROBLEM_REJECTED)) { const gchar *error = NULL; const gchar *etype = NULL; switch (bp) { case BIND_PROBLEM_INVALID: error = "bad-request"; etype = "modify"; break; case BIND_PROBLEM_DENIED: error = "not-allowed"; etype = "cancel"; break; case BIND_PROBLEM_CONFLICT: error = "conflict"; etype = "cancel"; break; default: error = "badger-badger-badger-mushroom"; etype = "moomins"; } iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', '(', "error", '@', "type", etype, '(', error, ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (problems & BIND_PROBLEM_FAILED) { /* deliberately nonsensical response */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else if (problems & BIND_PROBLEM_NONSENSE) { /* deliberately nonsensical response */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else if (problems & BIND_PROBLEM_CLASH) { iq = error_stanza ("conflict", NULL, FALSE); } else { WockyNode *ciq = wocky_stanza_get_top_node (xml); WockyNode *bind = wocky_node_get_child_ns (ciq, "bind", WOCKY_XMPP_NS_BIND); WockyNode *res = wocky_node_get_child (bind, "resource"); const gchar *uniq = NULL; gchar *jid = NULL; if (res != NULL) uniq = res->content; if (uniq == NULL) uniq = "a-made-up-resource"; if (problems & BIND_PROBLEM_NO_JID) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else { jid = g_strdup_printf ("[email protected]/%s", uniq); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, '(', "jid", '$', jid, ')', ')', NULL); g_free (jid); } } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, iq_sent, self); g_object_unref (xml); g_object_unref (iq); }
static void iq_set_query_JABBER_AUTH (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); WockyNode *qry = wocky_node_get_child (env, "query"); JabberProblem problems = priv->problem.connector->jabber; JabberProblem jp = JABBER_PROBLEM_NONE; WockyNode *username = wocky_node_get_child (qry, "username"); WockyNode *password = wocky_node_get_child (qry, "password"); WockyNode *resource = wocky_node_get_child (qry, "resource"); WockyNode *sha1hash = wocky_node_get_child (qry, "digest"); const gchar *id = wocky_node_get_attribute (env, "id"); DEBUG (""); if (username == NULL || resource == NULL) problems |= JABBER_PROBLEM_AUTH_PARTIAL; else if (password != NULL) { if (wocky_strdiff (priv->user, username->content) || wocky_strdiff (priv->pass, password->content)) problems |= JABBER_PROBLEM_AUTH_REJECT; } else if (sha1hash != NULL) { gchar *hsrc = g_strconcat (INITIAL_STREAM_ID, priv->pass, NULL); gchar *sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, hsrc, -1); DEBUG ("checksum: %s vs %s", sha1, sha1hash->content); if (wocky_strdiff (priv->user, username->content) || wocky_strdiff (sha1, sha1hash->content)) problems |= JABBER_PROBLEM_AUTH_REJECT; g_free (hsrc); g_free (sha1); } else problems |= JABBER_PROBLEM_AUTH_PARTIAL; if ((jp = problems & JABBER_PROBLEM_AUTH_REJECT) || (jp = problems & JABBER_PROBLEM_AUTH_BIND) || (jp = problems & JABBER_PROBLEM_AUTH_PARTIAL) || (jp = problems & JABBER_PROBLEM_AUTH_FAILED)) { const gchar *error = NULL; const gchar *etype = NULL; const gchar *ecode = NULL; switch (jp) { case JABBER_PROBLEM_AUTH_REJECT: error = "not-authorized"; etype = "auth"; ecode = "401"; break; case JABBER_PROBLEM_AUTH_BIND: error = "conflict"; etype = "cancel"; ecode = "409"; break; case JABBER_PROBLEM_AUTH_PARTIAL: error = "not-acceptable"; etype = "modify"; ecode = "406"; break; default: error = "bad-request"; etype = "modify"; ecode = "500"; break; } DEBUG ("error: %s/%s", error, etype); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", etype, '@', "code", ecode, '(', error, ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (problems & JABBER_PROBLEM_AUTH_STRANGE) { DEBUG ("auth WEIRD"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '@', "id", id, '(', "surstromming", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else if (problems & JABBER_PROBLEM_AUTH_NONSENSE) { DEBUG ("auth NONSENSE"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '@', "id", id, '(', "surstromming", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else { DEBUG ("auth OK"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, NULL); } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, iq_sent, self); g_object_unref (iq); g_object_unref (xml); }
static void iq_get_query_JABBER_AUTH (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); const gchar *id = wocky_node_get_attribute (env, "id"); WockyNode *query = wocky_node_get_child (env, "query"); WockyNode *user = (query != NULL) ? wocky_node_get_child (query, "username") : NULL; const gchar *name = (user != NULL) ? user->content : NULL; DEBUG (""); if (priv->problem.connector->jabber & JABBER_PROBLEM_AUTH_NIH) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "cancel", '(', "service-unavailable", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (name == NULL || *name == '\0') { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "modify", '(', "not-acceptable", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', "You must include the username in the initial IQ get to work " "around a bug in jabberd 1.4. See " "https://bugs.freedesktop.org/show_bug.cgi?id=24013", ')', ')', NULL); } else if (priv->mech != NULL) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_JABBER_NS_AUTH, '(', "username", ')', '(', priv->mech, ')', '(', "resource", ')', ')', NULL); } else { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_JABBER_NS_AUTH, '(', "username", ')', '(', "password", ')', '(', "resource", ')', '(', "digest", ')', ')', NULL); } DEBUG ("responding to iq get"); server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, iq_sent, self); DEBUG ("sent iq get response"); g_object_unref (xml); g_object_unref (iq); }
static void iq_get_query_XEP77_REGISTER (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); WockyNode *query = NULL; const gchar *id = wocky_node_get_attribute (env, "id"); DEBUG (""); if (priv->problem.connector->xep77 & XEP77_PROBLEM_NOT_AVAILABLE) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "cancel", '(', "service-unavailable", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_QUERY_NONSENSE) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '@', "id", id, '(', "plankton", ':', WOCKY_XEP77_NS_REGISTER, ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_QUERY_ALREADY) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '(', "registered", ')', '(', "username", '$', "foo", ')', '(', "password", '$', "bar", ')', ')', NULL); } else { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '*', &query, ')', NULL); if (!(priv->problem.connector->xep77 & XEP77_PROBLEM_NO_ARGS)) { wocky_node_add_child (query, "username"); wocky_node_add_child (query, "password"); if (priv->problem.connector->xep77 & XEP77_PROBLEM_EMAIL_ARG) wocky_node_add_child (query, "email"); if (priv->problem.connector->xep77 & XEP77_PROBLEM_STRANGE_ARG) wocky_node_add_child (query, "wildebeest"); } } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, NULL, iq_sent, self); g_object_unref (xml); g_object_unref (iq); }
static void xmpp_init (GObject *source, GAsyncResult *result, gpointer data) { TestConnectorServer *self; TestConnectorServerPrivate *priv; WockyStanza *xml; WockyXmppConnection *conn; self = TEST_CONNECTOR_SERVER (data); priv = self->priv; conn = priv->conn; DEBUG ("test_connector_server:xmpp_init %d", priv->state); DEBUG ("connection: %p", conn); switch (priv->state) { /* wait for <stream:stream… from the client */ case SERVER_STATE_START: DEBUG ("SERVER_STATE_START"); priv->state = SERVER_STATE_CLIENT_OPENED; server_enc_outstanding (self); if (priv->problem.connector->death & SERVER_DEATH_SERVER_START) { wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else { wocky_xmpp_connection_recv_open_async (conn, priv->cancellable, xmpp_init, self); } break; /* send our own <stream:stream… */ case SERVER_STATE_CLIENT_OPENED: DEBUG ("SERVER_STATE_CLIENT_OPENED"); priv->state = SERVER_STATE_SERVER_OPENED; wocky_xmpp_connection_recv_open_finish (conn, result, NULL, NULL, NULL, NULL, NULL, NULL); if (server_dec_outstanding (self)) return; server_enc_outstanding (self); if (priv->problem.connector->death & SERVER_DEATH_CLIENT_OPEN) { wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else { wocky_xmpp_connection_send_open_async (conn, NULL, "testserver", priv->version, NULL, INITIAL_STREAM_ID, priv->cancellable, xmpp_init, self); } break; /* send our feature set */ case SERVER_STATE_SERVER_OPENED: DEBUG ("SERVER_STATE_SERVER_OPENED"); priv->state = SERVER_STATE_FEATURES_SENT; wocky_xmpp_connection_send_open_finish (conn, result, NULL); if (server_dec_outstanding (self)) return; if (priv->problem.connector->death & SERVER_DEATH_SERVER_OPEN) { server_enc_outstanding (self); wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else if (priv->problem.connector->xmpp & XMPP_PROBLEM_OLD_SERVER) { DEBUG ("diverting to old-jabber-auth"); server_enc_outstanding (self); wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, xmpp_handler, self); } else if (priv->problem.connector->xmpp & XMPP_PROBLEM_SEE_OTHER_HOST) { WockyStanza *stanza; WockyNode *node; gchar *host_and_port; host_and_port = g_strdup_printf ("%s:%u", self->priv->other_host, self->priv->other_port); DEBUG ("Redirect to another host: %s", host_and_port); stanza = wocky_stanza_new ("error", WOCKY_XMPP_NS_STREAM); node = wocky_stanza_get_top_node (stanza); wocky_node_add_child_with_content_ns (node, "see-other-host", host_and_port, WOCKY_XMPP_NS_STREAMS); server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (self->priv->conn, stanza, self->priv->cancellable, see_other_host_cb, self); g_object_unref (stanza); } else { xml = feature_stanza (self); server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, xml, priv->cancellable, xmpp_init, self); g_object_unref (xml); } break; /* ok, we're done with initial stream setup */ case SERVER_STATE_FEATURES_SENT: DEBUG ("SERVER_STATE_FEATURES_SENT"); wocky_xmpp_connection_send_stanza_finish (conn, result, NULL); if (server_dec_outstanding (self)) return; server_enc_outstanding (self); if (priv->problem.connector->death & SERVER_DEATH_FEATURES) { wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else { wocky_xmpp_connection_recv_stanza_async (conn, priv->cancellable, xmpp_handler, self); } break; default: DEBUG ("Unknown Server state. Broken code flow."); } }
static void xmpp_handler (GObject *source, GAsyncResult *result, gpointer user_data) { TestConnectorServer *self; TestConnectorServerPrivate *priv; WockyStanza *xml = NULL; WockyXmppConnection *conn = NULL; const gchar *ns = NULL; const gchar *name = NULL; gboolean handled = FALSE; GError *error = NULL; WockyStanzaType type = WOCKY_STANZA_TYPE_NONE; WockyStanzaSubType subtype = WOCKY_STANZA_SUB_TYPE_NONE; int i; DEBUG (""); self = TEST_CONNECTOR_SERVER (user_data); priv = self->priv; conn = priv->conn; xml = wocky_xmpp_connection_recv_stanza_finish (conn, result, &error); /* A real XMPP server would need to do some error handling here, but if * we got this far, we can just exit: The client (ie the test) will * report any error that actually needs reporting - we don't need to */ if (error != NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); server_dec_outstanding (self); return; } g_assert_not_reached (); } if (server_dec_outstanding (self)) return; ns = wocky_node_get_ns (wocky_stanza_get_top_node (xml)); name = wocky_stanza_get_top_node (xml)->name; wocky_stanza_get_type_info (xml, &type, &subtype); /* if we find a handler, the handler is responsible for listening for the next stanza and setting up the next callback in the chain: */ if (type == WOCKY_STANZA_TYPE_IQ) for (i = 0; iq_handlers[i].payload != NULL; i++) { iq_handler *iq = &iq_handlers[i]; WockyNode *payload = wocky_node_get_child_ns (wocky_stanza_get_top_node (xml), iq->payload, iq->ns); /* namespace, stanza subtype and payload tag name must match: */ if ((payload == NULL) || (subtype != iq->subtype)) continue; DEBUG ("test_connector_server:invoking iq handler %s", iq->payload); (iq->func) (self, xml); handled = TRUE; break; } else for (i = 0; handlers[i].ns != NULL; i++) { if (!strcmp (ns, handlers[i].ns) && !strcmp (name, handlers[i].name)) { DEBUG ("test_connector_server:invoking handler %s.%s", ns, name); (handlers[i].func) (self, xml); handled = TRUE; break; } } /* no handler found: just complain and sit waiting for the next stanza */ if (!handled) { DEBUG ("<%s xmlns=\"%s\"… not handled", name, ns); server_enc_outstanding (self); wocky_xmpp_connection_recv_stanza_async (conn, priv->cancellable, xmpp_handler, self); g_object_unref (xml); } }
static gboolean update_location_from_msg (GabbleConnection *conn, TpHandle contact, LmMessage *msg) { LmMessageNode *node; GHashTable *location = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_free, (GDestroyNotify) tp_g_value_slice_free); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); const gchar *from = tp_handle_inspect (contact_repo, contact); NodeIter i; const gchar *lang; node = lm_message_node_find_child (wocky_stanza_get_top_node (msg), "geoloc"); if (node == NULL) return FALSE; DEBUG ("LocationsUpdate for %s:", from); lang = lm_message_node_get_attribute (node, "xml:lang"); if (lang != NULL) { g_hash_table_insert (location, g_strdup ("language"), tp_g_value_slice_new_string (lang)); } build_mapping_tables (); for (i = node_iter (node); i; i = node_iter_next (i)) { LmMessageNode *subloc_node = node_iter_data (i); GValue *value = NULL; gchar *xmpp_name; const gchar *str; LocationMapping *mapping; xmpp_name = subloc_node->name; str = lm_message_node_get_value (subloc_node); if (str == NULL) continue; mapping = g_hash_table_lookup (xmpp_to_tp, xmpp_name); if (mapping == NULL) { DEBUG ("Unknown location attribute: %s\n", xmpp_name); continue; } if (mapping->type == G_TYPE_DOUBLE) { gdouble double_value; gchar *end; double_value = g_ascii_strtod (str, &end); if (end == str) continue; value = tp_g_value_slice_new_double (double_value); DEBUG ("\t - %s: %f", xmpp_name, double_value); } else if (strcmp (xmpp_name, "timestamp") == 0) { GTimeVal timeval; if (g_time_val_from_iso8601 (str, &timeval)) { value = tp_g_value_slice_new_int64 (timeval.tv_sec); DEBUG ("\t - %s: %s", xmpp_name, str); } else { DEBUG ("\t - %s: %s: unknown date format", xmpp_name, str); continue; } } else if (mapping->type == G_TYPE_STRING) { value = tp_g_value_slice_new_string (str); DEBUG ("\t - %s: %s", xmpp_name, str); } else { g_assert_not_reached (); } g_hash_table_insert (location, g_strdup (mapping->tp_name), value); } tp_svc_connection_interface_location_emit_location_updated (conn, contact, location); gabble_presence_cache_update_location (conn->presence_cache, contact, location); return TRUE; }
static void got_jingle_info_stanza ( GabbleJingleInfo *self, WockyStanza *stanza) { WockyNode *node, *query_node; query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "query", NS_GOOGLE_JINGLE_INFO); if (query_node == NULL) return; if (self->priv->get_stun_from_jingle) node = wocky_node_get_child (query_node, "stun"); else node = NULL; if (node != NULL) { node = wocky_node_get_child (node, "server"); if (node != NULL) { const gchar *server; const gchar *port_attr; guint port = 0; server = wocky_node_get_attribute (node, "host"); port_attr = wocky_node_get_attribute (node, "udp"); if (port_attr != NULL) port = atoi (port_attr); if (server != NULL && port_attr != NULL && port > 0 && port <= G_MAXUINT16) { DEBUG ("jingle info: got stun server %s, port %u", server, port); gabble_jingle_info_take_stun_server (self, g_strdup (server), port, FALSE); } } } #ifdef ENABLE_GOOGLE_RELAY node = wocky_node_get_child (query_node, "relay"); if (node != NULL) { WockyNode *subnode = wocky_node_get_child (node, "token"); if (subnode != NULL) { const gchar *token = subnode->content; if (token != NULL) { DEBUG ("jingle info: got Google relay token %s", token); g_free (self->priv->relay_token); self->priv->relay_token = g_strdup (token); } } subnode = wocky_node_get_child (node, "server"); if (subnode != NULL) { const gchar *server; const gchar *port; server = wocky_node_get_attribute (subnode, "host"); if (server != NULL) { DEBUG ("jingle info: got relay server %s", server); g_free (self->priv->relay_server); self->priv->relay_server = g_strdup (server); } if (test_mode) { /* this is not part of the real protocol, but we can't listen on * port 80 in an unprivileged regression test */ port = wocky_node_get_attribute (subnode, "gabble-test-http-port"); if (port != NULL) { DEBUG ("jingle info: diverting 'Google' HTTP requests to " "port %s", port); self->priv->relay_http_port = atoi (port); } } /* FIXME: these are not really actually used anywhere at * the moment, because we get the same info when creating * relay session. */ port = wocky_node_get_attribute (subnode, "udp"); if (port != NULL) { DEBUG ("jingle info: got relay udp port %s", port); self->priv->relay_udp = atoi (port); } port = wocky_node_get_attribute (subnode, "tcp"); if (port != NULL) { DEBUG ("jingle info: got relay tcp port %s", port); self->priv->relay_tcp = atoi (port); } port = wocky_node_get_attribute (subnode, "tcpssl"); if (port != NULL) { DEBUG ("jingle info: got relay tcpssl port %s", port); self->priv->relay_ssltcp = atoi (port); } } } #endif /* ENABLE_GOOGLE_RELAY */ }
/* ************************************************************************* */ static void iq_set_query_XEP77_REGISTER (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); WockyNode *query = wocky_node_get_child (env, "query"); const gchar *id = wocky_node_get_attribute (env, "id"); gpointer cb = iq_sent; DEBUG (""); if (priv->problem.connector->xep77 & XEP77_PROBLEM_ALREADY) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '(', "registered", ')', '(', "username", '$', "foo", ')', '(', "password", '$', "bar", ')', ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_FAIL_CONFLICT) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "cancel", '(', "conflict", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_FAIL_REJECTED) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "modify", '(', "not-acceptable", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else { if (wocky_node_get_child (query, "remove") == NULL) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, NULL); } else { XEP77Problem problem = priv->problem.connector->xep77; XEP77Problem p = XEP77_PROBLEM_NONE; DEBUG ("handling CANCEL"); if ((p = problem & XEP77_PROBLEM_CANCEL_REJECTED) || (p = problem & XEP77_PROBLEM_CANCEL_DISABLED) || (p = problem & XEP77_PROBLEM_CANCEL_FAILED)) { const gchar *error = NULL; const gchar *etype = NULL; const gchar *ecode = NULL; switch (p) { case XEP77_PROBLEM_CANCEL_REJECTED: error = "bad-request"; etype = "modify"; ecode = "400"; break; case XEP77_PROBLEM_CANCEL_DISABLED: error = "not-allowed"; etype = "cancel"; ecode = "405"; break; default: error = "forbidden"; etype = "cancel"; ecode = "401"; } DEBUG ("error: %s/%s", error, etype); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", etype, '@', "code", ecode, '(', error, ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else { if (priv->problem.connector->xep77 & XEP77_PROBLEM_CANCEL_STREAM) { iq = error_stanza ("not-authorized", NULL, FALSE); cb = finished; } else { cb = iq_sent_unregistered; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, NULL); } } } } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, cb, self); g_object_unref (xml); g_object_unref (iq); }