/* 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; }
/* * 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 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_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 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_item ( GabbleConnection *conn, TpHandle contact, WockyNode *item_node) { WockyNode *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); WockyNodeIter i; WockyNode *subloc_node; const gchar *lang; if (item_node == NULL) return FALSE; node = wocky_node_get_child_ns (item_node, "geoloc", NS_GEOLOC); if (node == NULL) return FALSE; DEBUG ("LocationsUpdate for %s:", from); lang = wocky_node_get_language (node); if (lang != NULL) { g_hash_table_insert (location, g_strdup ("language"), tp_g_value_slice_new_string (lang)); } build_mapping_tables (); wocky_node_iter_init (&i, node, NULL, NULL); while (wocky_node_iter_next (&i, &subloc_node)) { GValue *value = NULL; gchar *xmpp_name; const gchar *str; LocationMapping *mapping; xmpp_name = subloc_node->name; str = subloc_node->content; 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; }