From 11d4da4957cb576abe9ee79c9893809a34f1f3d9 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 29 Feb 2020 16:19:44 +0100 Subject: [PATCH] Add meshlink_set_external_address_discovery_url(). This function can be used to override the default meshlink.io service to query a host's own externally visible address. --- src/meshlink++.h | 11 ++++++++ src/meshlink.c | 58 ++++++++++++++++++++++++++++++++++++++--- src/meshlink.h | 11 ++++++++ src/meshlink.sym | 1 + src/meshlink_internal.h | 1 + 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/meshlink++.h b/src/meshlink++.h index 4d900448..11e7eabb 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -1030,6 +1030,17 @@ public: meshlink_set_inviter_commits_first(handle, inviter_commits_first); } + /// Set the URL used to discover the host's external address + /** For generating invitation URLs, MeshLink can look up the externally visible address of the local node. + * It does so by querying an external service. By default, this is http://meshlink.io/host.cgi. + * Only URLs starting with http:// are supported. + * + * @param url The URL to use for external address queries, or NULL to revert back to the default URL. + */ + void set_external_address_discovery_url(const char *url) { + meshlink_set_external_address_discovery_url(handle, url); + } + private: // non-copyable: mesh(const mesh &) /* TODO: C++11: = delete */; diff --git a/src/meshlink.c b/src/meshlink.c index def3e6ef..3ebaee01 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -221,12 +221,42 @@ char *meshlink_get_external_address(meshlink_handle_t *mesh) { } char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int family) { - char *hostname = NULL; + const char *url = mesh->external_address_url; + + if(!url) { + url = "http://meshlink.io/host.cgi"; + } + + /* Find the hostname part between the slashes */ + if(strncmp(url, "http://", 7)) { + abort(); + meshlink_errno = MESHLINK_EINTERNAL; + return NULL; + } + + const char *begin = url + 7; + + const char *end = strchr(begin, '/'); + + if(!end) { + end = begin + strlen(begin); + } + + /* Make a copy */ + char host[end - begin + 1]; + strncpy(host, begin, end - begin); + host[end - begin] = 0; + + char *port = strchr(host, ':'); + + if(port) { + *port++ = 0; + } logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n"); - struct addrinfo *ai = str2addrinfo("meshlink.io", "80", SOCK_STREAM); - static const char request[] = "GET http://www.meshlink.io/host.cgi HTTP/1.0\r\n\r\n"; + struct addrinfo *ai = str2addrinfo(host, port ? port : "80", SOCK_STREAM); char line[256]; + char *hostname = NULL; for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { if(family != AF_UNSPEC && aip->ai_family != family) { @@ -245,7 +275,9 @@ char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int fami } if(s >= 0) { - send(s, request, sizeof(request) - 1, 0); + send(s, "GET ", 4, 0); + send(s, url, strlen(url), 0); + send(s, " HTTP/1.0\r\n\r\n", 13, 0); int len = recv(s, line, sizeof(line) - 1, MSG_WAITALL); if(len > 0) { @@ -1754,6 +1786,7 @@ void meshlink_close(meshlink_handle_t *mesh) { free(mesh->appname); free(mesh->confbase); free(mesh->config_key); + free(mesh->external_address_url); ecdsa_free(mesh->private_key); main_config_unlock(mesh); @@ -3986,6 +4019,23 @@ extern void meshlink_set_inviter_commits_first(struct meshlink_handle *mesh, boo pthread_mutex_unlock(&mesh->mutex); } +void meshlink_set_external_address_discovery_url(struct meshlink_handle *mesh, const char *url) { + if(!mesh) { + meshlink_errno = EINVAL; + return; + } + + if(url && (strncmp(url, "http://", 7) || strchr(url, ' '))) { + meshlink_errno = EINVAL; + return; + } + + pthread_mutex_lock(&mesh->mutex); + free(mesh->external_address_url); + mesh->external_address_url = url ? xstrdup(url) : NULL; + pthread_mutex_unlock(&mesh->mutex); +} + void handle_network_change(meshlink_handle_t *mesh, bool online) { (void)online; diff --git a/src/meshlink.h b/src/meshlink.h index 385c12ce..2877c64e 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -1562,6 +1562,17 @@ extern void meshlink_set_dev_class_fast_retry_period(struct meshlink_handle *mes */ extern void meshlink_set_inviter_commits_first(struct meshlink_handle *mesh, bool inviter_commits_first); +/// Set the URL used to discover the host's external address +/** For generating invitation URLs, MeshLink can look up the externally visible address of the local node. + * It does so by querying an external service. By default, this is http://meshlink.io/host.cgi. + * Only URLs starting with http:// are supported. + * + * \memberof meshlink_handle + * @param mesh A handle which represents an instance of MeshLink. + * @param url The URL to use for external address queries, or NULL to revert back to the default URL. + */ +extern void meshlink_set_external_address_discovery_url(struct meshlink_handle *mesh, const char *url); + #ifdef __cplusplus } #endif diff --git a/src/meshlink.sym b/src/meshlink.sym index de640c0c..6c4dd572 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -70,6 +70,7 @@ meshlink_set_default_blacklist meshlink_set_dev_class_fast_retry_period meshlink_set_dev_class_timeouts meshlink_set_error_cb +meshlink_set_external_address_discovery_url meshlink_set_invitation_timeout meshlink_set_inviter_commits_first meshlink_set_log_cb diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index f895e02f..8c67aa3e 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -174,6 +174,7 @@ struct meshlink_handle { char *confbase; FILE *lockfile; void *config_key; + char *external_address_url; // Thread management pthread_t thread; -- 2.39.2