diff options
author | Oliver Smith <osmith@sysmocom.de> | 2019-11-20 10:56:35 +0100 |
---|---|---|
committer | laforge <laforge@osmocom.org> | 2020-01-10 16:07:40 +0000 |
commit | bf7deda0fc30dba8cdd8f3cc9d5047f9800ca50f (patch) | |
tree | e93fac5ab953405b086ed182037298c53ccb9788 /include/osmocom/mslookup | |
parent | 81b92bbe69fdc548680af651a44071d948a50292 (diff) |
add libosmo-mslookup abstract client
mslookup is a key concept in Distributed GSM, which allows querying the current
location of a subscriber in a number of cooperating but independent core
network sites, by arbitrary service names and by MSISDN/IMSI.
Add the abstract mslookup client library. An actual lookup method (besides
mslookup_client_fake.c) is added in a subsequent patch.
For a detailed overview of this and upcoming patches, please see the elaborate
comment at the top of mslookup.c.
Add as separate library, libosmo-mslookup, to allow adding D-GSM capability to
arbitrary client programs.
osmo-hlr will be the only mslookup server implementation, added in a subsequent
patch.
osmo-hlr itself will also use this library and act as an mslookup client, when
requesting the home HLR for locally unknown IMSIs.
Related: OS#4237
Patch-by: osmith, nhofmeyr
Change-Id: I83487ab8aad1611eb02e997dafbcb8344da13df1
Diffstat (limited to 'include/osmocom/mslookup')
-rw-r--r-- | include/osmocom/mslookup/mslookup.h | 121 | ||||
-rw-r--r-- | include/osmocom/mslookup/mslookup_client.h | 132 | ||||
-rw-r--r-- | include/osmocom/mslookup/mslookup_client_fake.h | 34 |
3 files changed, 287 insertions, 0 deletions
diff --git a/include/osmocom/mslookup/mslookup.h b/include/osmocom/mslookup/mslookup.h new file mode 100644 index 0000000..e90af33 --- /dev/null +++ b/include/osmocom/mslookup/mslookup.h @@ -0,0 +1,121 @@ +/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * 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, see <http://www.gnu.org/licenses/>. + */ + +/*! \defgroup mslookup Distributed GSM: finding subscribers + * @{ + * \file mslookup.h + */ + +#pragma once + +#include <osmocom/core/utils.h> +#include <osmocom/core/sockaddr_str.h> +#include <osmocom/gsm/protocol/gsm_23_003.h> + +#define OSMO_MSLOOKUP_SERVICE_MAXLEN 64 + +bool osmo_mslookup_service_valid(const char *service); + +enum osmo_mslookup_id_type { + OSMO_MSLOOKUP_ID_NONE = 0, + OSMO_MSLOOKUP_ID_IMSI, + OSMO_MSLOOKUP_ID_MSISDN, +}; + +extern const struct value_string osmo_mslookup_id_type_names[]; +static inline const char *osmo_mslookup_id_type_name(enum osmo_mslookup_id_type val) +{ return get_value_string(osmo_mslookup_id_type_names, val); } + +struct osmo_mslookup_id { + enum osmo_mslookup_id_type type; + union { + char imsi[GSM23003_IMSI_MAX_DIGITS+1]; + char msisdn[GSM23003_MSISDN_MAX_DIGITS+1]; + }; +}; + +int osmo_mslookup_id_cmp(const struct osmo_mslookup_id *a, const struct osmo_mslookup_id *b); +bool osmo_mslookup_id_valid(const struct osmo_mslookup_id *id); + +enum osmo_mslookup_result_code { + OSMO_MSLOOKUP_RC_NONE = 0, + /*! An intermediate valid result. The request is still open for more results. */ + OSMO_MSLOOKUP_RC_RESULT, + /*! Returned when the final request timeout has elapsed without results. */ + OSMO_MSLOOKUP_RC_NOT_FOUND, +}; + +extern const struct value_string osmo_mslookup_result_code_names[]; +static inline const char *osmo_mslookup_result_code_name(enum osmo_mslookup_result_code val) +{ return get_value_string(osmo_mslookup_result_code_names, val); } + +/*! Information to request from a lookup. */ +struct osmo_mslookup_query { + /*! Which service to request, by freely invented names. For service name conventions (for voice, SMS, HLR,...), + * refer to the OsmoHLR user's manual http://ftp.osmocom.org/docs/latest/osmohlr-usermanual.pdf */ + char service[OSMO_MSLOOKUP_SERVICE_MAXLEN + 1]; + /*! IMSI or MSISDN to look up. */ + struct osmo_mslookup_id id; + + /*! Caller provided private data, if desired. */ + void *priv; +}; + +/*! Result data as passed back to a lookup client that invoked an osmo_mslookup_client_request. */ +struct osmo_mslookup_result { + /*! Outcome of the request. */ + enum osmo_mslookup_result_code rc; + + /*! IP address and port to reach the given service via IPv4, if any. */ + struct osmo_sockaddr_str host_v4; + + /*! IP address and port to reach the given service via IPv6, if any. */ + struct osmo_sockaddr_str host_v6; + + /*! How long ago the service last verified presence of the subscriber, in seconds, or zero if the presence is + * invariable (like the home HLR record for an IMSI). + * If a subscriber has recently moved to a different location, we get multiple replies and want to choose the + * most recent one. If this were a timestamp, firstly the time zones would need to be taken care of. + * Even if we choose UTC, a service provider with an inaccurate date/time would end up affecting the result. + * The least susceptible to configuration errors or difference in local and remote clock is a value that + * indicates the actual age of the record in seconds. The time that the lookup query took to be answered should + * be neglectable here, since we would typically wait one second (or very few seconds) for lookup replies, + * while typical Location Updating periods are in the range of 15 minutes. */ + uint32_t age; + + /*! Whether this is the last result returned for this request. */ + bool last; +}; + +int osmo_mslookup_query_init_from_domain_str(struct osmo_mslookup_query *q, const char *domain); + +size_t osmo_mslookup_id_name_buf(char *buf, size_t buflen, const struct osmo_mslookup_id *id); +char *osmo_mslookup_id_name_c(void *ctx, const struct osmo_mslookup_id *id); +char *osmo_mslookup_id_name_b(char *buf, size_t buflen, const struct osmo_mslookup_id *id); + +size_t osmo_mslookup_result_to_str_buf(char *buf, size_t buflen, + const struct osmo_mslookup_query *query, + const struct osmo_mslookup_result *result); +char *osmo_mslookup_result_name_c(void *ctx, + const struct osmo_mslookup_query *query, + const struct osmo_mslookup_result *result); +char *osmo_mslookup_result_name_b(char *buf, size_t buflen, + const struct osmo_mslookup_query *query, + const struct osmo_mslookup_result *result); + +/*! @} */ diff --git a/include/osmocom/mslookup/mslookup_client.h b/include/osmocom/mslookup/mslookup_client.h new file mode 100644 index 0000000..cd0c21f --- /dev/null +++ b/include/osmocom/mslookup/mslookup_client.h @@ -0,0 +1,132 @@ +/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * 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, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/sockaddr_str.h> +#include <osmocom/mslookup/mslookup.h> + +struct osmo_mslookup_client; +struct osmo_mslookup_result; + +typedef void (*osmo_mslookup_cb_t)(struct osmo_mslookup_client *client, + uint32_t request_handle, + const struct osmo_mslookup_query *query, + const struct osmo_mslookup_result *result); + +/*! This handling information is passed along with a lookup request. + * It tells the osmo_mslookup_client layer how to handle responses received from various mslookup methods (at the time + * of writing only mDNS exists as a method, but the intention is to easily allow adding other methods in the future). + * This query handling info is not seen by the individual method implementations, to clarify that it is the + * osmo_mslookup_client layer that takes care of these details. */ +struct osmo_mslookup_query_handling { + /*! Wait at least this long before returning any results. + * + * If nonzero, result_cb will be called as soon as this delay has elapsed, either with the so far youngest age + * result, or with a "not found yet" result. After this delay has elapsed, receiving results will continue + * until result_timeout_milliseconds has elapsed. + * + * If zero, responses are fed to the result_cb right from the start, every time a younger aged result than + * before comes in. + * + * If a result with age == 0 is received, min_wait_milliseconds is ignored, the result is returned immediately + * and listening for responses ends. + * + * Rationale: If a subscriber has recently moved between sites, multiple results will arrive, and the youngest + * age wins. It can make sense to wait a minimum time for responses before determining the winning result. + * + * However, if no result or no valid result has arrived within a short period, the subscriber may be at a site + * that is far away or that is currently experiencing high latency. It is thus a good safety net to still + * receive results for an extended period of time. + * + * For some services, it is possible to establish links to every received result, and whichever link succeeds + * will be used (for example for SIP calls: first to pick up the call gets connected, the others are dropped + * silently). + */ + uint32_t min_wait_milliseconds; + + /*! Total time in milliseconds to listen for lookup responses. + * + * When this timeout elapses, osmo_mslookup_client_request_cancel() is called implicitly; Manually invoking + * osmo_mslookup_client_request_cancel() after result_timeout_milliseconds has elapsed is not necessary, but is + * still safe to do anyway. + * + * If zero, min_wait_milliseconds is also used as result_timeout_milliseconds; if that is also zero, a default + * timeout value is used. + * + * If result_timeout_milliseconds <= min_wait_milliseconds, then min_wait_milliseconds is used as + * result_timeout_milliseconds, i.e. the timeout triggers as soon as min_wait_milliseconds hits. + * + * osmo_mslookup_client_request_cancel() can be called any time to end the request. + */ + uint32_t result_timeout_milliseconds; + + /*! Invoked every time a result with a younger age than the previous result has arrived. + * To stop receiving results before result_timeout_milliseconds has elapsed, call + * osmo_mslookup_client_request_cancel(). + */ + osmo_mslookup_cb_t result_cb; +}; + +uint32_t osmo_mslookup_client_request(struct osmo_mslookup_client *client, + const struct osmo_mslookup_query *query, + const struct osmo_mslookup_query_handling *handling); + +void osmo_mslookup_client_request_cancel(struct osmo_mslookup_client *client, uint32_t request_handle); + +struct osmo_mslookup_client *osmo_mslookup_client_new(void *ctx); +bool osmo_mslookup_client_active(struct osmo_mslookup_client *client); +void osmo_mslookup_client_free(struct osmo_mslookup_client *client); + +/*! Describe a specific mslookup client method implementation. This struct is only useful for a lookup method + * implementation to add itself to an osmo_mslookup_client, see for example osmo_mslookup_client_add_mdns(). */ +struct osmo_mslookup_client_method { + struct llist_head entry; + + /*! Human readable name of this lookup method. */ + const char *name; + + /*! Private data for the lookup method implementation. */ + void *priv; + + /*! Backpointer to the client this method is added to. */ + struct osmo_mslookup_client *client; + + /*! Launch a lookup query. Called from osmo_mslookup_client_request(). + * The implementation returns results by calling osmo_mslookup_client_rx_result(). */ + void (*request)(struct osmo_mslookup_client_method *method, + const struct osmo_mslookup_query *query, + uint32_t request_handle); + /*! End a lookup query. Called from osmo_mslookup_client_request_cancel(). It is guaranteed to be called + * exactly once per above request() invocation. (The API user is required to invoke + * osmo_mslookup_client_request_cancel() exactly once per osmo_mslookup_client_request().) */ + void (*request_cleanup)(struct osmo_mslookup_client_method *method, + uint32_t request_handle); + + /*! The mslookup_client is removing this method, clean up all open requests, lists and allocations. */ + void (*destruct)(struct osmo_mslookup_client_method *method); +}; + +void osmo_mslookup_client_method_add(struct osmo_mslookup_client *client, + struct osmo_mslookup_client_method *method); +bool osmo_mslookup_client_method_del(struct osmo_mslookup_client *client, + struct osmo_mslookup_client_method *method); +void osmo_mslookup_client_rx_result(struct osmo_mslookup_client *client, uint32_t request_handle, + const struct osmo_mslookup_result *result); diff --git a/include/osmocom/mslookup/mslookup_client_fake.h b/include/osmocom/mslookup/mslookup_client_fake.h new file mode 100644 index 0000000..9fffc94 --- /dev/null +++ b/include/osmocom/mslookup/mslookup_client_fake.h @@ -0,0 +1,34 @@ +/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * 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, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +/*! MS lookup fake API for testing purposes. */ +#include <osmocom/mslookup/mslookup_client.h> + +struct osmo_mslookup_fake_response { + struct timeval time_to_reply; + struct osmo_mslookup_id for_id; + const char *for_service; + struct osmo_mslookup_result result; + bool sent; +}; + +struct osmo_mslookup_client_method *osmo_mslookup_client_add_fake(struct osmo_mslookup_client *client, + struct osmo_mslookup_fake_response *responses, + size_t responses_len); |