Commit 657202df authored by Jussi Kukkonen's avatar Jussi Kukkonen

libconic-enable hostip-backend

hostip position backend now works with libconic if it is present:
It queries the position from hostip.info whenever there is a new
network connection and saves it. Saved data is considered valid
as long as the connection is alive. This means that
   a) current_position method has no network latency
   b) position_changed events are fired
parent 55f65a6f
......@@ -18,8 +18,8 @@ $(service_DATA): $(service_in_files) Makefile
done
AM_CPPFLAGS = $(YAHOO_CFLAGS) -I$(top_srcdir)
AM_LDFLAGS = $(YAHOO_LIBS) ../../geoclue/libgeoclue.la
AM_CPPFLAGS = $(YAHOO_CFLAGS) $(CONIC_CFLAGS) -I$(top_srcdir)
AM_LDFLAGS = $(YAHOO_LIBS) $(CONIC_LIBS) ../../geoclue/libgeoclue.la
EXTRA_DIST = \
geoclue_position_server_hostip.h \
......
......@@ -17,10 +17,15 @@
* Boston, MA 02111-1307, USA.
*/
#include <geoclue_position_server_hostip.h>
#include "geoclue_position_server_hostip.h"
#include <geoclue_position_server_glue.h>
#include <geoclue_position_signal_marshal.h>
#include <dbus/dbus-glib-bindings.h>
#include <dbus/dbus.h>
#ifdef HAVE_LIBCONIC
#include <conicconnectionevent.h>
#endif
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
......@@ -31,104 +36,128 @@
#include <string.h>
#include "../geoclue_position_error.h"
#define HOSTIP_API "http://api.hostip.info/"
static void init_net_connection_monitoring (GeocluePosition* obj);
static void close_net_connection_monitoring (GeocluePosition* obj);
static gboolean get_hostip_xml (gchar **xml);
static gboolean query_position (gdouble* OUT_latitude, gdouble* OUT_longitude, GError **error);
static void set_current_position (GeocluePosition *obj, gdouble lat, gdouble lon);
G_DEFINE_TYPE(GeocluePosition, geoclue_position, G_TYPE_OBJECT)
/*
* Define the following for both libconic-enabled and other platforms:
* - OBSERVING_NET_CONNECTIONS
* - init_net_connection_monitoring ()
* - close_net_connection_monitoring ()
*/
#ifdef HAVE_LIBCONIC
#define OBSERVING_NET_CONNECTIONS TRUE
/* callback for libconic connection events */
static void net_connection_event_cb (ConIcConnection *connection,
ConIcConnectionEvent *event,
gpointer user_data)
{
gdouble lat, lon;
enum {
CURRENT_POSITION_CHANGED,
LAST_SIGNAL
};
g_return_if_fail (IS_GEOCLUE_POSITION (user_data));
/* NOTE: this macro is broken in libconic 0.12
g_return_if_fail (CON_IC_IS_CONNECTION_EVENT (event));
*/
static guint signals[LAST_SIGNAL];
//Default handler
void geoclue_position_current_position_changed(GeocluePosition* obj, gdouble lat, gdouble lon)
{
g_print("Current Position Changed\n");
GeocluePosition* obj = (GeocluePosition*)user_data;
switch (con_ic_connection_event_get_status (event)) {
case CON_IC_STATUS_CONNECTED:
/* TODO: maybe should save the name of the AP and only do this if it's changed */
/* try to get a position */
if (query_position (&lat, &lon, NULL)) {
set_current_position (obj, lat, lon);
}
break;
case CON_IC_STATUS_DISCONNECTED:
obj->is_current_valid = FALSE;
break;
default:
break;
}
}
static void
geoclue_position_init (GeocluePosition *obj)
static void init_net_connection_monitoring (GeocluePosition* obj)
{
GError *error = NULL;
DBusGProxy *driver_proxy;
GeocluePositionClass *klass = GEOCLUE_POSITION_GET_CLASS(obj);
guint request_ret;
dbus_g_connection_register_g_object (klass->connection,
GEOCLUE_POSITION_DBUS_PATH ,
G_OBJECT (obj));
g_return_if_fail (IS_GEOCLUE_POSITION (obj));
/* init dbus connection -- this needs to be done,
connection signals do not work otherwise */
obj->dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
dbus_connection_setup_with_g_main(obj->dbus_connection, NULL);
/* TODO: dbus error handling */
/* setup the connection signal callback */
obj->net_connection = con_ic_connection_new ();
/*
GValue val = {0,};
g_value_init (&val, G_TYPE_BOOLEAN);
g_value_set_boolean (&val, TRUE);
g_object_set_property (G_OBJECT (obj->net_connection),
"automatic-connection-events", &val);
*/
g_object_set (obj->net_connection, "automatic-connection-events",
TRUE, NULL);
g_signal_connect (obj->net_connection, "connection-event",
G_CALLBACK(net_connection_event_cb), obj);
g_debug ("Internet connection event monitoring started");
}
driver_proxy = dbus_g_proxy_new_for_name (klass->connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
static void close_net_connection_monitoring (GeocluePosition* obj)
{
g_return_if_fail (IS_GEOCLUE_POSITION (obj));
g_object_unref (obj->net_connection);
dbus_connection_disconnect (obj->dbus_connection);
dbus_connection_unref (obj->dbus_connection);
}
#else
if(!org_freedesktop_DBus_request_name (driver_proxy,
GEOCLUE_POSITION_DBUS_SERVICE,
0, &request_ret,
&error))
{
g_printerr("Unable to register geoclue service: %s", error->message);
g_error_free (error);
}
}
#define OBSERVING_NET_CONNECTIONS FALSE
/* empty functions for non-libconic platforms */
static void init_net_connection_monitoring (GeocluePosition* obj) {g_debug("empty init_net_connection_monitoring");}
static void close_net_connection_monitoring (GeocluePosition* obj) {}
#endif
static void
geoclue_position_class_init (GeocluePositionClass *klass)
{
GError *error = NULL;
klass->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
signals[CURRENT_POSITION_CHANGED] =
g_signal_new ("current_position_changed",
TYPE_GEOCLUE_POSITION,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GeocluePositionClass, current_position_changed),
NULL,
NULL,
_geoclue_position_VOID__DOUBLE_DOUBLE,
G_TYPE_NONE, 2 ,G_TYPE_DOUBLE, G_TYPE_DOUBLE);
klass->current_position_changed = geoclue_position_current_position_changed;
if (klass->connection == NULL)
{
g_printerr("Unable to connect to dbus: %s", error->message);
g_error_free (error);
return;
}
#define HOSTIP_API "http://api.hostip.info/"
dbus_g_object_type_install_info (TYPE_GEOCLUE_POSITION, &dbus_glib_geoclue_position_object_info);
}
G_DEFINE_TYPE(GeocluePosition, geoclue_position, G_TYPE_OBJECT)
gboolean geoclue_position_version (GeocluePosition *obj, gint* OUT_major, gint* OUT_minor, gint* OUT_micro, GError **error)
{
*OUT_major = 1;
*OUT_minor = 0;
*OUT_micro = 0;
return TRUE;
}
enum {
CURRENT_POSITION_CHANGED,
LAST_SIGNAL
};
gboolean geoclue_position_service_provider(GeocluePosition *obj, char** name, GError **error)
{
*name = "www.hostip.info";
return TRUE;
static guint signals[LAST_SIGNAL];
//Default handler
void geoclue_position_current_position_changed(GeocluePosition* obj, gdouble lat, gdouble lon)
{
g_print("Current Position Changed\n");
}
/* some static helper functions */
static gboolean get_hostip_xml (gchar **xml)
{
SoupSession *session;
......@@ -166,8 +195,12 @@ static gboolean get_hostip_xml (gchar **xml)
return TRUE;
}
gboolean geoclue_position_current_position(GeocluePosition *obj, gdouble* OUT_latitude, gdouble* OUT_longitude, GError **error )
static gboolean query_position (gdouble* OUT_latitude, gdouble* OUT_longitude, GError **error)
{
gchar *xml = NULL;
xmlDocPtr doc;
xmlXPathContextPtr xpathCtx;
......@@ -196,7 +229,6 @@ gboolean geoclue_position_current_position(GeocluePosition *obj, gdouble* OUT_la
return FALSE;
}
gboolean success = FALSE;
xpathCtx = xmlXPathNewContext(doc);
if (!xpathCtx) {
g_set_error (error,
......@@ -233,6 +265,117 @@ gboolean geoclue_position_current_position(GeocluePosition *obj, gdouble* OUT_la
g_free(xml);
return TRUE;
}
static void set_current_position (GeocluePosition *obj, gdouble lat, gdouble lon)
{
if ((lat != obj->current_lat) || (lat != obj->current_lat)) {
obj->current_lat = lat;
obj->current_lon = lon;
geoclue_position_current_position_changed (obj, lat, lon);
}
/* if net connection is monitored, the validity of position can be guaranteed */
obj->is_current_valid = OBSERVING_NET_CONNECTIONS;
}
static void
geoclue_position_init (GeocluePosition *obj)
{
GError *error = NULL;
DBusGProxy *driver_proxy;
GeocluePositionClass *klass = GEOCLUE_POSITION_GET_CLASS(obj);
guint request_ret;
dbus_g_connection_register_g_object (klass->connection,
GEOCLUE_POSITION_DBUS_PATH ,
G_OBJECT (obj));
driver_proxy = dbus_g_proxy_new_for_name (klass->connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
if(!org_freedesktop_DBus_request_name (driver_proxy,
GEOCLUE_POSITION_DBUS_SERVICE,
0, &request_ret,
&error))
{
g_printerr("Unable to register geoclue service: %s", error->message);
g_error_free (error);
}
init_net_connection_monitoring (obj);
}
static void
geoclue_position_class_init (GeocluePositionClass *klass)
{
GError *error = NULL;
klass->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
signals[CURRENT_POSITION_CHANGED] =
g_signal_new ("current_position_changed",
TYPE_GEOCLUE_POSITION,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GeocluePositionClass, current_position_changed),
NULL,
NULL,
_geoclue_position_VOID__DOUBLE_DOUBLE,
G_TYPE_NONE, 2 ,G_TYPE_DOUBLE, G_TYPE_DOUBLE);
klass->current_position_changed = geoclue_position_current_position_changed;
if (klass->connection == NULL)
{
g_printerr("Unable to connect to dbus: %s", error->message);
g_error_free (error);
return;
}
dbus_g_object_type_install_info (TYPE_GEOCLUE_POSITION, &dbus_glib_geoclue_position_object_info);
}
gboolean geoclue_position_version (GeocluePosition *obj, gint* OUT_major, gint* OUT_minor, gint* OUT_micro, GError **error)
{
*OUT_major = 1;
*OUT_minor = 0;
*OUT_micro = 0;
return TRUE;
}
gboolean geoclue_position_service_provider(GeocluePosition *obj, char** name, GError **error)
{
*name = "www.hostip.info";
return TRUE;
}
gboolean geoclue_position_current_position (GeocluePosition *obj, gdouble* OUT_latitude, gdouble* OUT_longitude, GError **error)
{
if (obj->is_current_valid)
{
*OUT_latitude = obj->current_lat;
*OUT_longitude = obj->current_lon;
return TRUE;
}
else if (query_position (OUT_latitude, OUT_longitude, error)) {
set_current_position (obj, *OUT_latitude, *OUT_longitude);
return TRUE;
}
else
{
return FALSE;
}
}
gboolean geoclue_position_current_position_error(GeocluePosition *obj, gdouble* OUT_latitude_error, gdouble* OUT_longitude_error, GError **error )
......@@ -350,6 +493,7 @@ gboolean geoclue_position_service_available(GeocluePosition *obj, gboolean* OUT_
gboolean geoclue_position_shutdown(GeocluePosition *obj, GError** error)
{
close_net_connection_monitoring (obj);
g_main_loop_quit (obj->loop);
return TRUE;
}
......
......@@ -22,9 +22,18 @@
#define DBUS_API_SUBJECT_TO_CHANGE
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <glib.h>
#ifdef HAVE_LIBCONIC
#include <conicconnection.h>
#endif
#define GEOCLUE_POSITION_DBUS_SERVICE "org.foinse_project.geoclue.position.hostip"
#define GEOCLUE_POSITION_DBUS_PATH "/org/foinse_project/geoclue/position/hostip"
#define GEOCLUE_POSITION_DBUS_INTERFACE "org.foinse_project.geoclue.position"
......@@ -39,8 +48,15 @@ GType geoclue_position_get_type (void);
struct GeocluePosition
{
GObject parent;
GMainLoop* loop;
GMainLoop* loop;
gdouble current_lat;
gdouble current_lon;
gboolean is_current_valid;
#ifdef HAVE_LIBCONIC
ConIcConnection* net_connection;
DBusConnection* dbus_connection;
#endif
};
struct GeocluePositionClass
......
......@@ -64,10 +64,18 @@ if test "x$ac_cv_libgps" != xyes; then
AC_MSG_ERROR([Install gpsd Debian package or its source-code equivalent])
fi
dnl check for libgpsbt
dnl check for libgpsbt and libgpsmgr
AC_CHECK_LIB(gpsmgr, gpsmgr_is_gpsd_running)
AC_CHECK_LIB(gpsbt, gpsbt_start)
dnl check for libconic
PKG_CHECK_MODULES(CONIC, conic, [have_libconic=yes], [have_libconic=no])
AC_SUBST(CONIC_CFLAGS)
AC_SUBST(CONIC_LIBS)
if test "x$have_libconic" = "xyes"; then
AC_DEFINE(HAVE_LIBCONIC, 1, [define if libconic is installed])
fi
PKG_CHECK_MODULES(HTTPXML, libsoup-2.2 libxml-2.0)
AC_SUBST(HTTPXML_CFLAGS)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment