diff options
author | Maciej S. Szmigiero <mail@maciej.szmigiero.name> | 2021-11-19 14:36:02 +0100 |
---|---|---|
committer | Maciej S. Szmigiero <mail@maciej.szmigiero.name> | 2022-08-07 17:12:20 +0200 |
commit | 0de88a82727ab2a3a156df63206453556d80d707 (patch) | |
tree | c62a6e1b163b3735debed810e62d62bf731a7f46 /src/gclue-mozilla.c | |
parent | 8b07a08ed5c611a0f7db9f41ca87a3711489797c (diff) | |
download | geoclue-0de88a82727ab2a3a156df63206453556d80d707.tar.gz |
Submit MLS requests with combined WiFi and 3GPP tower data
Currently, there is no combining of WiFi Access Points data and 3GPP tower
data to make a single, combined MLS geolocation request.
Instead, the code does two separate MLS requests if both of these sources
are available, each containing only either WiFi AP data or 3GPP tower data.
This results in two different location determinations.
If these two locations differ (which happens often) the Geoclue location
jumps between these two locations as WiFi and 3GPP location sources are
refreshed.
There is also a problem of reduced accuracy since with two separate
requests the MLS backend can't cross-correlate data between both.
Instead, one is supposed to send a MLS query containing all the collected
data at the same time, like the example at MLS API page shows.
The same goes for MLS location submissions.
Sending WiFi and 3GPP tower data combined makes Geoclue location
determination significantly more stable indeed when both of these sources
are active.
Diffstat (limited to 'src/gclue-mozilla.c')
-rw-r--r-- | src/gclue-mozilla.c | 199 |
1 files changed, 183 insertions, 16 deletions
diff --git a/src/gclue-mozilla.c b/src/gclue-mozilla.c index b0e5b29..fee637e 100644 --- a/src/gclue-mozilla.c +++ b/src/gclue-mozilla.c @@ -25,8 +25,10 @@ #include <string.h> #include <config.h> #include "gclue-mozilla.h" +#include "gclue-3g-tower.h" #include "gclue-config.h" #include "gclue-error.h" +#include "gclue-wifi.h" /** * SECTION:gclue-mozilla @@ -40,6 +42,22 @@ * its easy to switch to Google's API. **/ +struct _GClueMozillaPrivate +{ + GClueWifi *wifi; + + GClue3GTower tower; + gboolean tower_valid; + gboolean tower_submitted; + + gboolean bss_submitted; +}; + +G_DEFINE_TYPE_WITH_CODE (GClueMozilla, + gclue_mozilla, + G_TYPE_OBJECT, + G_ADD_PRIVATE (GClueMozilla)) + #define BSSID_LEN 6 #define BSSID_STR_LEN 17 #define MAX_SSID_LEN 32 @@ -137,12 +155,14 @@ error: } SoupMessage * -gclue_mozilla_create_query (GList *bss_list, /* As in Access Points */ - GClue3GTower *tower, +gclue_mozilla_create_query (GClueMozilla *mozilla, + gboolean skip_tower, + gboolean skip_bss, GError **error) { SoupMessage *ret = NULL; JsonBuilder *builder; + g_autoptr(GList) bss_list = NULL; JsonGenerator *generator; JsonNode *root_node; char *data; @@ -155,6 +175,9 @@ gclue_mozilla_create_query (GList *bss_list, /* As in Access Points */ builder = json_builder_new (); json_builder_begin_object (builder); + if (mozilla->priv->wifi && !skip_bss) { + bss_list = gclue_wifi_get_bss_list (mozilla->priv->wifi); + } /* We send pure geoip query using empty object if both bss_list and * tower are NULL. * @@ -172,9 +195,8 @@ gclue_mozilla_create_query (GList *bss_list, /* As in Access Points */ n_non_ignored_bsss++; } - if (tower != NULL && - operator_code_to_mcc_mnc (tower->opc, &mcc, &mnc)) { - + if (mozilla->priv->tower_valid && !skip_tower && + operator_code_to_mcc_mnc (mozilla->priv->tower.opc, &mcc, &mnc)) { json_builder_set_member_name (builder, "radioType"); json_builder_add_string_value (builder, "gsm"); @@ -184,14 +206,14 @@ gclue_mozilla_create_query (GList *bss_list, /* As in Access Points */ json_builder_begin_object (builder); json_builder_set_member_name (builder, "cellId"); - json_builder_add_int_value (builder, tower->cell_id); + json_builder_add_int_value (builder, mozilla->priv->tower.cell_id); json_builder_set_member_name (builder, "mobileCountryCode"); json_builder_add_int_value (builder, mcc); json_builder_set_member_name (builder, "mobileNetworkCode"); json_builder_add_int_value (builder, mnc); json_builder_set_member_name (builder, "locationAreaCode"); - json_builder_add_int_value (builder, tower->lac); - if (tower->tec == GCLUE_TOWER_TEC_4G) { + json_builder_add_int_value (builder, mozilla->priv->tower.lac); + if (mozilla->priv->tower.tec == GCLUE_TOWER_TEC_4G) { json_builder_set_member_name (builder, "radioType"); json_builder_add_string_value (builder, "lte"); } @@ -316,9 +338,8 @@ get_submit_config (const char **nick) } SoupMessage * -gclue_mozilla_create_submit_query (GClueLocation *location, - GList *bss_list, /* As in Access Points */ - GClue3GTower *tower, +gclue_mozilla_create_submit_query (GClueMozilla *mozilla, + GClueLocation *location, GError **error) { SoupMessage *ret = NULL; @@ -326,6 +347,7 @@ gclue_mozilla_create_submit_query (GClueLocation *location, JsonGenerator *generator; JsonNode *root_node; char *data, *timestr; + g_autoptr(GList) bss_list = NULL; const char *url, *nick; gsize data_len; GList *iter; @@ -333,6 +355,17 @@ gclue_mozilla_create_submit_query (GClueLocation *location, GDateTime *datetime; gint64 mcc, mnc; + if (mozilla->priv->bss_submitted && + (!mozilla->priv->tower_valid || + mozilla->priv->tower_submitted)) + { + g_debug ("Already created submit req for this data (bss submitted %d; tower: valid %d submitted %d)", + (int)mozilla->priv->bss_submitted, + (int)mozilla->priv->tower_valid, + (int)mozilla->priv->tower_submitted); + goto out; + } + url = get_submit_config (&nick); if (url == NULL) goto out; @@ -379,6 +412,9 @@ gclue_mozilla_create_submit_query (GClueLocation *location, json_builder_set_member_name (builder, "radioType"); json_builder_add_string_value (builder, "gsm"); + if (mozilla->priv->wifi) { + bss_list = gclue_wifi_get_bss_list (mozilla->priv->wifi); + } if (bss_list != NULL) { json_builder_set_member_name (builder, "wifi"); json_builder_begin_array (builder); @@ -410,9 +446,8 @@ gclue_mozilla_create_submit_query (GClueLocation *location, json_builder_end_array (builder); /* wifi */ } - if (tower != NULL && - operator_code_to_mcc_mnc (tower->opc, &mcc, &mnc)) { - + if (mozilla->priv->tower_valid && + operator_code_to_mcc_mnc (mozilla->priv->tower.opc, &mcc, &mnc)) { json_builder_set_member_name (builder, "cell"); json_builder_begin_array (builder); @@ -421,13 +456,13 @@ gclue_mozilla_create_submit_query (GClueLocation *location, json_builder_set_member_name (builder, "radio"); json_builder_add_string_value (builder, "gsm"); json_builder_set_member_name (builder, "cid"); - json_builder_add_int_value (builder, tower->cell_id); + json_builder_add_int_value (builder, mozilla->priv->tower.cell_id); json_builder_set_member_name (builder, "mcc"); json_builder_add_int_value (builder, mcc); json_builder_set_member_name (builder, "mnc"); json_builder_add_int_value (builder, mnc); json_builder_set_member_name (builder, "lac"); - json_builder_add_int_value (builder, tower->lac); + json_builder_add_int_value (builder, mozilla->priv->tower.lac); json_builder_end_object (builder); @@ -459,6 +494,9 @@ gclue_mozilla_create_submit_query (GClueLocation *location, data_len); g_debug ("Sending following request to '%s':\n%s", url, data); + mozilla->priv->bss_submitted = TRUE; + mozilla->priv->tower_submitted = TRUE; + out: return ret; } @@ -485,3 +523,132 @@ gclue_mozilla_should_ignore_bss (WPABSS *bss) return FALSE; } + +static void +gclue_mozilla_finalize (GObject *object) +{ + GClueMozilla *mozilla = GCLUE_MOZILLA (object); + + g_clear_weak_pointer (&mozilla->priv->wifi); + + G_OBJECT_CLASS (gclue_mozilla_parent_class)->finalize (object); +} + +static void +gclue_mozilla_init (GClueMozilla *mozilla) +{ + mozilla->priv = gclue_mozilla_get_instance_private (mozilla); + mozilla->priv->wifi = NULL; + mozilla->priv->tower_valid = FALSE; + mozilla->priv->bss_submitted = FALSE; +} + +static void +gclue_mozilla_class_init (GClueMozillaClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gclue_mozilla_finalize; +} + +GClueMozilla * +gclue_mozilla_get_singleton (void) +{ + static GClueMozilla *mozilla = NULL; + + if (!mozilla) { + mozilla = g_object_new (GCLUE_TYPE_MOZILLA, NULL); + g_object_add_weak_pointer (G_OBJECT (mozilla), (gpointer) &mozilla); + } else + g_object_ref (mozilla); + + return mozilla; +} + +void +gclue_mozilla_set_wifi (GClueMozilla *mozilla, + GClueWifi *wifi) +{ + g_return_if_fail (GCLUE_IS_MOZILLA (mozilla)); + + if (mozilla->priv->wifi == wifi) + return; + + g_clear_weak_pointer (&mozilla->priv->wifi); + + if (!wifi) { + return; + } + + mozilla->priv->wifi = wifi; + g_object_add_weak_pointer (G_OBJECT (mozilla->priv->wifi), + (gpointer) &mozilla->priv->wifi); +} + +gboolean +gclue_mozilla_test_set_wifi (GClueMozilla *mozilla, + GClueWifi *old, GClueWifi *new) +{ + if (mozilla->priv->wifi != old) + return FALSE; + + gclue_mozilla_set_wifi (mozilla, new); + return TRUE; +} + +void +gclue_mozilla_set_bss_dirty (GClueMozilla *mozilla) +{ + g_return_if_fail (GCLUE_IS_MOZILLA (mozilla)); + + mozilla->priv->bss_submitted = FALSE; +} + +static gboolean gclue_mozilla_tower_identical (const GClue3GTower *t1, + const GClue3GTower *t2) +{ + return g_strcmp0 (t1->opc, t2->opc) == 0 && t1->lac == t2->lac && + t1->cell_id == t2->cell_id && t1->tec == t2->tec; +} + +void +gclue_mozilla_set_tower (GClueMozilla *mozilla, + const GClue3GTower *tower) +{ + g_return_if_fail (GCLUE_IS_MOZILLA (mozilla)); + + if (!tower) { + mozilla->priv->tower_valid = FALSE; + return; + } + + if (mozilla->priv->tower_valid && + mozilla->priv->tower_submitted) { + mozilla->priv->tower_submitted = + gclue_mozilla_tower_identical (&mozilla->priv->tower, + tower); + } else + mozilla->priv->tower_submitted = FALSE; + + mozilla->priv->tower = *tower; + mozilla->priv->tower_valid = TRUE; +} + +gboolean +gclue_mozilla_has_tower (GClueMozilla *mozilla) +{ + g_return_val_if_fail (GCLUE_IS_MOZILLA (mozilla), FALSE); + + return mozilla->priv->tower_valid; +} + +GClue3GTower * +gclue_mozilla_get_tower (GClueMozilla *mozilla) +{ + g_return_val_if_fail (GCLUE_IS_MOZILLA (mozilla), NULL); + + if (!mozilla->priv->tower_valid) + return NULL; + + return &mozilla->priv->tower; +} |