/* xmpp-geoloc.c - XMPP Geolocation support * * Copyright 2008 OpenMoko, Inc. * Authored by Daniel Willmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #define DIVERSITY_XMPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), DIVERSITY_TYPE_XMPP, DiversityXmppPrivate)) typedef struct _DiversityXmppPrivate DiversityXmppPrivate; struct _DiversityXmppPrivate { gchar *jid; gchar *username; gchar *password; gchar *resource; gchar *server; gint port; guint presence; gchar *statusmsg; LmConnection *connection; LmMessageHandler *msghandle; XmppDisco *disco; }; /* TODO: Make the following two functions part of a general pubsub * implementation*/ /* Returns the pubsub item if there is one in this message, otherwise NULL */ LmMessageNode *xmpp_pubsub_get_item(LmMessageNode *node, const gchar *pubsubnode) { LmMessageNode *result = NULL; if (node = lm_message_node_get_child(node, "event")) { if (!strcmp(lm_message_node_get_attribute(node, "xmlns"), "http://jabber.org/protocol/pubsub#event") && (node = lm_message_node_get_child(node, "items"))) { if (!strcmp(lm_message_node_get_attribute(node, "node"), pubsubnode)) { result = lm_message_node_get_child(node, "item"); } } } return result; } /* Generates a pubsub message */ LmMessage *xmpp_pubsub_publish_item(LmMessageNode *node, const char *pubsubnode) { LmMessageNode *tmpnode; LmMessage *msg = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET); tmpnode = lm_message_get_node(msg); tmpnode = lm_message_node_add_child(tmpnode, "pubsub", NULL); lm_message_node_set_attribute(tmpnode, "xmlns", "http://jabber.org/protocol/pubsub"); tmpnode = lm_message_node_add_child(tmpnode, "publish", NULL); lm_message_node_set_attribute(tmpnode, "node", pubsubnode); lm_message_node_ref(node); tmpnode->children = node; node->parent = tmpnode; return msg; } LmHandlerResult xmpp_geoloc_handle_msg (LmMessageHandler *handler, LmConnection *connection, LmMessage *message, DiversityXmpp *xmpp) { LmMessageNode *temp; gchar *from; LmMessageNode *node = lm_message_get_node(message); double lat = 0, lon = 0, alt = 0, err = 0; from = lm_message_node_get_attribute(node, "from"); if (!(node = xmpp_pubsub_get_item(node, "http://jabber.org/protocol/geoloc"))) return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; if (!(node = lm_message_node_get_child(node, "geoloc"))) return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; g_debug("Location of %s:", from); if (temp = lm_message_node_get_child(node, "lat")) { lat = atof(lm_message_node_get_value(temp)); g_debug("Lat: %f", lat); } if (temp = lm_message_node_get_child(node, "lon")) { lon = atof(lm_message_node_get_value(temp)); g_debug("Lon: %f", lon); } if (temp = lm_message_node_get_child(node, "alt")) { alt = atof(lm_message_node_get_value(temp)); g_debug("Alt: %f", alt); } if (temp = lm_message_node_get_child(node, "error")) { err = atof(lm_message_node_get_value(temp)); g_debug("Err: %f", err); } g_signal_emit_by_name(xmpp, "geoloc-message-received", from, lat, lon, alt, err); return LM_HANDLER_RESULT_REMOVE_MESSAGE; } void xmpp_geoloc_init(DiversityXmpp *xmpp) { DiversityXmppPrivate *priv = DIVERSITY_XMPP_GET_PRIVATE(xmpp); /* Add message handler for incoming location events */ LmMessageHandler *msghandle = lm_message_handler_new(xmpp_geoloc_handle_msg, xmpp, NULL); lm_connection_register_message_handler(priv->connection, msghandle, LM_MESSAGE_TYPE_MESSAGE, LM_HANDLER_PRIORITY_NORMAL); xmpp_disco_add_feature(priv->disco, "http://jabber.org/protocol/geoloc"); xmpp_disco_add_feature(priv->disco, "http://jabber.org/protocol/geoloc+notify"); } void xmpp_geoloc_publish_position(DiversityXmpp *xmpp, float lat, float lon, float alt, float err) { DiversityXmppPrivate *priv = DIVERSITY_XMPP_GET_PRIVATE(xmpp); LmMessage *msg; LmMessageNode *geoloc; gchar *value; geoloc = g_new0(LmMessageNode, 1); geoloc->name = g_strdup ("item"); geoloc->value = NULL; geoloc->raw_mode = FALSE; geoloc->attributes = NULL; geoloc->next = NULL; geoloc->prev = NULL; geoloc->parent = NULL; geoloc->children = NULL; // xmpp_pubsub_publish_item will ref this geoloc->ref_count = 0; msg = xmpp_pubsub_publish_item(geoloc, "http://jabber.org/protocol/geoloc"); geoloc = lm_message_node_add_child(geoloc, "geoloc", NULL); lm_message_node_set_attributes(geoloc, "xmlns", "http://jabber.org/protocol/geoloc", "xml:lang", "en", NULL); value = g_new0(char, 16); snprintf(value, 16, "%.10f", lat); lm_message_node_add_child(geoloc, "lat", value); g_free(value); value = g_new0(char, 16); snprintf(value, 16, "%.10f", lon); lm_message_node_add_child(geoloc, "lon", value); g_free(value); value = g_new0(char, 16); snprintf(value, 16, "%.10f", alt); lm_message_node_add_child(geoloc, "alt", value); g_free(value); value = g_new0(char, 16); snprintf(value, 16, "%.10f", err); lm_message_node_add_child(geoloc, "error", value); lm_connection_send(priv->connection, msg, NULL); lm_message_unref(msg); }