From 31cc8a750f8df10f0a69a8ba9db08a15efa2f415 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 3 Nov 2018 22:11:42 +0100 Subject: change cmp to be case-insensitive (to get tests to pass) --- src/gns/test_gns_cname_lookup.sh | 3 +++ src/gns/test_gns_mx_lookup.sh | 4 ++++ 2 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/gns/test_gns_cname_lookup.sh b/src/gns/test_gns_cname_lookup.sh index f6b7a842d..de575c561 100755 --- a/src/gns/test_gns_cname_lookup.sh +++ b/src/gns/test_gns_cname_lookup.sh @@ -54,6 +54,9 @@ gnunet-identity -D $MY_EGO -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` +# make cmp case-insensitive by converting to lower case first +RES_CNAME_RAW=`echo $RES_CNAME_RAW | tr [A-Z] [a-z]` +TESTEGOZONE=`echo $TESTEGOZONE | tr [A-Z] [a-z]` if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE" ] then echo "PASS: CNAME resolution from GNS" diff --git a/src/gns/test_gns_mx_lookup.sh b/src/gns/test_gns_mx_lookup.sh index 3a360494b..79ac37b0a 100755 --- a/src/gns/test_gns_mx_lookup.sh +++ b/src/gns/test_gns_mx_lookup.sh @@ -31,6 +31,10 @@ gnunet-identity -D $MY_EGO -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf `gnunet-config -c test_gns_lookup.conf -f -s paths -o GNUNET_TEST_HOME` +# make cmp case-insensitive by converting to lower case first +RES_MX=`echo $RES_MX | tr [A-Z] [a-z]` +WANT_MX=`echo $WANT_MX | tr [A-Z] [a-z]` + if [ "$RES_MX" == "$WANT_MX" ] then exit 0 -- cgit v1.2.3 From 3a4e51894442b7fdde457836c6f99d710e47b3f1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 4 Nov 2018 11:17:09 +0100 Subject: fix #5454 --- src/util/configuration.c | 25 +++++++++++++++++-------- src/util/getopt.c | 8 ++++---- src/util/getopt_helpers.c | 25 ++++++++++++++++--------- src/util/service.c | 8 +++++--- src/util/strings.c | 43 ++++++++++++++++++++++++++++++------------- 5 files changed, 72 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/util/configuration.c b/src/util/configuration.c index e00bbd64a..41eb3188d 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -893,22 +893,27 @@ GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg, * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle - *cfg, const char *section, +GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, const char *option, unsigned long long *number) { struct ConfigEntry *e; + char dummy[2]; if (NULL == (e = find_entry (cfg, section, option))) return GNUNET_SYSERR; if (NULL == e->val) return GNUNET_SYSERR; - if (1 != SSCANF (e->val, "%llu", number)) + if (1 != SSCANF (e->val, + "%llu%1s", + number, + dummy)) return GNUNET_SYSERR; - return GNUNET_OK; + return GNUNET_OK; } + /** * Get a configuration value that should be a floating point number. * @@ -919,18 +924,22 @@ GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int -GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle - *cfg, const char *section, +GNUNET_CONFIGURATION_get_value_float (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, const char *option, float *number) { struct ConfigEntry *e; - + char dummy[2]; + if (NULL == (e = find_entry (cfg, section, option))) return GNUNET_SYSERR; if (NULL == e->val) return GNUNET_SYSERR; - if (1 != SSCANF (e->val, "%f", number)) + if (1 != SSCANF (e->val, + "%f%1s", + number, + dummy)) return GNUNET_SYSERR; return GNUNET_OK; } diff --git a/src/util/getopt.c b/src/util/getopt.c index 036e0f4be..4a7f35f51 100644 --- a/src/util/getopt.c +++ b/src/util/getopt.c @@ -866,7 +866,7 @@ GNgetopt_long (int argc, * @param argc number of arguments * @param argv actual arguments * @return index into argv with first non-option - * argument, or -1 on error + * argument, or #GNUNET_SYSERR on error */ int GNUNET_GETOPT_run (const char *binaryOptions, @@ -967,9 +967,9 @@ GNUNET_GETOPT_run (const char *binaryOptions, GNUNET_free (seen); /* call cleaners, if available */ - for (count = 0; NULL != allOptions[count].name; count++) - if (NULL != allOptions[count].cleaner) - allOptions[count].cleaner (allOptions[count].scls); + for (unsigned int i = 0; NULL != allOptions[i].name; i++) + if (NULL != allOptions[i].cleaner) + allOptions[i].cleaner (allOptions[i].scls); if (GNUNET_OK != cont) return cont; diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c index 32cce65dd..661521c45 100644 --- a/src/util/getopt_helpers.c +++ b/src/util/getopt_helpers.c @@ -108,9 +108,10 @@ format_help (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, (void) value; if (NULL != about) { - printf ("%s\n%s\n", ctx->binaryOptions, gettext (about)); - printf (_ - ("Arguments mandatory for long options are also mandatory for short options.\n")); + printf ("%s\n%s\n", + ctx->binaryOptions, + gettext (about)); + printf (_("Arguments mandatory for long options are also mandatory for short options.\n")); } i = 0; opt = ctx->allOptions; @@ -549,11 +550,13 @@ set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, const char *value) { unsigned long long *val = scls; + char dummy[2]; (void) ctx; if (1 != SSCANF (value, - "%llu", - val)) + "%llu%1s", + val, + dummy)) { FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), @@ -746,6 +749,7 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, const char *value) { unsigned int *val = scls; + char dummy[2]; (void) ctx; if('-' == *value) @@ -756,8 +760,9 @@ set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, return GNUNET_SYSERR; } if (1 != SSCANF (value, - "%u", - val)) + "%u%1s", + val, + dummy)) { FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), @@ -820,11 +825,13 @@ set_uint16 (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, { uint16_t *val = scls; unsigned int v; + char dummy[2]; (void) ctx; if (1 != SSCANF (value, - "%u", - &v)) + "%u%1s", + &v, + dummy)) { FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), diff --git a/src/util/service.c b/src/util/service.c index 20cc1036d..ea34abc6c 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -1175,8 +1175,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) const char *nfds; unsigned int cnt; int flags; + char dummy[2]; #endif - + if (GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, @@ -1203,8 +1204,9 @@ setup_service (struct GNUNET_SERVICE_Handle *sh) errno = 0; if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) && (1 == SSCANF (nfds, - "%u", - &cnt)) && + "%u%1s", + &cnt, + dummy)) && (cnt > 0) && (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE) ) diff --git a/src/util/strings.c b/src/util/strings.c index b7a7fcb8b..3f85384e1 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -1262,6 +1262,7 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, int ret; char *port_colon; unsigned int port; + char dummy[2]; if (addrlen < 6) return GNUNET_SYSERR; @@ -1286,7 +1287,10 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, _("IPv6 address did contain ']' before ':' to separate port number\n")); return GNUNET_SYSERR; } - ret = SSCANF (port_colon, ":%u", &port); + ret = SSCANF (port_colon, + ":%u%1s", + &port, + dummy); if ( (1 != ret) || (port > 65535) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -1332,16 +1336,18 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, unsigned int temps[4]; unsigned int port; unsigned int cnt; + char dummy[2]; if (addrlen < 9) return GNUNET_SYSERR; cnt = SSCANF (zt_addr, - "%u.%u.%u.%u:%u", + "%u.%u.%u.%u:%u%1s", &temps[0], &temps[1], &temps[2], &temps[3], - &port); + &port, + dummy); if (5 != cnt) return GNUNET_SYSERR; for (cnt = 0; cnt < 4; cnt++) @@ -1563,7 +1569,9 @@ parse_port_policy (const char *port_policy, } if (2 == sscanf (pos, "%u-%u%1s", - &s, &e, eol)) + &s, + &e, + eol)) { if ( (0 == s) || (s > 0xFFFF) || @@ -1629,7 +1637,8 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) int colon; int end; char *routeList; - + char dummy[2]; + if (NULL == routeListX) return NULL; len = strlen (routeListX); @@ -1664,7 +1673,7 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) } cnt = SSCANF (&routeList[pos], - "%u.%u.%u.%u/%u.%u.%u.%u", + "%u.%u.%u.%u/%u.%u.%u.%u%1s", &temps[0], &temps[1], &temps[2], @@ -1672,7 +1681,8 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) &temps[4], &temps[5], &temps[6], - &temps[7]); + &temps[7], + dummy); if (8 == cnt) { for (j = 0; j < 8; j++) @@ -1698,12 +1708,13 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) /* try second notation */ cnt = SSCANF (&routeList[pos], - "%u.%u.%u.%u/%u", + "%u.%u.%u.%u/%u%1s", &temps[0], &temps[1], &temps[2], &temps[3], - &slash); + &slash, + dummy); if (5 == cnt) { for (j = 0; j < 4; j++) @@ -1747,11 +1758,12 @@ GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) slash = 32; cnt = SSCANF (&routeList[pos], - "%u.%u.%u.%u", + "%u.%u.%u.%u%1s", &temps[0], &temps[1], &temps[2], - &temps[3]); + &temps[3], + dummy); if (4 == cnt) { for (j = 0; j < 4; j++) @@ -1826,7 +1838,8 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX) unsigned int off; int save; int colon; - + char dummy[2]; + if (NULL == routeListX) return NULL; len = strlen (routeListX); @@ -1886,7 +1899,11 @@ GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX) if (ret <= 0) { save = errno; - if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128)) + if ( (1 != SSCANF (&routeList[slash + 1], + "%u%1s", + &bits, + dummy)) || + (bits > 128) ) { if (0 == ret) LOG (GNUNET_ERROR_TYPE_WARNING, -- cgit v1.2.3 From b0f1f0f3fac0120b116132dfd90742b0115b152f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 6 Nov 2018 14:28:29 +0100 Subject: indentation fixes --- src/fs/fs_getopt.c | 29 +++++++++++++++++++---------- src/fs/gnunet-publish.c | 35 ++++++++++++++++++----------------- src/fs/gnunet-search.c | 49 ++++++++++++++++++++++--------------------------- 3 files changed, 59 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/fs/fs_getopt.c b/src/fs/fs_getopt.c index 7b5c2991d..cbd9339c9 100644 --- a/src/fs/fs_getopt.c +++ b/src/fs/fs_getopt.c @@ -38,19 +38,20 @@ * @param scls must be of type "struct GNUNET_FS_Uri **" * @param option name of the option (typically 'k') * @param value command line argument given - * @return GNUNET_OK on success + * @return #GNUNET_OK on success */ static int -getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext - *ctx, void *scls, const char *option, - const char *value) +getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, + void *scls, + const char *option, + const char *value) { struct GNUNET_FS_Uri **uri = scls; struct GNUNET_FS_Uri *u = *uri; char *val; size_t slen; - if (u == NULL) + if (NULL == u) { u = GNUNET_new (struct GNUNET_FS_Uri); *uri = u; @@ -60,10 +61,10 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext } else { - GNUNET_assert (u->type == GNUNET_FS_URI_KSK); + GNUNET_assert (GNUNET_FS_URI_KSK == u->type); } slen = strlen (value); - if (slen == 0) + if (0 == slen) return GNUNET_SYSERR; /* cannot be empty */ if (value[0] == '+') { @@ -75,7 +76,9 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext /* remove the quotes, keep the '+' */ val = GNUNET_malloc (slen - 1); val[0] = '+'; - GNUNET_memcpy (&val[1], &value[2], slen - 3); + GNUNET_memcpy (&val[1], + &value[2], + slen - 3); val[slen - 2] = '\0'; } else @@ -91,7 +94,9 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext /* remove the quotes, add a space */ val = GNUNET_malloc (slen); val[0] = ' '; - GNUNET_memcpy (&val[1], &value[1], slen - 2); + GNUNET_memcpy (&val[1], + &value[1], + slen - 2); val[slen - 1] = '\0'; } else @@ -102,10 +107,13 @@ getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext strcat (val, value); } } - GNUNET_array_append (u->data.ksk.keywords, u->data.ksk.keywordCount, val); + GNUNET_array_append (u->data.ksk.keywords, + u->data.ksk.keywordCount, + val); return GNUNET_OK; } + /** * Allow user to specify keywords. * @@ -135,6 +143,7 @@ GNUNET_FS_GETOPT_KEYWORDS (char shortName, return clo; } + /** * Command-line option parser function that allows the user to specify * one or more '-m' options with metadata. Each specified entry of diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c index 999301c2f..8501141ce 100644 --- a/src/fs/gnunet-publish.c +++ b/src/fs/gnunet-publish.c @@ -728,7 +728,8 @@ identity_continuation (const char *args0) GNUNET_SCHEDULER_shutdown (); return; } - GNUNET_FS_publish_ksk (ctx, topKeywords, + GNUNET_FS_publish_ksk (ctx, + topKeywords, meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, @@ -889,7 +890,8 @@ run (void *cls, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_option_uint ('a', @@ -922,26 +924,22 @@ main (int argc, char *const *argv) "TYPE:VALUE", gettext_noop ("set the meta-data for the given TYPE to the given VALUE"), &meta), - GNUNET_GETOPT_option_flag ('n', - "noindex", - gettext_noop ("do not index, perform full insertion (stores " - "entire file in encrypted form in GNUnet database)"), - &do_insert), - + "noindex", + gettext_noop ("do not index, perform full insertion (stores " + "entire file in encrypted form in GNUnet database)"), + &do_insert), GNUNET_GETOPT_option_string ('N', "next", "ID", gettext_noop ("specify ID of an updated version to be " "published in the future (for namespace insertions only)"), &next_id), - GNUNET_GETOPT_option_uint ('p', - "priority", - "PRIORITY", - gettext_noop ("specify the priority of the content"), - &bo.content_priority), - + "priority", + "PRIORITY", + gettext_noop ("specify the priority of the content"), + &bo.content_priority), GNUNET_GETOPT_option_string ('P', "pseudonym", "NAME", @@ -964,7 +962,6 @@ main (int argc, char *const *argv) gettext_noop ("set the ID of this version of the publication " "(for namespace insertions only)"), &this_id), - GNUNET_GETOPT_option_string ('u', "uri", "URI", @@ -982,10 +979,14 @@ main (int argc, char *const *argv) if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-publish [OPTIONS] FILENAME", + GNUNET_PROGRAM_run (argc, + argv, + "gnunet-publish [OPTIONS] FILENAME", gettext_noop ("Publish a file or directory on GNUnet"), - options, &run, NULL)) ? ret : 1; + options, + &run, + NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } diff --git a/src/fs/gnunet-search.c b/src/fs/gnunet-search.c index 780b3c93d..2a0a153e7 100644 --- a/src/fs/gnunet-search.c +++ b/src/fs/gnunet-search.c @@ -304,49 +304,44 @@ int main (int argc, char *const *argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_option_uint ('a', - "anonymity", - "LEVEL", - gettext_noop ("set the desired LEVEL of receiver-anonymity"), - &anonymity), - - + "anonymity", + "LEVEL", + gettext_noop ("set the desired LEVEL of receiver-anonymity"), + &anonymity), GNUNET_GETOPT_option_flag ('n', - "no-network", - gettext_noop ("only search the local peer (no P2P network search)"), - &local_only), - + "no-network", + gettext_noop ("only search the local peer (no P2P network search)"), + &local_only), GNUNET_GETOPT_option_string ('o', "output", "PREFIX", gettext_noop ("write search results to file starting with PREFIX"), &output_filename), - GNUNET_GETOPT_option_relative_time ('t', - "timeout", - "DELAY", - gettext_noop ("automatically terminate search after DELAY"), - &timeout), - - + "timeout", + "DELAY", + gettext_noop ("automatically terminate search after DELAY"), + &timeout), GNUNET_GETOPT_option_verbose (&verbose), - GNUNET_GETOPT_option_uint ('N', - "results", - "VALUE", - gettext_noop ("automatically terminate search " - "after VALUE results are found"), - &results_limit), - + "results", + "VALUE", + gettext_noop ("automatically terminate search " + "after VALUE results are found"), + &results_limit), GNUNET_GETOPT_OPTION_END }; - if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + if (GNUNET_OK != + GNUNET_STRINGS_get_utf8_args (argc, argv, + &argc, &argv)) return 2; ret = (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-search [OPTIONS] KEYWORD", + GNUNET_PROGRAM_run (argc, + argv, + "gnunet-search [OPTIONS] KEYWORD", gettext_noop ("Search GNUnet for files that were published on GNUnet"), options, &run, NULL)) ? ret : 1; -- cgit v1.2.3 From 403957f04d3b27297c204772f2bf77969a7b2d0b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 6 Nov 2018 14:31:15 +0100 Subject: indentation fixes --- src/fs/gnunet-publish.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c index 8501141ce..ffcf9b5d0 100644 --- a/src/fs/gnunet-publish.c +++ b/src/fs/gnunet-publish.c @@ -496,21 +496,22 @@ uri_ksk_continuation (void *cls, emsg); ret = 1; } - if (NULL != namespace) + if (NULL == namespace) { - priv = GNUNET_IDENTITY_ego_get_private_key (namespace); - GNUNET_FS_publish_sks (ctx, - priv, - this_id, - next_id, - meta, - uri, - &bo, - GNUNET_FS_PUBLISH_OPTION_NONE, - &uri_sks_continuation, NULL); + GNUNET_SCHEDULER_shutdown (); return; } - GNUNET_SCHEDULER_shutdown (); + priv = GNUNET_IDENTITY_ego_get_private_key (namespace); + GNUNET_FS_publish_sks (ctx, + priv, + this_id, + next_id, + meta, + uri, + &bo, + GNUNET_FS_PUBLISH_OPTION_NONE, + &uri_sks_continuation, + NULL); } -- cgit v1.2.3 From c0ccb5ea455f6e0fc446dfe4b744b3447e002a27 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 6 Nov 2018 15:12:39 +0100 Subject: add option to allow manipulating entire sets in one operation --- src/namestore/gnunet-namestore.c | 273 ++++++++++++++++++++++++++++++++++----- 1 file changed, 238 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c index c5f48848e..0f0660edc 100644 --- a/src/namestore/gnunet-namestore.c +++ b/src/namestore/gnunet-namestore.c @@ -32,6 +32,24 @@ #include +/** + * Entry in record set for bulk processing. + */ +struct RecordSetEntry +{ + /** + * Kept in a linked list. + */ + struct RecordSetEntry *next; + + /** + * The record to add/remove. + */ + struct GNUNET_GNSRECORD_Data record; + +}; + + /** * Handle to the namestore. */ @@ -197,6 +215,11 @@ static struct GNUNET_NAMESTORE_ZoneMonitor *zm; */ static int monitor; +/** + * Entry in record set for processing records in bulk. + */ +static struct RecordSetEntry *recordset; + /** * Task run on shutdown. Cleans up everything. @@ -863,6 +886,56 @@ del_monitor (void *cls, } +/** + * Parse expiration time. + * + * @param expirationstring text to parse + * @param etime_is_rel[out] set to #GNUNET_YES if time is relative + * @param etime[out] set to expiration time (abs or rel) + * @return #GNUNET_OK on success + */ +static int +parse_expiration (const char *expirationstring, + int *etime_is_rel, + uint64_t *etime) +{ + struct GNUNET_TIME_Relative etime_rel; + struct GNUNET_TIME_Absolute etime_abs; + + if (0 == strcmp (expirationstring, + "never")) + { + *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + *etime_is_rel = GNUNET_NO; + return GNUNET_OK; + } + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_relative (expirationstring, + &etime_rel)) + { + *etime_is_rel = GNUNET_YES; + *etime = etime_rel.rel_value_us; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Storing record with relative expiration time of %s\n", + GNUNET_STRINGS_relative_time_to_string (etime_rel, + GNUNET_NO)); + return GNUNET_OK; + } + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, + &etime_abs)) + { + *etime_is_rel = GNUNET_NO; + *etime = etime_abs.abs_value_us; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Storing record with absolute expiration time of %s\n", + GNUNET_STRINGS_absolute_time_to_string (etime_abs)); + return GNUNET_OK; + } + return GNUNET_SYSERR; +} + + /** * Callback invoked from identity service with ego information. * An @a ego of NULL means the ego was not found. @@ -877,6 +950,7 @@ identity_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_GNSRECORD_Data rd; + uint64_t etime; el = NULL; if (NULL == ego) @@ -976,32 +1050,10 @@ identity_cb (void *cls, ret = 1; return; } - if (0 == strcmp (expirationstring, - "never")) - { - etime_abs = GNUNET_TIME_UNIT_FOREVER_ABS; - etime_is_rel = GNUNET_NO; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_relative (expirationstring, - &etime_rel)) - { - etime_is_rel = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Storing record with relative expiration time of %s\n", - GNUNET_STRINGS_relative_time_to_string (etime_rel, - GNUNET_NO)); - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, - &etime_abs)) - { - etime_is_rel = GNUNET_NO; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Storing record with absolute expiration time of %s\n", - GNUNET_STRINGS_absolute_time_to_string (etime_abs)); - } - else + if (GNUNET_OK != + parse_expiration (expirationstring, + &etime_is_rel, + &etime)) { fprintf (stderr, _("Invalid time format `%s'\n"), @@ -1106,16 +1158,9 @@ identity_cb (void *cls, rd.data = &pkey; rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; - if (GNUNET_YES == etime_is_rel) - { - rd.expiration_time = etime_rel.rel_value_us; + rd.expiration_time = etime; + if (GNUNET_YES == etime_is_rel) rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_NO == etime_is_rel) - rd.expiration_time = etime_abs.abs_value_us; - else - rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - if (1 == is_shadow) rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; add_qe_uri = GNUNET_NAMESTORE_records_store (ns, @@ -1246,6 +1291,159 @@ run (void *cls, } +/** + * Command-line option parser function that allows the user to specify + * a complete record as one argument for adding/removing. A pointer + * to the head of the list of record sets must be passed as the "scls" + * argument. + * + * @param ctx command line processor context + * @param scls must be of type "struct GNUNET_FS_Uri **" + * @param option name of the option (typically 'R') + * @param value command line argument given; format is + * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs), + * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or + * a combination of 's' (shadow) and 'p' (public) and VALUE is the + * value (in human-readable format) + * @return #GNUNET_OK on success + */ +static int +multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, + void *scls, + const char *option, + const char *value) +{ + struct RecordSetEntry **head = scls; + struct RecordSetEntry *r; + struct GNUNET_GNSRECORD_Data record; + char *cp; + char *tok; + int etime_is_rel; + void *raw_data; + + cp = GNUNET_strdup (value); + tok = strtok (cp, " "); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Empty record line argument is not allowed.\n")); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + parse_expiration (tok, + &etime_is_rel, + &record.expiration_time)) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Invalid expiration time `%s'\n"), + tok); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + tok = strtok (NULL, " "); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Missing entries in record line `%s'.\n"), + value); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + record.record_type = GNUNET_GNSRECORD_typename_to_number (tok); + if (UINT32_MAX == record.record_type) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Unknown record type `%s'\n"), + tok); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + tok = strtok (NULL, " "); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Missing entries in record line `%s'.\n"), + value); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + record.flags = GNUNET_GNSRECORD_RF_NONE; + if (etime_is_rel) + record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */ + record.flags |= GNUNET_GNSRECORD_RF_PRIVATE; + if (NULL != strchr (tok, (unsigned char) 's')) + record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; + /* find beginning of record value */ + tok = strchr (&value[tok - cp], (unsigned char) ' '); + if (NULL == tok) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Missing entries in record line `%s'.\n"), + value); + GNUNET_free (cp); + return GNUNET_SYSERR; + } + GNUNET_free (cp); + tok++; /* skip space */ + if (GNUNET_OK != + GNUNET_GNSRECORD_string_to_value (record.record_type, + tok, + &raw_data, + &record.data_size)) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Invalid record data for type %s: `%s'.\n"), + GNUNET_GNSRECORD_number_to_typename (record.record_type), + tok); + return GNUNET_SYSERR; + } + + r = GNUNET_malloc (sizeof (struct RecordSetEntry) + record.data_size); + r->next = *head; + record.data = &r[1]; + memcpy (&r[1], + raw_data, + record.data_size); + GNUNET_free (raw_data); + r->record = record; + *head = r; + return GNUNET_OK; +} + + +/** + * Allow user to specify keywords. + * + * @param shortName short name of the option + * @param name long name of the option + * @param argumentHelp help text for the option argument + * @param description long help text for the option + * @param[out] topKeywords set to the desired value + */ +struct GNUNET_GETOPT_CommandLineOption +multirecord_option (char shortName, + const char *name, + const char *argumentHelp, + const char *description, + struct RecordSetEntry **rs) +{ + struct GNUNET_GETOPT_CommandLineOption clo = { + .shortName = shortName, + .name = name, + .argumentHelp = argumentHelp, + .description = description, + .require_argument = 1, + .processor = &multirecord_process, + .scls = (void *) rs + }; + + return clo; +} + + + /** * The main function for gnunet-namestore. * @@ -1294,6 +1492,11 @@ main (int argc, "PKEY", gettext_noop ("determine our name for the given PKEY"), &reverse_pkey), + multirecord_option ('R', + "record", + "RECORDLINE", + gettext_noop ("complete record on one line to add/delete/display; can be specified multiple times"), + &recordset), GNUNET_GETOPT_option_string ('t', "type", "TYPE", -- cgit v1.2.3 From 4103a2bf2aef3fb3a6059a99e0a941bc35406cfb Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 6 Nov 2018 15:22:13 +0100 Subject: template for Patrick --- src/namestore/gnunet-namestore.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'src') diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c index 0f0660edc..865481746 100644 --- a/src/namestore/gnunet-namestore.c +++ b/src/namestore/gnunet-namestore.c @@ -936,6 +936,44 @@ parse_expiration (const char *expirationstring, } +#if 0 +/* globals? */ +unsigned int rd_count; +struct GNUNET_GNSRECORD_Data *rd; + + +rd_count = 0; +for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) + rd_count++; +rd = GNUNET_new_array (rd_count, + struct GNUNET_GNSRECORD_Data); +rd_count = 0; +for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) +{ + rd[rd_count] = e->record; + rd_count++; +} + +/* if add: */ +qe = GNUNET_NAMESTORE_records_store (..., + rd_count, + rd, + &my_cont + ..); + +in 'my_cont' and/or shutdown: + +qe = NULL; +GNUNET_free (rd); + +in shutdown: + +if NULL != qe NAMESTORE_cancel (qe); +GNUNET_free (rd); + +#endif + + /** * Callback invoked from identity service with ego information. * An @a ego of NULL means the ego was not found. -- cgit v1.2.3 From 59e432288a4d83a371a9a3efaba2376b44873473 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 7 Nov 2018 19:25:35 +0100 Subject: get new libgnunettransportcommunicator to build --- src/include/gnunet_protocols.h | 14 +- .../gnunet_transport_communication_service.h | 1 + src/transport/Makefile.am | 12 ++ src/transport/transport.h | 26 +++- src/transport/transport_api2_communication.c | 161 +++++++++++++-------- 5 files changed, 144 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 898ad6258..16105d5a8 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -3050,15 +3050,25 @@ extern "C" */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE 1206 +/** + * Response from communicator: will try to create queue. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK 1207 + +/** + * Response from communicator: address bogus, will not try to create queue. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL 1208 + /** * @brief transport tells communicator it wants to transmit */ -#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG 1207 +#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG 1209 /** * @brief communicator tells transports that message was sent */ -#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1208 +#define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1210 /** diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h index d93d5134e..b1a248e51 100644 --- a/src/include/gnunet_transport_communication_service.h +++ b/src/include/gnunet_transport_communication_service.h @@ -42,6 +42,7 @@ extern "C" #endif #include "gnunet_util_lib.h" +#include "gnunet_ats_service.h" /** * Version number of the transport communication API. diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index d0db6b141..c6c02c6ed 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -149,6 +149,7 @@ endif lib_LTLIBRARIES = \ libgnunettransport.la \ + libgnunettransportcommunicator.la \ $(TESTING_LIBS) libgnunettransporttesting_la_SOURCES = \ @@ -187,6 +188,17 @@ libgnunettransport_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 4:0:2 + + +libgnunettransportcommunicator_la_SOURCES = \ + transport_api2_communication.c +libgnunettransportcommunicator_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +libgnunettransportcommunicator_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + libexec_PROGRAMS = \ $(WLAN_BIN) \ $(WLAN_BIN_DUMMY) \ diff --git a/src/transport/transport.h b/src/transport/transport.h index e68536bcc..5662d6c4d 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -769,7 +769,7 @@ struct GNUNET_TRANSPORT_AddQueueMessage { /** - * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE. + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP. */ struct GNUNET_MessageHeader header; @@ -799,7 +799,7 @@ struct GNUNET_TRANSPORT_DelQueueMessage { /** - * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE. + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN. */ struct GNUNET_MessageHeader header; @@ -828,9 +828,9 @@ struct GNUNET_TRANSPORT_CreateQueue struct GNUNET_MessageHeader header; /** - * Always zero. + * Unique ID for the request. */ - uint32_t reserved GNUNET_PACKED; + uint32_t request_id GNUNET_PACKED; /** * Receiver that can be addressed via the queue. @@ -841,6 +841,24 @@ struct GNUNET_TRANSPORT_CreateQueue }; +/** + * Transport tells communicator that it wants a new queue. + */ +struct GNUNET_TRANSPORT_CreateQueueResponse +{ + + /** + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK or #GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL. + */ + struct GNUNET_MessageHeader header; + + /** + * Unique ID for the request. + */ + uint32_t request_id GNUNET_PACKED; +}; + + /** * Inform communicator about transport's desire to send a message. */ diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c index d446516bd..e5be53150 100644 --- a/src/transport/transport_api2_communication.c +++ b/src/transport/transport_api2_communication.c @@ -89,6 +89,11 @@ struct AckPending */ struct AckPending *prev; + /** + * Communicator this entry belongs to. + */ + struct GNUNET_TRANSPORT_CommunicatorHandle *ch; + /** * Which peer is this about? */ @@ -134,17 +139,17 @@ struct GNUNET_TRANSPORT_CommunicatorHandle /** * DLL of messages awaiting transmission confirmation (ack). */ - struct AckPending *ac_tail; + struct AckPending *ap_tail; /** * DLL of queues we offer. */ - struct QueueHandle *queue_head; + struct GNUNET_TRANSPORT_QueueHandle *queue_head; /** * DLL of queues we offer. */ - struct QueueHandle *queue_tail; + struct GNUNET_TRANSPORT_QueueHandle *queue_tail; /** * Our configuration. @@ -167,6 +172,11 @@ struct GNUNET_TRANSPORT_CommunicatorHandle */ void *mq_init_cls; + /** + * Queue to talk to the transport service. + */ + struct GNUNET_MQ_Handle *mq; + /** * Maximum permissable queue length. */ @@ -202,6 +212,17 @@ struct GNUNET_TRANSPORT_CommunicatorHandle */ struct GNUNET_TRANSPORT_QueueHandle { + + /** + * Kept in a DLL. + */ + struct GNUNET_TRANSPORT_QueueHandle *next; + + /** + * Kept in a DLL. + */ + struct GNUNET_TRANSPORT_QueueHandle *prev; + /** * Handle this queue belongs to. */ @@ -308,7 +329,7 @@ send_add_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai) env = GNUNET_MQ_msg_extra (aam, strlen (ai->address) + 1, GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS); - aam->expiration = GNUNET_TIME_relative_to_nbo (ai->expiration); + aam->expiration = GNUNET_TIME_relative_hton (ai->expiration); aam->nt = htonl ((uint32_t) ai->nt); memcpy (&aam[1], ai->address, @@ -334,7 +355,7 @@ send_del_address (struct GNUNET_TRANSPORT_AddressIdentifier *ai) return; env = GNUNET_MQ_msg (dam, GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS); - dam.aid = htonl (ai->aid); + dam->aid = htonl (ai->aid); GNUNET_MQ_send (ai->ch->mq, env); } @@ -352,18 +373,18 @@ send_add_queue (struct GNUNET_TRANSPORT_QueueHandle *qh) struct GNUNET_MQ_Envelope *env; struct GNUNET_TRANSPORT_AddQueueMessage *aqm; - if (NULL == ai->ch->mq) + if (NULL == qh->ch->mq) return; env = GNUNET_MQ_msg_extra (aqm, - strlen (ai->address) + 1, - GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_QUEUE); - aqm.receiver = qh->peer; - aqm.nt = htonl ((uint32_t) qh->nt); - aqm.qid = htonl (qh->qid); + strlen (qh->address) + 1, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP); + aqm->receiver = qh->peer; + aqm->nt = htonl ((uint32_t) qh->nt); + aqm->qid = htonl (qh->queue_id); memcpy (&aqm[1], - ai->address, - strlen (ai->address) + 1); - GNUNET_MQ_send (ai->ch->mq, + qh->address, + strlen (qh->address) + 1); + GNUNET_MQ_send (qh->ch->mq, env); } @@ -380,13 +401,13 @@ send_del_queue (struct GNUNET_TRANSPORT_QueueHandle *qh) struct GNUNET_MQ_Envelope *env; struct GNUNET_TRANSPORT_DelQueueMessage *dqm; - if (NULL == ai->ch->mq) + if (NULL == qh->ch->mq) return; env = GNUNET_MQ_msg (dqm, - GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_QUEUE); - dqm.qid = htonl (qh->qid); - dqm.receiver = qh->peer; - GNUNET_MQ_send (ai->ch->mq, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN); + dqm->qid = htonl (qh->queue_id); + dqm->receiver = qh->peer; + GNUNET_MQ_send (qh->ch->mq, env); } @@ -444,7 +465,8 @@ error_handler (void *cls, struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "MQ failure, reconnecting to transport service.\n"); + "MQ failure %d, reconnecting to transport service.\n", + error); disconnect (ch); /* TODO: maybe do this with exponential backoff/delay */ reconnect (ch); @@ -460,7 +482,7 @@ error_handler (void *cls, */ static void handle_incoming_ack (void *cls, - struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack) + const struct GNUNET_TRANSPORT_IncomingMessageAck *incoming_ack) { struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; @@ -470,7 +492,7 @@ handle_incoming_ack (void *cls, { if ( (fc->id == incoming_ack->fc_id) && (0 == memcmp (&fc->sender, - incoming_ack->sender, + &incoming_ack->sender, sizeof (struct GNUNET_PeerIdentity))) ) { GNUNET_CONTAINER_DLL_remove (ch->fc_head, @@ -499,11 +521,12 @@ handle_incoming_ack (void *cls, */ static int check_create_queue (void *cls, - struct GNUNET_TRANSPORT_CreateQueue *cq) + const struct GNUNET_TRANSPORT_CreateQueue *cq) { uint16_t len = ntohs (cq->header.size) - sizeof (*cq); const char *addr = (const char *) &cq[1]; + (void) cls; if ( (0 == len) || ('\0' != addr[len-1]) ) { @@ -522,11 +545,13 @@ check_create_queue (void *cls, */ static void handle_create_queue (void *cls, - struct GNUNET_TRANSPORT_CreateQueue *cq) + const struct GNUNET_TRANSPORT_CreateQueue *cq) { struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; const char *addr = (const char *) &cq[1]; - + struct GNUNET_TRANSPORT_CreateQueueResponse *cqr; + struct GNUNET_MQ_Envelope *env; + if (GNUNET_OK != ch->mq_init (ch->mq_init_cls, &cq->receiver, @@ -535,8 +560,17 @@ handle_create_queue (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address `%s' invalid for this communicator\n", addr); - // TODO: do we notify the transport!? + env = GNUNET_MQ_msg (cqr, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_FAIL); } + else + { + env = GNUNET_MQ_msg (cqr, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE_OK); + } + cqr->request_id = cq->request_id; + GNUNET_MQ_send (ch->mq, + env); } @@ -550,11 +584,12 @@ handle_create_queue (void *cls, */ static int check_send_msg (void *cls, - struct GNUNET_TRANSPORT_SendMessageTo *smt) + const struct GNUNET_TRANSPORT_SendMessageTo *smt) { uint16_t len = ntohs (smt->header.size) - sizeof (*smt); const struct GNUNET_MessageHeader *mh = (const struct GNUNET_MessageHeader *) &smt[1]; + (void) cls; if (ntohs (mh->size) != len) { GNUNET_break (0); @@ -584,9 +619,9 @@ send_ack (struct GNUNET_TRANSPORT_CommunicatorHandle *ch, env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK); - ack->status = htonl (GNUNET_OK); - ack->mid = ap->mid; - ack->receiver = ap->receiver; + ack->status = htonl (status); + ack->mid = mid; + ack->receiver = *receiver; GNUNET_MQ_send (ch->mq, env); } @@ -623,18 +658,18 @@ send_ack_cb (void *cls) */ static void handle_send_msg (void *cls, - struct GNUNET_TRANSPORT_SendMessageTo *smt) + const struct GNUNET_TRANSPORT_SendMessageTo *smt) { struct GNUNET_TRANSPORT_CommunicatorHandle *ch = cls; const struct GNUNET_MessageHeader *mh; struct GNUNET_MQ_Envelope *env; struct AckPending *ap; - struct QueueHandle *qh; + struct GNUNET_TRANSPORT_QueueHandle *qh; for (qh = ch->queue_head;NULL != qh; qh = qh->next) if ( (qh->queue_id == smt->qid) && (0 == memcmp (&qh->peer, - &smt->target, + &smt->receiver, sizeof (struct GNUNET_PeerIdentity))) ) break; if (NULL == qh) @@ -653,7 +688,7 @@ handle_send_msg (void *cls, ap->receiver = smt->receiver; ap->mid = smt->mid; GNUNET_CONTAINER_DLL_insert (ch->ap_head, - cp->ap_tail, + ch->ap_tail, ap); mh = (const struct GNUNET_MessageHeader *) &smt[1]; env = GNUNET_MQ_msg_copy (mh); @@ -679,7 +714,7 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) struct GNUNET_TRANSPORT_IncomingMessageAck, ch), GNUNET_MQ_hd_var_size (create_queue, - GNUNET_MESSAGE_TYPE_TRANSPORT_CREATE_QUEUE, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_CREATE, struct GNUNET_TRANSPORT_CreateQueue, ch), GNUNET_MQ_hd_var_size (send_msg, @@ -689,7 +724,7 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) GNUNET_MQ_handler_end() }; - ch->mq = GNUNET_CLIENT_connect (cfg, + ch->mq = GNUNET_CLIENT_connect (ch->cfg, "transport", handlers, &error_handler, @@ -798,32 +833,15 @@ GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandl struct GNUNET_TRANSPORT_IncomingMessage *im; uint16_t msize; - if (NULL == ai->ch->mq) + if (NULL == ch->mq) return GNUNET_SYSERR; - if (NULL != cb) - { - struct FlowControl *fc; - - im->fc_on = htonl (GNUNET_YES); - im->fc_id = ai->ch->fc_gen++; - fc = GNUNET_new (struct FlowControl); - fc->sender = *sender; - fc->id = im->fc_id; - fc->cb = cb; - fc->cb_cls = cb_cls; - GNUNET_CONTAINER_DLL_insert (ch->fc_head, - ch->fc_tail, - fc); - } - else + if ( (NULL == cb) && + (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length) ) { - if (GNUNET_MQ_get_length (ch->mq) >= ch->max_queue_length) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Dropping message: transprot is too slow, queue length %u exceeded\n", - ch->max_queue_length); - return GNUNET_NO; - } + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Dropping message: transprot is too slow, queue length %llu exceeded\n", + ch->max_queue_length); + return GNUNET_NO; } msize = ntohs (msg->size); @@ -839,7 +857,22 @@ GNUNET_TRANSPORT_communicator_receive (struct GNUNET_TRANSPORT_CommunicatorHandl memcpy (&im[1], msg, msize); - GNUNET_MQ_send (ai->ch->mq, + if (NULL != cb) + { + struct FlowControl *fc; + + im->fc_on = htonl (GNUNET_YES); + im->fc_id = ch->fc_gen++; + fc = GNUNET_new (struct FlowControl); + fc->sender = *sender; + fc->id = im->fc_id; + fc->cb = cb; + fc->cb_cls = cb_cls; + GNUNET_CONTAINER_DLL_insert (ch->fc_head, + ch->fc_tail, + fc); + } + GNUNET_MQ_send (ch->mq, env); return GNUNET_OK; } @@ -927,9 +960,9 @@ GNUNET_TRANSPORT_communicator_address_add (struct GNUNET_TRANSPORT_CommunicatorH ai->address = GNUNET_strdup (address); ai->nt = nt; ai->expiration = expiration; - ai->aid = handle->aid_gen++; - GNUNET_CONTAINER_DLL_insert (handle->ai_head, - handle->ai_tail, + ai->aid = ch->aid_gen++; + GNUNET_CONTAINER_DLL_insert (ch->ai_head, + ch->ai_tail, ai); send_add_address (ai); return ai; -- cgit v1.2.3 From 49b581dd1c00d769e97031c51b5865846e802f8f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 7 Nov 2018 21:28:59 +0100 Subject: starting with communicator --- src/topology/gnunet-daemon-topology.c | 3 +- src/transport/gnunet-communicator-unix.c | 1649 ++++++++++++++++++++++++++++++ 2 files changed, 1651 insertions(+), 1 deletion(-) create mode 100644 src/transport/gnunet-communicator-unix.c (limited to 'src') diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c index f7a4e4525..dd384d9a1 100644 --- a/src/topology/gnunet-daemon-topology.c +++ b/src/topology/gnunet-daemon-topology.c @@ -1213,7 +1213,8 @@ run (void *cls, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c new file mode 100644 index 000000000..373b74149 --- /dev/null +++ b/src/transport/gnunet-communicator-unix.c @@ -0,0 +1,1649 @@ +/* + This file is part of GNUnet + Copyright (C) 2010-2014, 2018 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file transport/gnunet-communicator-unix.c + * @brief Transport plugin using unix domain sockets (!) + * Clearly, can only be used locally on Unix/Linux hosts... + * ONLY INTENDED FOR TESTING!!! + * @author Christian Grothoff + * @author Nathan Evans + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_statistics_service.h" +#include "gnunet_transport_communication_service.h" + +/** + * Name of the communicator. + */ +#define COMMUNICATOR_NAME "unix" + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * UNIX Message-Packet header. + */ +struct UNIXMessage +{ + /** + * Message header. + */ + struct GNUNET_MessageHeader header; + + /** + * What is the identity of the sender (GNUNET_hash of public key) + */ + struct GNUNET_PeerIdentity sender; + +}; + +GNUNET_NETWORK_STRUCT_END + + +/** + * Information we track for a message awaiting transmission. + */ +struct UNIXMessageWrapper +{ + /** + * We keep messages in a doubly linked list. + */ + struct UNIXMessageWrapper *next; + + /** + * We keep messages in a doubly linked list. + */ + struct UNIXMessageWrapper *prev; + + /** + * The actual payload (allocated separately right now). + */ + struct UNIXMessage *msg; + + /** + * Queue this message belongs to. + */ + struct Queue *queue; + + /** + * Function to call upon transmission. + */ + GNUNET_TRANSPORT_TransmitContinuation cont; + + /** + * Closure for @e cont. + */ + void *cont_cls; + + /** + * Timeout for this message. + */ + struct GNUNET_TIME_Absolute timeout; + + /** + * Number of bytes in @e msg. + */ + size_t msgsize; + + /** + * Number of bytes of payload encapsulated in @e msg. + */ + size_t payload; + + /** + * Priority of the message (ignored, just dragged along in UNIX). + */ + unsigned int priority; +}; + + +/** + * Handle for a queue. + */ +struct Queue +{ + + /** + * Queues with pending messages (!) are kept in a DLL. + */ + struct Queue *next; + + /** + * Queues with pending messages (!) are kept in a DLL. + */ + struct Queue *prev; + + /** + * To whom are we talking to (set to our identity + * if we are still waiting for the welcome message). + * + * FIXME: information duplicated with 'peer' in address! + */ + struct GNUNET_PeerIdentity target; + + /** + * Address of the other peer. + */ + struct sockaddr_un *address; + + /** + * Length of the address. + */ + socklen_t address_len; + + /** + * Message queue we are providing for the #ch. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * handle for this queue with the #ch. + */ + struct GNUNET_TRANSPORT_QueueHandle *qh; + + /** + * Number of bytes we currently have in our write queue. + */ + unsigned long long bytes_in_queue; + + /** + * Timeout for this queue. + */ + struct GNUNET_TIME_Absolute timeout; + + /** + * Queue timeout task. + */ + struct GNUNET_SCHEDULER_Task * timeout_task; + + /** + * Number of messages we currently have in our write queue. + */ + unsigned int msgs_in_queue; + +}; + + + +/** + * ID of read task + */ +static struct GNUNET_SCHEDULER_Task *read_task; + +/** + * ID of write task + */ +static struct GNUNET_SCHEDULER_Task *write_task; + +/** + * Number of bytes we currently have in our write queues. + */ +static unsigned long long bytes_in_queue; + +/** + * Our environment. + */ +static struct GNUNET_TRANSPORT_CommunicatorHandle *ch; + +/** + * Queues (map from peer identity to `struct Queue`) + */ +static struct GNUNET_CONTAINER_MultiPeerMap *queue_map; + +/** + * Head of queue of messages to transmit. + */ +static struct UNIXMessageWrapper *msg_head; + +/** + * Tail of queue of messages to transmit. + */ +static struct UNIXMessageWrapper *msg_tail; + +/** + * socket that we transmit all data with + */ +static struct GNUNET_NETWORK_Handle *unix_sock; + +/** + * Handle to the operation that publishes our address. + */ +static struct GNUNET_TRANSPORT_AddressIdentifier *ai; + + +/** + * If a queue monitor is attached, notify it about the new + * queue state. + * + * @param plugin our plugin + * @param queue queue that changed state + * @param state new state of the queue + */ +static void +notify_queue_monitor (struct Plugin *plugin, + struct Queue *queue, + enum GNUNET_TRANSPORT_QueueState state) +{ + struct GNUNET_TRANSPORT_QueueInfo info; + + if (NULL == plugin->sic) + return; + memset (&info, 0, sizeof (info)); + info.state = state; + info.is_inbound = GNUNET_SYSERR; /* hard to say */ + info.num_msg_pending = queue->msgs_in_queue; + info.num_bytes_pending = queue->bytes_in_queue; + /* info.receive_delay remains zero as this is not supported by UNIX + (cannot selectively not receive from 'some' peer while continuing + to receive from others) */ + info.queue_timeout = queue->timeout; + info.address = queue->address; + plugin->sic (plugin->sic_cls, + queue, + &info); +} + + +/** + * Function called for a quick conversion of the binary address to + * a numeric address. Note that the caller must not free the + * address and that the next call to this function is allowed + * to override the address again. + * + * @param cls closure + * @param addr binary address + * @param addrlen length of the @a addr + * @return string representing the same address + */ +static const char * +unix_plugin_address_to_string (void *cls, + const void *addr, + size_t addrlen) +{ + static char rbuf[1024]; + struct UnixAddress *ua = (struct UnixAddress *) addr; + char *addrstr; + size_t addr_str_len; + unsigned int off; + + if ((NULL == addr) || (sizeof (struct UnixAddress) > addrlen)) + { + GNUNET_break(0); + return NULL; + } + addrstr = (char *) &ua[1]; + addr_str_len = ntohl (ua->addrlen); + + if (addr_str_len != addrlen - sizeof(struct UnixAddress)) + { + GNUNET_break(0); + return NULL; + } + if ('\0' != addrstr[addr_str_len - 1]) + { + GNUNET_break(0); + return NULL; + } + if (strlen (addrstr) + 1 != addr_str_len) + { + GNUNET_break(0); + return NULL; + } + + off = 0; + if ('\0' == addrstr[0]) + off++; + memset (rbuf, 0, sizeof (rbuf)); + GNUNET_snprintf (rbuf, + sizeof (rbuf) - 1, + "%s.%u.%s%.*s", + PLUGIN_NAME, + ntohl (ua->options), + (off == 1) ? "@" : "", + (int) (addr_str_len - off), + &addrstr[off]); + return rbuf; +} + + +/** + * Functions with this signature are called whenever we need + * to close a queue due to a disconnect or failure to + * establish a connection. + * + * @param queue queue to close down + */ +static void +unix_plugin_queue_disconnect (struct Queue *queue) +{ + struct Plugin *plugin = cls; + struct UNIXMessageWrapper *msgw; + struct UNIXMessageWrapper *next; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Disconnecting queue for peer `%s'\n", + GNUNET_i2s (&queue->target)); + plugin->env->queue_end (plugin->env->cls, + queue->address, + queue); + next = plugin->msg_head; + while (NULL != next) + { + msgw = next; + next = msgw->next; + if (msgw->queue != queue) + continue; + GNUNET_CONTAINER_DLL_remove (plugin->msg_head, + plugin->msg_tail, + msgw); + queue->msgs_in_queue--; + GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); + queue->bytes_in_queue -= msgw->msgsize; + GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); + plugin->bytes_in_queue -= msgw->msgsize; + if (NULL != msgw->cont) + msgw->cont (msgw->cont_cls, + &msgw->queue->target, + GNUNET_SYSERR, + msgw->payload, 0); + GNUNET_free (msgw->msg); + GNUNET_free (msgw); + } + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (plugin->queue_map, + &queue->target, + queue)); + GNUNET_STATISTICS_set (stats, + "# UNIX queues active", + GNUNET_CONTAINER_multipeermap_size (plugin->queue_map), + GNUNET_NO); + if (NULL != queue->timeout_task) + { + GNUNET_SCHEDULER_cancel (queue->timeout_task); + queue->timeout_task = NULL; + queue->timeout = GNUNET_TIME_UNIT_ZERO_ABS; + } + GNUNET_free (queue->address); + GNUNET_break (0 == queue->bytes_in_queue); + GNUNET_break (0 == queue->msgs_in_queue); + GNUNET_free (queue); +} + + +/** + * Queue was idle for too long, so disconnect it + * + * @param cls the `struct Queue *` to disconnect + */ +static void +queue_timeout (void *cls) +{ + struct Queue *queue = cls; + struct GNUNET_TIME_Relative left; + + queue->timeout_task = NULL; + left = GNUNET_TIME_absolute_get_remaining (queue->timeout); + if (0 != left.rel_value_us) + { + /* not actually our turn yet, but let's at least update + the monitor, it may think we're about to die ... */ + queue->timeout_task + = GNUNET_SCHEDULER_add_delayed (left, + &queue_timeout, + queue); + return; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Queue %p was idle for %s, disconnecting\n", + queue, + GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + GNUNET_YES)); + unix_plugin_queue_disconnect (queue); +} + + +/** + * Increment queue timeout due to activity. We do not immediately + * notify the monitor here as that might generate excessive + * signalling. + * + * @param queue queue for which the timeout should be rescheduled + */ +static void +reschedule_queue_timeout (struct Queue *queue) +{ + GNUNET_assert (NULL != queue->timeout_task); + queue->timeout + = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); +} + + +/** + * Convert unix path to a `struct sockaddr_un *` + * + * @param unixpath path to convert + * @param[out] sock_len set to the length of the address + * @param is_abstract is this an abstract @a unixpath + * @return converted unix path + */ +static struct sockaddr_un * +unix_address_to_sockaddr (const char *unixpath, + socklen_t *sock_len, + int is_abstract) +{ + struct sockaddr_un *un; + size_t slen; + + GNUNET_assert (0 < strlen (unixpath)); /* sanity check */ + un = GNUNET_new (struct sockaddr_un); + un->sun_family = AF_UNIX; + slen = strlen (unixpath); + if (slen >= sizeof (un->sun_path)) + slen = sizeof (un->sun_path) - 1; + GNUNET_memcpy (un->sun_path, unixpath, slen); + un->sun_path[slen] = '\0'; + slen = sizeof (struct sockaddr_un); +#if HAVE_SOCKADDR_UN_SUN_LEN + un->sun_len = (u_char) slen; +#endif + (*sock_len) = slen; + if (GNUNET_YES == is_abstract) + un->sun_path[0] = '\0'; + return un; +} + + +/** + * Closure to #lookup_queue_it(). + */ +struct LookupCtx +{ + /** + * Location to store the queue, if found. + */ + struct Queue *res; + + /** + * Address we are looking for. + */ + const sockaddr_un *un; + + /** + * Number of bytes in @a un + */ + socklen_t un_len; +}; + + +/** + * Function called to find a queue by address. + * + * @param cls the `struct LookupCtx *` + * @param key peer we are looking for (unused) + * @param value a queue + * @return #GNUNET_YES if not found (continue looking), #GNUNET_NO on success + */ +static int +lookup_queue_it (void *cls, + const struct GNUNET_PeerIdentity * key, + void *value) +{ + struct LookupCtx *lctx = cls; + struct Queue *queue = value; + + if ( (queue->address_len = lctx->un_len) && + (0 == memcmp (lctx->un, + queue->address, + queue->address_len)) ) + { + lctx->res = queue; + return GNUNET_NO; + } + return GNUNET_YES; +} + + +/** + * Find an existing queue by address. + * + * @param plugin the plugin + * @param address the address to find + * @return NULL if queue was not found + */ +static struct Queue * +lookup_queue (const struct GNUNET_PeerIdentity *peer, + const sockaddr_un *un, + socklen_t un_len) +{ + struct LookupCtx lctx; + + lctx.un = un; + lctx.un_len = un_len; + GNUNET_CONTAINER_multipeermap_get_multiple (plugin->queue_map, + peer, + &lookup_queue_it, + &lctx); + return lctx.res; +} + + + +/** + * Actually send out the message, assume we've got the address and + * send_handle squared away! + * + * @param cls closure + * @param send_handle which handle to send message on + * @param target who should receive this message (ignored by UNIX) + * @param msgbuf one or more GNUNET_MessageHeader(s) strung together + * @param msgbuf_size the size of the @a msgbuf to send + * @param priority how important is the message (ignored by UNIX) + * @param timeout when should we time out (give up) if we can not transmit? + * @param addr the addr to send the message to, needs to be a sockaddr for us + * @param addrlen the len of @a addr + * @param payload bytes payload to send + * @param cont continuation to call once the message has + * been transmitted (or if the transport is ready + * for the next transmission call; or if the + * peer disconnected...) + * @param cont_cls closure for @a cont + * @return on success the number of bytes written, RETRY for retry, -1 on errors + */ +static ssize_t +unix_real_send (void *cls, + struct GNUNET_NETWORK_Handle *send_handle, + const struct GNUNET_PeerIdentity *target, + const char *msgbuf, + size_t msgbuf_size, + unsigned int priority, + struct GNUNET_TIME_Absolute timeout, + const struct UnixAddress *addr, + size_t addrlen, + size_t payload, + GNUNET_TRANSPORT_TransmitContinuation cont, + void *cont_cls) +{ + struct Plugin *plugin = cls; + ssize_t sent; + struct sockaddr_un *un; + socklen_t un_len; + const char *unixpath; + + if (NULL == send_handle) + { + GNUNET_break (0); /* We do not have a send handle */ + return GNUNET_SYSERR; + } + if ((NULL == addr) || (0 == addrlen)) + { + GNUNET_break (0); /* Can never send if we don't have an address */ + return GNUNET_SYSERR; + } + + /* Prepare address */ + unixpath = (const char *) &addr[1]; + if (NULL == (un = unix_address_to_sockaddr (unixpath, + &un_len))) + { + GNUNET_break (0); + return -1; + } + + if ((GNUNET_YES == plugin->is_abstract) && + (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & ntohl(addr->options) )) ) + { + un->sun_path[0] = '\0'; + } +resend: + /* Send the data */ + sent = GNUNET_NETWORK_socket_sendto (send_handle, + msgbuf, + msgbuf_size, + (const struct sockaddr *) un, + un_len); + if (GNUNET_SYSERR == sent) + { + if ( (EAGAIN == errno) || + (ENOBUFS == errno) ) + { + GNUNET_free (un); + return RETRY; /* We have to retry later */ + } + if (EMSGSIZE == errno) + { + socklen_t size = 0; + socklen_t len = sizeof (size); + + GNUNET_NETWORK_socket_getsockopt ((struct GNUNET_NETWORK_Handle *) + send_handle, SOL_SOCKET, SO_SNDBUF, &size, + &len); + if (size < msgbuf_size) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Trying to increase socket buffer size from %u to %u for message size %u\n", + (unsigned int) size, + (unsigned int) ((msgbuf_size / 1000) + 2) * 1000, + (unsigned int) msgbuf_size); + size = ((msgbuf_size / 1000) + 2) * 1000; + if (GNUNET_OK == + GNUNET_NETWORK_socket_setsockopt ((struct GNUNET_NETWORK_Handle *) send_handle, + SOL_SOCKET, SO_SNDBUF, + &size, sizeof (size))) + goto resend; /* Increased buffer size, retry sending */ + else + { + /* Could not increase buffer size: error, no retry */ + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt"); + GNUNET_free (un); + return GNUNET_SYSERR; + } + } + else + { + /* Buffer is bigger than message: error, no retry + * This should never happen!*/ + GNUNET_break (0); + GNUNET_free (un); + return GNUNET_SYSERR; + } + } + } + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "UNIX transmitted %u-byte message to %s (%d: %s)\n", + (unsigned int) msgbuf_size, + GNUNET_a2s ((const struct sockaddr *)un, un_len), + (int) sent, + (sent < 0) ? STRERROR (errno) : "ok"); + GNUNET_free (un); + return sent; +} + + +/** + * Function obtain the network type for a queue + * + * @param cls closure ('struct Plugin*') + * @param queue the queue + * @return the network type in HBO or #GNUNET_SYSERR + */ +static enum GNUNET_ATS_Network_Type +unix_plugin_get_network (void *cls, + struct Queue *queue) +{ + GNUNET_assert (NULL != queue); + return GNUNET_ATS_NET_LOOPBACK; +} + + +/** + * Function obtain the network type for a queue + * + * @param cls closure (`struct Plugin *`) + * @param address the address + * @return the network type + */ +static enum GNUNET_ATS_Network_Type +unix_plugin_get_network_for_address (void *cls, + const struct GNUNET_HELLO_Address *address) + +{ + return GNUNET_ATS_NET_LOOPBACK; +} + + +/** + * Creates a new outbound queue the transport service will use to send data to the + * peer + * + * @param cls the plugin + * @param address the address + * @return the queue or NULL of max connections exceeded + */ +static struct Queue * +unix_plugin_get_queue (void *cls, + const struct GNUNET_HELLO_Address *address) +{ + struct Plugin *plugin = cls; + struct Queue *queue; + struct UnixAddress *ua; + char * addrstr; + uint32_t addr_str_len; + uint32_t addr_option; + + ua = (struct UnixAddress *) address->address; + if ((NULL == address->address) || (0 == address->address_length) || + (sizeof (struct UnixAddress) > address->address_length)) + { + GNUNET_break (0); + return NULL; + } + addrstr = (char *) &ua[1]; + addr_str_len = ntohl (ua->addrlen); + addr_option = ntohl (ua->options); + + if ( (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & addr_option)) && + (GNUNET_NO == plugin->is_abstract)) + { + return NULL; + } + + if (addr_str_len != address->address_length - sizeof (struct UnixAddress)) + { + return NULL; /* This can be a legacy address */ + } + + if ('\0' != addrstr[addr_str_len - 1]) + { + GNUNET_break (0); + return NULL; + } + if (strlen (addrstr) + 1 != addr_str_len) + { + GNUNET_break (0); + return NULL; + } + + /* Check if a queue for this address already exists */ + if (NULL != (queue = lookup_queue (plugin, + address))) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Found existing queue %p for address `%s'\n", + queue, + unix_plugin_address_to_string (NULL, + address->address, + address->address_length)); + return queue; + } + + /* create a new queue */ + queue = GNUNET_new (struct Queue); + queue->target = address->peer; + queue->address = GNUNET_HELLO_address_copy (address); + queue->plugin = plugin; + queue->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); + queue->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + &queue_timeout, + queue); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Creating a new queue %p for address `%s'\n", + queue, + unix_plugin_address_to_string (NULL, + address->address, + address->address_length)); + (void) GNUNET_CONTAINER_multipeermap_put (plugin->queue_map, + &address->peer, queue, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + GNUNET_STATISTICS_set (plugin->env->stats, + "# UNIX queues active", + GNUNET_CONTAINER_multipeermap_size (plugin->queue_map), + GNUNET_NO); + notify_queue_monitor (plugin, + queue, + GNUNET_TRANSPORT_SS_INIT); + notify_queue_monitor (plugin, + queue, + GNUNET_TRANSPORT_SS_UP); + return queue; +} + + +/** + * Function that will be called whenever the transport service wants + * to notify the plugin that a queue is still active and in use and + * therefore the queue timeout for this queue has to be updated + * + * @param cls closure with the `struct Plugin *` + * @param peer which peer was the queue for + * @param queue which queue is being updated + */ +static void +unix_plugin_update_queue_timeout (void *cls, + const struct GNUNET_PeerIdentity *peer, + struct Queue *queue) +{ + struct Plugin *plugin = cls; + + if (GNUNET_OK != + GNUNET_CONTAINER_multipeermap_contains_value (plugin->queue_map, + &queue->target, + queue)) + { + GNUNET_break (0); + return; + } + reschedule_queue_timeout (queue); +} + + +/** + * Demultiplexer for UNIX messages + * + * @param plugin the main plugin for this transport + * @param sender from which peer the message was received + * @param currhdr pointer to the header of the message + * @param ua address to look for + * @param ua_len length of the address @a ua + */ +static void +unix_demultiplexer (struct Plugin *plugin, + struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *currhdr, + const struct UnixAddress *ua, + size_t ua_len) +{ + struct Queue *queue; + struct GNUNET_HELLO_Address *address; + + GNUNET_assert (ua_len >= sizeof (struct UnixAddress)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received message from %s\n", + unix_plugin_address_to_string (NULL, ua, ua_len)); + GNUNET_STATISTICS_update (plugin->env->stats, + "# bytes received via UNIX", + ntohs (currhdr->size), + GNUNET_NO); + + /* Look for existing queue */ + address = GNUNET_HELLO_address_allocate (sender, + PLUGIN_NAME, + ua, ua_len, + GNUNET_HELLO_ADDRESS_INFO_NONE); /* UNIX does not have "inbound" queues */ + queue = lookup_queue (plugin, address); + if (NULL == queue) + { + queue = unix_plugin_get_queue (plugin, address); + /* Notify transport and ATS about new inbound queue */ + plugin->env->queue_start (NULL, + queue->address, + queue, + GNUNET_ATS_NET_LOOPBACK); + } + else + { + reschedule_queue_timeout (queue); + } + GNUNET_HELLO_address_free (address); + plugin->env->receive (plugin->env->cls, + queue->address, + queue, + currhdr); +} + + +/** + * Read from UNIX domain socket (it is ready). + * + * @param plugin the plugin + */ +static void +unix_plugin_do_read (struct Plugin *plugin) +{ + char buf[65536] GNUNET_ALIGN; + struct UnixAddress *ua; + struct UNIXMessage *msg; + struct GNUNET_PeerIdentity sender; + struct sockaddr_un un; + socklen_t addrlen; + ssize_t ret; + int offset; + int tsize; + int is_abstract; + char *msgbuf; + const struct GNUNET_MessageHeader *currhdr; + uint16_t csize; + size_t ua_len; + + addrlen = sizeof (un); + memset (&un, 0, sizeof (un)); + ret = GNUNET_NETWORK_socket_recvfrom (unix_sock, + buf, sizeof (buf), + (struct sockaddr *) &un, + &addrlen); + if ((GNUNET_SYSERR == ret) && ((errno == EAGAIN) || (errno == ENOBUFS))) + return; + if (GNUNET_SYSERR == ret) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "recvfrom"); + return; + } + else + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Read %d bytes from socket %s\n", + (int) ret, + un.sun_path); + } + + GNUNET_assert (AF_UNIX == (un.sun_family)); + is_abstract = GNUNET_NO; + if ('\0' == un.sun_path[0]) + { + un.sun_path[0] = '@'; + is_abstract = GNUNET_YES; + } + + ua_len = sizeof (struct UnixAddress) + strlen (un.sun_path) + 1; + ua = GNUNET_malloc (ua_len); + ua->addrlen = htonl (strlen (&un.sun_path[0]) +1); + GNUNET_memcpy (&ua[1], &un.sun_path[0], strlen (un.sun_path) + 1); + if (is_abstract) + ua->options = htonl(UNIX_OPTIONS_USE_ABSTRACT_SOCKETS); + else + ua->options = htonl(UNIX_OPTIONS_NONE); + + msg = (struct UNIXMessage *) buf; + csize = ntohs (msg->header.size); + if ((csize < sizeof (struct UNIXMessage)) || (csize > ret)) + { + GNUNET_break_op (0); + GNUNET_free (ua); + return; + } + msgbuf = (char *) &msg[1]; + GNUNET_memcpy (&sender, + &msg->sender, + sizeof (struct GNUNET_PeerIdentity)); + offset = 0; + tsize = csize - sizeof (struct UNIXMessage); + while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize) + { + currhdr = (struct GNUNET_MessageHeader *) &msgbuf[offset]; + csize = ntohs (currhdr->size); + if ((csize < sizeof (struct GNUNET_MessageHeader)) || + (csize > tsize - offset)) + { + GNUNET_break_op (0); + break; + } + unix_demultiplexer (plugin, &sender, currhdr, ua, ua_len); + offset += csize; + } + GNUNET_free (ua); +} + + +/** + * Write to UNIX domain socket (it is ready). + * + * @param plugin handle to the plugin + */ +static void +unix_plugin_do_write (struct Plugin *plugin) +{ + ssize_t sent = 0; + struct UNIXMessageWrapper *msgw; + struct Queue *queue; + int did_delete; + + queue = NULL; + did_delete = GNUNET_NO; + while (NULL != (msgw = plugin->msg_head)) + { + if (GNUNET_TIME_absolute_get_remaining (msgw->timeout).rel_value_us > 0) + break; /* Message is ready for sending */ + /* Message has a timeout */ + did_delete = GNUNET_YES; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Timeout for message with %u bytes \n", + (unsigned int) msgw->msgsize); + GNUNET_CONTAINER_DLL_remove (plugin->msg_head, + plugin->msg_tail, + msgw); + queue = msgw->queue; + queue->msgs_in_queue--; + GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); + queue->bytes_in_queue -= msgw->msgsize; + GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); + plugin->bytes_in_queue -= msgw->msgsize; + GNUNET_STATISTICS_set (plugin->env->stats, + "# bytes currently in UNIX buffers", + plugin->bytes_in_queue, + GNUNET_NO); + GNUNET_STATISTICS_update (plugin->env->stats, + "# UNIX bytes discarded", + msgw->msgsize, + GNUNET_NO); + if (NULL != msgw->cont) + msgw->cont (msgw->cont_cls, + &msgw->queue->target, + GNUNET_SYSERR, + msgw->payload, + 0); + GNUNET_free (msgw->msg); + GNUNET_free (msgw); + } + if (NULL == msgw) + { + if (GNUNET_YES == did_delete) + notify_queue_monitor (plugin, + queue, + GNUNET_TRANSPORT_SS_UPDATE); + return; /* Nothing to send at the moment */ + } + queue = msgw->queue; + sent = unix_real_send (plugin, + unix_sock, + &queue->target, + (const char *) msgw->msg, + msgw->msgsize, + msgw->priority, + msgw->timeout, + msgw->queue->address->address, + msgw->queue->address->address_length, + msgw->payload, + msgw->cont, msgw->cont_cls); + if (RETRY == sent) + { + GNUNET_STATISTICS_update (plugin->env->stats, + "# UNIX retry attempts", + 1, GNUNET_NO); + notify_queue_monitor (plugin, + queue, + GNUNET_TRANSPORT_SS_UPDATE); + return; + } + GNUNET_CONTAINER_DLL_remove (plugin->msg_head, + plugin->msg_tail, + msgw); + queue->msgs_in_queue--; + GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); + queue->bytes_in_queue -= msgw->msgsize; + GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); + plugin->bytes_in_queue -= msgw->msgsize; + GNUNET_STATISTICS_set (plugin->env->stats, + "# bytes currently in UNIX buffers", + plugin->bytes_in_queue, GNUNET_NO); + notify_queue_monitor (plugin, + queue, + GNUNET_TRANSPORT_SS_UPDATE); + if (GNUNET_SYSERR == sent) + { + /* failed and no retry */ + if (NULL != msgw->cont) + msgw->cont (msgw->cont_cls, + &msgw->queue->target, + GNUNET_SYSERR, + msgw->payload, 0); + GNUNET_STATISTICS_update (plugin->env->stats, + "# UNIX bytes discarded", + msgw->msgsize, + GNUNET_NO); + GNUNET_free (msgw->msg); + GNUNET_free (msgw); + return; + } + /* successfully sent bytes */ + GNUNET_break (sent > 0); + GNUNET_STATISTICS_update (plugin->env->stats, + "# bytes transmitted via UNIX", + msgw->msgsize, + GNUNET_NO); + if (NULL != msgw->cont) + msgw->cont (msgw->cont_cls, + &msgw->queue->target, + GNUNET_OK, + msgw->payload, + msgw->msgsize); + GNUNET_free (msgw->msg); + GNUNET_free (msgw); +} + + +/** + * We have been notified that our socket has something to read. + * Then reschedule this function to be called again once more is available. + * + * @param cls the plugin handle + */ +static void +unix_plugin_select_read (void *cls) +{ + struct Plugin *plugin = cls; + const struct GNUNET_SCHEDULER_TaskContext *tc; + + plugin->read_task = NULL; + tc = GNUNET_SCHEDULER_get_task_context (); + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) + unix_plugin_do_read (plugin); + plugin->read_task = + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &unix_plugin_select_read, plugin); +} + + +/** + * We have been notified that our socket is ready to write. + * Then reschedule this function to be called again once more is available. + * + * @param cls the plugin handle + */ +static void +unix_plugin_select_write (void *cls) +{ + struct Plugin *plugin = cls; + const struct GNUNET_SCHEDULER_TaskContext *tc; + + plugin->write_task = NULL; + tc = GNUNET_SCHEDULER_get_task_context (); + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) + unix_plugin_do_write (plugin); + if (NULL == plugin->msg_head) + return; /* write queue empty */ + plugin->write_task = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &unix_plugin_select_write, plugin); +} + + +/** + * Function that can be used by the transport service to transmit + * a message using the plugin. Note that in the case of a + * peer disconnecting, the continuation MUST be called + * prior to the disconnect notification itself. This function + * will be called with this peer's HELLO message to initiate + * a fresh connection to another peer. + * + * @param cls closure + * @param queue which queue must be used + * @param msgbuf the message to transmit + * @param msgbuf_size number of bytes in @a msgbuf + * @param priority how important is the message (most plugins will + * ignore message priority and just FIFO) + * @param to how long to wait at most for the transmission (does not + * require plugins to discard the message after the timeout, + * just advisory for the desired delay; most plugins will ignore + * this as well) + * @param cont continuation to call once the message has + * been transmitted (or if the transport is ready + * for the next transmission call; or if the + * peer disconnected...); can be NULL + * @param cont_cls closure for @a cont + * @return number of bytes used (on the physical network, with overheads); + * -1 on hard errors (i.e. address invalid); 0 is a legal value + * and does NOT mean that the message was not transmitted (DV) + */ +static ssize_t +unix_plugin_send (void *cls, + struct Queue *queue, + const char *msgbuf, + size_t msgbuf_size, + unsigned int priority, + struct GNUNET_TIME_Relative to, + GNUNET_TRANSPORT_TransmitContinuation cont, + void *cont_cls) +{ + struct Plugin *plugin = cls; + struct UNIXMessageWrapper *wrapper; + struct UNIXMessage *message; + int ssize; + + if (GNUNET_OK != + GNUNET_CONTAINER_multipeermap_contains_value (plugin->queue_map, + &queue->target, + queue)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Invalid queue for peer `%s' `%s'\n", + GNUNET_i2s (&queue->target), + unix_plugin_address_to_string (NULL, + queue->address->address, + queue->address->address_length)); + GNUNET_break (0); + return GNUNET_SYSERR; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Sending %u bytes with queue for peer `%s' `%s'\n", + msgbuf_size, + GNUNET_i2s (&queue->target), + unix_plugin_address_to_string (NULL, + queue->address->address, + queue->address->address_length)); + ssize = sizeof (struct UNIXMessage) + msgbuf_size; + message = GNUNET_malloc (sizeof (struct UNIXMessage) + msgbuf_size); + message->header.size = htons (ssize); + message->header.type = htons (0); + GNUNET_memcpy (&message->sender, plugin->env->my_identity, + sizeof (struct GNUNET_PeerIdentity)); + GNUNET_memcpy (&message[1], msgbuf, msgbuf_size); + wrapper = GNUNET_new (struct UNIXMessageWrapper); + wrapper->msg = message; + wrapper->msgsize = ssize; + wrapper->payload = msgbuf_size; + wrapper->priority = priority; + wrapper->timeout = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + to); + wrapper->cont = cont; + wrapper->cont_cls = cont_cls; + wrapper->queue = queue; + GNUNET_CONTAINER_DLL_insert_tail (plugin->msg_head, + plugin->msg_tail, + wrapper); + plugin->bytes_in_queue += ssize; + queue->bytes_in_queue += ssize; + queue->msgs_in_queue++; + GNUNET_STATISTICS_set (plugin->env->stats, + "# bytes currently in UNIX buffers", + plugin->bytes_in_queue, + GNUNET_NO); + notify_queue_monitor (plugin, + queue, + GNUNET_TRANSPORT_SS_UPDATE); + if (NULL == plugin->write_task) + plugin->write_task = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &unix_plugin_select_write, plugin); + return ssize; +} + + +/** + * Signature of functions implementing the + * sending functionality of a message queue. + * + * @param mq the message queue + * @param msg the message to send + * @param impl_state state of the implementation + */ +static void +mq_send (struct GNUNET_MQ_Handle *mq, + const struct GNUNET_MessageHeader *msg, + void *impl_state) +{ +} + + +/** + * Signature of functions implementing the + * destruction of a message queue. + * Implementations must not free @a mq, but should + * take care of @a impl_state. + * + * @param mq the message queue to destroy + * @param impl_state state of the implementation + */ +static void +mq_destroy (struct GNUNET_MQ_Handle *mq, + void *impl_state) +{ +} + + +/** + * Implementation function that cancels the currently sent message. + * + * @param mq message queue + * @param impl_state state specific to the implementation + */ +static void +mq_cancel (struct GNUNET_MQ_Handle *mq, + void *impl_state) +{ +} + + +/** + * Generic error handler, called with the appropriate + * error code and the same closure specified at the creation of + * the message queue. + * Not every message queue implementation supports an error handler. + * + * @param cls closure + * @param error error code + */ +static void +mq_error (void *cls, + enum GNUNET_MQ_Error error) +{ +} + + + +/** + * Function called by the transport service to initialize a + * message queue given address information about another peer. + * If and when the communication channel is established, the + * communicator must call #GNUNET_TRANSPORT_communicator_mq_add() + * to notify the service that the channel is now up. It is + * the responsibility of the communicator to manage sane + * retries and timeouts for any @a peer/@a address combination + * provided by the transport service. Timeouts and retries + * do not need to be signalled to the transport service. + * + * @param cls closure + * @param peer identity of the other peer + * @param address where to send the message, human-readable + * communicator-specific format, 0-terminated, UTF-8 + * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid + */ +static int +mq_init (void *cls, + const struct GNUNET_PeerIdentity *peer, + const void *address) +{ + struct Queue *queue; + char *a; + char *e; + int is_abs; + sockaddr_un *un; + socklen_t un_len; + + if (NULL == strncmp (address, + COMMUNICATOR_NAME "-", + strlen (COMMUNICATOR_NAME "-"))) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + a = GNUNET_strdup (&address[strlen (COMMUNICATOR_NAME "-")]); + e = strchr (a, + (unsigned char) '#'); + if (NULL == e) + { + GNUNET_free (a); + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + is_abs = ('1' == e[1]); + *e = '\0'; + un = unix_address_to_sockaddr (a, + &un_len, + is_abs); + queue = lookup_queue (peer, + un, + un_len); + if (NULL != queue) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Address `%s' ignored, queue exists\n", + address); + GNUNET_free (un); + return GNUNET_OK; + } + queue = GNUNET_new (struct Queue); + queue->target = *peer; + queue->address = un; + queue->address_len = un_len; + (void) GNUNET_CONTAINER_multihashmap_put (queue_map, + &queue->target, + queue, + GNUET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + GNUNET_STATISTICS_set (stats, + "# UNIX queues active", + GNUNET_CONTAINER_multipeermap_size (plugin->queue_map), + GNUNET_NO); + queue->timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + &queue_timeout, + queue); + queue->mq + = GNUNET_MQ_queue_for_callbacks (&mq_send, + &mq_destroy, + &mq_cancel, + queue, + NULL, + &mq_error, + queue); + queue->qh + = GNUNET_TRANSPORT_communicator_mq_add (ch, + &queue->target, + address, + ATS, + queue->mq); + return GNUNET_OK; +} + + +/** + * Shutdown the UNIX communicator. + * + * @param cls NULL (always) + */ +static void +do_shutdown (void *cls) +{ + struct UNIXMessageWrapper *msgw; + + while (NULL != (msgw = msg_head)) + { + GNUNET_CONTAINER_DLL_remove (msg_head, + msg_tail, + msgw); + queue = msgw->queue; + queue->msgs_in_queue--; + GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); + queue->bytes_in_queue -= msgw->msgsize; + GNUNET_assert (bytes_in_queue >= msgw->msgsize); + bytes_in_queue -= msgw->msgsize; + GNUNET_free (msgw->msg); + GNUNET_free (msgw); + } + if (NULL != read_task) + { + GNUNET_SCHEDULER_cancel (read_task); + read_task = NULL; + } + if (NULL != write_task) + { + GNUNET_SCHEDULER_cancel (write_task); + write_task = NULL; + } + if (NULL != unix_sock) + { + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (unix_sock)); + unix_sock = NULL; + } + GNUNET_CONTAINER_multipeermap_iterate (queue_map, + &get_queue_delete_it, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (queue_map); + if (NULL != ai) + { + GNUNET_TRANSPORT_communicator_address_remove (ai); + ai = NULL; + } + if (NULL != ch) + { + GNUNET_TRANSPORT_communicator_disconnect (ch); + ch = NULL; + } + GNUNET_break (0 == bytes_in_queue); +} + + +/** + * Setup communicator and launch network interactions. + * + * @param cls NULL (always) + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *unix_socket_path; + int is_abstract; + struct sockaddr_un *un; + socklen_t un_len; + char *my_addr; + (void) cls; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, + "transport-unix", + "UNIXPATH", + &unix_socket_path)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "communicator-unix", + "UNIXPATH"); + return; + } + + /* Initialize my flags */ + is_abstract = 0; +#ifdef LINUX + is_abstract + = GNUNET_CONFIGURATION_get_value_yesno (cfg, + "testing", + "USE_ABSTRACT_SOCKETS"); +#endif + un = unix_address_to_sockaddr (unix_socket_path, + &un_len, + is_abstract); + unix_sock = GNUNET_NETWORK_socket_create (AF_UNIX, + SOCK_DGRAM, + 0); + if (NULL == unix_sock) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "socket"); + GNUNET_free (un); + GNUNET_free (unix_socket_path); + return; + } + if ( ('\0' != un->sun_path[0]) && + (GNUNET_OK != + GNUNET_DISK_directory_create_for_file (un->sun_path)) ) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Cannot create path to `%s'\n"), + un->sun_path); + GNUNET_NETWORK_socket_close (unix_sock); + unix_sock = NULL; + GNUNET_free (un); + GNUNET_free (unix_socket_path); + return; + } + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (unix_sock, + (const struct sockaddr *) un, + un_len)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "bind"); + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Cannot bind to `%s'\n"), + un->sun_path); + GNUNET_NETWORK_socket_close (unix_sock); + unix_sock = NULL; + GNUNET_free (un); + GNUNET_free (unix_socket_path); + return; + } + GNUNET_free (un); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Bound to `%s'\n", + unix_socket_path); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, + NULL); + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &unix_plugin_select_read, + NULL); + queue_map = GNUNET_CONTAINER_multipeermap_create (10, + GNUNET_NO); + ch = GNUNET_TRANSPORT_communicator_connect (cfg, + "unix", + 65535, + &mq_init, + NULL); + if (NULL == ch) + { + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + GNUNET_free (unix_socket_path); + return; + } + GNUNET_asprintf (&my_addr, + "%s-%s#%d", + COMMUNICATOR_NAME, + unix_socket_path, + is_abstract); + + ai = GNUNET_TRANSPORT_communicator_address_add (ch, + my_addr, + GNUNET_ATS_NET_LOOPBACK, + GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_free (my_addr); + GNUNET_free (unix_socket_path); +} + + +/** + * The main function for the UNIX communicator. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, + char *const *argv) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + int ret; + + if (GNUNET_OK != + GNUNET_STRINGS_get_utf8_args (argc, argv, + &argc, &argv)) + return 2; + + ret = + (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, + "gnunet-communicator-unix", + _("GNUnet UNIX domain socket communicator"), + options, + &run, + NULL)) ? 0 : 1; + GNUNET_free ((void*) argv); + return ret; +} + + +#if defined(LINUX) && defined(__GLIBC__) +#include + +/** + * MINIMIZE heap size (way below 128k) since this process doesn't need much. + */ +void __attribute__ ((constructor)) +GNUNET_ARM_memory_init () +{ + mallopt (M_TRIM_THRESHOLD, 4 * 1024); + mallopt (M_TOP_PAD, 1 * 1024); + malloc_trim (0); +} +#endif + +/* end of gnunet-communicator-unix.c */ -- cgit v1.2.3 From a18d1f2587ca5df5a9c6e47c012bfbaf3f19098c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 8 Nov 2018 11:32:03 +0100 Subject: work on UNIX communicator --- src/transport/gnunet-communicator-unix.c | 1072 ++++++++------------------ src/transport/transport_api2_communication.c | 1 + 2 files changed, 315 insertions(+), 758 deletions(-) (limited to 'src') diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c index 373b74149..f07975186 100644 --- a/src/transport/gnunet-communicator-unix.c +++ b/src/transport/gnunet-communicator-unix.c @@ -30,6 +30,16 @@ #include "gnunet_statistics_service.h" #include "gnunet_transport_communication_service.h" +/** + * How many messages do we keep at most in the queue to the + * transport service before we start to drop (default, + * can be changed via the configuration file). + * Should be _below_ the level of the communicator API, as + * otherwise we may read messages just to have them dropped + * by the communicator API. + */ +#define DEFAULT_MAX_QUEUE_LENGTH 8 + /** * Name of the communicator. */ @@ -58,63 +68,6 @@ struct UNIXMessage GNUNET_NETWORK_STRUCT_END -/** - * Information we track for a message awaiting transmission. - */ -struct UNIXMessageWrapper -{ - /** - * We keep messages in a doubly linked list. - */ - struct UNIXMessageWrapper *next; - - /** - * We keep messages in a doubly linked list. - */ - struct UNIXMessageWrapper *prev; - - /** - * The actual payload (allocated separately right now). - */ - struct UNIXMessage *msg; - - /** - * Queue this message belongs to. - */ - struct Queue *queue; - - /** - * Function to call upon transmission. - */ - GNUNET_TRANSPORT_TransmitContinuation cont; - - /** - * Closure for @e cont. - */ - void *cont_cls; - - /** - * Timeout for this message. - */ - struct GNUNET_TIME_Absolute timeout; - - /** - * Number of bytes in @e msg. - */ - size_t msgsize; - - /** - * Number of bytes of payload encapsulated in @e msg. - */ - size_t payload; - - /** - * Priority of the message (ignored, just dragged along in UNIX). - */ - unsigned int priority; -}; - - /** * Handle for a queue. */ @@ -132,10 +85,7 @@ struct Queue struct Queue *prev; /** - * To whom are we talking to (set to our identity - * if we are still waiting for the welcome message). - * - * FIXME: information duplicated with 'peer' in address! + * To whom are we talking to. */ struct GNUNET_PeerIdentity target; @@ -149,6 +99,12 @@ struct Queue */ socklen_t address_len; + /** + * Message currently scheduled for transmission, non-NULL if and only + * if this queue is in the #queue_head DLL. + */ + const struct GNUNET_MessageHeader *msg; + /** * Message queue we are providing for the #ch. */ @@ -172,17 +128,11 @@ struct Queue /** * Queue timeout task. */ - struct GNUNET_SCHEDULER_Task * timeout_task; - - /** - * Number of messages we currently have in our write queue. - */ - unsigned int msgs_in_queue; + struct GNUNET_SCHEDULER_Task *timeout_task; }; - /** * ID of read task */ @@ -194,9 +144,14 @@ static struct GNUNET_SCHEDULER_Task *read_task; static struct GNUNET_SCHEDULER_Task *write_task; /** - * Number of bytes we currently have in our write queues. + * Number of messages we currently have in our queues towards the transport service. */ -static unsigned long long bytes_in_queue; +static unsigned long long delivering_messages; + +/** + * Maximum queue length before we stop reading towards the transport service. + */ +static unsigned long long max_queue_length; /** * Our environment. @@ -211,12 +166,12 @@ static struct GNUNET_CONTAINER_MultiPeerMap *queue_map; /** * Head of queue of messages to transmit. */ -static struct UNIXMessageWrapper *msg_head; +static struct Queue *queue_head; /** * Tail of queue of messages to transmit. */ -static struct UNIXMessageWrapper *msg_tail; +static struct Queue *queue_tail; /** * socket that we transmit all data with @@ -229,101 +184,6 @@ static struct GNUNET_NETWORK_Handle *unix_sock; static struct GNUNET_TRANSPORT_AddressIdentifier *ai; -/** - * If a queue monitor is attached, notify it about the new - * queue state. - * - * @param plugin our plugin - * @param queue queue that changed state - * @param state new state of the queue - */ -static void -notify_queue_monitor (struct Plugin *plugin, - struct Queue *queue, - enum GNUNET_TRANSPORT_QueueState state) -{ - struct GNUNET_TRANSPORT_QueueInfo info; - - if (NULL == plugin->sic) - return; - memset (&info, 0, sizeof (info)); - info.state = state; - info.is_inbound = GNUNET_SYSERR; /* hard to say */ - info.num_msg_pending = queue->msgs_in_queue; - info.num_bytes_pending = queue->bytes_in_queue; - /* info.receive_delay remains zero as this is not supported by UNIX - (cannot selectively not receive from 'some' peer while continuing - to receive from others) */ - info.queue_timeout = queue->timeout; - info.address = queue->address; - plugin->sic (plugin->sic_cls, - queue, - &info); -} - - -/** - * Function called for a quick conversion of the binary address to - * a numeric address. Note that the caller must not free the - * address and that the next call to this function is allowed - * to override the address again. - * - * @param cls closure - * @param addr binary address - * @param addrlen length of the @a addr - * @return string representing the same address - */ -static const char * -unix_plugin_address_to_string (void *cls, - const void *addr, - size_t addrlen) -{ - static char rbuf[1024]; - struct UnixAddress *ua = (struct UnixAddress *) addr; - char *addrstr; - size_t addr_str_len; - unsigned int off; - - if ((NULL == addr) || (sizeof (struct UnixAddress) > addrlen)) - { - GNUNET_break(0); - return NULL; - } - addrstr = (char *) &ua[1]; - addr_str_len = ntohl (ua->addrlen); - - if (addr_str_len != addrlen - sizeof(struct UnixAddress)) - { - GNUNET_break(0); - return NULL; - } - if ('\0' != addrstr[addr_str_len - 1]) - { - GNUNET_break(0); - return NULL; - } - if (strlen (addrstr) + 1 != addr_str_len) - { - GNUNET_break(0); - return NULL; - } - - off = 0; - if ('\0' == addrstr[0]) - off++; - memset (rbuf, 0, sizeof (rbuf)); - GNUNET_snprintf (rbuf, - sizeof (rbuf) - 1, - "%s.%u.%s%.*s", - PLUGIN_NAME, - ntohl (ua->options), - (off == 1) ? "@" : "", - (int) (addr_str_len - off), - &addrstr[off]); - return rbuf; -} - - /** * Functions with this signature are called whenever we need * to close a queue due to a disconnect or failure to @@ -332,58 +192,40 @@ unix_plugin_address_to_string (void *cls, * @param queue queue to close down */ static void -unix_plugin_queue_disconnect (struct Queue *queue) +queue_destroy (struct Queue *queue) { struct Plugin *plugin = cls; - struct UNIXMessageWrapper *msgw; - struct UNIXMessageWrapper *next; + struct GNUNET_MQ_Handle *mq; LOG (GNUNET_ERROR_TYPE_DEBUG, - "Disconnecting queue for peer `%s'\n", + "Disconnecting queue for peer `%s'\n", GNUNET_i2s (&queue->target)); - plugin->env->queue_end (plugin->env->cls, - queue->address, - queue); - next = plugin->msg_head; - while (NULL != next) + if (0 != queue->bytes_in_queue) { - msgw = next; - next = msgw->next; - if (msgw->queue != queue) - continue; - GNUNET_CONTAINER_DLL_remove (plugin->msg_head, - plugin->msg_tail, - msgw); - queue->msgs_in_queue--; - GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); - queue->bytes_in_queue -= msgw->msgsize; - GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); - plugin->bytes_in_queue -= msgw->msgsize; - if (NULL != msgw->cont) - msgw->cont (msgw->cont_cls, - &msgw->queue->target, - GNUNET_SYSERR, - msgw->payload, 0); - GNUNET_free (msgw->msg); - GNUNET_free (msgw); + GNUNET_CONTAINER_DLL_remove (queue_head, + queue_tail, + queue); + queue->bytes_in_queue = 0; + } + if (NULL != (mq = queue->mq)) + { + queue->mq = NULL; + GNUNET_MQ_destroy (mq); } GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (plugin->queue_map, + GNUNET_CONTAINER_multipeermap_remove (queue_map, &queue->target, queue)); GNUNET_STATISTICS_set (stats, "# UNIX queues active", - GNUNET_CONTAINER_multipeermap_size (plugin->queue_map), + GNUNET_CONTAINER_multipeermap_size (queue_map), GNUNET_NO); if (NULL != queue->timeout_task) { GNUNET_SCHEDULER_cancel (queue->timeout_task); queue->timeout_task = NULL; - queue->timeout = GNUNET_TIME_UNIT_ZERO_ABS; } GNUNET_free (queue->address); - GNUNET_break (0 == queue->bytes_in_queue); - GNUNET_break (0 == queue->msgs_in_queue); GNUNET_free (queue); } @@ -416,7 +258,7 @@ queue_timeout (void *cls) queue, GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_YES)); - unix_plugin_queue_disconnect (queue); + queue_destroy (queue); } @@ -458,7 +300,9 @@ unix_address_to_sockaddr (const char *unixpath, slen = strlen (unixpath); if (slen >= sizeof (un->sun_path)) slen = sizeof (un->sun_path) - 1; - GNUNET_memcpy (un->sun_path, unixpath, slen); + GNUNET_memcpy (un->sun_path, + unixpath, + slen); un->sun_path[slen] = '\0'; slen = sizeof (struct sockaddr_un); #if HAVE_SOCKADDR_UN_SUN_LEN @@ -545,182 +389,19 @@ lookup_queue (const struct GNUNET_PeerIdentity *peer, } - -/** - * Actually send out the message, assume we've got the address and - * send_handle squared away! - * - * @param cls closure - * @param send_handle which handle to send message on - * @param target who should receive this message (ignored by UNIX) - * @param msgbuf one or more GNUNET_MessageHeader(s) strung together - * @param msgbuf_size the size of the @a msgbuf to send - * @param priority how important is the message (ignored by UNIX) - * @param timeout when should we time out (give up) if we can not transmit? - * @param addr the addr to send the message to, needs to be a sockaddr for us - * @param addrlen the len of @a addr - * @param payload bytes payload to send - * @param cont continuation to call once the message has - * been transmitted (or if the transport is ready - * for the next transmission call; or if the - * peer disconnected...) - * @param cont_cls closure for @a cont - * @return on success the number of bytes written, RETRY for retry, -1 on errors - */ -static ssize_t -unix_real_send (void *cls, - struct GNUNET_NETWORK_Handle *send_handle, - const struct GNUNET_PeerIdentity *target, - const char *msgbuf, - size_t msgbuf_size, - unsigned int priority, - struct GNUNET_TIME_Absolute timeout, - const struct UnixAddress *addr, - size_t addrlen, - size_t payload, - GNUNET_TRANSPORT_TransmitContinuation cont, - void *cont_cls) -{ - struct Plugin *plugin = cls; - ssize_t sent; - struct sockaddr_un *un; - socklen_t un_len; - const char *unixpath; - - if (NULL == send_handle) - { - GNUNET_break (0); /* We do not have a send handle */ - return GNUNET_SYSERR; - } - if ((NULL == addr) || (0 == addrlen)) - { - GNUNET_break (0); /* Can never send if we don't have an address */ - return GNUNET_SYSERR; - } - - /* Prepare address */ - unixpath = (const char *) &addr[1]; - if (NULL == (un = unix_address_to_sockaddr (unixpath, - &un_len))) - { - GNUNET_break (0); - return -1; - } - - if ((GNUNET_YES == plugin->is_abstract) && - (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & ntohl(addr->options) )) ) - { - un->sun_path[0] = '\0'; - } -resend: - /* Send the data */ - sent = GNUNET_NETWORK_socket_sendto (send_handle, - msgbuf, - msgbuf_size, - (const struct sockaddr *) un, - un_len); - if (GNUNET_SYSERR == sent) - { - if ( (EAGAIN == errno) || - (ENOBUFS == errno) ) - { - GNUNET_free (un); - return RETRY; /* We have to retry later */ - } - if (EMSGSIZE == errno) - { - socklen_t size = 0; - socklen_t len = sizeof (size); - - GNUNET_NETWORK_socket_getsockopt ((struct GNUNET_NETWORK_Handle *) - send_handle, SOL_SOCKET, SO_SNDBUF, &size, - &len); - if (size < msgbuf_size) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Trying to increase socket buffer size from %u to %u for message size %u\n", - (unsigned int) size, - (unsigned int) ((msgbuf_size / 1000) + 2) * 1000, - (unsigned int) msgbuf_size); - size = ((msgbuf_size / 1000) + 2) * 1000; - if (GNUNET_OK == - GNUNET_NETWORK_socket_setsockopt ((struct GNUNET_NETWORK_Handle *) send_handle, - SOL_SOCKET, SO_SNDBUF, - &size, sizeof (size))) - goto resend; /* Increased buffer size, retry sending */ - else - { - /* Could not increase buffer size: error, no retry */ - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt"); - GNUNET_free (un); - return GNUNET_SYSERR; - } - } - else - { - /* Buffer is bigger than message: error, no retry - * This should never happen!*/ - GNUNET_break (0); - GNUNET_free (un); - return GNUNET_SYSERR; - } - } - } - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "UNIX transmitted %u-byte message to %s (%d: %s)\n", - (unsigned int) msgbuf_size, - GNUNET_a2s ((const struct sockaddr *)un, un_len), - (int) sent, - (sent < 0) ? STRERROR (errno) : "ok"); - GNUNET_free (un); - return sent; -} - - /** - * Function obtain the network type for a queue + * Creates a new outbound queue the transport service will use to send + * data to another peer. * - * @param cls closure ('struct Plugin*') - * @param queue the queue - * @return the network type in HBO or #GNUNET_SYSERR - */ -static enum GNUNET_ATS_Network_Type -unix_plugin_get_network (void *cls, - struct Queue *queue) -{ - GNUNET_assert (NULL != queue); - return GNUNET_ATS_NET_LOOPBACK; -} - - -/** - * Function obtain the network type for a queue - * - * @param cls closure (`struct Plugin *`) - * @param address the address - * @return the network type - */ -static enum GNUNET_ATS_Network_Type -unix_plugin_get_network_for_address (void *cls, - const struct GNUNET_HELLO_Address *address) - -{ - return GNUNET_ATS_NET_LOOPBACK; -} - - -/** - * Creates a new outbound queue the transport service will use to send data to the - * peer - * - * @param cls the plugin - * @param address the address + * @param peer the target peer + * @param un the address + * @param un_len number of bytes in @a un * @return the queue or NULL of max connections exceeded */ static struct Queue * -unix_plugin_get_queue (void *cls, - const struct GNUNET_HELLO_Address *address) +unix_plugin_get_queue (const struct GNUNET_PeerIdentity *target, + const struct sockaddr_un *un, + socklen_t un_len) { struct Plugin *plugin = cls; struct Queue *queue; @@ -728,53 +409,22 @@ unix_plugin_get_queue (void *cls, char * addrstr; uint32_t addr_str_len; uint32_t addr_option; + char *foreign_addr; + int is_abstract; + + if (is_abstract = ('\0' == un.sun_path[0])) + un.sun_path[0] = '/'; + GNUNET_asprintf (&foreign_addr, + "%s-%s#%d", + COMMUNICATOR_NAME, + un.sun_path, + is_abstract); + - ua = (struct UnixAddress *) address->address; - if ((NULL == address->address) || (0 == address->address_length) || - (sizeof (struct UnixAddress) > address->address_length)) - { - GNUNET_break (0); - return NULL; - } addrstr = (char *) &ua[1]; addr_str_len = ntohl (ua->addrlen); addr_option = ntohl (ua->options); - if ( (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & addr_option)) && - (GNUNET_NO == plugin->is_abstract)) - { - return NULL; - } - - if (addr_str_len != address->address_length - sizeof (struct UnixAddress)) - { - return NULL; /* This can be a legacy address */ - } - - if ('\0' != addrstr[addr_str_len - 1]) - { - GNUNET_break (0); - return NULL; - } - if (strlen (addrstr) + 1 != addr_str_len) - { - GNUNET_break (0); - return NULL; - } - - /* Check if a queue for this address already exists */ - if (NULL != (queue = lookup_queue (plugin, - address))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Found existing queue %p for address `%s'\n", - queue, - unix_plugin_address_to_string (NULL, - address->address, - address->address_length)); - return queue; - } - /* create a new queue */ queue = GNUNET_new (struct Queue); queue->target = address->peer; @@ -795,14 +445,8 @@ unix_plugin_get_queue (void *cls, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GNUNET_STATISTICS_set (plugin->env->stats, "# UNIX queues active", - GNUNET_CONTAINER_multipeermap_size (plugin->queue_map), + GNUNET_CONTAINER_multipeermap_size (queue_map), GNUNET_NO); - notify_queue_monitor (plugin, - queue, - GNUNET_TRANSPORT_SS_INIT); - notify_queue_monitor (plugin, - queue, - GNUNET_TRANSPORT_SS_UP); return queue; } @@ -891,245 +535,146 @@ unix_demultiplexer (struct Plugin *plugin, /** - * Read from UNIX domain socket (it is ready). + * We have been notified that our socket has something to read. Do the + * read and reschedule this function to be called again once more is + * available. * - * @param plugin the plugin + * @param cls NULL + */ +static void +select_read_cb (void *cls); + + +/** + * Function called when message was successfully passed to + * transport service. Continue read activity. + * + * @param cls NULL + */ +static void +receive_complete_cb (void *cls) +{ + delivering_messages--; + if ( (NULL == read_task) && + (delivering_messages < max_queue_length) ) + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); +} + + +/** + * We have been notified that our socket has something to read. Do the + * read and reschedule this function to be called again once more is + * available. + * + * @param cls NULL */ static void -unix_plugin_do_read (struct Plugin *plugin) +select_read_cb (void *cls) { char buf[65536] GNUNET_ALIGN; - struct UnixAddress *ua; - struct UNIXMessage *msg; - struct GNUNET_PeerIdentity sender; + struct Queue *queue; + const struct UNIXMessage *msg; struct sockaddr_un un; socklen_t addrlen; ssize_t ret; - int offset; - int tsize; - int is_abstract; - char *msgbuf; - const struct GNUNET_MessageHeader *currhdr; - uint16_t csize; - size_t ua_len; + uint16_t msize; + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); addrlen = sizeof (un); - memset (&un, 0, sizeof (un)); + memset (&un, + 0, + sizeof (un)); ret = GNUNET_NETWORK_socket_recvfrom (unix_sock, - buf, sizeof (buf), + buf, + sizeof (buf), (struct sockaddr *) &un, &addrlen); - if ((GNUNET_SYSERR == ret) && ((errno == EAGAIN) || (errno == ENOBUFS))) + if ( (-1 == ret) && + ( (EAGAIN == errno) || + (ENOBUFS == errno) ) ) return; - if (GNUNET_SYSERR == ret) + if (-1 == ret) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom"); return; } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Read %d bytes from socket %s\n", - (int) ret, - un.sun_path); - } - + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Read %d bytes from socket %s\n", + (int) ret, + un.sun_path); GNUNET_assert (AF_UNIX == (un.sun_family)); - is_abstract = GNUNET_NO; - if ('\0' == un.sun_path[0]) - { - un.sun_path[0] = '@'; - is_abstract = GNUNET_YES; - } - - ua_len = sizeof (struct UnixAddress) + strlen (un.sun_path) + 1; - ua = GNUNET_malloc (ua_len); - ua->addrlen = htonl (strlen (&un.sun_path[0]) +1); - GNUNET_memcpy (&ua[1], &un.sun_path[0], strlen (un.sun_path) + 1); - if (is_abstract) - ua->options = htonl(UNIX_OPTIONS_USE_ABSTRACT_SOCKETS); - else - ua->options = htonl(UNIX_OPTIONS_NONE); - msg = (struct UNIXMessage *) buf; - csize = ntohs (msg->header.size); - if ((csize < sizeof (struct UNIXMessage)) || (csize > ret)) + msize = ntohs (msg->header.size); + if ( (msize < sizeof (struct UNIXMessage)) || + (msize > ret) ) { GNUNET_break_op (0); - GNUNET_free (ua); return; } - msgbuf = (char *) &msg[1]; - GNUNET_memcpy (&sender, - &msg->sender, - sizeof (struct GNUNET_PeerIdentity)); - offset = 0; - tsize = csize - sizeof (struct UNIXMessage); - while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize) + queue = lookup_queue (&msg->sender, + un, + addrlen); + if (NULL == queue) + queue = setup_queue (&msg->sender, + un, + addrlen); + if (NULL == queue) { - currhdr = (struct GNUNET_MessageHeader *) &msgbuf[offset]; - csize = ntohs (currhdr->size); - if ((csize < sizeof (struct GNUNET_MessageHeader)) || - (csize > tsize - offset)) - { - GNUNET_break_op (0); - break; - } - unix_demultiplexer (plugin, &sender, currhdr, ua, ua_len); - offset += csize; + GNUENT_log (GNUNET_ERROR_TYPE_ERROR, + _("Maximum number of UNIX connections exceeded, dropping incoming message\n")); + return; } - GNUNET_free (ua); -} - - -/** - * Write to UNIX domain socket (it is ready). - * - * @param plugin handle to the plugin - */ -static void -unix_plugin_do_write (struct Plugin *plugin) -{ - ssize_t sent = 0; - struct UNIXMessageWrapper *msgw; - struct Queue *queue; - int did_delete; + - queue = NULL; - did_delete = GNUNET_NO; - while (NULL != (msgw = plugin->msg_head)) - { - if (GNUNET_TIME_absolute_get_remaining (msgw->timeout).rel_value_us > 0) - break; /* Message is ready for sending */ - /* Message has a timeout */ - did_delete = GNUNET_YES; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Timeout for message with %u bytes \n", - (unsigned int) msgw->msgsize); - GNUNET_CONTAINER_DLL_remove (plugin->msg_head, - plugin->msg_tail, - msgw); - queue = msgw->queue; - queue->msgs_in_queue--; - GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); - queue->bytes_in_queue -= msgw->msgsize; - GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); - plugin->bytes_in_queue -= msgw->msgsize; - GNUNET_STATISTICS_set (plugin->env->stats, - "# bytes currently in UNIX buffers", - plugin->bytes_in_queue, - GNUNET_NO); - GNUNET_STATISTICS_update (plugin->env->stats, - "# UNIX bytes discarded", - msgw->msgsize, - GNUNET_NO); - if (NULL != msgw->cont) - msgw->cont (msgw->cont_cls, - &msgw->queue->target, - GNUNET_SYSERR, - msgw->payload, - 0); - GNUNET_free (msgw->msg); - GNUNET_free (msgw); - } - if (NULL == msgw) { - if (GNUNET_YES == did_delete) - notify_queue_monitor (plugin, - queue, - GNUNET_TRANSPORT_SS_UPDATE); - return; /* Nothing to send at the moment */ - } - queue = msgw->queue; - sent = unix_real_send (plugin, - unix_sock, - &queue->target, - (const char *) msgw->msg, - msgw->msgsize, - msgw->priority, - msgw->timeout, - msgw->queue->address->address, - msgw->queue->address->address_length, - msgw->payload, - msgw->cont, msgw->cont_cls); - if (RETRY == sent) - { - GNUNET_STATISTICS_update (plugin->env->stats, - "# UNIX retry attempts", - 1, GNUNET_NO); - notify_queue_monitor (plugin, - queue, - GNUNET_TRANSPORT_SS_UPDATE); - return; + uint16_t offset = 0; + uint16_t tsize = msize - sizeof (struct UNIXMessage); + const char *msgbuf = (const char *) &msg[1]; + + while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize) + { + const struct GNUNET_MessageHeader *currhdr; + struct GNUNET_MessageHeader al_hdr; + uint16_t csize; + + currhdr = (const struct GNUNET_MessageHeader *) &msgbuf[offset]; + /* ensure aligned access */ + memcpy (&al_hdr, + currhdr, + sizeof (al_hdr)); + csize = ntohs (al_hdr.size); + if ( (csize < sizeof (struct GNUNET_MessageHeader)) || + (csize > tsize - offset)) + { + GNUNET_break_op (0); + break; + } + ret = GNUNET_TRANSPORT_communicator_receive (ch, + &msg->sender, + currhdr, + &receive_complete_cb, + NULL); + if (GNUNET_SYSERR == ret) + return; /* transport not up */ + if (GNUNET_NO == ret) + break; + delivering_messages++; + offset += csize; + } } - GNUNET_CONTAINER_DLL_remove (plugin->msg_head, - plugin->msg_tail, - msgw); - queue->msgs_in_queue--; - GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); - queue->bytes_in_queue -= msgw->msgsize; - GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); - plugin->bytes_in_queue -= msgw->msgsize; - GNUNET_STATISTICS_set (plugin->env->stats, - "# bytes currently in UNIX buffers", - plugin->bytes_in_queue, GNUNET_NO); - notify_queue_monitor (plugin, - queue, - GNUNET_TRANSPORT_SS_UPDATE); - if (GNUNET_SYSERR == sent) + if (delivering_messages >= max_queue_length) { - /* failed and no retry */ - if (NULL != msgw->cont) - msgw->cont (msgw->cont_cls, - &msgw->queue->target, - GNUNET_SYSERR, - msgw->payload, 0); - GNUNET_STATISTICS_update (plugin->env->stats, - "# UNIX bytes discarded", - msgw->msgsize, - GNUNET_NO); - GNUNET_free (msgw->msg); - GNUNET_free (msgw); - return; + /* we should try to apply 'back pressure' */ + GNUNET_SCHEDULER_cancel (read_task); + read_task = NULL; } - /* successfully sent bytes */ - GNUNET_break (sent > 0); - GNUNET_STATISTICS_update (plugin->env->stats, - "# bytes transmitted via UNIX", - msgw->msgsize, - GNUNET_NO); - if (NULL != msgw->cont) - msgw->cont (msgw->cont_cls, - &msgw->queue->target, - GNUNET_OK, - msgw->payload, - msgw->msgsize); - GNUNET_free (msgw->msg); - GNUNET_free (msgw); -} - - -/** - * We have been notified that our socket has something to read. - * Then reschedule this function to be called again once more is available. - * - * @param cls the plugin handle - */ -static void -unix_plugin_select_read (void *cls) -{ - struct Plugin *plugin = cls; - const struct GNUNET_SCHEDULER_TaskContext *tc; - - plugin->read_task = NULL; - tc = GNUNET_SCHEDULER_get_task_context (); - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) - unix_plugin_do_read (plugin); - plugin->read_task = - GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - unix_sock, - &unix_plugin_select_read, plugin); } @@ -1137,158 +682,155 @@ unix_plugin_select_read (void *cls) * We have been notified that our socket is ready to write. * Then reschedule this function to be called again once more is available. * - * @param cls the plugin handle + * @param cls NULL */ static void -unix_plugin_select_write (void *cls) +select_write_cb (void *cls) { - struct Plugin *plugin = cls; - const struct GNUNET_SCHEDULER_TaskContext *tc; - - plugin->write_task = NULL; - tc = GNUNET_SCHEDULER_get_task_context (); - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) - unix_plugin_do_write (plugin); - if (NULL == plugin->msg_head) - return; /* write queue empty */ - plugin->write_task = - GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, - unix_sock, - &unix_plugin_select_write, plugin); -} - + struct Queue *queue = queue_tail; + const struct GNUNET_MessageHeader *msg = queue->msg; + size_t msg_size = ntohs (msg->size); + ssize_t sent; -/** - * Function that can be used by the transport service to transmit - * a message using the plugin. Note that in the case of a - * peer disconnecting, the continuation MUST be called - * prior to the disconnect notification itself. This function - * will be called with this peer's HELLO message to initiate - * a fresh connection to another peer. - * - * @param cls closure - * @param queue which queue must be used - * @param msgbuf the message to transmit - * @param msgbuf_size number of bytes in @a msgbuf - * @param priority how important is the message (most plugins will - * ignore message priority and just FIFO) - * @param to how long to wait at most for the transmission (does not - * require plugins to discard the message after the timeout, - * just advisory for the desired delay; most plugins will ignore - * this as well) - * @param cont continuation to call once the message has - * been transmitted (or if the transport is ready - * for the next transmission call; or if the - * peer disconnected...); can be NULL - * @param cont_cls closure for @a cont - * @return number of bytes used (on the physical network, with overheads); - * -1 on hard errors (i.e. address invalid); 0 is a legal value - * and does NOT mean that the message was not transmitted (DV) - */ -static ssize_t -unix_plugin_send (void *cls, - struct Queue *queue, - const char *msgbuf, - size_t msgbuf_size, - unsigned int priority, - struct GNUNET_TIME_Relative to, - GNUNET_TRANSPORT_TransmitContinuation cont, - void *cont_cls) -{ - struct Plugin *plugin = cls; - struct UNIXMessageWrapper *wrapper; - struct UNIXMessage *message; - int ssize; + /* take queue of the ready list */ + write_task = NULL; + GNUNET_CONTAINER_DLL_remove (queue_head, + queue_tail, + queue); + if (NULL != queue_head) + write_task = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_write_cb, + NULL); - if (GNUNET_OK != - GNUNET_CONTAINER_multipeermap_contains_value (plugin->queue_map, - &queue->target, - queue)) + /* send 'msg' */ + queue->msg = NULL; + GNUNET_MQ_impl_send_continue (queue->mq); + resend: + /* Send the data */ + sent = GNUNET_NETWORK_socket_sendto (unix_sock, + queue->msg, + msg_size, + (const struct sockaddr *) mq->address, + mq->address_len); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "UNIX transmitted message to %s (%d/%u: %s)\n", + GNUNET_i2s (&queue->target), + (int) sent, + (unsigned int) msg_size, + (sent < 0) ? STRERROR (errno) : "ok"); + if (-1 != sent) + return; /* all good */ + switch (errno) { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Invalid queue for peer `%s' `%s'\n", - GNUNET_i2s (&queue->target), - unix_plugin_address_to_string (NULL, - queue->address->address, - queue->address->address_length)); - GNUNET_break (0); - return GNUNET_SYSERR; + case EAGAIN: + case ENOBUFS: + /* We should retry later... */ + GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, + "send"); + return; + case EMSGSIZE: + { + socklen_t size = 0; + socklen_t len = sizeof (size); + + GNUNET_NETWORK_socket_getsockopt (unix_sock, + SOL_SOCKET, + SO_SNDBUF, + &size, + &len); + if (size > ntohs (msg->size)) + { + /* Buffer is bigger than message: error, no retry + * This should never happen!*/ + GNUNET_break (0); + return; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Trying to increase socket buffer size from %u to %u for message size %u\n", + (unsigned int) size, + (unsigned int) m((msg_size / 1000) + 2) * 1000, + (unsigned int) msg_size); + size = ((msg_size / 1000) + 2) * 1000; + if (GNUNET_OK == + GNUNET_NETWORK_socket_setsockopt (unix_sock, + SOL_SOCKET, + SO_SNDBUF, + &size, + sizeof (size))) + goto resend; /* Increased buffer size, retry sending */ + /* Ok, then just try very modest increase */ + size = msg_size; + if (GNUNET_OK == + GNUNET_NETWORK_socket_setsockopt (unix_sock, + SOL_SOCKET, + SO_SNDBUF, + &size, + sizeof (size))) + goto resend; /* Increased buffer size, retry sending */ + /* Could not increase buffer size: error, no retry */ + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "setsockopt"); + return; + } + default: + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "send"); + return; } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Sending %u bytes with queue for peer `%s' `%s'\n", - msgbuf_size, - GNUNET_i2s (&queue->target), - unix_plugin_address_to_string (NULL, - queue->address->address, - queue->address->address_length)); - ssize = sizeof (struct UNIXMessage) + msgbuf_size; - message = GNUNET_malloc (sizeof (struct UNIXMessage) + msgbuf_size); - message->header.size = htons (ssize); - message->header.type = htons (0); - GNUNET_memcpy (&message->sender, plugin->env->my_identity, - sizeof (struct GNUNET_PeerIdentity)); - GNUNET_memcpy (&message[1], msgbuf, msgbuf_size); - wrapper = GNUNET_new (struct UNIXMessageWrapper); - wrapper->msg = message; - wrapper->msgsize = ssize; - wrapper->payload = msgbuf_size; - wrapper->priority = priority; - wrapper->timeout = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - to); - wrapper->cont = cont; - wrapper->cont_cls = cont_cls; - wrapper->queue = queue; - GNUNET_CONTAINER_DLL_insert_tail (plugin->msg_head, - plugin->msg_tail, - wrapper); - plugin->bytes_in_queue += ssize; - queue->bytes_in_queue += ssize; - queue->msgs_in_queue++; - GNUNET_STATISTICS_set (plugin->env->stats, - "# bytes currently in UNIX buffers", - plugin->bytes_in_queue, - GNUNET_NO); - notify_queue_monitor (plugin, - queue, - GNUNET_TRANSPORT_SS_UPDATE); - if (NULL == plugin->write_task) - plugin->write_task = - GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, - unix_sock, - &unix_plugin_select_write, plugin); - return ssize; } /** - * Signature of functions implementing the - * sending functionality of a message queue. + * Signature of functions implementing the sending functionality of a + * message queue. * * @param mq the message queue * @param msg the message to send - * @param impl_state state of the implementation + * @param impl_state our `struct Queue` */ static void mq_send (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state) { + struct Queue *queue = impl_state; + + GNUNET_assert (mq == queue->mq); + GNUNET_assert (NULL == queue->msg); + queue->msg = msg; + GNUNET_CONTAINER_DLL_insert (queue_head, + queue_tail, + queue); + if (NULL == write_task) + write_task = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_write_cb, + NULL); } /** - * Signature of functions implementing the - * destruction of a message queue. - * Implementations must not free @a mq, but should - * take care of @a impl_state. + * Signature of functions implementing the destruction of a message + * queue. Implementations must not free @a mq, but should take care + * of @a impl_state. * * @param mq the message queue to destroy - * @param impl_state state of the implementation + * @param impl_state our `struct Queue` */ static void mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state) { + struct Queue *queue = impl_state; + + if (mq == queue->mq) + { + queue->mq = NULL; + queue_destroy (queue); + } } @@ -1296,12 +838,15 @@ mq_destroy (struct GNUNET_MQ_Handle *mq, * Implementation function that cancels the currently sent message. * * @param mq message queue - * @param impl_state state specific to the implementation + * @param impl_state our `struct Queue` */ static void mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state) { + struct Queue *queue = impl_state; + + // FIXME: TBD! } @@ -1311,15 +856,17 @@ mq_cancel (struct GNUNET_MQ_Handle *mq, * the message queue. * Not every message queue implementation supports an error handler. * - * @param cls closure + * @param cls our `struct Queue` * @param error error code */ static void mq_error (void *cls, enum GNUNET_MQ_Error error) { -} + struct Queue *queue = cls; + // FIXME: TBD! +} /** @@ -1470,7 +1017,6 @@ do_shutdown (void *cls) GNUNET_TRANSPORT_communicator_disconnect (ch); ch = NULL; } - GNUNET_break (0 == bytes_in_queue); } @@ -1497,7 +1043,7 @@ run (void *cls, if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, - "transport-unix", + "communicator-unix", "UNIXPATH", &unix_socket_path)) { @@ -1506,7 +1052,14 @@ run (void *cls, "UNIXPATH"); return; } - + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + "communicator-unix", + "MAX_QUEUE_LENGTH", + &max_queue_length)) + max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; + + /* Initialize my flags */ is_abstract = 0; #ifdef LINUX @@ -1571,7 +1124,7 @@ run (void *cls, queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); ch = GNUNET_TRANSPORT_communicator_connect (cfg, - "unix", + COMMUNICATOR_NAME, 65535, &mq_init, NULL); @@ -1587,13 +1140,16 @@ run (void *cls, COMMUNICATOR_NAME, unix_socket_path, is_abstract); - ai = GNUNET_TRANSPORT_communicator_address_add (ch, my_addr, GNUNET_ATS_NET_LOOPBACK, GNUNET_TIME_UNIT_FOREVER_REL); GNUNET_free (my_addr); GNUNET_free (unix_socket_path); + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); } diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c index e5be53150..434138e19 100644 --- a/src/transport/transport_api2_communication.c +++ b/src/transport/transport_api2_communication.c @@ -729,6 +729,7 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) handlers, &error_handler, ch); + // FIXME: must notify transport that we are responsible for 'ch->name' addresses!!! for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai; ai = ai->next) -- cgit v1.2.3 From 304bfc5d18d5613a38b5d927925dbfa00adfc82a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 8 Nov 2018 14:20:33 +0100 Subject: unix communicator now builds --- .../gnunet_transport_communication_service.h | 2 +- src/transport/Makefile.am | 9 + src/transport/gnunet-communicator-unix.c | 769 ++++++++++----------- 3 files changed, 363 insertions(+), 417 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h index b1a248e51..ab5d3742a 100644 --- a/src/include/gnunet_transport_communication_service.h +++ b/src/include/gnunet_transport_communication_service.h @@ -70,7 +70,7 @@ extern "C" typedef int (*GNUNET_TRANSPORT_CommunicatorMqInit) (void *cls, const struct GNUNET_PeerIdentity *peer, - const void *address); + const char *address); /** diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index c6c02c6ed..92b53137f 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -140,6 +140,7 @@ endif noinst_PROGRAMS = \ gnunet-transport-profiler \ + gnunet-communicator-unix \ $(WLAN_BIN_SENDER) \ $(WLAN_BIN_RECEIVER) @@ -219,6 +220,14 @@ gnunet_transport_certificate_creation_SOURCES = \ gnunet_transport_certificate_creation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +gnunet_communicator_unix_SOURCES = \ + gnunet-communicator-unix.c +gnunet_communicator_unix_LDADD = \ + libgnunettransportcommunicator.la \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la + + gnunet_helper_transport_wlan_SOURCES = \ gnunet-helper-transport-wlan.c diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c index f07975186..2879b1738 100644 --- a/src/transport/gnunet-communicator-unix.c +++ b/src/transport/gnunet-communicator-unix.c @@ -153,6 +153,11 @@ static unsigned long long delivering_messages; */ static unsigned long long max_queue_length; +/** + * For logging statistics. + */ +static struct GNUNET_STATISTICS_Handle *stats; + /** * Our environment. */ @@ -194,12 +199,11 @@ static struct GNUNET_TRANSPORT_AddressIdentifier *ai; static void queue_destroy (struct Queue *queue) { - struct Plugin *plugin = cls; struct GNUNET_MQ_Handle *mq; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Disconnecting queue for peer `%s'\n", - GNUNET_i2s (&queue->target)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Disconnecting queue for peer `%s'\n", + GNUNET_i2s (&queue->target)); if (0 != queue->bytes_in_queue) { GNUNET_CONTAINER_DLL_remove (queue_head, @@ -253,11 +257,11 @@ queue_timeout (void *cls) queue); return; } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Queue %p was idle for %s, disconnecting\n", - queue, - GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, - GNUNET_YES)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Queue %p was idle for %s, disconnecting\n", + queue, + GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + GNUNET_YES)); queue_destroy (queue); } @@ -288,8 +292,7 @@ reschedule_queue_timeout (struct Queue *queue) */ static struct sockaddr_un * unix_address_to_sockaddr (const char *unixpath, - socklen_t *sock_len, - int is_abstract) + socklen_t *sock_len) { struct sockaddr_un *un; size_t slen; @@ -309,7 +312,7 @@ unix_address_to_sockaddr (const char *unixpath, un->sun_len = (u_char) slen; #endif (*sock_len) = slen; - if (GNUNET_YES == is_abstract) + if ('@' == un->sun_path[0]) un->sun_path[0] = '\0'; return un; } @@ -328,7 +331,7 @@ struct LookupCtx /** * Address we are looking for. */ - const sockaddr_un *un; + const struct sockaddr_un *un; /** * Number of bytes in @a un @@ -347,7 +350,7 @@ struct LookupCtx */ static int lookup_queue_it (void *cls, - const struct GNUNET_PeerIdentity * key, + const struct GNUNET_PeerIdentity *key, void *value) { struct LookupCtx *lctx = cls; @@ -374,14 +377,14 @@ lookup_queue_it (void *cls, */ static struct Queue * lookup_queue (const struct GNUNET_PeerIdentity *peer, - const sockaddr_un *un, + const struct sockaddr_un *un, socklen_t un_len) { struct LookupCtx lctx; lctx.un = un; lctx.un_len = un_len; - GNUNET_CONTAINER_multipeermap_get_multiple (plugin->queue_map, + GNUNET_CONTAINER_multipeermap_get_multiple (queue_map, peer, &lookup_queue_it, &lctx); @@ -389,295 +392,6 @@ lookup_queue (const struct GNUNET_PeerIdentity *peer, } -/** - * Creates a new outbound queue the transport service will use to send - * data to another peer. - * - * @param peer the target peer - * @param un the address - * @param un_len number of bytes in @a un - * @return the queue or NULL of max connections exceeded - */ -static struct Queue * -unix_plugin_get_queue (const struct GNUNET_PeerIdentity *target, - const struct sockaddr_un *un, - socklen_t un_len) -{ - struct Plugin *plugin = cls; - struct Queue *queue; - struct UnixAddress *ua; - char * addrstr; - uint32_t addr_str_len; - uint32_t addr_option; - char *foreign_addr; - int is_abstract; - - if (is_abstract = ('\0' == un.sun_path[0])) - un.sun_path[0] = '/'; - GNUNET_asprintf (&foreign_addr, - "%s-%s#%d", - COMMUNICATOR_NAME, - un.sun_path, - is_abstract); - - - addrstr = (char *) &ua[1]; - addr_str_len = ntohl (ua->addrlen); - addr_option = ntohl (ua->options); - - /* create a new queue */ - queue = GNUNET_new (struct Queue); - queue->target = address->peer; - queue->address = GNUNET_HELLO_address_copy (address); - queue->plugin = plugin; - queue->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); - queue->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, - &queue_timeout, - queue); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Creating a new queue %p for address `%s'\n", - queue, - unix_plugin_address_to_string (NULL, - address->address, - address->address_length)); - (void) GNUNET_CONTAINER_multipeermap_put (plugin->queue_map, - &address->peer, queue, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - GNUNET_STATISTICS_set (plugin->env->stats, - "# UNIX queues active", - GNUNET_CONTAINER_multipeermap_size (queue_map), - GNUNET_NO); - return queue; -} - - -/** - * Function that will be called whenever the transport service wants - * to notify the plugin that a queue is still active and in use and - * therefore the queue timeout for this queue has to be updated - * - * @param cls closure with the `struct Plugin *` - * @param peer which peer was the queue for - * @param queue which queue is being updated - */ -static void -unix_plugin_update_queue_timeout (void *cls, - const struct GNUNET_PeerIdentity *peer, - struct Queue *queue) -{ - struct Plugin *plugin = cls; - - if (GNUNET_OK != - GNUNET_CONTAINER_multipeermap_contains_value (plugin->queue_map, - &queue->target, - queue)) - { - GNUNET_break (0); - return; - } - reschedule_queue_timeout (queue); -} - - -/** - * Demultiplexer for UNIX messages - * - * @param plugin the main plugin for this transport - * @param sender from which peer the message was received - * @param currhdr pointer to the header of the message - * @param ua address to look for - * @param ua_len length of the address @a ua - */ -static void -unix_demultiplexer (struct Plugin *plugin, - struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *currhdr, - const struct UnixAddress *ua, - size_t ua_len) -{ - struct Queue *queue; - struct GNUNET_HELLO_Address *address; - - GNUNET_assert (ua_len >= sizeof (struct UnixAddress)); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received message from %s\n", - unix_plugin_address_to_string (NULL, ua, ua_len)); - GNUNET_STATISTICS_update (plugin->env->stats, - "# bytes received via UNIX", - ntohs (currhdr->size), - GNUNET_NO); - - /* Look for existing queue */ - address = GNUNET_HELLO_address_allocate (sender, - PLUGIN_NAME, - ua, ua_len, - GNUNET_HELLO_ADDRESS_INFO_NONE); /* UNIX does not have "inbound" queues */ - queue = lookup_queue (plugin, address); - if (NULL == queue) - { - queue = unix_plugin_get_queue (plugin, address); - /* Notify transport and ATS about new inbound queue */ - plugin->env->queue_start (NULL, - queue->address, - queue, - GNUNET_ATS_NET_LOOPBACK); - } - else - { - reschedule_queue_timeout (queue); - } - GNUNET_HELLO_address_free (address); - plugin->env->receive (plugin->env->cls, - queue->address, - queue, - currhdr); -} - - -/** - * We have been notified that our socket has something to read. Do the - * read and reschedule this function to be called again once more is - * available. - * - * @param cls NULL - */ -static void -select_read_cb (void *cls); - - -/** - * Function called when message was successfully passed to - * transport service. Continue read activity. - * - * @param cls NULL - */ -static void -receive_complete_cb (void *cls) -{ - delivering_messages--; - if ( (NULL == read_task) && - (delivering_messages < max_queue_length) ) - read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - unix_sock, - &select_read_cb, - NULL); -} - - -/** - * We have been notified that our socket has something to read. Do the - * read and reschedule this function to be called again once more is - * available. - * - * @param cls NULL - */ -static void -select_read_cb (void *cls) -{ - char buf[65536] GNUNET_ALIGN; - struct Queue *queue; - const struct UNIXMessage *msg; - struct sockaddr_un un; - socklen_t addrlen; - ssize_t ret; - uint16_t msize; - - read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - unix_sock, - &select_read_cb, - NULL); - addrlen = sizeof (un); - memset (&un, - 0, - sizeof (un)); - ret = GNUNET_NETWORK_socket_recvfrom (unix_sock, - buf, - sizeof (buf), - (struct sockaddr *) &un, - &addrlen); - if ( (-1 == ret) && - ( (EAGAIN == errno) || - (ENOBUFS == errno) ) ) - return; - if (-1 == ret) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, - "recvfrom"); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Read %d bytes from socket %s\n", - (int) ret, - un.sun_path); - GNUNET_assert (AF_UNIX == (un.sun_family)); - msg = (struct UNIXMessage *) buf; - msize = ntohs (msg->header.size); - if ( (msize < sizeof (struct UNIXMessage)) || - (msize > ret) ) - { - GNUNET_break_op (0); - return; - } - queue = lookup_queue (&msg->sender, - un, - addrlen); - if (NULL == queue) - queue = setup_queue (&msg->sender, - un, - addrlen); - if (NULL == queue) - { - GNUENT_log (GNUNET_ERROR_TYPE_ERROR, - _("Maximum number of UNIX connections exceeded, dropping incoming message\n")); - return; - } - - - { - uint16_t offset = 0; - uint16_t tsize = msize - sizeof (struct UNIXMessage); - const char *msgbuf = (const char *) &msg[1]; - - while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize) - { - const struct GNUNET_MessageHeader *currhdr; - struct GNUNET_MessageHeader al_hdr; - uint16_t csize; - - currhdr = (const struct GNUNET_MessageHeader *) &msgbuf[offset]; - /* ensure aligned access */ - memcpy (&al_hdr, - currhdr, - sizeof (al_hdr)); - csize = ntohs (al_hdr.size); - if ( (csize < sizeof (struct GNUNET_MessageHeader)) || - (csize > tsize - offset)) - { - GNUNET_break_op (0); - break; - } - ret = GNUNET_TRANSPORT_communicator_receive (ch, - &msg->sender, - currhdr, - &receive_complete_cb, - NULL); - if (GNUNET_SYSERR == ret) - return; /* transport not up */ - if (GNUNET_NO == ret) - break; - delivering_messages++; - offset += csize; - } - } - if (delivering_messages >= max_queue_length) - { - /* we should try to apply 'back pressure' */ - GNUNET_SCHEDULER_cancel (read_task); - read_task = NULL; - } -} - - /** * We have been notified that our socket is ready to write. * Then reschedule this function to be called again once more is available. @@ -712,16 +426,27 @@ select_write_cb (void *cls) sent = GNUNET_NETWORK_socket_sendto (unix_sock, queue->msg, msg_size, - (const struct sockaddr *) mq->address, - mq->address_len); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "UNIX transmitted message to %s (%d/%u: %s)\n", - GNUNET_i2s (&queue->target), - (int) sent, - (unsigned int) msg_size, - (sent < 0) ? STRERROR (errno) : "ok"); + (const struct sockaddr *) queue->address, + queue->address_len); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "UNIX transmitted message to %s (%d/%u: %s)\n", + GNUNET_i2s (&queue->target), + (int) sent, + (unsigned int) msg_size, + (sent < 0) ? STRERROR (errno) : "ok"); if (-1 != sent) + { + GNUNET_STATISTICS_update (stats, + "# bytes sent", + (long long) sent, + GNUNET_NO); + reschedule_queue_timeout (queue); return; /* all good */ + } + GNUNET_STATISTICS_update (stats, + "# network transmission failures", + 1, + GNUNET_NO); switch (errno) { case EAGAIN: @@ -747,11 +472,11 @@ select_write_cb (void *cls) GNUNET_break (0); return; } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Trying to increase socket buffer size from %u to %u for message size %u\n", - (unsigned int) size, - (unsigned int) m((msg_size / 1000) + 2) * 1000, - (unsigned int) msg_size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to increase socket buffer size from %u to %u for message size %u\n", + (unsigned int) size, + (unsigned int) ((msg_size / 1000) + 2) * 1000, + (unsigned int) msg_size); size = ((msg_size / 1000) + 2) * 1000; if (GNUNET_OK == GNUNET_NETWORK_socket_setsockopt (unix_sock, @@ -846,7 +571,17 @@ mq_cancel (struct GNUNET_MQ_Handle *mq, { struct Queue *queue = impl_state; - // FIXME: TBD! + GNUNET_assert (NULL != queue->msg); + queue->msg = NULL; + GNUNET_CONTAINER_DLL_remove (queue_head, + queue_tail, + queue); + GNUNET_assert (NULL != write_task); + if (NULL == queue_head) + { + GNUNET_SCHEDULER_cancel (write_task); + write_task = NULL; + } } @@ -865,7 +600,230 @@ mq_error (void *cls, { struct Queue *queue = cls; - // FIXME: TBD! + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "UNIX MQ error in queue to %s: %d\n", + GNUNET_i2s (&queue->target), + (int) error); + queue_destroy (queue); +} + + +/** + * Creates a new outbound queue the transport service will use to send + * data to another peer. + * + * @param peer the target peer + * @param un the address + * @param un_len number of bytes in @a un + * @return the queue or NULL of max connections exceeded + */ +static struct Queue * +setup_queue (const struct GNUNET_PeerIdentity *target, + const struct sockaddr_un *un, + socklen_t un_len) +{ + struct Queue *queue; + + queue = GNUNET_new (struct Queue); + queue->target = *target; + queue->address = GNUNET_memdup (un, + un_len); + queue->address_len = un_len; + (void) GNUNET_CONTAINER_multipeermap_put (queue_map, + &queue->target, + queue, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + GNUNET_STATISTICS_set (stats, + "# queues active", + GNUNET_CONTAINER_multipeermap_size (queue_map), + GNUNET_NO); + queue->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); + queue->timeout_task + = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, + &queue_timeout, + queue); + queue->mq + = GNUNET_MQ_queue_for_callbacks (&mq_send, + &mq_destroy, + &mq_cancel, + queue, + NULL, + &mq_error, + queue); + { + char *foreign_addr; + + if ('\0' == un->sun_path[0]) + GNUNET_asprintf (&foreign_addr, + "%s-@%s", + COMMUNICATOR_NAME, + &un->sun_path[1]); + else + GNUNET_asprintf (&foreign_addr, + "%s-%s", + COMMUNICATOR_NAME, + un->sun_path); + queue->qh + = GNUNET_TRANSPORT_communicator_mq_add (ch, + &queue->target, + foreign_addr, + GNUNET_ATS_NET_LOOPBACK, + queue->mq); + GNUNET_free (foreign_addr); + } + return queue; +} + + +/** + * We have been notified that our socket has something to read. Do the + * read and reschedule this function to be called again once more is + * available. + * + * @param cls NULL + */ +static void +select_read_cb (void *cls); + + +/** + * Function called when message was successfully passed to + * transport service. Continue read activity. + * + * @param cls NULL + * @param success #GNUNET_OK on success + */ +static void +receive_complete_cb (void *cls, + int success) +{ + delivering_messages--; + if (GNUNET_OK != success) + GNUNET_STATISTICS_update (stats, + "# transport transmission failures", + 1, + GNUNET_NO); + if ( (NULL == read_task) && + (delivering_messages < max_queue_length) ) + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); +} + + +/** + * We have been notified that our socket has something to read. Do the + * read and reschedule this function to be called again once more is + * available. + * + * @param cls NULL + */ +static void +select_read_cb (void *cls) +{ + char buf[65536] GNUNET_ALIGN; + struct Queue *queue; + const struct UNIXMessage *msg; + struct sockaddr_un un; + socklen_t addrlen; + ssize_t ret; + uint16_t msize; + + read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + unix_sock, + &select_read_cb, + NULL); + addrlen = sizeof (un); + memset (&un, + 0, + sizeof (un)); + ret = GNUNET_NETWORK_socket_recvfrom (unix_sock, + buf, + sizeof (buf), + (struct sockaddr *) &un, + &addrlen); + if ( (-1 == ret) && + ( (EAGAIN == errno) || + (ENOBUFS == errno) ) ) + return; + if (-1 == ret) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "recvfrom"); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Read %d bytes from socket %s\n", + (int) ret, + un.sun_path); + GNUNET_assert (AF_UNIX == (un.sun_family)); + msg = (struct UNIXMessage *) buf; + msize = ntohs (msg->header.size); + if ( (msize < sizeof (struct UNIXMessage)) || + (msize > ret) ) + { + GNUNET_break_op (0); + return; + } + queue = lookup_queue (&msg->sender, + &un, + addrlen); + if (NULL == queue) + queue = setup_queue (&msg->sender, + &un, + addrlen); + else + reschedule_queue_timeout (queue); + if (NULL == queue) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Maximum number of UNIX connections exceeded, dropping incoming message\n")); + return; + } + + { + uint16_t offset = 0; + uint16_t tsize = msize - sizeof (struct UNIXMessage); + const char *msgbuf = (const char *) &msg[1]; + + while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize) + { + const struct GNUNET_MessageHeader *currhdr; + struct GNUNET_MessageHeader al_hdr; + uint16_t csize; + + currhdr = (const struct GNUNET_MessageHeader *) &msgbuf[offset]; + /* ensure aligned access */ + memcpy (&al_hdr, + currhdr, + sizeof (al_hdr)); + csize = ntohs (al_hdr.size); + if ( (csize < sizeof (struct GNUNET_MessageHeader)) || + (csize > tsize - offset)) + { + GNUNET_break_op (0); + break; + } + ret = GNUNET_TRANSPORT_communicator_receive (ch, + &msg->sender, + currhdr, + &receive_complete_cb, + NULL); + if (GNUNET_SYSERR == ret) + return; /* transport not up */ + if (GNUNET_NO == ret) + break; + delivering_messages++; + offset += csize; + } + } + if (delivering_messages >= max_queue_length) + { + /* we should try to apply 'back pressure' */ + GNUNET_SCHEDULER_cancel (read_task); + read_task = NULL; + } } @@ -889,76 +847,69 @@ mq_error (void *cls, static int mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, - const void *address) + const char *address) { struct Queue *queue; - char *a; - char *e; - int is_abs; - sockaddr_un *un; + const char *path; + struct sockaddr_un *un; socklen_t un_len; - if (NULL == strncmp (address, - COMMUNICATOR_NAME "-", - strlen (COMMUNICATOR_NAME "-"))) + if (0 != strncmp (address, + COMMUNICATOR_NAME "-", + strlen (COMMUNICATOR_NAME "-"))) { GNUNET_break_op (0); return GNUNET_SYSERR; } - a = GNUNET_strdup (&address[strlen (COMMUNICATOR_NAME "-")]); - e = strchr (a, - (unsigned char) '#'); - if (NULL == e) - { - GNUNET_free (a); - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - is_abs = ('1' == e[1]); - *e = '\0'; - un = unix_address_to_sockaddr (a, - &un_len, - is_abs); + path = &address[strlen (COMMUNICATOR_NAME "-")]; + un = unix_address_to_sockaddr (path, + &un_len); queue = lookup_queue (peer, un, un_len); if (NULL != queue) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Address `%s' ignored, queue exists\n", - address); + "Address `%s' for %s ignored, queue exists\n", + path, + GNUNET_i2s (peer)); GNUNET_free (un); return GNUNET_OK; } - queue = GNUNET_new (struct Queue); - queue->target = *peer; - queue->address = un; - queue->address_len = un_len; - (void) GNUNET_CONTAINER_multihashmap_put (queue_map, - &queue->target, - queue, - GNUET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - GNUNET_STATISTICS_set (stats, - "# UNIX queues active", - GNUNET_CONTAINER_multipeermap_size (plugin->queue_map), - GNUNET_NO); - queue->timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, - &queue_timeout, - queue); - queue->mq - = GNUNET_MQ_queue_for_callbacks (&mq_send, - &mq_destroy, - &mq_cancel, - queue, - NULL, - &mq_error, - queue); - queue->qh - = GNUNET_TRANSPORT_communicator_mq_add (ch, - &queue->target, - address, - ATS, - queue->mq); + queue = setup_queue (peer, + un, + un_len); + GNUNET_free (un); + if (NULL == queue) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Failed to setup queue to %s at `%s'\n", + GNUNET_i2s (peer), + path); + return GNUNET_NO; + } + return GNUNET_OK; +} + + +/** + * Iterator over all message queues to clean up. + * + * @param cls NULL + * @param target unused + * @param value the queue to destroy + * @return #GNUNET_OK to continue to iterate + */ +static int +get_queue_delete_it (void *cls, + const struct GNUNET_PeerIdentity *target, + void *value) +{ + struct Queue *queue = value; + + (void) cls; + (void) target; + queue_destroy (queue); return GNUNET_OK; } @@ -971,22 +922,6 @@ mq_init (void *cls, static void do_shutdown (void *cls) { - struct UNIXMessageWrapper *msgw; - - while (NULL != (msgw = msg_head)) - { - GNUNET_CONTAINER_DLL_remove (msg_head, - msg_tail, - msgw); - queue = msgw->queue; - queue->msgs_in_queue--; - GNUNET_assert (queue->bytes_in_queue >= msgw->msgsize); - queue->bytes_in_queue -= msgw->msgsize; - GNUNET_assert (bytes_in_queue >= msgw->msgsize); - bytes_in_queue -= msgw->msgsize; - GNUNET_free (msgw->msg); - GNUNET_free (msgw); - } if (NULL != read_task) { GNUNET_SCHEDULER_cancel (read_task); @@ -1017,6 +952,12 @@ do_shutdown (void *cls) GNUNET_TRANSPORT_communicator_disconnect (ch); ch = NULL; } + if (NULL != stats) + { + GNUNET_STATISTICS_destroy (stats, + GNUNET_NO); + stats = NULL; + } } @@ -1035,7 +976,6 @@ run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *unix_socket_path; - int is_abstract; struct sockaddr_un *un; socklen_t un_len; char *my_addr; @@ -1059,18 +999,16 @@ run (void *cls, &max_queue_length)) max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; - - /* Initialize my flags */ - is_abstract = 0; -#ifdef LINUX - is_abstract - = GNUNET_CONFIGURATION_get_value_yesno (cfg, - "testing", - "USE_ABSTRACT_SOCKETS"); -#endif un = unix_address_to_sockaddr (unix_socket_path, - &un_len, - is_abstract); + &un_len); + if (NULL == un) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to setup UNIX domain socket address with path `%s'\n", + unix_socket_path); + GNUNET_free (unix_socket_path); + return; + } unix_sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0); @@ -1086,9 +1024,9 @@ run (void *cls, (GNUNET_OK != GNUNET_DISK_directory_create_for_file (un->sun_path)) ) { - LOG (GNUNET_ERROR_TYPE_ERROR, - _("Cannot create path to `%s'\n"), - un->sun_path); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Cannot create path to `%s'\n"), + un->sun_path); GNUNET_NETWORK_socket_close (unix_sock); unix_sock = NULL; GNUNET_free (un); @@ -1100,11 +1038,9 @@ run (void *cls, (const struct sockaddr *) un, un_len)) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "bind"); - LOG (GNUNET_ERROR_TYPE_ERROR, - _("Cannot bind to `%s'\n"), - un->sun_path); + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "bind", + un->sun_path); GNUNET_NETWORK_socket_close (unix_sock); unix_sock = NULL; GNUNET_free (un); @@ -1112,14 +1048,16 @@ run (void *cls, return; } GNUNET_free (un); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Bound to `%s'\n", - unix_socket_path); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Bound to `%s'\n", + unix_socket_path); + stats = GNUNET_STATISTICS_create ("C-UNIX", + cfg); GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, unix_sock, - &unix_plugin_select_read, + &select_read_cb, NULL); queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); @@ -1136,10 +1074,9 @@ run (void *cls, return; } GNUNET_asprintf (&my_addr, - "%s-%s#%d", + "%s-%s", COMMUNICATOR_NAME, - unix_socket_path, - is_abstract); + unix_socket_path); ai = GNUNET_TRANSPORT_communicator_address_add (ch, my_addr, GNUNET_ATS_NET_LOOPBACK, -- cgit v1.2.3 From 6dc4bacb0197e96d5d9c6e5f881a104ab054a1f0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 8 Nov 2018 14:40:01 +0100 Subject: send NEW_COMMUNICATOR message on startup --- src/include/gnunet_protocols.h | 5 ++++ .../gnunet_transport_communication_service.h | 7 +++-- src/transport/gnunet-communicator-unix.c | 30 +++++++++++-------- src/transport/transport.h | 16 ++++++++++ src/transport/transport_api2_communication.c | 34 +++++++++++++++++----- 5 files changed, 71 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 16105d5a8..fbdee5415 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -3070,6 +3070,11 @@ extern "C" */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK 1210 +/** + * Message sent to indicate to the transport which address + * prefix is supported by a communicator. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR 1211 /** * Next available: 1300 diff --git a/src/include/gnunet_transport_communication_service.h b/src/include/gnunet_transport_communication_service.h index ab5d3742a..50f94bddf 100644 --- a/src/include/gnunet_transport_communication_service.h +++ b/src/include/gnunet_transport_communication_service.h @@ -83,7 +83,9 @@ struct GNUNET_TRANSPORT_CommunicatorHandle; * Connect to the transport service. * * @param cfg configuration to use - * @param name name of the communicator that is connecting + * @param config_section section of the configuration to use for options + * @param addr_prefix address prefix for addresses supported by this + * communicator, could be NULL for incoming-only communicators * @param mtu maximum message size supported by communicator, 0 if * sending is not supported, SIZE_MAX for no MTU * @param mq_init function to call to initialize a message queue given @@ -94,7 +96,8 @@ struct GNUNET_TRANSPORT_CommunicatorHandle; */ struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *name, + const char *config_section_name, + const char *addr_prefix, size_t mtu, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls); diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c index 2879b1738..cd3ae5dce 100644 --- a/src/transport/gnunet-communicator-unix.c +++ b/src/transport/gnunet-communicator-unix.c @@ -41,9 +41,14 @@ #define DEFAULT_MAX_QUEUE_LENGTH 8 /** - * Name of the communicator. + * Address prefix used by the communicator. */ -#define COMMUNICATOR_NAME "unix" +#define COMMUNICATOR_ADDRESS_PREFIX "unix" + +/** + * Configuration section used by the communicator. + */ +#define COMMUNICATOR_CONFIG_SECTION "communicator-unix" GNUNET_NETWORK_STRUCT_BEGIN @@ -656,12 +661,12 @@ setup_queue (const struct GNUNET_PeerIdentity *target, if ('\0' == un->sun_path[0]) GNUNET_asprintf (&foreign_addr, "%s-@%s", - COMMUNICATOR_NAME, + COMMUNICATOR_ADDRESS_PREFIX, &un->sun_path[1]); else GNUNET_asprintf (&foreign_addr, "%s-%s", - COMMUNICATOR_NAME, + COMMUNICATOR_ADDRESS_PREFIX, un->sun_path); queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, @@ -855,13 +860,13 @@ mq_init (void *cls, socklen_t un_len; if (0 != strncmp (address, - COMMUNICATOR_NAME "-", - strlen (COMMUNICATOR_NAME "-"))) + COMMUNICATOR_ADDRESS_PREFIX "-", + strlen (COMMUNICATOR_ADDRESS_PREFIX "-"))) { GNUNET_break_op (0); return GNUNET_SYSERR; } - path = &address[strlen (COMMUNICATOR_NAME "-")]; + path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")]; un = unix_address_to_sockaddr (path, &un_len); queue = lookup_queue (peer, @@ -983,18 +988,18 @@ run (void *cls, if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, - "communicator-unix", + COMMUNICATOR_CONFIG_SECTION, "UNIXPATH", &unix_socket_path)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "communicator-unix", + COMMUNICATOR_CONFIG_SECTION, "UNIXPATH"); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, - "communicator-unix", + COMMUNICATOR_CONFIG_SECTION, "MAX_QUEUE_LENGTH", &max_queue_length)) max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; @@ -1062,7 +1067,8 @@ run (void *cls, queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); ch = GNUNET_TRANSPORT_communicator_connect (cfg, - COMMUNICATOR_NAME, + COMMUNICATOR_CONFIG_SECTION, + COMMUNICATOR_ADDRESS_PREFIX, 65535, &mq_init, NULL); @@ -1075,7 +1081,7 @@ run (void *cls, } GNUNET_asprintf (&my_addr, "%s-%s", - COMMUNICATOR_NAME, + COMMUNICATOR_ADDRESS_PREFIX, unix_socket_path); ai = GNUNET_TRANSPORT_communicator_address_add (ch, my_addr, diff --git a/src/transport/transport.h b/src/transport/transport.h index 5662d6c4d..f21863aef 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -653,6 +653,22 @@ struct TransportPluginMonitorMessage /* *********************** TNG messages ***************** */ +/** + * Communicator goes online. Note which addresses it can + * work with. + */ +struct GNUNET_TRANSPORT_CommunicatorAvailableMessage +{ + + /** + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR. + */ + struct GNUNET_MessageHeader header; + + /* Followed by the address prefix of the communicator */ +}; + + /** * Add address to the list. */ diff --git a/src/transport/transport_api2_communication.c b/src/transport/transport_api2_communication.c index 434138e19..3a68c6eba 100644 --- a/src/transport/transport_api2_communication.c +++ b/src/transport/transport_api2_communication.c @@ -157,9 +157,14 @@ struct GNUNET_TRANSPORT_CommunicatorHandle const struct GNUNET_CONFIGURATION_Handle *cfg; /** - * Name of the communicator. + * Config section to use. */ - const char *name; + const char *config_section; + + /** + * Address prefix to use. + */ + const char *addr_prefix; /** * Function to call when the transport service wants us to initiate @@ -723,13 +728,24 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) ch), GNUNET_MQ_handler_end() }; + struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam; + struct GNUNET_MQ_Envelope *env; ch->mq = GNUNET_CLIENT_connect (ch->cfg, "transport", handlers, &error_handler, ch); - // FIXME: must notify transport that we are responsible for 'ch->name' addresses!!! + if (NULL == ch->mq) + return; + env = GNUNET_MQ_msg_extra (cam, + strlen (ch->addr_prefix) + 1, + GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR); + memcpy (&cam[1], + ch->addr_prefix, + strlen (ch->addr_prefix) + 1); + GNUNET_MQ_send (ch->mq, + env); for (struct GNUNET_TRANSPORT_AddressIdentifier *ai = ch->ai_head; NULL != ai; ai = ai->next) @@ -745,7 +761,9 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) * Connect to the transport service. * * @param cfg configuration to use - * @param name name of the communicator that is connecting + * @param config_section section of the configuration to use for options + * @param addr_prefix address prefix for addresses supported by this + * communicator, could be NULL for incoming-only communicators * @param mtu maximum message size supported by communicator, 0 if * sending is not supported, SIZE_MAX for no MTU * @param mq_init function to call to initialize a message queue given @@ -756,7 +774,8 @@ reconnect (struct GNUNET_TRANSPORT_CommunicatorHandle *ch) */ struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *name, + const char *config_section, + const char *addr_prefix, size_t mtu, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls) @@ -765,14 +784,15 @@ GNUNET_TRANSPORT_communicator_connect (const struct GNUNET_CONFIGURATION_Handle ch = GNUNET_new (struct GNUNET_TRANSPORT_CommunicatorHandle); ch->cfg = cfg; - ch->name = name; + ch->config_section = config_section; + ch->addr_prefix = addr_prefix; ch->mtu = mtu; ch->mq_init = mq_init; ch->mq_init_cls = mq_init_cls; reconnect (ch); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, - name, + config_section, "MAX_QUEUE_LENGTH", &ch->max_queue_length)) ch->max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; -- cgit v1.2.3 From 54f722729882247a318fbf686f2b2c31137ab72b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 8 Nov 2018 23:10:47 +0100 Subject: starting with TNG implementation --- src/transport/gnunet-service-tng.c | 719 +++++++++++++++++++++++++++++++++++++ src/transport/transport.h | 23 +- 2 files changed, 731 insertions(+), 11 deletions(-) create mode 100644 src/transport/gnunet-service-tng.c (limited to 'src') diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c new file mode 100644 index 000000000..8cbca3188 --- /dev/null +++ b/src/transport/gnunet-service-tng.c @@ -0,0 +1,719 @@ +/* + This file is part of GNUnet. + Copyright (C) 2010-2016, 2018 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @file transport/gnunet-service-transport.c + * @brief main for gnunet-service-transport + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_statistics_service.h" +#include "gnunet_transport_service.h" +#include "gnunet_peerinfo_service.h" +#include "gnunet_ats_service.h" +#include "gnunet-service-transport.h" +#include "transport.h" + + +/** + * How many messages can we have pending for a given client process + * before we start to drop incoming messages? We typically should + * have only one client and so this would be the primary buffer for + * messages, so the number should be chosen rather generously. + * + * The expectation here is that most of the time the queue is large + * enough so that a drop is virtually never required. Note that + * this value must be about as large as 'TOTAL_MSGS' in the + * 'test_transport_api_reliability.c', otherwise that testcase may + * fail. + */ +#define MAX_PENDING (128 * 1024) + + +/** + * What type of client is the `struct TransportClient` about? + */ +enum ClientType +{ + /** + * We do not know yet (client is fresh). + */ + CT_NONE = 0, + + /** + * Is the CORE service, we need to forward traffic to it. + */ + CT_CORE = 1, + + /** + * It is a monitor, forward monitor data. + */ + CT_MONITOR = 2, + + /** + * It is a communicator, use for communication. + */ + CT_COMMUNICATOR = 3 +}; + + +/** + * Client connected to the transport service. + */ +struct TransportClient +{ + + /** + * Kept in a DLL. + */ + struct TransportClient *next; + + /** + * Kept in a DLL. + */ + struct TransportClient *prev; + + /** + * Handle to the client. + */ + struct GNUNET_SERVICE_Client *client; + + /** + * Message queue to the client. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * What type of client is this? + */ + enum ClientType type; + + union + { + + /** + * Peer identity to monitor the addresses of. + * Zero to monitor all neighbours. Valid if + * @e type is #CT_MONITOR. + */ + struct GNUNET_PeerIdentity monitor_peer; + + /** + * If @e type is #CT_COMMUNICATOR, this communicator + * supports communicating using these addresses. + */ + const char *address_prefix; + + } details; + +}; + + +/** + * Head of linked list of all clients to this service. + */ +static struct TransportClient *clients_head; + +/** + * Tail of linked list of all clients to this service. + */ +static struct TransportClient *clients_tail; + +/** + * Statistics handle. + */ +struct GNUNET_STATISTICS_Handle *GST_stats; + +/** + * Configuration handle. + */ +const struct GNUNET_CONFIGURATION_Handle *GST_cfg; + +/** + * Configuration handle. + */ +struct GNUNET_PeerIdentity GST_my_identity; + +/** + * Handle to peerinfo service. + */ +struct GNUNET_PEERINFO_Handle *GST_peerinfo; + +/** + * Our private key. + */ +struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; + + +/** + * Called whenever a client connects. Allocates our + * data structures associated with that client. + * + * @param cls closure, NULL + * @param client identification of the client + * @param mq message queue for the client + * @return our `struct TransportClient` + */ +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + struct TransportClient *tc; + + tc = GNUNET_new (struct TransportClient); + tc->client = client; + tc->mq = mq; + GNUNET_CONTAINER_DLL_insert (clients_head, + clients_tail, + tc); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p connected\n", + tc); + return tc; +} + + +/** + * Called whenever a client is disconnected. Frees our + * resources associated with that client. + * + * @param cls closure, NULL + * @param client identification of the client + * @param app_ctx our `struct TransportClient` + */ +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) +{ + struct TransportClient *tc = app_ctx; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p disconnected, cleaning up.\n", + tc); + GNUNET_CONTAINER_DLL_remove (clients_head, + clients_tail, + tc); + switch (tc->type) + { + case CT_NONE: + break; + case CT_CORE: + break; + case CT_MONITOR: + break; + case CT_COMMUNICATOR: + break; + } + GNUNET_free (tc); +} + + +/** + * Initialize a "CORE" client. We got a start message from this + * client, so add it to the list of clients for broadcasting of + * inbound messages. + * + * @param cls the client + * @param start the start message that was sent + */ +static void +handle_client_start (void *cls, + const struct StartMessage *start) +{ + struct TransportClient *tc = cls; + const struct GNUNET_MessageHeader *hello; + uint32_t options; + + options = ntohl (start->options); + if ( (0 != (1 & options)) && + (0 != + memcmp (&start->self, + &GST_my_identity, + sizeof (struct GNUNET_PeerIdentity)) ) ) + { + /* client thinks this is a different peer, reject */ + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + if (CT_NONE != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + tc->type = CT_CORE; +#if 0 + hello = GST_hello_get (); + if (NULL != hello) + unicast (tc, + hello, + GNUNET_NO); +#endif + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client sent us a HELLO. Check the request. + * + * @param cls the client + * @param message the HELLO message + */ +static int +check_client_hello (void *cls, + const struct GNUNET_MessageHeader *message) +{ + (void) cls; + return GNUNET_OK; /* FIXME: check here? */ +} + + +/** + * Client sent us a HELLO. Process the request. + * + * @param cls the client + * @param message the HELLO message + */ +static void +handle_client_hello (void *cls, + const struct GNUNET_MessageHeader *message) +{ + struct TransportClient *tc = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received HELLO message\n"); + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static int +check_client_send (void *cls, + const struct OutboundMessage *obm) +{ + uint16_t size; + const struct GNUNET_MessageHeader *obmm; + + (void) cls; + size = ntohs (obm->header.size) - sizeof (struct OutboundMessage); + if (size < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + obmm = (const struct GNUNET_MessageHeader *) &obm[1]; + if (size != ntohs (obmm->size)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static void +handle_client_send (void *cls, + const struct OutboundMessage *obm) +{ + struct TransportClient *tc = cls; + const struct GNUNET_MessageHeader *obmm; + + obmm = (const struct GNUNET_MessageHeader *) &obm[1]; +} + + +/** + * Communicator started. Test message is well-formed. + * + * @param cls the client + * @param cam the send message that was sent + */ +static int +check_communicator_available (void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (cam->header.size) - sizeof (*cam); + if (0 == size) + return GNUNET_OK; /* receive-only communicator */ + addr = (const char *) &cam[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Communicator started. Process the request. + * + * @param cls the client + * @param cam the send message that was sent + */ +static void +handle_communicator_available (void *cls, + const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam) +{ + struct TransportClient *tc = cls; + uint16_t size; + + if (CT_NONE != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + tc->type = CT_COMMUNICATOR; + size = ntohs (cam->header.size) - sizeof (*cam); + if (0 == size) + return GNUNET_OK; /* receive-only communicator */ + tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]); + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Address of our peer added. Test message is well-formed. + * + * @param cls the client + * @param aam the send message that was sent + */ +static int +check_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *aam) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (aam->header.size) - sizeof (*aam); + if (0 == size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + addr = (const char *) &cam[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Address of our peer added. Process the request. + * + * @param cls the client + * @param aam the send message that was sent + */ +static void +handle_add_address (void *cls, + const struct GNUNET_TRANSPORT_AddAddressMessage *aam) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Address of our peer deleted. Process the request. + * + * @param cls the client + * @param dam the send message that was sent + */ +static void +handle_del_address (void *cls, + const struct GNUNET_TRANSPORT_DelAddressMessage *dam) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Client asked for transmission to a peer. Process the request. + * + * @param cls the client + * @param obm the send message that was sent + */ +static int +check_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *im) +{ + uint16_t size; + const struct GNUNET_MessageHeader *obmm; + + (void) cls; + size = ntohs (im->header.size) - sizeof (*im); + if (size < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + obmm = (const struct GNUNET_MessageHeader *) &im[1]; + if (size != ntohs (obmm->size)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Incoming meessage. Process the request. + * + * @param cls the client + * @param im the send message that was received + */ +static void +handle_incoming_msg (void *cls, + const struct GNUNET_TRANSPORT_IncomingMessage *im) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * New queue became available. Check message. + * + * @param cls the client + * @param aqm the send message that was sent + */ +static int +check_add_queue_message (void *cls, + const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) +{ + const char *addr; + uint16_t size; + + (void) cls; + size = ntohs (aqm->header.size) - sizeof (*aqm); + if (0 == size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + addr = (const char *) &aqm[1]; + if ('\0' != addr[size-1]) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * New queue became available. Process the request. + * + * @param cls the client + * @param aqm the send message that was sent + */ +static void +handle_add_queue_message (void *cls, + const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Queue to a peer went down. Process the request. + * + * @param cls the client + * @param dqm the send message that was sent + */ +static void +handle_del_queue_message (void *cls, + const struct GNUNET_TRANSPORT_DelQueueMessage *dqm) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Message was transmitted. Process the request. + * + * @param cls the client + * @param sma the send message that was sent + */ +static void +handle_send_message_ack (void *cls, + const struct GNUNET_TRANSPORT_SendMessageToAck *sma) +{ + struct TransportClient *tc = cls; + + GNUNET_SERVICE_client_continue (tc->client); +} + + +/** + * Function called when the service shuts down. Unloads our plugins + * and cancels pending validations. + * + * @param cls closure, unused + */ +static void +shutdown_task (void *cls) +{ + (void) cls; + + if (NULL != GST_stats) + { + GNUNET_STATISTICS_destroy (GST_stats, + GNUNET_NO); + GST_stats = NULL; + } + if (NULL != GST_my_private_key) + { + GNUNET_free (GST_my_private_key); + GST_my_private_key = NULL; + } +} + + +/** + * Initiate transport service. + * + * @param cls closure + * @param c configuration to use + * @param service the initialized service + */ +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *service) +{ + /* setup globals */ + GST_cfg = c; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (c, + "transport", + "HELLO_EXPIRATION", + &hello_expiration)) + { + hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; + } + GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); + if (NULL == GST_my_private_key) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + _("Transport service is lacking key configuration settings. Exiting.\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key, + &GST_my_identity.public_key); + GNUNET_log(GNUNET_ERROR_TYPE_INFO, + "My identity is `%s'\n", + GNUNET_i2s_full (&GST_my_identity)); + + GST_stats = GNUNET_STATISTICS_create ("transport", + GST_cfg); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + /* start subsystems */ +} + + +/** + * Define "main" method using service macro. + */ +GNUNET_SERVICE_MAIN +("transport", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + /* communication with core */ + GNUNET_MQ_hd_fixed_size (client_start, + GNUNET_MESSAGE_TYPE_TRANSPORT_START, + struct StartMessage, + NULL), + GNUNET_MQ_hd_var_size (client_hello, + GNUNET_MESSAGE_TYPE_HELLO, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_hd_var_size (client_send, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, + struct OutboundMessage, + NULL), + /* communication with communicators */ + GNUNET_MQ_hd_var_size (communicator_available, + GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR, + struct GNUNET_TRANSPORT_CommunicatorAvailableMessage, + NULL), + GNUNET_MQ_hd_var_size (add_address, + GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS, + struct GNUNET_TRANSPORT_AddAddressMessage, + NULL), + GNUNET_MQ_hd_fixed_size (del_address, + GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS, + struct GNUNET_TRANSPORT_DelAddressMessage, + NULL), + GNUNET_MQ_hd_var_size (incoming_msg, + GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG, + struct GNUNET_TRANSPORT_IncomingMessage, + NULL), + GNUNET_MQ_hd_var_size (add_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP, + struct GNUNET_TRANSPORT_AddQueueMessage, + NULL), + GNUNET_MQ_hd_fixed_size (del_queue_message, + GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN, + struct GNUNET_TRANSPORT_DelQueueMessage, + NULL), + GNUNET_MQ_hd_fixed_size (send_message_ack, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, + struct GNUNET_TRANSPORT_SendMessageToAck, + NULL), + GNUNET_MQ_handler_end ()); + + +/* end of file gnunet-service-transport.c */ diff --git a/src/transport/transport.h b/src/transport/transport.h index f21863aef..1b46213cf 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -94,7 +94,7 @@ struct StartMessage /** * 0: no options - * 1: The 'self' field should be checked + * 1: The @e self field should be checked * 2: this client is interested in payload traffic */ uint32_t options; @@ -404,6 +404,7 @@ struct ValidationIterateResponseMessage struct GNUNET_TIME_AbsoluteNBO next_validation; }; + /** * Message from the library to the transport service * asking for binary addresses known for a peer. @@ -667,7 +668,7 @@ struct GNUNET_TRANSPORT_CommunicatorAvailableMessage /* Followed by the address prefix of the communicator */ }; - + /** * Add address to the list. @@ -694,7 +695,7 @@ struct GNUNET_TRANSPORT_AddAddressMessage * An `enum GNUNET_ATS_Network_Type` in NBO. */ uint32_t nt; - + /* followed by UTF-8 encoded, 0-terminated human-readable address */ }; @@ -733,12 +734,12 @@ struct GNUNET_TRANSPORT_IncomingMessage * Do we use flow control or not? */ uint32_t fc_on GNUNET_PACKED; - + /** * 64-bit number to identify the matching ACK. */ uint64_t fc_id GNUNET_PACKED; - + /** * Sender identifier. */ @@ -764,12 +765,12 @@ struct GNUNET_TRANSPORT_IncomingMessageAck * Reserved (0) */ uint32_t reserved GNUNET_PACKED; - + /** * Which message is being ACKed? */ uint64_t fc_id GNUNET_PACKED; - + /** * Sender identifier of the original message. */ @@ -803,7 +804,7 @@ struct GNUNET_TRANSPORT_AddQueueMessage * An `enum GNUNET_ATS_Network_Type` in NBO. */ uint32_t nt; - + /* followed by UTF-8 encoded, 0-terminated human-readable address */ }; @@ -895,7 +896,7 @@ struct GNUNET_TRANSPORT_SendMessageTo * Message ID, used for flow control. */ uint64_t mid GNUNET_PACKED; - + /** * Receiver identifier. */ @@ -925,7 +926,7 @@ struct GNUNET_TRANSPORT_SendMessageToAck * Message ID of the original message. */ uint64_t mid GNUNET_PACKED; - + /** * Receiver identifier. */ -- cgit v1.2.3 From b237fcbd7e189f755dd8b372398a0ea94255d090 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 10 Nov 2018 17:36:11 +0100 Subject: new convenience function to do operations on a configuration object to avoid repetitive configuration_create, _load and _destroy logic --- po/POTFILES.in | 2 ++ src/include/gnunet_configuration_lib.h | 31 ++++++++++++++++++++- src/util/configuration.c | 35 +++++++++++++++++++++++ src/util/disk.c | 51 +++++++++++++++++++--------------- src/util/service.c | 10 ++++--- 5 files changed, 102 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/po/POTFILES.in b/po/POTFILES.in index caf7353be..54fe7b4e7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -398,9 +398,11 @@ src/testing/list-keys.c src/testing/testing.c src/topology/friends.c src/topology/gnunet-daemon-topology.c +src/transport/gnunet-communicator-unix.c src/transport/gnunet-helper-transport-bluetooth.c src/transport/gnunet-helper-transport-wlan.c src/transport/gnunet-helper-transport-wlan-dummy.c +src/transport/gnunet-service-tng.c src/transport/gnunet-service-transport_ats.c src/transport/gnunet-service-transport.c src/transport/gnunet-service-transport_hello.c diff --git a/src/include/gnunet_configuration_lib.h b/src/include/gnunet_configuration_lib.h index e3eefa18d..ec3d12738 100644 --- a/src/include/gnunet_configuration_lib.h +++ b/src/include/gnunet_configuration_lib.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2006, 2008, 2009 GNUnet e.V. + Copyright (C) 2006, 2008, 2009, 2018 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published @@ -190,6 +190,35 @@ int GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg); +/** + * Signature of a function to be run with a configuration. + * + * @param cls closure + * @param cfg the configuration + * @return status code + */ +typedef int +(*GNUNET_CONFIGURATION_Callback)(void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * Parse a configuration file @a filename and run the function + * @a cb with the resulting configuration object. Then free the + * configuration object and return the status value from @a cb. + * + * @param filename configuration to parse, NULL for "default" + * @param cb function to run + * @param cb_cls closure for @a cb + * @return #GNUNET_SYSERR if parsing the configuration failed, + * otherwise return value from @a cb. + */ +int +GNUNET_CONFIGURATION_parse_and_run (const char *filename, + GNUNET_CONFIGURATION_Callback cb, + void *cb_cls); + + /** * Function to iterate over options. * diff --git a/src/util/configuration.c b/src/util/configuration.c index 41eb3188d..a8e492a32 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -137,6 +137,41 @@ GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) } +/** + * Parse a configuration file @a filename and run the function + * @a cb with the resulting configuration object. Then free the + * configuration object and return the status value from @a cb. + * + * @param filename configuration to parse, NULL for "default" + * @param cb function to run + * @param cb_cls closure for @a cb + * @return #GNUNET_SYSERR if parsing the configuration failed, + * otherwise return value from @a cb. + */ +int +GNUNET_CONFIGURATION_parse_and_run (const char *filename, + GNUNET_CONFIGURATION_Callback cb, + void *cb_cls) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + int ret; + + cfg = GNUNET_CONFIGURATION_create (); + if (GNUNET_OK != + GNUNET_CONFIGURATION_load (cfg, + filename)) + { + GNUNET_break (0); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + ret = cb (cb_cls, + cfg); + GNUNET_CONFIGURATION_destroy (cfg); + return ret; +} + + /** * De-serializes configuration * diff --git a/src/util/disk.c b/src/util/disk.c index e0227be70..dc38d1137 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -2668,28 +2668,19 @@ GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh, /** - * Remove the directory given under @a option in - * section [PATHS] in configuration under @a cfg_filename + * Helper function for #GNUNET_DISK_purge_cfg_dir. * - * @param cfg_filename configuration file to parse - * @param option option with the dir name to purge + * @param cls a `const char *` with the option to purge + * @param cfg our configuration + * @return #GNUNET_OK on success */ -void -GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, - const char *option) +static int +purge_cfg_dir (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg) { - struct GNUNET_CONFIGURATION_Handle *cfg; + const char *option = cls; char *tmpname; - - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_load (cfg, - cfg_filename)) - { - GNUNET_break (0); - GNUNET_CONFIGURATION_destroy (cfg); - return; - } + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", @@ -2699,10 +2690,8 @@ GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "PATHS", option); - GNUNET_CONFIGURATION_destroy (cfg); - return; + return GNUNET_NO; } - GNUNET_CONFIGURATION_destroy (cfg); if (GNUNET_SYSERR == GNUNET_DISK_directory_remove (tmpname)) { @@ -2710,11 +2699,29 @@ GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, "remove", tmpname); GNUNET_free (tmpname); - return; + return GNUNET_OK; } GNUNET_free (tmpname); + return GNUNET_OK; } +/** + * Remove the directory given under @a option in + * section [PATHS] in configuration under @a cfg_filename + * + * @param cfg_filename configuration file to parse + * @param option option with the dir name to purge + */ +void +GNUNET_DISK_purge_cfg_dir (const char *cfg_filename, + const char *option) +{ + GNUNET_break (GNUNET_OK == + GNUNET_CONFIGURATION_parse_and_run (cfg_filename, + &purge_cfg_dir, + (void *) option)); +} + /* end of disk.c */ diff --git a/src/util/service.c b/src/util/service.c index ea34abc6c..b61168570 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -1815,8 +1815,9 @@ GNUNET_SERVICE_run_ (int argc, opt_cfg_filename = GNUNET_strdup (cfg_filename); if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_filename)) { - if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, - opt_cfg_filename)) + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_load (cfg, + opt_cfg_filename)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration file `%s', exit ...\n"), @@ -1826,8 +1827,9 @@ GNUNET_SERVICE_run_ (int argc, } else { - if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, - NULL)) + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_load (cfg, + NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration, exit ...\n")); -- cgit v1.2.3 From f8b930e0574cd205cc91c22df400fe95047a7dc8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 10 Nov 2018 19:27:02 +0100 Subject: ignore new binary --- src/transport/.gitignore | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/transport/.gitignore b/src/transport/.gitignore index d035b4011..90f908a47 100644 --- a/src/transport/.gitignore +++ b/src/transport/.gitignore @@ -83,3 +83,4 @@ test_transport_blacklisting_outbound_bl_full test_transport_blacklisting_outbound_bl_plugin test_transport_testing_restart test_transport_testing_startstop +gnunet-communicator-unix -- cgit v1.2.3 From 748788145250b3a012b0d3164461363d9add79a8 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Mon, 12 Nov 2018 16:15:32 +0100 Subject: GNSRECORD: fix build w/o jansson --- po/POTFILES.in | 110 +++++++++++++++++++++++----------------------- src/gnsrecord/gnsrecord.c | 3 -- 2 files changed, 55 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/po/POTFILES.in b/po/POTFILES.in index 54fe7b4e7..5f4c5ee7f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,13 +4,21 @@ src/arm/arm_monitor_api.c src/arm/gnunet-arm.c src/arm/gnunet-service-arm.c src/arm/mockup-service.c +src/ats-tests/ats-testing-experiment.c +src/ats-tests/ats-testing-log.c +src/ats-tests/ats-testing-preferences.c +src/ats-tests/ats-testing-traffic.c +src/ats-tests/ats-testing.c +src/ats-tests/gnunet-ats-sim.c +src/ats-tests/gnunet-solver-eval.c +src/ats-tool/gnunet-ats.c src/ats/ats_api_connectivity.c src/ats/ats_api_performance.c src/ats/ats_api_scanner.c src/ats/ats_api_scheduling.c src/ats/gnunet-ats-solver-eval.c -src/ats/gnunet-service-ats_addresses.c src/ats/gnunet-service-ats.c +src/ats/gnunet-service-ats_addresses.c src/ats/gnunet-service-ats_connectivity.c src/ats/gnunet-service-ats_normalization.c src/ats/gnunet-service-ats_performance.c @@ -21,14 +29,6 @@ src/ats/gnunet-service-ats_scheduling.c src/ats/plugin_ats_mlp.c src/ats/plugin_ats_proportional.c src/ats/plugin_ats_ril.c -src/ats-tests/ats-testing.c -src/ats-tests/ats-testing-experiment.c -src/ats-tests/ats-testing-log.c -src/ats-tests/ats-testing-preferences.c -src/ats-tests/ats-testing-traffic.c -src/ats-tests/gnunet-ats-sim.c -src/ats-tests/gnunet-solver-eval.c -src/ats-tool/gnunet-ats.c src/auction/gnunet-auction-create.c src/auction/gnunet-auction-info.c src/auction/gnunet-auction-join.c @@ -40,8 +40,8 @@ src/block/plugin_block_test.c src/cadet/cadet_api.c src/cadet/cadet_test_lib.c src/cadet/desirability_table.c -src/cadet/gnunet-cadet.c src/cadet/gnunet-cadet-profiler.c +src/cadet/gnunet-cadet.c src/cadet/gnunet-service-cadet.c src/cadet/gnunet-service-cadet_channel.c src/cadet/gnunet-service-cadet_connection.c @@ -57,15 +57,15 @@ src/consensus/gnunet-service-consensus.c src/consensus/plugin_block_consensus.c src/conversation/conversation_api.c src/conversation/conversation_api_call.c -src/conversation/gnunet-conversation.c src/conversation/gnunet-conversation-test.c -src/conversation/gnunet_gst.c -src/conversation/gnunet_gst_test.c -src/conversation/gnunet-helper-audio-playback.c +src/conversation/gnunet-conversation.c src/conversation/gnunet-helper-audio-playback-gst.c -src/conversation/gnunet-helper-audio-record.c +src/conversation/gnunet-helper-audio-playback.c src/conversation/gnunet-helper-audio-record-gst.c +src/conversation/gnunet-helper-audio-record.c src/conversation/gnunet-service-conversation.c +src/conversation/gnunet_gst.c +src/conversation/gnunet_gst_test.c src/conversation/microphone.c src/conversation/plugin_gnsrecord_conversation.c src/conversation/speaker.c @@ -101,7 +101,6 @@ src/dht/dht_api.c src/dht/dht_test_lib.c src/dht/gnunet-dht-get.c src/dht/gnunet-dht-monitor.c -src/dht/gnunet_dht_profiler.c src/dht/gnunet-dht-put.c src/dht/gnunet-service-dht.c src/dht/gnunet-service-dht_clients.c @@ -110,6 +109,7 @@ src/dht/gnunet-service-dht_hello.c src/dht/gnunet-service-dht_neighbours.c src/dht/gnunet-service-dht_nse.c src/dht/gnunet-service-dht_routing.c +src/dht/gnunet_dht_profiler.c src/dht/plugin_block_dht.c src/dns/dns_api.c src/dns/gnunet-dns-monitor.c @@ -123,8 +123,8 @@ src/dv/gnunet-dv.c src/dv/gnunet-service-dv.c src/dv/plugin_transport_dv.c src/exit/gnunet-daemon-exit.c -src/exit/gnunet-helper-exit.c src/exit/gnunet-helper-exit-windows.c +src/exit/gnunet-helper-exit.c src/fragmentation/defragmentation.c src/fragmentation/fragmentation.c src/fs/fs_api.c @@ -149,8 +149,8 @@ src/fs/gnunet-auto-share.c src/fs/gnunet-daemon-fsprofiler.c src/fs/gnunet-directory.c src/fs/gnunet-download.c -src/fs/gnunet-fs.c src/fs/gnunet-fs-profiler.c +src/fs/gnunet-fs.c src/fs/gnunet-helper-fs-publish.c src/fs/gnunet-publish.c src/fs/gnunet-search.c @@ -170,10 +170,10 @@ src/gns/gns_tld_api.c src/gns/gnunet-bcd.c src/gns/gnunet-dns2gns.c src/gns/gnunet-gns-benchmark.c -src/gns/gnunet-gns.c src/gns/gnunet-gns-helper-service-w32.c src/gns/gnunet-gns-import.c src/gns/gnunet-gns-proxy.c +src/gns/gnunet-gns.c src/gns/gnunet-service-gns.c src/gns/gnunet-service-gns_interceptor.c src/gns/gnunet-service-gns_resolver.c @@ -181,15 +181,15 @@ src/gns/nss/nss_gns.c src/gns/nss/nss_gns_query.c src/gns/plugin_block_gns.c src/gns/plugin_gnsrecord_gns.c +src/gns/w32nsp-install.c +src/gns/w32nsp-resolve.c +src/gns/w32nsp-uninstall.c +src/gns/w32nsp.c src/gnsrecord/gnsrecord.c src/gnsrecord/gnsrecord_crypto.c src/gnsrecord/gnsrecord_misc.c src/gnsrecord/gnsrecord_serialization.c src/gnsrecord/plugin_gnsrecord_dns.c -src/gns/w32nsp.c -src/gns/w32nsp-install.c -src/gns/w32nsp-resolve.c -src/gns/w32nsp-uninstall.c src/hello/address.c src/hello/gnunet-hello.c src/hello/hello.c @@ -218,8 +218,8 @@ src/namecache/namecache_api.c src/namecache/plugin_namecache_flat.c src/namecache/plugin_namecache_postgres.c src/namecache/plugin_namecache_sqlite.c -src/namestore/gnunet-namestore.c src/namestore/gnunet-namestore-fcfsd.c +src/namestore/gnunet-namestore.c src/namestore/gnunet-service-namestore.c src/namestore/gnunet-zoneimport.c src/namestore/namestore_api.c @@ -234,10 +234,10 @@ src/nat-auto/gnunet-service-nat-auto.c src/nat-auto/gnunet-service-nat-auto_legacy.c src/nat-auto/nat_auto_api.c src/nat-auto/nat_auto_api_test.c -src/nat/gnunet-helper-nat-client.c src/nat/gnunet-helper-nat-client-windows.c -src/nat/gnunet-helper-nat-server.c +src/nat/gnunet-helper-nat-client.c src/nat/gnunet-helper-nat-server-windows.c +src/nat/gnunet-helper-nat-server.c src/nat/gnunet-nat.c src/nat/gnunet-service-nat.c src/nat/gnunet-service-nat_externalip.c @@ -246,15 +246,15 @@ src/nat/gnunet-service-nat_mini.c src/nat/gnunet-service-nat_stun.c src/nat/nat_api.c src/nat/nat_api_stun.c -src/nse/gnunet-nse.c src/nse/gnunet-nse-profiler.c +src/nse/gnunet-nse.c src/nse/gnunet-service-nse.c src/nse/nse_api.c +src/peerinfo-tool/gnunet-peerinfo.c +src/peerinfo-tool/gnunet-peerinfo_plugins.c src/peerinfo/gnunet-service-peerinfo.c src/peerinfo/peerinfo_api.c src/peerinfo/peerinfo_api_notify.c -src/peerinfo-tool/gnunet-peerinfo.c -src/peerinfo-tool/gnunet-peerinfo_plugins.c src/peerstore/gnunet-peerstore.c src/peerstore/gnunet-service-peerstore.c src/peerstore/peerstore_api.c @@ -301,7 +301,6 @@ src/regex/regex_internal_dht.c src/regex/regex_test_graph.c src/regex/regex_test_lib.c src/regex/regex_test_random.c -src/rest/gnunet-rest-server.c src/rest-plugins/json_reclaim.c src/rest-plugins/oidc_helper.c src/rest-plugins/plugin_rest_copying.c @@ -312,27 +311,28 @@ src/rest-plugins/plugin_rest_namestore.c src/rest-plugins/plugin_rest_openid_connect.c src/rest-plugins/plugin_rest_peerinfo.c src/rest-plugins/plugin_rest_reclaim.c +src/rest/gnunet-rest-server.c src/rest/rest.c src/revocation/gnunet-revocation.c src/revocation/gnunet-service-revocation.c src/revocation/plugin_block_revocation.c src/revocation/revocation_api.c -src/rps/gnunet-rps.c src/rps/gnunet-rps-profiler.c +src/rps/gnunet-rps.c src/rps/gnunet-service-rps.c src/rps/gnunet-service-rps_custommap.c src/rps/gnunet-service-rps_sampler.c src/rps/gnunet-service-rps_sampler_elem.c src/rps/gnunet-service-rps_view.c -src/rps/rps_api.c src/rps/rps-sampler_client.c src/rps/rps-sampler_common.c src/rps/rps-test_util.c +src/rps/rps_api.c src/scalarproduct/gnunet-scalarproduct.c -src/scalarproduct/gnunet-service-scalarproduct_alice.c -src/scalarproduct/gnunet-service-scalarproduct_bob.c src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c +src/scalarproduct/gnunet-service-scalarproduct_alice.c +src/scalarproduct/gnunet-service-scalarproduct_bob.c src/scalarproduct/scalarproduct_api.c src/secretsharing/gnunet-secretsharing-profiler.c src/secretsharing/gnunet-service-secretsharing.c @@ -361,15 +361,16 @@ src/statistics/gnunet-statistics.c src/statistics/statistics_api.c src/template/gnunet-service-template.c src/template/gnunet-template.c +src/testbed-logger/gnunet-service-testbed-logger.c +src/testbed-logger/testbed_logger_api.c src/testbed/generate-underlay-topology.c src/testbed/gnunet-daemon-latency-logger.c src/testbed/gnunet-daemon-testbed-blacklist.c src/testbed/gnunet-daemon-testbed-underlay.c src/testbed/gnunet-helper-testbed.c -src/testbed/gnunet_mpi_test.c src/testbed/gnunet-service-test-barriers.c -src/testbed/gnunet-service-testbed_barriers.c src/testbed/gnunet-service-testbed.c +src/testbed/gnunet-service-testbed_barriers.c src/testbed/gnunet-service-testbed_cache.c src/testbed/gnunet-service-testbed_connectionpool.c src/testbed/gnunet-service-testbed_cpustatus.c @@ -377,20 +378,19 @@ src/testbed/gnunet-service-testbed_links.c src/testbed/gnunet-service-testbed_meminfo.c src/testbed/gnunet-service-testbed_oc.c src/testbed/gnunet-service-testbed_peers.c -src/testbed/gnunet_testbed_mpi_spawn.c src/testbed/gnunet-testbed-profiler.c -src/testbed-logger/gnunet-service-testbed-logger.c -src/testbed-logger/testbed_logger_api.c -src/testbed/testbed_api_barriers.c +src/testbed/gnunet_mpi_test.c +src/testbed/gnunet_testbed_mpi_spawn.c src/testbed/testbed_api.c +src/testbed/testbed_api_barriers.c src/testbed/testbed_api_hosts.c src/testbed/testbed_api_operations.c src/testbed/testbed_api_peers.c src/testbed/testbed_api_sd.c src/testbed/testbed_api_services.c src/testbed/testbed_api_statistics.c -src/testbed/testbed_api_testbed.c src/testbed/testbed_api_test.c +src/testbed/testbed_api_testbed.c src/testbed/testbed_api_topology.c src/testbed/testbed_api_underlay.c src/testing/gnunet-testing.c @@ -400,29 +400,29 @@ src/topology/friends.c src/topology/gnunet-daemon-topology.c src/transport/gnunet-communicator-unix.c src/transport/gnunet-helper-transport-bluetooth.c -src/transport/gnunet-helper-transport-wlan.c src/transport/gnunet-helper-transport-wlan-dummy.c +src/transport/gnunet-helper-transport-wlan.c src/transport/gnunet-service-tng.c -src/transport/gnunet-service-transport_ats.c src/transport/gnunet-service-transport.c +src/transport/gnunet-service-transport_ats.c src/transport/gnunet-service-transport_hello.c src/transport/gnunet-service-transport_manipulation.c src/transport/gnunet-service-transport_neighbours.c src/transport/gnunet-service-transport_plugins.c src/transport/gnunet-service-transport_validation.c -src/transport/gnunet-transport.c src/transport/gnunet-transport-certificate-creation.c src/transport/gnunet-transport-profiler.c src/transport/gnunet-transport-wlan-receiver.c src/transport/gnunet-transport-wlan-sender.c +src/transport/gnunet-transport.c src/transport/plugin_transport_http_client.c src/transport/plugin_transport_http_common.c src/transport/plugin_transport_http_server.c src/transport/plugin_transport_smtp.c src/transport/plugin_transport_tcp.c src/transport/plugin_transport_template.c -src/transport/plugin_transport_udp_broadcasting.c src/transport/plugin_transport_udp.c +src/transport/plugin_transport_udp_broadcasting.c src/transport/plugin_transport_unix.c src/transport/plugin_transport_wlan.c src/transport/plugin_transport_xt.c @@ -431,6 +431,11 @@ src/transport/tcp_connection_legacy.c src/transport/tcp_server_legacy.c src/transport/tcp_server_mst_legacy.c src/transport/tcp_service_legacy.c +src/transport/transport-testing-filenames.c +src/transport/transport-testing-loggers.c +src/transport/transport-testing-main.c +src/transport/transport-testing-send.c +src/transport/transport-testing.c src/transport/transport_api2_communication.c src/transport/transport_api_address_to_string.c src/transport/transport_api_blacklist.c @@ -440,11 +445,6 @@ src/transport/transport_api_manipulation.c src/transport/transport_api_monitor_peers.c src/transport/transport_api_monitor_plugins.c src/transport/transport_api_offer_hello.c -src/transport/transport-testing.c -src/transport/transport-testing-filenames.c -src/transport/transport-testing-loggers.c -src/transport/transport-testing-main.c -src/transport/transport-testing-send.c src/util/bandwidth.c src/util/benchmark.c src/util/bio.c @@ -457,8 +457,8 @@ src/util/configuration_loader.c src/util/container_bloomfilter.c src/util/container_heap.c src/util/container_meta_data.c -src/util/container_multihashmap32.c src/util/container_multihashmap.c +src/util/container_multihashmap32.c src/util/container_multipeermap.c src/util/container_multishortmap.c src/util/crypto_abe.c @@ -480,15 +480,15 @@ src/util/dnsparser.c src/util/dnsstub.c src/util/getopt.c src/util/getopt_helpers.c -src/util/gnunet-config.c src/util/gnunet-config-diff.c +src/util/gnunet-config.c src/util/gnunet-ecc.c src/util/gnunet-helper-w32-console.c src/util/gnunet-resolver.c src/util/gnunet-scrypt.c src/util/gnunet-service-resolver.c -src/util/gnunet-timeout.c src/util/gnunet-timeout-w32.c +src/util/gnunet-timeout.c src/util/gnunet-uri.c src/util/helper.c src/util/load.c @@ -516,13 +516,13 @@ src/util/tun.c src/util/w32cat.c src/util/win.c src/util/winproc.c -src/vpn/gnunet-helper-vpn.c src/vpn/gnunet-helper-vpn-windows.c +src/vpn/gnunet-helper-vpn.c src/vpn/gnunet-service-vpn.c src/vpn/gnunet-vpn.c src/vpn/vpn_api.c -src/zonemaster/gnunet-service-zonemaster.c src/zonemaster/gnunet-service-zonemaster-monitor.c +src/zonemaster/gnunet-service-zonemaster.c src/fs/fs_api.h src/include/gnunet_common.h src/include/gnunet_mq_lib.h diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c index b80d86073..f0d7a839e 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c @@ -28,10 +28,7 @@ #include "gnunet_constants.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gnsrecord_plugin.h" -#include "gnunet_json_lib.h" #include "gnunet_tun_lib.h" -#include - #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) -- cgit v1.2.3 From b26dc73654be36d70f1b3c06e23fec42330db4f6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 12 Nov 2018 20:48:43 +0100 Subject: fix etime setting in gnunet-namestore --- src/namestore/gnunet-namestore.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c index 865481746..619d0c528 100644 --- a/src/namestore/gnunet-namestore.c +++ b/src/namestore/gnunet-namestore.c @@ -191,14 +191,10 @@ static void *data; static size_t data_size; /** - * Expirationstring converted to relative time. + * Expiration string converted to numeric value. */ -static struct GNUNET_TIME_Relative etime_rel; +static uint64_t etime; -/** - * Expirationstring converted to absolute time. - */ -static struct GNUNET_TIME_Absolute etime_abs; /** * Is expiration time relative or absolute time? @@ -539,6 +535,8 @@ display_record_lookup (void *cls, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { + (void) cls; + (void) zone_key; get_qe = NULL; display_record (rname, rd_len, @@ -717,14 +715,10 @@ get_existing_record (void *cls, rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; if (1 != is_public) rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; + rde->expiration_time = etime; if (GNUNET_YES == etime_is_rel) - { - rde->expiration_time = etime_rel.rel_value_us; rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_NO == etime_is_rel) - rde->expiration_time = etime_abs.abs_value_us; - else + else if (GNUNET_NO != etime_is_rel) rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; GNUNET_assert (NULL != name); add_qe = GNUNET_NAMESTORE_records_store (ns, @@ -988,7 +982,6 @@ identity_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_GNSRECORD_Data rd; - uint64_t etime; el = NULL; if (NULL == ego) @@ -1359,6 +1352,8 @@ multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, int etime_is_rel; void *raw_data; + (void) ctx; + (void) option; cp = GNUNET_strdup (value); tok = strtok (cp, " "); if (NULL == tok) -- cgit v1.2.3 From 21eec1db5fa782ab36dbc250317dbe117bc52af8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 12 Nov 2018 20:55:33 +0100 Subject: trying to fix #5472 --- src/cadet/test_cadet.conf | 4 ++++ src/gns/gnunet-gns-proxy.c | 48 +++++++++++++++++++++++++++++------------- src/gns/test_gns_defaults.conf | 12 +++++++++++ 3 files changed, 49 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cadet/test_cadet.conf b/src/cadet/test_cadet.conf index 5ad67fec2..30e496aff 100644 --- a/src/cadet/test_cadet.conf +++ b/src/cadet/test_cadet.conf @@ -98,3 +98,7 @@ START_ON_DEMAND = NO [topology] IMMEDIATE_START = NO START_ON_DEMAND = NO + +[rps] +IMMEDIATE_START = NO +START_ON_DEMAND = NO diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index a9013390e..e1997e215 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c @@ -58,6 +58,12 @@ */ #define MAX_HTTP_URI_LENGTH 2048 +/** + * Maximum number of DANE records we support + * per domain name (and port and protocol). + */ +#define MAX_DANES 32 + /** * Size of the buffer for the data upload / download. Must be * enough for curl, thus CURL_MAX_WRITE_SIZE is needed here (16k). @@ -543,9 +549,9 @@ struct Socks5Request char *leho; /** - * Payload of the (last) DANE record encountered. + * Payload of the DANE records encountered. */ - char *dane_data; + char *dane_data[MAX_DANES + 1]; /** * The URL to fetch @@ -575,7 +581,13 @@ struct Socks5Request /** * Number of bytes in @e dane_data. */ - size_t dane_data_len; + int dane_data_len[MAX_DANES + 1]; + + /** + * Number of entries used in @e dane_data_len + * and @e dane_data. + */ + unsigned int num_danes; /** * Number of bytes already in read buffer @@ -816,7 +828,8 @@ cleanup_s5r (struct Socks5Request *s5r) GNUNET_free_non_null (s5r->domain); GNUNET_free_non_null (s5r->leho); GNUNET_free_non_null (s5r->url); - GNUNET_free_non_null (s5r->dane_data); + for (unsigned int i=0;inum_danes;i++) + GNUNET_free (s5r->dane_data[i]); GNUNET_free (s5r); } @@ -989,10 +1002,8 @@ check_ssl_certificate (struct Socks5Request *s5r) } /* check for TLSA/DANE records */ #if HAVE_GNUTLS_DANE - if (NULL != s5r->dane_data) + if (0 != s5r->num_danes) { - char *dd[] = { s5r->dane_data, NULL }; - int dlen[] = { s5r->dane_data_len, 0}; dane_state_t dane_state; dane_query_t dane_query; unsigned int verify; @@ -1010,10 +1021,12 @@ check_ssl_certificate (struct Socks5Request *s5r) gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } + s5r->dane_data[s5r->num_danes] = NULL; + s5r->dane_data_len[s5r->num_danes] = 0; if (0 != (rc = dane_raw_tlsa (dane_state, &dane_query, - dd, - dlen, + s5r->dane_data, + s5r->dane_data_len, GNUNET_YES, GNUNET_NO))) { @@ -3070,12 +3083,17 @@ handle_gns_result (void *cls, (ntohs (box->protocol) != IPPROTO_TCP) || (ntohs (box->service) != s5r->port) ) break; /* BOX record does not apply */ - GNUNET_free_non_null (s5r->dane_data); - s5r->dane_data_len = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord); - s5r->dane_data = GNUNET_malloc (s5r->dane_data_len); - GNUNET_memcpy (s5r->dane_data, - &box[1], - s5r->dane_data_len); + if (s5r->num_danes >= MAX_DANES) + { + GNUNET_break (0); /* MAX_DANES too small */ + break; + } + s5r->dane_data_len[s5r->num_danes] + = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord); + s5r->dane_data[s5r->num_danes] + = GNUNET_memdup (&box[1], + s5r->dane_data_len); + s5r->num_danes++; break; } default: diff --git a/src/gns/test_gns_defaults.conf b/src/gns/test_gns_defaults.conf index 19ba01ebb..80a2f3c44 100644 --- a/src/gns/test_gns_defaults.conf +++ b/src/gns/test_gns_defaults.conf @@ -20,3 +20,15 @@ PLUGINS = tcp [transport-tcp] BINDTO = 127.0.0.1 + +[fs] +IMMEDIATE_START = NO +START_ON_DEMAND = NO + +[rps] +IMMEDIATE_START = NO +START_ON_DEMAND = NO + +[topology] +IMMEDIATE_START = NO +START_ON_DEMAND = NO -- cgit v1.2.3 From 5db18738ebf3c284d4bc0d7080e542e5ab1c7462 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 12 Nov 2018 21:13:30 +0100 Subject: fix resolver bugs and warnings --- src/util/gnunet-service-resolver.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c index d907bd8d9..3b871ce33 100644 --- a/src/util/gnunet-service-resolver.c +++ b/src/util/gnunet-service-resolver.c @@ -364,7 +364,7 @@ lookup_dns_servers (char ***server_addrs) GNUNET_DISK_file_close (fh); return -1; } - if (bytes_read > SIZE_MAX) + if ((size_t) bytes_read > SIZE_MAX) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "/etc/resolv.conf file too large to mmap. " @@ -379,7 +379,7 @@ lookup_dns_servers (char ***server_addrs) *server_addrs = NULL; read_offset = 0; num_dns_servers = 0; - while (read_offset < bytes_read) + while (read_offset < (size_t) bytes_read) { const char *newline; size_t line_len; @@ -648,11 +648,16 @@ try_cache (const char *hostname, struct ResolveCache *pos; struct ResolveCache *next; int found; + int in_hosts; + in_hosts = GNUNET_NO; for (pos = hosts_head; NULL != pos; pos = pos->next) if (0 == strcmp (pos->hostname, hostname)) + { + in_hosts = GNUNET_YES; break; + } if (NULL == pos) { next = cache_head; @@ -673,7 +678,8 @@ try_cache (const char *hostname, hostname); return GNUNET_NO; } - if (cache_head != pos) + if ( (GNUNET_NO == in_hosts) && + (cache_head != pos) ) { /* move result to head to achieve LRU for cache eviction */ GNUNET_CONTAINER_DLL_remove (cache_head, @@ -1313,7 +1319,7 @@ extract_hosts (const char *line, if (NULL != c) line_len = c - line; /* ignore leading whitespace */ - while ( (0 > line_len) && + while ( (0 < line_len) && isspace ((unsigned char) *line) ) { line++; @@ -1382,7 +1388,7 @@ load_etc_hosts (void) GNUNET_DISK_file_close (fh); return; } - if (bytes_read > SIZE_MAX) + if ((size_t) bytes_read > SIZE_MAX) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "/etc/hosts file too large to mmap. " @@ -1395,7 +1401,7 @@ load_etc_hosts (void) GNUNET_DISK_MAP_TYPE_READ, (size_t) bytes_read); read_offset = 0; - while (read_offset < bytes_read) + while (read_offset < (size_t) bytes_read) { const char *newline; size_t line_len; -- cgit v1.2.3 From 98288a7b26344294a3668101b9c2b502dfc19e12 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 12 Nov 2018 21:25:06 +0100 Subject: add logic to skip tests if DNS or /etc/hosts does not like us --- src/gns/test_gns_gns2dns_cname_lookup.sh | 9 ++++++++- src/gns/test_gns_gns2dns_lookup.sh | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gns/test_gns_gns2dns_cname_lookup.sh b/src/gns/test_gns_gns2dns_cname_lookup.sh index 84ad8549f..17196f820 100755 --- a/src/gns/test_gns_gns2dns_cname_lookup.sh +++ b/src/gns/test_gns_gns2dns_cname_lookup.sh @@ -43,7 +43,15 @@ MY_EGO="myego" # various names we will use for resolution TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO" +which timeout &> /dev/null && DO_TIMEOUT="timeout 15" + + gnunet-arm -s -c test_gns_lookup.conf + +echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found, skipping test"; exit 77; } +echo $OUT | grep $TEST6_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found, skipping test"; exit 77; } + + gnunet-identity -C $MY_EGO -c test_gns_lookup.conf # set IP address for DNS resolver for resolving in gnunet.org domain @@ -52,7 +60,6 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECOR gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS2 -e never -c test_gns_lookup.conf gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS3 -e never -c test_gns_lookup.conf -which timeout &> /dev/null && DO_TIMEOUT="timeout 15" echo "EGOs:" gnunet-identity -d diff --git a/src/gns/test_gns_gns2dns_lookup.sh b/src/gns/test_gns_gns2dns_lookup.sh index 122e45525..431f01086 100755 --- a/src/gns/test_gns_gns2dns_lookup.sh +++ b/src/gns/test_gns_gns2dns_lookup.sh @@ -44,8 +44,17 @@ TEST_DOMAIN="www.${TEST_RECORD_NAME}.$MY_EGO" TEST_DOMAIN_ALT="${TEST_RECORD_NAME}.$MY_EGO" TEST_DOMAIN_ALT2="docs.${TEST_RECORD_NAME}.$MY_EGO" +which timeout &> /dev/null && DO_TIMEOUT="timeout 15" + gnunet-arm -s -c test_gns_lookup.conf + +OUT=`$DO_TIMEOUT gnunet-resolver -c test_gns_lookup.conf gnunet.org` +echo $OUT | grep $TEST_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv4 for gnunet.org not found, skipping test"; exit 77; } +echo $OUT | grep $TEST6_IP - > /dev/null || { gnunet-arm -e -c test_gns_lookup.conf ; echo "IPv6 for gnunet.org not found, skipping test"; exit 77; } + + + gnunet-identity -C $MY_EGO -c test_gns_lookup.conf # set IP address for DNS resolver for resolving in gnunet.org domain @@ -53,7 +62,6 @@ gnunet-namestore -p -z $MY_EGO -a -n $TEST_RESOLVER_LABEL -t A -V $TEST_IP_GNS2D # map '$TEST_RECORD_NAME.$MY_EGO' to 'gnunet.org' in DNS gnunet-namestore -p -z $MY_EGO -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf -which timeout &> /dev/null && DO_TIMEOUT="timeout 15" echo "EGOs:" gnunet-identity -d -- cgit v1.2.3 From e8a1a082555f98af40f98fd3a20ccd803ad478f8 Mon Sep 17 00:00:00 2001 From: Nils Gillmann Date: Tue, 13 Nov 2018 11:41:15 +0000 Subject: Partial application of diff send in beberking, Issue #5476 Signed-off-by: Nils Gillmann --- po/de.po | 2 +- po/sv.po | 2 +- po/vi.po | 2 +- po/zh_CN.po | 2 +- src/cadet/gnunet-service-cadet_paths.c | 6 +++--- src/cadet/gnunet-service-cadet_tunnels.c | 2 +- src/dht/gnunet-dht-get.c | 2 +- src/dht/gnunet-service-dht_clients.c | 2 +- src/fs/gnunet-service-fs.c | 2 +- src/include/gnunet_consensus_service.h | 2 +- src/include/gnunet_testbed_service.h | 4 ++-- src/my/my.c | 2 +- src/namestore/gnunet-zoneimport.c | 2 +- src/namestore/namestore_api.c | 2 +- src/testbed/testbed.h | 2 +- src/testbed/testbed_api_hosts.c | 2 +- src/transport/gnunet-transport.c | 2 +- src/util/configuration.c | 2 +- 18 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/po/de.po b/po/de.po index eb6b2a4d3..d036280f7 100644 --- a/po/de.po +++ b/po/de.po @@ -7501,7 +7501,7 @@ msgstr "Adresse des Knotens `%s' konnte nicht ermittelt werden.\n" #: src/transport/gnunet-transport.c:492 #, fuzzy -msgid "Failed to list connections, timeout occured\n" +msgid "Failed to list connections, timeout occurred\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-transport.c:525 diff --git a/po/sv.po b/po/sv.po index 323f2de49..388ff2f82 100644 --- a/po/sv.po +++ b/po/sv.po @@ -7575,7 +7575,7 @@ msgstr "Misslyckades att binda till UDP-port %d.\n" #: src/transport/gnunet-transport.c:492 #, fuzzy -msgid "Failed to list connections, timeout occured\n" +msgid "Failed to list connections, timeout occurred\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:525 diff --git a/po/vi.po b/po/vi.po index 2f05f3daf..85131f055 100644 --- a/po/vi.po +++ b/po/vi.po @@ -7638,7 +7638,7 @@ msgstr "Lỗi đóng kết đến cổng %s %d.\n" #: src/transport/gnunet-transport.c:492 #, fuzzy -msgid "Failed to list connections, timeout occured\n" +msgid "Failed to list connections, timeout occurred\n" msgstr "Không kết nối được đến trình nền gnunetd." #: src/transport/gnunet-transport.c:525 diff --git a/po/zh_CN.po b/po/zh_CN.po index cd3a10b4e..d881d0591 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -7353,7 +7353,7 @@ msgstr "找不到接口“%s”的一个 IP 地址。\n" #: src/transport/gnunet-transport.c:492 #, fuzzy -msgid "Failed to list connections, timeout occured\n" +msgid "Failed to list connections, timeout occurred\n" msgstr "初始化“%s”服务失败。\n" #: src/transport/gnunet-transport.c:525 diff --git a/src/cadet/gnunet-service-cadet_paths.c b/src/cadet/gnunet-service-cadet_paths.c index 40f464e9b..7769a6043 100644 --- a/src/cadet/gnunet-service-cadet_paths.c +++ b/src/cadet/gnunet-service-cadet_paths.c @@ -354,7 +354,7 @@ check_match (void *cls, (off + 1 != cm_ctx->cpath_length) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, - "check_match missmatch because path %s is too long (%u vs. %u vs. %u)\n", + "check_match mismatch because path %s is too long (%u vs. %u vs. %u)\n", GCPP_2s (path), path->entries_length, off + 1, @@ -367,10 +367,10 @@ check_match (void *cls, i)) { LOG (GNUNET_ERROR_TYPE_DEBUG, - "check_match path %s missmatches at offset %u\n", + "check_match path %s mismatches at offset %u\n", GCPP_2s (path), i); - return GNUNET_YES; /* missmatch, ignore */ + return GNUNET_YES; /* mismatch, ignore */ } LOG (GNUNET_ERROR_TYPE_DEBUG, "check_match found match with path %s\n", diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c index 1e7a8e086..874c7e706 100644 --- a/src/cadet/gnunet-service-cadet_tunnels.c +++ b/src/cadet/gnunet-service-cadet_tunnels.c @@ -1983,7 +1983,7 @@ GCT_handle_kx_auth (struct CadetTConnection *ct, 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_WARNING, - "KX AUTH missmatch!\n"); + "KX AUTH mismatch!\n"); #if DEBUG_KX { struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; diff --git a/src/dht/gnunet-dht-get.c b/src/dht/gnunet-dht-get.c index 3742ed739..2d9d76585 100644 --- a/src/dht/gnunet-dht-get.c +++ b/src/dht/gnunet-dht-get.c @@ -214,7 +214,7 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key); if (verbose) FPRINTF (stderr, "%s `%s' \n", - _("Issueing DHT GET with key"), + _("Issuing DHT GET with key"), GNUNET_h2s_full (&key)); GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL); tt = GNUNET_SCHEDULER_add_delayed (timeout_request, diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c index 862654c83..332bc1eda 100644 --- a/src/dht/gnunet-service-dht_clients.c +++ b/src/dht/gnunet-service-dht_clients.c @@ -1018,7 +1018,7 @@ forward_reply (void *cls, (record->type != frc->type)) { LOG (GNUNET_ERROR_TYPE_DEBUG, - "Record type missmatch, not passing request for key %s to local client\n", + "Record type mismatch, not passing request for key %s to local client\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index 594896c93..fea22f279 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c @@ -1232,7 +1232,7 @@ peer_init_handler (void *cls, my_identity)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Peer identity missmatch, refusing to start!\n"); + "Peer identity mismatch, refusing to start!\n"); GNUNET_SCHEDULER_shutdown (); } } diff --git a/src/include/gnunet_consensus_service.h b/src/include/gnunet_consensus_service.h index eee9fc23b..c6aed298c 100644 --- a/src/include/gnunet_consensus_service.h +++ b/src/include/gnunet_consensus_service.h @@ -53,7 +53,7 @@ extern "C" /** - * Called when a new element was received from another peer, or an error occured. + * Called when a new element was received from another peer, or an error occurred. * May deliver duplicate values. * Elements given to a consensus operation by the local peer are NOT given * to this callback. diff --git a/src/include/gnunet_testbed_service.h b/src/include/gnunet_testbed_service.h index 4b8d63ad2..302b32019 100644 --- a/src/include/gnunet_testbed_service.h +++ b/src/include/gnunet_testbed_service.h @@ -443,7 +443,7 @@ typedef void /** - * Starts a controller process at the given host. The given host's configration + * Starts a controller process at the given host. The given host's configuration * is used as a Template configuration to use for the remote controller; the * remote controller will be started with a slightly modified configuration * (port numbers, unix domain sockets and service home values are changed as per @@ -486,7 +486,7 @@ GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc); /** * Connect to a controller process. The configuration to use for the connection - * is retreived from the given host where a controller is started using + * is retrieved from the given host where a controller is started using * GNUNET_TESTBED_controller_start(). * * @param host host to run the controller on; This should be the same host if diff --git a/src/my/my.c b/src/my/my.c index 2f4cd3ba3..16df437b2 100644 --- a/src/my/my.c +++ b/src/my/my.c @@ -157,7 +157,7 @@ GNUNET_MY_extract_result (struct GNUNET_MYSQL_StatementHandle *sh, if (mysql_stmt_field_count (stmt) != num_fields) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Number of fields missmatch between SQL result and result specification\n"); + "Number of fields mismatch between SQL result and result specification\n"); return GNUNET_SYSERR; } diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c index ddc8b483a..01706b777 100644 --- a/src/namestore/gnunet-zoneimport.c +++ b/src/namestore/gnunet-zoneimport.c @@ -1159,7 +1159,7 @@ process_result (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DNS ID did not match request, ignoring reply\n"); GNUNET_STATISTICS_update (stats, - "# DNS ID missmatches", + "# DNS ID mismatches", 1, GNUNET_NO); return; diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index 527576718..2cc293b37 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c @@ -754,7 +754,7 @@ handle_zone_to_name_response (void *cls, { case GNUNET_SYSERR: LOG (GNUNET_ERROR_TYPE_DEBUG, - "An error occured during zone to name operation\n"); + "An error occurred during zone to name operation\n"); break; case GNUNET_NO: LOG (GNUNET_ERROR_TYPE_DEBUG, diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h index b6ce7fb09..5b01a8e7f 100644 --- a/src/testbed/testbed.h +++ b/src/testbed/testbed.h @@ -101,7 +101,7 @@ struct GNUNET_TESTBED_AddHostMessage /* followed by non 0-terminated host name */ /* followed by gzip compressed configuration to start or connect to a - controller on this host. While starting the controller this configration + controller on this host. While starting the controller this configuration is used as a template */ }; diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c index 2c25eabcf..84296b26a 100644 --- a/src/testbed/testbed_api_hosts.c +++ b/src/testbed/testbed_api_hosts.c @@ -1041,7 +1041,7 @@ helper_exp_cb (void *cls) /** - * Starts a controller process at the given host. The given host's configration + * Starts a controller process at the given host. The given host's configuration * is used as a Template configuration to use for the remote controller; the * remote controller will be started with a slightly modified configuration * (port numbers, unix domain sockets and service home values are changed as per diff --git a/src/transport/gnunet-transport.c b/src/transport/gnunet-transport.c index fed509fe1..6c589307b 100644 --- a/src/transport/gnunet-transport.c +++ b/src/transport/gnunet-transport.c @@ -489,7 +489,7 @@ operation_timeout (void *cls) } FPRINTF (stdout, "%s", - _("Failed to list connections, timeout occured\n")); + _("Failed to list connections, timeout occurred\n")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; diff --git a/src/util/configuration.c b/src/util/configuration.c index 41eb3188d..312e0acd3 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -522,7 +522,7 @@ GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_free (fn); GNUNET_free (cfg_buf); LOG (GNUNET_ERROR_TYPE_WARNING, - "Writing configration to file `%s' failed\n", + "Writing configuration to file `%s' failed\n", filename); cfg->dirty = GNUNET_SYSERR; /* last write failed */ return GNUNET_SYSERR; -- cgit v1.2.3 From c84054626c6cc460bad4b6562ee89c221be308aa Mon Sep 17 00:00:00 2001 From: rexxnor Date: Tue, 13 Nov 2018 14:22:01 +0100 Subject: added -R tests for multiple arguments --- src/namestore/test_namestore_put_multiple.sh | 124 +++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/namestore/test_namestore_put_multiple.sh (limited to 'src') diff --git a/src/namestore/test_namestore_put_multiple.sh b/src/namestore/test_namestore_put_multiple.sh new file mode 100644 index 000000000..48ad95a3c --- /dev/null +++ b/src/namestore/test_namestore_put_multiple.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +# Check for required packages +if ! [ -x "$(command -v gnunet-namestore)" ]; then + echo 'bind/named is not installed' >&2 + exit 1 +fi + +# Check if gnunet is running +gnunet-arm -I 2&>1 /dev/null +ret=$? +if [ 0 -ne $ret ]; then + echo 'gnunet services are not running' + exit 1 +fi + +## GNUNET part +# Check if identity exists and delets and readds it to get rid of entries in zone +gnunet-identity -d | grep randomtestingid 2>&1 /dev/null +ret=$? + +if [ 0 -ne $ret ]; then + gnunet-identity -D randomtestingid + gnunet-identity -C randomtestingid +fi + +function minimize_ttl { + ttl=10000000 + arr=$1 + # parse each element and update ttl to smallest one + for i in "${arr[@]}" + do + currttl=$(echo -n "$i" | cut -d' ' -f1) + if [ "$currttl" -lt "$ttl" ] + then + ttl=$currttl + fi + + done + echo "$ttl" +} + +function get_record_type { + arr=$1 + typ=$(echo -n "${arr[0]}" | cut -d' ' -f2) + echo "$typ" +} + +function get_value { + arr=$1 + val=$(echo -n "${arr[0]}" | cut -d' ' -f4-) + echo "$val" +} + +function testing { + label=$1 + records=$2 + recordstring="" + typ=$(get_record_type "${records[@]}") + for i in "${records[@]}" + do + recordstring+="-R $i" + done + #echo "$recordstring" + gnunet-namestore -z randomtestingid -n "$label" "$recordstring" 2>&1 /dev/null + if [ 0 -ne $ret ]; then + echo "failed to add record $label: $recordstring" + fi + gnunet-gns -t "$typ" -u foo2.randomtestingid 2>&1 /dev/null + if [ 0 -ne $ret ]; then + echo "record $label could not be found" + fi +} + +# TEST CASES +# 1 +echo "Testing adding of single A record with -R" +declare -a arr=('1200 A n 127.0.0.1') +testing test1 "${arr[@]}" +# 2 +echo "Testing adding of multiple A records with -R" +declare -a arr=('1200 A n 127.0.0.1' '2400 A n 127.0.0.2') +testing test2 "${arr[@]}" +# 3 +echo "Testing adding of multiple different records with -R" +declare -a arr=('1200 A n 127.0.0.1' '2400 AAAA n 2002::') +testing test3 "${arr[@]}" +# 4 +echo "Testing adding of single GNS2DNS record with -R" +declare -a arr=('86400 GNS2DNS n gnu.org@127.0.0.1') +testing test4 "${arr[@]}" +# 5 +echo "Testing adding of single GNS2DNS shadow record with -R" +declare -a arr=('86409 GNS2DNS s gnu.org@127.0.0.250') +testing test5 "${arr[@]}" +# 6 +echo "Testing adding of multiple GNS2DNS record with -R" +declare -a arr=('1 GNS2DNS n gnunet.org@127.0.0.1' '3600 GNS2DNS s gnunet.org@127.0.0.2') +testing test6 "${arr[@]}" +val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid) +if [[ $val == *"127.0.0.1"* ]]; then + echo "shadow!" +fi +echo "Sleeping to let record expire" +sleep 5 +val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid) +if [[ $val == *"127.0.0.2"* ]]; then + echo "no shadow!" +fi +# 7 +echo "Testing adding MX record with -R" +declare -a arr=('3600 MX n 10,mail') +testing test7 "${arr[@]}" +# 8 +echo "Testing adding TXT record with -R" +declare -a arr=('3600 TXT n Pretty_Unicorns') +testing test8 "${arr[@]}" +# 8 +echo "Testing adding TXT record with -R" +declare -a arr=('3600 SRV n _autodiscover_old._tcp.bfh.ch.') +testing test8 "${arr[@]}" + +# CLEANUP +gnunet-identity -D randomtestingid -- cgit v1.2.3 From c30a518e58479c6ffc5e634db3624f5e82e25f1d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 13 Nov 2018 14:59:14 +0100 Subject: complete implementation of -R, to be tested by r --- doc/man/gnunet-namestore.1 | 8 ++ po/POTFILES.in | 110 ++++++++++++------------- src/namestore/gnunet-namestore.c | 117 ++++++++++++++++++--------- src/namestore/test_namestore_put_multiple.sh | 1 - 4 files changed, 140 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/doc/man/gnunet-namestore.1 b/doc/man/gnunet-namestore.1 index 10577a0d9..9f4b4d2d6 100644 --- a/doc/man/gnunet-namestore.1 +++ b/doc/man/gnunet-namestore.1 @@ -61,6 +61,14 @@ label) Determine our GNS name for the given public key (reverse lookup of the PKEY) in the given zone. .B +.IP "\-R RECORDLINE, \-\-replace=RECORDLINE" +Sets record set to values given in RECORDLINE. This option can be specified multiple +times to provide multiple records for the record set. Existing records under the +same label will be deleted. The format for the RECORDLINE is +"TTL TYPE FLAGS VALUE" where TTL is the time to live in seconds, TYPE is the +DNS/GNS record type, FLAGS is "(N)ORMAL", "(S)HADOW" or "(P)UBLIC". The VALUE +follows the usual human-readable value format(s) of DNS/GNS. +.B .IP "\-s, \-\-shadow" Create a record that is a shadow record. Shadow records are only used once all other records of the same type under the same label have diff --git a/po/POTFILES.in b/po/POTFILES.in index 5f4c5ee7f..54fe7b4e7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,21 +4,13 @@ src/arm/arm_monitor_api.c src/arm/gnunet-arm.c src/arm/gnunet-service-arm.c src/arm/mockup-service.c -src/ats-tests/ats-testing-experiment.c -src/ats-tests/ats-testing-log.c -src/ats-tests/ats-testing-preferences.c -src/ats-tests/ats-testing-traffic.c -src/ats-tests/ats-testing.c -src/ats-tests/gnunet-ats-sim.c -src/ats-tests/gnunet-solver-eval.c -src/ats-tool/gnunet-ats.c src/ats/ats_api_connectivity.c src/ats/ats_api_performance.c src/ats/ats_api_scanner.c src/ats/ats_api_scheduling.c src/ats/gnunet-ats-solver-eval.c -src/ats/gnunet-service-ats.c src/ats/gnunet-service-ats_addresses.c +src/ats/gnunet-service-ats.c src/ats/gnunet-service-ats_connectivity.c src/ats/gnunet-service-ats_normalization.c src/ats/gnunet-service-ats_performance.c @@ -29,6 +21,14 @@ src/ats/gnunet-service-ats_scheduling.c src/ats/plugin_ats_mlp.c src/ats/plugin_ats_proportional.c src/ats/plugin_ats_ril.c +src/ats-tests/ats-testing.c +src/ats-tests/ats-testing-experiment.c +src/ats-tests/ats-testing-log.c +src/ats-tests/ats-testing-preferences.c +src/ats-tests/ats-testing-traffic.c +src/ats-tests/gnunet-ats-sim.c +src/ats-tests/gnunet-solver-eval.c +src/ats-tool/gnunet-ats.c src/auction/gnunet-auction-create.c src/auction/gnunet-auction-info.c src/auction/gnunet-auction-join.c @@ -40,8 +40,8 @@ src/block/plugin_block_test.c src/cadet/cadet_api.c src/cadet/cadet_test_lib.c src/cadet/desirability_table.c -src/cadet/gnunet-cadet-profiler.c src/cadet/gnunet-cadet.c +src/cadet/gnunet-cadet-profiler.c src/cadet/gnunet-service-cadet.c src/cadet/gnunet-service-cadet_channel.c src/cadet/gnunet-service-cadet_connection.c @@ -57,15 +57,15 @@ src/consensus/gnunet-service-consensus.c src/consensus/plugin_block_consensus.c src/conversation/conversation_api.c src/conversation/conversation_api_call.c -src/conversation/gnunet-conversation-test.c src/conversation/gnunet-conversation.c -src/conversation/gnunet-helper-audio-playback-gst.c +src/conversation/gnunet-conversation-test.c +src/conversation/gnunet_gst.c +src/conversation/gnunet_gst_test.c src/conversation/gnunet-helper-audio-playback.c -src/conversation/gnunet-helper-audio-record-gst.c +src/conversation/gnunet-helper-audio-playback-gst.c src/conversation/gnunet-helper-audio-record.c +src/conversation/gnunet-helper-audio-record-gst.c src/conversation/gnunet-service-conversation.c -src/conversation/gnunet_gst.c -src/conversation/gnunet_gst_test.c src/conversation/microphone.c src/conversation/plugin_gnsrecord_conversation.c src/conversation/speaker.c @@ -101,6 +101,7 @@ src/dht/dht_api.c src/dht/dht_test_lib.c src/dht/gnunet-dht-get.c src/dht/gnunet-dht-monitor.c +src/dht/gnunet_dht_profiler.c src/dht/gnunet-dht-put.c src/dht/gnunet-service-dht.c src/dht/gnunet-service-dht_clients.c @@ -109,7 +110,6 @@ src/dht/gnunet-service-dht_hello.c src/dht/gnunet-service-dht_neighbours.c src/dht/gnunet-service-dht_nse.c src/dht/gnunet-service-dht_routing.c -src/dht/gnunet_dht_profiler.c src/dht/plugin_block_dht.c src/dns/dns_api.c src/dns/gnunet-dns-monitor.c @@ -123,8 +123,8 @@ src/dv/gnunet-dv.c src/dv/gnunet-service-dv.c src/dv/plugin_transport_dv.c src/exit/gnunet-daemon-exit.c -src/exit/gnunet-helper-exit-windows.c src/exit/gnunet-helper-exit.c +src/exit/gnunet-helper-exit-windows.c src/fragmentation/defragmentation.c src/fragmentation/fragmentation.c src/fs/fs_api.c @@ -149,8 +149,8 @@ src/fs/gnunet-auto-share.c src/fs/gnunet-daemon-fsprofiler.c src/fs/gnunet-directory.c src/fs/gnunet-download.c -src/fs/gnunet-fs-profiler.c src/fs/gnunet-fs.c +src/fs/gnunet-fs-profiler.c src/fs/gnunet-helper-fs-publish.c src/fs/gnunet-publish.c src/fs/gnunet-search.c @@ -170,10 +170,10 @@ src/gns/gns_tld_api.c src/gns/gnunet-bcd.c src/gns/gnunet-dns2gns.c src/gns/gnunet-gns-benchmark.c +src/gns/gnunet-gns.c src/gns/gnunet-gns-helper-service-w32.c src/gns/gnunet-gns-import.c src/gns/gnunet-gns-proxy.c -src/gns/gnunet-gns.c src/gns/gnunet-service-gns.c src/gns/gnunet-service-gns_interceptor.c src/gns/gnunet-service-gns_resolver.c @@ -181,15 +181,15 @@ src/gns/nss/nss_gns.c src/gns/nss/nss_gns_query.c src/gns/plugin_block_gns.c src/gns/plugin_gnsrecord_gns.c -src/gns/w32nsp-install.c -src/gns/w32nsp-resolve.c -src/gns/w32nsp-uninstall.c -src/gns/w32nsp.c src/gnsrecord/gnsrecord.c src/gnsrecord/gnsrecord_crypto.c src/gnsrecord/gnsrecord_misc.c src/gnsrecord/gnsrecord_serialization.c src/gnsrecord/plugin_gnsrecord_dns.c +src/gns/w32nsp.c +src/gns/w32nsp-install.c +src/gns/w32nsp-resolve.c +src/gns/w32nsp-uninstall.c src/hello/address.c src/hello/gnunet-hello.c src/hello/hello.c @@ -218,8 +218,8 @@ src/namecache/namecache_api.c src/namecache/plugin_namecache_flat.c src/namecache/plugin_namecache_postgres.c src/namecache/plugin_namecache_sqlite.c -src/namestore/gnunet-namestore-fcfsd.c src/namestore/gnunet-namestore.c +src/namestore/gnunet-namestore-fcfsd.c src/namestore/gnunet-service-namestore.c src/namestore/gnunet-zoneimport.c src/namestore/namestore_api.c @@ -234,10 +234,10 @@ src/nat-auto/gnunet-service-nat-auto.c src/nat-auto/gnunet-service-nat-auto_legacy.c src/nat-auto/nat_auto_api.c src/nat-auto/nat_auto_api_test.c -src/nat/gnunet-helper-nat-client-windows.c src/nat/gnunet-helper-nat-client.c -src/nat/gnunet-helper-nat-server-windows.c +src/nat/gnunet-helper-nat-client-windows.c src/nat/gnunet-helper-nat-server.c +src/nat/gnunet-helper-nat-server-windows.c src/nat/gnunet-nat.c src/nat/gnunet-service-nat.c src/nat/gnunet-service-nat_externalip.c @@ -246,15 +246,15 @@ src/nat/gnunet-service-nat_mini.c src/nat/gnunet-service-nat_stun.c src/nat/nat_api.c src/nat/nat_api_stun.c -src/nse/gnunet-nse-profiler.c src/nse/gnunet-nse.c +src/nse/gnunet-nse-profiler.c src/nse/gnunet-service-nse.c src/nse/nse_api.c -src/peerinfo-tool/gnunet-peerinfo.c -src/peerinfo-tool/gnunet-peerinfo_plugins.c src/peerinfo/gnunet-service-peerinfo.c src/peerinfo/peerinfo_api.c src/peerinfo/peerinfo_api_notify.c +src/peerinfo-tool/gnunet-peerinfo.c +src/peerinfo-tool/gnunet-peerinfo_plugins.c src/peerstore/gnunet-peerstore.c src/peerstore/gnunet-service-peerstore.c src/peerstore/peerstore_api.c @@ -301,6 +301,7 @@ src/regex/regex_internal_dht.c src/regex/regex_test_graph.c src/regex/regex_test_lib.c src/regex/regex_test_random.c +src/rest/gnunet-rest-server.c src/rest-plugins/json_reclaim.c src/rest-plugins/oidc_helper.c src/rest-plugins/plugin_rest_copying.c @@ -311,28 +312,27 @@ src/rest-plugins/plugin_rest_namestore.c src/rest-plugins/plugin_rest_openid_connect.c src/rest-plugins/plugin_rest_peerinfo.c src/rest-plugins/plugin_rest_reclaim.c -src/rest/gnunet-rest-server.c src/rest/rest.c src/revocation/gnunet-revocation.c src/revocation/gnunet-service-revocation.c src/revocation/plugin_block_revocation.c src/revocation/revocation_api.c -src/rps/gnunet-rps-profiler.c src/rps/gnunet-rps.c +src/rps/gnunet-rps-profiler.c src/rps/gnunet-service-rps.c src/rps/gnunet-service-rps_custommap.c src/rps/gnunet-service-rps_sampler.c src/rps/gnunet-service-rps_sampler_elem.c src/rps/gnunet-service-rps_view.c +src/rps/rps_api.c src/rps/rps-sampler_client.c src/rps/rps-sampler_common.c src/rps/rps-test_util.c -src/rps/rps_api.c src/scalarproduct/gnunet-scalarproduct.c -src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c -src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c src/scalarproduct/gnunet-service-scalarproduct_alice.c src/scalarproduct/gnunet-service-scalarproduct_bob.c +src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c +src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c src/scalarproduct/scalarproduct_api.c src/secretsharing/gnunet-secretsharing-profiler.c src/secretsharing/gnunet-service-secretsharing.c @@ -361,16 +361,15 @@ src/statistics/gnunet-statistics.c src/statistics/statistics_api.c src/template/gnunet-service-template.c src/template/gnunet-template.c -src/testbed-logger/gnunet-service-testbed-logger.c -src/testbed-logger/testbed_logger_api.c src/testbed/generate-underlay-topology.c src/testbed/gnunet-daemon-latency-logger.c src/testbed/gnunet-daemon-testbed-blacklist.c src/testbed/gnunet-daemon-testbed-underlay.c src/testbed/gnunet-helper-testbed.c +src/testbed/gnunet_mpi_test.c src/testbed/gnunet-service-test-barriers.c -src/testbed/gnunet-service-testbed.c src/testbed/gnunet-service-testbed_barriers.c +src/testbed/gnunet-service-testbed.c src/testbed/gnunet-service-testbed_cache.c src/testbed/gnunet-service-testbed_connectionpool.c src/testbed/gnunet-service-testbed_cpustatus.c @@ -378,19 +377,20 @@ src/testbed/gnunet-service-testbed_links.c src/testbed/gnunet-service-testbed_meminfo.c src/testbed/gnunet-service-testbed_oc.c src/testbed/gnunet-service-testbed_peers.c -src/testbed/gnunet-testbed-profiler.c -src/testbed/gnunet_mpi_test.c src/testbed/gnunet_testbed_mpi_spawn.c -src/testbed/testbed_api.c +src/testbed/gnunet-testbed-profiler.c +src/testbed-logger/gnunet-service-testbed-logger.c +src/testbed-logger/testbed_logger_api.c src/testbed/testbed_api_barriers.c +src/testbed/testbed_api.c src/testbed/testbed_api_hosts.c src/testbed/testbed_api_operations.c src/testbed/testbed_api_peers.c src/testbed/testbed_api_sd.c src/testbed/testbed_api_services.c src/testbed/testbed_api_statistics.c -src/testbed/testbed_api_test.c src/testbed/testbed_api_testbed.c +src/testbed/testbed_api_test.c src/testbed/testbed_api_topology.c src/testbed/testbed_api_underlay.c src/testing/gnunet-testing.c @@ -400,29 +400,29 @@ src/topology/friends.c src/topology/gnunet-daemon-topology.c src/transport/gnunet-communicator-unix.c src/transport/gnunet-helper-transport-bluetooth.c -src/transport/gnunet-helper-transport-wlan-dummy.c src/transport/gnunet-helper-transport-wlan.c +src/transport/gnunet-helper-transport-wlan-dummy.c src/transport/gnunet-service-tng.c -src/transport/gnunet-service-transport.c src/transport/gnunet-service-transport_ats.c +src/transport/gnunet-service-transport.c src/transport/gnunet-service-transport_hello.c src/transport/gnunet-service-transport_manipulation.c src/transport/gnunet-service-transport_neighbours.c src/transport/gnunet-service-transport_plugins.c src/transport/gnunet-service-transport_validation.c +src/transport/gnunet-transport.c src/transport/gnunet-transport-certificate-creation.c src/transport/gnunet-transport-profiler.c src/transport/gnunet-transport-wlan-receiver.c src/transport/gnunet-transport-wlan-sender.c -src/transport/gnunet-transport.c src/transport/plugin_transport_http_client.c src/transport/plugin_transport_http_common.c src/transport/plugin_transport_http_server.c src/transport/plugin_transport_smtp.c src/transport/plugin_transport_tcp.c src/transport/plugin_transport_template.c -src/transport/plugin_transport_udp.c src/transport/plugin_transport_udp_broadcasting.c +src/transport/plugin_transport_udp.c src/transport/plugin_transport_unix.c src/transport/plugin_transport_wlan.c src/transport/plugin_transport_xt.c @@ -431,11 +431,6 @@ src/transport/tcp_connection_legacy.c src/transport/tcp_server_legacy.c src/transport/tcp_server_mst_legacy.c src/transport/tcp_service_legacy.c -src/transport/transport-testing-filenames.c -src/transport/transport-testing-loggers.c -src/transport/transport-testing-main.c -src/transport/transport-testing-send.c -src/transport/transport-testing.c src/transport/transport_api2_communication.c src/transport/transport_api_address_to_string.c src/transport/transport_api_blacklist.c @@ -445,6 +440,11 @@ src/transport/transport_api_manipulation.c src/transport/transport_api_monitor_peers.c src/transport/transport_api_monitor_plugins.c src/transport/transport_api_offer_hello.c +src/transport/transport-testing.c +src/transport/transport-testing-filenames.c +src/transport/transport-testing-loggers.c +src/transport/transport-testing-main.c +src/transport/transport-testing-send.c src/util/bandwidth.c src/util/benchmark.c src/util/bio.c @@ -457,8 +457,8 @@ src/util/configuration_loader.c src/util/container_bloomfilter.c src/util/container_heap.c src/util/container_meta_data.c -src/util/container_multihashmap.c src/util/container_multihashmap32.c +src/util/container_multihashmap.c src/util/container_multipeermap.c src/util/container_multishortmap.c src/util/crypto_abe.c @@ -480,15 +480,15 @@ src/util/dnsparser.c src/util/dnsstub.c src/util/getopt.c src/util/getopt_helpers.c -src/util/gnunet-config-diff.c src/util/gnunet-config.c +src/util/gnunet-config-diff.c src/util/gnunet-ecc.c src/util/gnunet-helper-w32-console.c src/util/gnunet-resolver.c src/util/gnunet-scrypt.c src/util/gnunet-service-resolver.c -src/util/gnunet-timeout-w32.c src/util/gnunet-timeout.c +src/util/gnunet-timeout-w32.c src/util/gnunet-uri.c src/util/helper.c src/util/load.c @@ -516,13 +516,13 @@ src/util/tun.c src/util/w32cat.c src/util/win.c src/util/winproc.c -src/vpn/gnunet-helper-vpn-windows.c src/vpn/gnunet-helper-vpn.c +src/vpn/gnunet-helper-vpn-windows.c src/vpn/gnunet-service-vpn.c src/vpn/gnunet-vpn.c src/vpn/vpn_api.c -src/zonemaster/gnunet-service-zonemaster-monitor.c src/zonemaster/gnunet-service-zonemaster.c +src/zonemaster/gnunet-service-zonemaster-monitor.c src/fs/fs_api.h src/include/gnunet_common.h src/include/gnunet_mq_lib.h diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c index 619d0c528..8386a696d 100644 --- a/src/namestore/gnunet-namestore.c +++ b/src/namestore/gnunet-namestore.c @@ -135,6 +135,11 @@ static int is_shadow; */ static struct GNUNET_NAMESTORE_QueueEntry *del_qe; +/** + * Queue entry for the 'set/replace' operation. + */ +static struct GNUNET_NAMESTORE_QueueEntry *set_qe; + /** * Name of the records to add/list/remove. */ @@ -195,7 +200,6 @@ static size_t data_size; */ static uint64_t etime; - /** * Is expiration time relative or absolute time? */ @@ -251,6 +255,11 @@ do_shutdown (void *cls) GNUNET_NAMESTORE_cancel (add_qe); add_qe = NULL; } + if (NULL != set_qe) + { + GNUNET_NAMESTORE_cancel (set_qe); + set_qe = NULL; + } if (NULL != add_qe_uri) { GNUNET_NAMESTORE_cancel (add_qe_uri); @@ -930,43 +939,34 @@ parse_expiration (const char *expirationstring, } -#if 0 -/* globals? */ -unsigned int rd_count; -struct GNUNET_GNSRECORD_Data *rd; - - -rd_count = 0; -for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) - rd_count++; -rd = GNUNET_new_array (rd_count, - struct GNUNET_GNSRECORD_Data); -rd_count = 0; -for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) +/** + * Function called when namestore is done with the replace + * operation. + * + * @param cls NULL + * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) + * #GNUNET_NO if content was already there or not found + * #GNUNET_YES (or other positive value) on success + * @param emsg NULL on success, otherwise an error message + */ +static void +replace_cont (void *cls, + int success, + const char *emsg) { - rd[rd_count] = e->record; - rd_count++; + (void) cls; + + set_qe = NULL; + if (GNUNET_OK != success) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + _("Failed to replace records: %s\n"), + emsg); + ret = 1; /* fail from 'main' */ + } + GNUNET_SCHEDULER_shutdown (); } -/* if add: */ -qe = GNUNET_NAMESTORE_records_store (..., - rd_count, - rd, - &my_cont - ..); - -in 'my_cont' and/or shutdown: - -qe = NULL; -GNUNET_free (rd); - -in shutdown: - -if NULL != qe NAMESTORE_cancel (qe); -GNUNET_free (rd); - -#endif - /** * Callback invoked from identity service with ego information. @@ -1000,7 +1000,7 @@ identity_cb (void *cls, GNUNET_free_non_null (ego_name); ego_name = NULL; - if (! (add|del|list|(NULL != nickstring)|(NULL != uri)|(NULL != reverse_pkey)) ) + if (! (add|del|list|(NULL != nickstring)|(NULL != uri)|(NULL != reverse_pkey))|(NULL != recordset) ) { /* nothing more to be done */ fprintf (stderr, @@ -1009,8 +1009,7 @@ identity_cb (void *cls, return; } GNUNET_CRYPTO_ecdsa_key_get_public (&zone_pkey, - &pub); - + &pub); ns = GNUNET_NAMESTORE_connect (cfg); if (NULL == ns) { @@ -1018,6 +1017,44 @@ identity_cb (void *cls, _("Failed to connect to namestore\n")); return; } + + if (NULL != recordset) + { + /* replace entire record set */ + unsigned int rd_count; + struct GNUNET_GNSRECORD_Data *rd; + + if (NULL == name) + { + fprintf (stderr, + _("Missing option `%s' for operation `%s'\n"), + "-n", _("replace")); + GNUNET_SCHEDULER_shutdown (); + ret = 1; + return; + } + rd_count = 0; + for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) + rd_count++; + rd = GNUNET_new_array (rd_count, + struct GNUNET_GNSRECORD_Data); + rd_count = 0; + for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next) + { + rd[rd_count] = e->record; + rd_count++; + } + set_qe = GNUNET_NAMESTORE_records_store (ns, + &zone_pkey, + name, + rd_count, + rd, + &replace_cont, + NULL); + GNUNET_free (rd); + return; + } + if (add) { if (NULL == name) @@ -1526,9 +1563,9 @@ main (int argc, gettext_noop ("determine our name for the given PKEY"), &reverse_pkey), multirecord_option ('R', - "record", + "replace", "RECORDLINE", - gettext_noop ("complete record on one line to add/delete/display; can be specified multiple times"), + gettext_noop ("set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"), &recordset), GNUNET_GETOPT_option_string ('t', "type", diff --git a/src/namestore/test_namestore_put_multiple.sh b/src/namestore/test_namestore_put_multiple.sh index 48ad95a3c..81e1ad2b5 100644 --- a/src/namestore/test_namestore_put_multiple.sh +++ b/src/namestore/test_namestore_put_multiple.sh @@ -75,7 +75,6 @@ function testing { # TEST CASES # 1 echo "Testing adding of single A record with -R" -declare -a arr=('1200 A n 127.0.0.1') testing test1 "${arr[@]}" # 2 echo "Testing adding of multiple A records with -R" -- cgit v1.2.3 From 2f3c9c69f7b6cea83930e8c927d35b519a5655a0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 14 Nov 2018 14:35:49 +0100 Subject: add first sketch of libgnunettransportmonitor.so implementation --- src/include/gnunet_protocols.h | 27 ++- src/include/gnunet_transport_monitor_service.h | 18 +- src/transport/Makefile.am | 12 + src/transport/gnunet-service-tng.c | 5 - src/transport/transport.h | 83 +++++++ src/transport/transport_api2_monitor.c | 313 +++++++++++++++++++++++++ 6 files changed, 440 insertions(+), 18 deletions(-) create mode 100644 src/transport/transport_api2_monitor.c (limited to 'src') diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index fbdee5415..6f3b886d8 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -3041,7 +3041,7 @@ extern "C" #define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP 1204 /** - * @brief inform transport that a queue was torn down + * @brief inform transport that a queue was torn down */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN 1205 @@ -3072,12 +3072,31 @@ extern "C" /** * Message sent to indicate to the transport which address - * prefix is supported by a communicator. + * prefix is supported by a communicator. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR 1211 + +/** + * Message sent to indicate to the transport that a monitor + * wants to observe certain events. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START 1250 + +/** + * Message sent to indicate to a monitor about events. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA 1251 + +/** + * Message sent to indicate to a monitor that a one-shot + * iteration over events is done. + */ +#define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END 1252 + + /** - * Next available: 1300 + * Next available: 1400 */ diff --git a/src/include/gnunet_transport_monitor_service.h b/src/include/gnunet_transport_monitor_service.h index b9d024d59..76fec0af4 100644 --- a/src/include/gnunet_transport_monitor_service.h +++ b/src/include/gnunet_transport_monitor_service.h @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -29,7 +29,6 @@ * * @{ */ - #ifndef GNUNET_TRANSPORT_MONITOR_SERVICE_H #define GNUNET_TRANSPORT_MONITOR_SERVICE_H @@ -42,6 +41,7 @@ extern "C" #endif #include "gnunet_util_lib.h" +#include "gnunet_ats_service.h" /** * Version number of the transport API. @@ -121,7 +121,7 @@ struct GNUNET_TRANSPORT_MonitorInformation * @param mi monitoring data on the peer */ typedef void -(*GNUNET_TRANSPORT_MontiorCallback) (void *cls, +(*GNUNET_TRANSPORT_MonitorCallback) (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TRANSPORT_MonitorInformation *mi); @@ -155,24 +155,24 @@ struct GNUNET_TRANSPORT_MonitorContext; * NULL for all peers * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL), * #GNUNET_NO to monitor peers continuously - * @param mc function to call with the results - * @param mc_cls closure for @a mc + * @param cb function to call with the results + * @param cb_cls closure for @a mc */ struct GNUNET_TRANSPORT_MonitorContext * GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *peer, int one_shot, - GNUNET_TRANSPORT_MonitorCallback mc, - void *mc_cls); + GNUNET_TRANSPORT_MonitorCallback cb, + void *cb_cls); /** * Cancel request to monitor peers * - * @param pmc handle for the request to cancel + * @param mc handle for the request to cancel */ void -GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *pmc); +GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc); #if 0 /* keep Emacsens' auto-indent happy */ diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 92b53137f..2a549d413 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -151,6 +151,7 @@ endif lib_LTLIBRARIES = \ libgnunettransport.la \ libgnunettransportcommunicator.la \ + libgnunettransportmonitor.la \ $(TESTING_LIBS) libgnunettransporttesting_la_SOURCES = \ @@ -200,6 +201,17 @@ libgnunettransportcommunicator_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 + +libgnunettransportmonitor_la_SOURCES = \ + transport_api2_monitor.c +libgnunettransportmonitor_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +libgnunettransportmonitor_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + + libexec_PROGRAMS = \ $(WLAN_BIN) \ $(WLAN_BIN_DUMMY) \ diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 8cbca3188..447e9fa5d 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -149,11 +149,6 @@ const struct GNUNET_CONFIGURATION_Handle *GST_cfg; */ struct GNUNET_PeerIdentity GST_my_identity; -/** - * Handle to peerinfo service. - */ -struct GNUNET_PEERINFO_Handle *GST_peerinfo; - /** * Our private key. */ diff --git a/src/transport/transport.h b/src/transport/transport.h index 1b46213cf..c5191a5ce 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -936,6 +936,89 @@ struct GNUNET_TRANSPORT_SendMessageToAck + +/** + * Request to start monitoring. + */ +struct GNUNET_TRANSPORT_MonitorStart +{ + + /** + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START. + */ + struct GNUNET_MessageHeader header; + + /** + * #GNUNET_YES for one-shot montoring, #GNUNET_NO for continuous monitoring. + */ + uint32_t one_shot; + + /** + * Target identifier to monitor, all zeros for "all peers". + */ + struct GNUNET_PeerIdentity peer; + +}; + + +/** + * Monitoring data. + */ +struct GNUNET_TRANSPORT_MonitorData +{ + + /** + * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA. + */ + struct GNUNET_MessageHeader header; + + /** + * Network type (an `enum GNUNET_ATS_Network_Type` in NBO). + */ + uint32_t nt GNUNET_PACKED; + + /** + * Target identifier. + */ + struct GNUNET_PeerIdentity peer; + + /** + * @deprecated To be discussed if we keep these... + */ + struct GNUNET_TIME_AbsoluteNBO last_validation; + struct GNUNET_TIME_AbsoluteNBO valid_until; + struct GNUNET_TIME_AbsoluteNBO next_validation; + + /** + * Current round-trip time estimate. + */ + struct GNUNET_TIME_RelativeNBO rtt; + + /** + * Is inbound (in NBO). + */ + uint32_t is_inbound GNUNET_PACKED; + + /** + * Messages pending (in NBO). + */ + uint32_t num_msg_pending GNUNET_PACKED; + + /** + * Bytes pending (in NBO). + */ + uint32_t num_bytes_pending GNUNET_PACKED; + + /* Followed by 0-terminated address of the peer + (TODO: do we allow no address? If so, + adjust transport_api2_monitor!) */ + +}; + + + + + GNUNET_NETWORK_STRUCT_END /* end of transport.h */ diff --git a/src/transport/transport_api2_monitor.c b/src/transport/transport_api2_monitor.c new file mode 100644 index 000000000..d7b13ec74 --- /dev/null +++ b/src/transport/transport_api2_monitor.c @@ -0,0 +1,313 @@ +/* + This file is part of GNUnet. + Copyright (C) 2018 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file transport/transport_api2_monitor.c + * @brief implementation of the gnunet_transport_monitor_service.h API + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_transport_monitor_service.h" +#include "transport.h" + + +/** + * Opaque handle to the transport service for monitors. + */ +struct GNUNET_TRANSPORT_MonitorContext +{ + /** + * Our configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Queue to talk to the transport service. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Peer we monitor, all zeros for "all" + */ + struct GNUNET_PeerIdentity peer; + + /** + * #GNUNET_YES to return the current state and then end. + */ + int one_shot; + + /** + * Function to call with monitor data. + */ + GNUNET_TRANSPORT_MonitorCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + +}; + + +/** + * (re)connect our monitor to the transport service + * + * @param mc handle to reconnect + */ +static void +reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc); + + +/** + * Send message to the transport service about our montoring + * desire. + * + * @param ai address to delete + */ +static void +send_start_monitor (struct GNUNET_TRANSPORT_MonitorContext *mc) +{ + struct GNUNET_MQ_Envelope *env; + struct GNUNET_TRANSPORT_MonitorStart *smm; + + if (NULL == mc->mq) + return; + env = GNUNET_MQ_msg (smm, + GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START); + smm->one_shot = htonl ((uint32_t) mc->one_shot); + smm->peer = mc->peer; + GNUNET_MQ_send (mc->mq, + env); +} + + +/** + * Disconnect from the transport service. + * + * @param mc service to disconnect from + */ +static void +disconnect (struct GNUNET_TRANSPORT_MonitorContext *mc) +{ + if (NULL == mc->mq) + return; + GNUNET_MQ_destroy (mc->mq); + mc->mq = NULL; +} + + +/** + * Function called on MQ errors. Reconnects to the service. + * + * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *` + * @param error what error happened? + */ +static void +error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_TRANSPORT_MonitorContext *mc = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "MQ failure %d, reconnecting to transport service.\n", + error); + disconnect (mc); + /* TODO: maybe do this with exponential backoff/delay */ + reconnect (mc); +} + + +/** + * Transport service sends us information about what is going on. + * Check if @a md is well-formed. + * + * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *` + * @param md the monitor data we got + * @return #GNUNET_OK if @a smt is well-formed + */ +static int +check_monitor_data (void *cls, + const struct GNUNET_TRANSPORT_MonitorData *md) +{ + uint16_t len = ntohs (md->header.size) - sizeof (*md); + const char *addr = (const char *) &md[1]; + + (void) cls; + if ( (0 == len) || + ('\0' != addr[len-1]) ) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Transport service sends us information about what is going on. + * + * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *` + * @param md monitor data + */ +static void +handle_monitor_data (void *cls, + const struct GNUNET_TRANSPORT_MonitorData *md) +{ + struct GNUNET_TRANSPORT_MonitorContext *mc = cls; + struct GNUNET_TRANSPORT_MonitorInformation mi; + + mi.address = (const char *) &md[1]; + mi.nt = (enum GNUNET_ATS_Network_Type) ntohl (md->nt); + mi.is_inbound = (int) ntohl (md->is_inbound); + mi.num_msg_pending = ntohl (md->num_msg_pending); + mi.num_bytes_pending = ntohl (md->num_bytes_pending); + mi.last_validation = GNUNET_TIME_absolute_ntoh (md->last_validation); + mi.valid_until = GNUNET_TIME_absolute_ntoh (md->valid_until); + mi.next_validation = GNUNET_TIME_absolute_ntoh (md->next_validation); + mi.rtt = GNUNET_TIME_relative_ntoh (md->rtt); + mc->cb (mc->cb_cls, + &md->peer, + &mi); +} + + +/** + * One shot was requested, and transport service is done. + * + * @param cls our `struct GNUNET_TRANSPORT_MonitorContext *` + * @param me end message + */ +static void +handle_monitor_end (void *cls, + const struct GNUNET_MessageHeader *me) +{ + struct GNUNET_TRANSPORT_MonitorContext *mc = cls; + + if (GNUNET_YES != mc->one_shot) + { + GNUNET_break (0); + disconnect (mc); + reconnect (mc); + return; + } + mc->cb (mc->cb_cls, + NULL, + NULL); + GNUNET_TRANSPORT_monitor_cancel (mc); +} + + +/** + * (re)connect our monitor to the transport service + * + * @param mc handle to reconnect + */ +static void +reconnect (struct GNUNET_TRANSPORT_MonitorContext *mc) +{ + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_var_size (monitor_data, + GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA, + struct GNUNET_TRANSPORT_MonitorData, + mc), + GNUNET_MQ_hd_fixed_size (monitor_end, + GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_END, + struct GNUNET_MessageHeader, + mc), + GNUNET_MQ_handler_end() + }; + + mc->mq = GNUNET_CLIENT_connect (mc->cfg, + "transport", + handlers, + &error_handler, + mc); + if (NULL == mc->mq) + return; + send_start_monitor (mc); +} + + +/** + * Return information about a specific peer or all peers currently known to + * transport service once or in monitoring mode. To obtain information about + * a specific peer, a peer identity can be passed. To obtain information about + * all peers currently known to transport service, NULL can be passed as peer + * identity. + * + * For each peer, the callback is called with information about the address used + * to communicate with this peer, the state this peer is currently in and the + * the current timeout for this state. + * + * Upon completion, the #GNUNET_TRANSPORT_PeerIterateCallback is called one + * more time with `NULL`. After this, the operation must no longer be + * explicitly canceled. + * + * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the + * the peer_callback! + * + * @param cfg configuration to use + * @param peer a specific peer identity to obtain information for, + * NULL for all peers + * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL), + * #GNUNET_NO to monitor peers continuously + * @param cb function to call with the results + * @param cb_cls closure for @a mc + */ +struct GNUNET_TRANSPORT_MonitorContext * +GNUNET_TRANSPORT_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_PeerIdentity *peer, + int one_shot, + GNUNET_TRANSPORT_MonitorCallback cb, + void *cb_cls) +{ + struct GNUNET_TRANSPORT_MonitorContext *mc; + + mc = GNUNET_new (struct GNUNET_TRANSPORT_MonitorContext); + mc->cfg = cfg; + if (NULL != peer) + mc->peer = *peer; + mc->one_shot = one_shot; + mc->cb = cb; + mc->cb_cls = cb_cls; + reconnect (mc); + if (NULL == mc->mq) + { + GNUNET_free (mc); + return NULL; + } + return mc; +} + + + +/** + * Cancel request to monitor peers + * + * @param pmc handle for the request to cancel + */ +void +GNUNET_TRANSPORT_monitor_cancel (struct GNUNET_TRANSPORT_MonitorContext *mc) +{ + disconnect (mc); + GNUNET_free (mc); +} + +/* end of transport_api2_monitor.c */ -- cgit v1.2.3 From da9d61bdbddb37424a465f63f6b4c691b342363e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 14 Nov 2018 14:42:12 +0100 Subject: add logic to handle monitor start to gnunet-service-tng.c --- src/transport/gnunet-service-tng.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 447e9fa5d..d92964654 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -145,7 +145,7 @@ struct GNUNET_STATISTICS_Handle *GST_stats; const struct GNUNET_CONFIGURATION_Handle *GST_cfg; /** - * Configuration handle. + * Our public key. */ struct GNUNET_PeerIdentity GST_my_identity; @@ -587,6 +587,31 @@ handle_send_message_ack (void *cls, } +/** + * Initialize a monitor client. + * + * @param cls the client + * @param start the start message that was sent + */ +static void +handle_monitor_start (void *cls, + const struct GNUNET_TRANSPORT_MonitorStart *start) +{ + struct TransportClient *tc = cls; + + if (CT_NONE != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + tc->type = CT_MONITOR; + tc->details.monitor_peer = start->peer; + // FIXME: remember also the one_shot flag! + GNUNET_SERVICE_client_continue (tc->client); +} + + /** * Function called when the service shuts down. Unloads our plugins * and cancels pending validations. @@ -708,6 +733,11 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK, struct GNUNET_TRANSPORT_SendMessageToAck, NULL), + /* communication with monitors */ + GNUNET_MQ_hd_fixed_size (monitor_start, + GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START, + struct GNUNET_TRANSPORT_MonitorStart, + NULL), GNUNET_MQ_handler_end ()); -- cgit v1.2.3 From ad1244d958b76cb249028c7ad87ff84df49293ff Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 09:27:35 +0100 Subject: make copy of transport_api_core.c --- src/transport/transport_api2_core.c | 970 ++++++++++++++++++++++++++++++++++++ 1 file changed, 970 insertions(+) create mode 100644 src/transport/transport_api2_core.c (limited to 'src') diff --git a/src/transport/transport_api2_core.c b/src/transport/transport_api2_core.c new file mode 100644 index 000000000..b7edc3cc1 --- /dev/null +++ b/src/transport/transport_api2_core.c @@ -0,0 +1,970 @@ +/* + This file is part of GNUnet. + Copyright (C) 2009-2013, 2016 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file transport/transport_api_core.c + * @brief library to access the transport service for message exchange + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_constants.h" +#include "gnunet_arm_service.h" +#include "gnunet_hello_lib.h" +#include "gnunet_protocols.h" +#include "gnunet_transport_core_service.h" +#include "transport.h" + +#define LOG(kind,...) GNUNET_log_from (kind, "transport-api-core",__VA_ARGS__) + +/** + * If we could not send any payload to a peer for this amount of + * time, we print a warning. + */ +#define UNREADY_WARN_TIME GNUNET_TIME_UNIT_MINUTES + +/** + * How large to start with for the hashmap of neighbours. + */ +#define STARTING_NEIGHBOURS_SIZE 16 + + +/** + * Entry in hash table of all of our current (connected) neighbours. + */ +struct Neighbour +{ + /** + * Overall transport handle. + */ + struct GNUNET_TRANSPORT_CoreHandle *h; + + /** + * Active message queue for the peer. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Envelope with the message we are currently transmitting (or NULL). + */ + struct GNUNET_MQ_Envelope *env; + + /** + * Closure for @e mq handlers. + */ + void *handlers_cls; + + /** + * Identity of this neighbour. + */ + struct GNUNET_PeerIdentity id; + + /** + * Outbound bandwidh tracker. + */ + struct GNUNET_BANDWIDTH_Tracker out_tracker; + + /** + * Entry in our readyness heap (which is sorted by @e next_ready + * value). NULL if there is no pending transmission request for + * this neighbour or if we're waiting for @e is_ready to become + * true AFTER the @e out_tracker suggested that this peer's quota + * has been satisfied (so once @e is_ready goes to #GNUNET_YES, + * we should immediately go back into the heap). + */ + struct GNUNET_CONTAINER_HeapNode *hn; + + /** + * Task to trigger MQ when we have enough bandwidth for the + * next transmission. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * Sending consumed more bytes on wire than payload was announced + * This overhead is added to the delay of next sending operation + */ + unsigned long long traffic_overhead; + + /** + * Is this peer currently ready to receive a message? + */ + int is_ready; + + /** + * Size of the message in @e env. + */ + uint16_t env_size; + +}; + + + +/** + * Handle for the transport service (includes all of the + * state for the transport service). + */ +struct GNUNET_TRANSPORT_CoreHandle +{ + + /** + * Closure for the callbacks. + */ + void *cls; + + /** + * Functions to call for received data (template for + * new message queues). + */ + struct GNUNET_MQ_MessageHandler *handlers; + + /** + * function to call on connect events + */ + GNUNET_TRANSPORT_NotifyConnecT nc_cb; + + /** + * function to call on disconnect events + */ + GNUNET_TRANSPORT_NotifyDisconnecT nd_cb; + + /** + * function to call on excess bandwidth events + */ + GNUNET_TRANSPORT_NotifyExcessBandwidtH neb_cb; + + /** + * My client connection to the transport service. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * My configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Hash map of the current connected neighbours of this peer. + * Maps peer identities to `struct Neighbour` entries. + */ + struct GNUNET_CONTAINER_MultiPeerMap *neighbours; + + /** + * Peer identity as assumed by this process, or all zeros. + */ + struct GNUNET_PeerIdentity self; + + /** + * ID of the task trying to reconnect to the service. + */ + struct GNUNET_SCHEDULER_Task *reconnect_task; + + /** + * Delay until we try to reconnect. + */ + struct GNUNET_TIME_Relative reconnect_delay; + + /** + * Should we check that @e self matches what the service thinks? + * (if #GNUNET_NO, then @e self is all zeros!). + */ + int check_self; + +}; + + +/** + * Function that will schedule the job that will try + * to connect us again to the client. + * + * @param h transport service to reconnect + */ +static void +disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h); + + +/** + * Get the neighbour list entry for the given peer + * + * @param h our context + * @param peer peer to look up + * @return NULL if no such peer entry exists + */ +static struct Neighbour * +neighbour_find (struct GNUNET_TRANSPORT_CoreHandle *h, + const struct GNUNET_PeerIdentity *peer) +{ + return GNUNET_CONTAINER_multipeermap_get (h->neighbours, + peer); +} + + +/** + * Function called by the bandwidth tracker if we have excess + * bandwidth. + * + * @param cls the `struct Neighbour` that has excess bandwidth + */ +static void +notify_excess_cb (void *cls) +{ + struct Neighbour *n = cls; + struct GNUNET_TRANSPORT_CoreHandle *h = n->h; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Notifying CORE that more bandwidth is available for %s\n", + GNUNET_i2s (&n->id)); + + if (NULL != h->neb_cb) + h->neb_cb (h->cls, + &n->id, + n->handlers_cls); +} + + +/** + * Iterator over hash map entries, for deleting state of a neighbour. + * + * @param cls the `struct GNUNET_TRANSPORT_CoreHandle *` + * @param key peer identity + * @param value value in the hash map, the neighbour entry to delete + * @return #GNUNET_YES if we should continue to + * iterate, + * #GNUNET_NO if not. + */ +static int +neighbour_delete (void *cls, + const struct GNUNET_PeerIdentity *key, + void *value) +{ + struct GNUNET_TRANSPORT_CoreHandle *handle = cls; + struct Neighbour *n = value; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Dropping entry for neighbour `%s'.\n", + GNUNET_i2s (key)); + GNUNET_BANDWIDTH_tracker_notification_stop (&n->out_tracker); + if (NULL != handle->nd_cb) + handle->nd_cb (handle->cls, + &n->id, + n->handlers_cls); + if (NULL != n->timeout_task) + { + GNUNET_SCHEDULER_cancel (n->timeout_task); + n->timeout_task = NULL; + } + if (NULL != n->env) + { + GNUNET_MQ_send_cancel (n->env); + n->env = NULL; + } + GNUNET_MQ_destroy (n->mq); + GNUNET_assert (NULL == n->mq); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (handle->neighbours, + key, + n)); + GNUNET_free (n); + return GNUNET_YES; +} + + +/** + * Generic error handler, called with the appropriate + * error code and the same closure specified at the creation of + * the message queue. + * Not every message queue implementation supports an error handler. + * + * @param cls closure with the `struct GNUNET_TRANSPORT_CoreHandle *` + * @param error error code + */ +static void +mq_error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_TRANSPORT_CoreHandle *h = cls; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Error receiving from transport service, disconnecting temporarily.\n"); + disconnect_and_schedule_reconnect (h); +} + + +/** + * Function we use for checking incoming HELLO messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` + * @param msg message received + * @return #GNUNET_OK if message is well-formed + */ +static int +check_hello (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + struct GNUNET_PeerIdentity me; + + if (GNUNET_OK != + GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg, + &me)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Function we use for handling incoming HELLO messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` + * @param msg message received + */ +static void +handle_hello (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + /* we do not care => FIXME: signal in options to NEVER send HELLOs! */ +} + + +/** + * A message from the handler's message queue to a neighbour was + * transmitted. Now trigger (possibly delayed) notification of the + * neighbour's message queue that we are done and thus ready for + * the next message. + * + * @param cls the `struct Neighbour` where the message was sent + */ +static void +notify_send_done_fin (void *cls) +{ + struct Neighbour *n = cls; + + n->timeout_task = NULL; + n->is_ready = GNUNET_YES; + GNUNET_MQ_impl_send_continue (n->mq); +} + + +/** + * A message from the handler's message queue to a neighbour was + * transmitted. Now trigger (possibly delayed) notification of the + * neighbour's message queue that we are done and thus ready for + * the next message. + * + * @param cls the `struct Neighbour` where the message was sent + */ +static void +notify_send_done (void *cls) +{ + struct Neighbour *n = cls; + struct GNUNET_TIME_Relative delay; + + n->timeout_task = NULL; + if (NULL != n->env) + { + GNUNET_BANDWIDTH_tracker_consume (&n->out_tracker, + n->env_size + n->traffic_overhead); + n->env = NULL; + n->traffic_overhead = 0; + } + delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, + 128); + if (0 == delay.rel_value_us) + { + n->is_ready = GNUNET_YES; + GNUNET_MQ_impl_send_continue (n->mq); + return; + } + GNUNET_MQ_impl_send_in_flight (n->mq); + /* cannot send even a small message without violating + quota, wait a before allowing MQ to send next message */ + n->timeout_task = GNUNET_SCHEDULER_add_delayed (delay, + ¬ify_send_done_fin, + n); +} + + +/** + * Implement sending functionality of a message queue. + * Called one message at a time. Should send the @a msg + * to the transport service and then notify the queue + * once we are ready for the next one. + * + * @param mq the message queue + * @param msg the message to send + * @param impl_state state of the implementation + */ +static void +mq_send_impl (struct GNUNET_MQ_Handle *mq, + const struct GNUNET_MessageHeader *msg, + void *impl_state) +{ + struct Neighbour *n = impl_state; + struct GNUNET_TRANSPORT_CoreHandle *h = n->h; + struct OutboundMessage *obm; + uint16_t msize; + + GNUNET_assert (GNUNET_YES == n->is_ready); + msize = ntohs (msg->size); + if (msize >= GNUNET_MAX_MESSAGE_SIZE - sizeof (*obm)) + { + GNUNET_break (0); + GNUNET_MQ_impl_send_continue (mq); + return; + } + GNUNET_assert (NULL == n->env); + n->env = GNUNET_MQ_msg_nested_mh (obm, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, + msg); + obm->reserved = htonl (0); + obm->timeout = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_MINUTES); /* FIXME: to be removed */ + obm->peer = n->id; + GNUNET_assert (NULL == n->timeout_task); + n->is_ready = GNUNET_NO; + n->env_size = ntohs (msg->size); + GNUNET_MQ_notify_sent (n->env, + ¬ify_send_done, + n); + GNUNET_MQ_send (h->mq, + n->env); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Queued message of type %u for neighbour `%s'.\n", + ntohs (msg->type), + GNUNET_i2s (&n->id)); +} + + +/** + * Handle destruction of a message queue. Implementations must not + * free @a mq, but should take care of @a impl_state. + * + * @param mq the message queue to destroy + * @param impl_state state of the implementation + */ +static void +mq_destroy_impl (struct GNUNET_MQ_Handle *mq, + void *impl_state) +{ + struct Neighbour *n = impl_state; + + GNUNET_assert (mq == n->mq); + n->mq = NULL; +} + + +/** + * Implementation function that cancels the currently sent message. + * Should basically undo whatever #mq_send_impl() did. + * + * @param mq message queue + * @param impl_state state specific to the implementation + */ +static void +mq_cancel_impl (struct GNUNET_MQ_Handle *mq, + void *impl_state) +{ + struct Neighbour *n = impl_state; + + GNUNET_assert (GNUNET_NO == n->is_ready); + if (NULL != n->env) + { + GNUNET_MQ_send_cancel (n->env); + n->env = NULL; + } + + n->is_ready = GNUNET_YES; +} + + +/** + * We had an error processing a message we forwarded from a peer to + * the CORE service. We should just complain about it but otherwise + * continue processing. + * + * @param cls closure + * @param error error code + */ +static void +peer_mq_error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + /* struct Neighbour *n = cls; */ + + GNUNET_break_op (0); +} + + +/** + * The outbound quota has changed in a way that may require + * us to reset the timeout. Update the timeout. + * + * @param cls the `struct Neighbour` for which the timeout changed + */ +static void +outbound_bw_tracker_update (void *cls) +{ + struct Neighbour *n = cls; + struct GNUNET_TIME_Relative delay; + + if (NULL == n->timeout_task) + return; + delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, + 128); + GNUNET_SCHEDULER_cancel (n->timeout_task); + n->timeout_task = GNUNET_SCHEDULER_add_delayed (delay, + ¬ify_send_done, + n); +} + + +/** + * Function we use for handling incoming connect messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_Handle *` + * @param cim message received + */ +static void +handle_connect (void *cls, + const struct ConnectInfoMessage *cim) +{ + struct GNUNET_TRANSPORT_CoreHandle *h = cls; + struct Neighbour *n; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Receiving CONNECT message for `%s' with quota %u\n", + GNUNET_i2s (&cim->id), + ntohl (cim->quota_out.value__)); + n = neighbour_find (h, &cim->id); + if (NULL != n) + { + GNUNET_break (0); + disconnect_and_schedule_reconnect (h); + return; + } + n = GNUNET_new (struct Neighbour); + n->id = cim->id; + n->h = h; + n->is_ready = GNUNET_YES; + n->traffic_overhead = 0; + GNUNET_BANDWIDTH_tracker_init2 (&n->out_tracker, + &outbound_bw_tracker_update, + n, + GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, + MAX_BANDWIDTH_CARRY_S, + ¬ify_excess_cb, + n); + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multipeermap_put (h->neighbours, + &n->id, + n, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + + GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, + cim->quota_out); + n->mq = GNUNET_MQ_queue_for_callbacks (&mq_send_impl, + &mq_destroy_impl, + &mq_cancel_impl, + n, + h->handlers, + &peer_mq_error_handler, + n); + if (NULL != h->nc_cb) + { + n->handlers_cls = h->nc_cb (h->cls, + &n->id, + n->mq); + GNUNET_MQ_set_handlers_closure (n->mq, + n->handlers_cls); + } +} + + +/** + * Function we use for handling incoming disconnect messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` + * @param dim message received + */ +static void +handle_disconnect (void *cls, + const struct DisconnectInfoMessage *dim) +{ + struct GNUNET_TRANSPORT_CoreHandle *h = cls; + struct Neighbour *n; + + GNUNET_break (ntohl (dim->reserved) == 0); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Receiving DISCONNECT message for `%s'.\n", + GNUNET_i2s (&dim->peer)); + n = neighbour_find (h, &dim->peer); + if (NULL == n) + { + GNUNET_break (0); + disconnect_and_schedule_reconnect (h); + return; + } + GNUNET_assert (GNUNET_YES == + neighbour_delete (h, + &dim->peer, + n)); +} + + +/** + * Function we use for handling incoming send-ok messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` + * @param okm message received + */ +static void +handle_send_ok (void *cls, + const struct SendOkMessage *okm) +{ + struct GNUNET_TRANSPORT_CoreHandle *h = cls; + struct Neighbour *n; + uint32_t bytes_msg; + uint32_t bytes_physical; + + bytes_msg = ntohl (okm->bytes_msg); + bytes_physical = ntohl (okm->bytes_physical); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Receiving SEND_OK message, transmission to %s %s.\n", + GNUNET_i2s (&okm->peer), + ntohl (okm->success) == GNUNET_OK ? "succeeded" : "failed"); + n = neighbour_find (h, + &okm->peer); + if (NULL == n) + { + /* We should never get a 'SEND_OK' for a peer that we are not + connected to */ + GNUNET_break (0); + disconnect_and_schedule_reconnect (h); + return; + } + if (bytes_physical > bytes_msg) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Overhead for %u byte message was %u\n", + bytes_msg, + bytes_physical - bytes_msg); + n->traffic_overhead += bytes_physical - bytes_msg; + } +} + + +/** + * Function we use for checking incoming "inbound" messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` + * @param im message received + */ +static int +check_recv (void *cls, + const struct InboundMessage *im) +{ + const struct GNUNET_MessageHeader *imm; + uint16_t size; + + size = ntohs (im->header.size) - sizeof (*im); + if (size < sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + imm = (const struct GNUNET_MessageHeader *) &im[1]; + if (ntohs (imm->size) != size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Function we use for handling incoming messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` + * @param im message received + */ +static void +handle_recv (void *cls, + const struct InboundMessage *im) +{ + struct GNUNET_TRANSPORT_CoreHandle *h = cls; + const struct GNUNET_MessageHeader *imm + = (const struct GNUNET_MessageHeader *) &im[1]; + struct Neighbour *n; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received message of type %u with %u bytes from `%s'.\n", + (unsigned int) ntohs (imm->type), + (unsigned int) ntohs (imm->size), + GNUNET_i2s (&im->peer)); + n = neighbour_find (h, &im->peer); + if (NULL == n) + { + GNUNET_break (0); + disconnect_and_schedule_reconnect (h); + return; + } + GNUNET_MQ_inject_message (n->mq, + imm); +} + + +/** + * Function we use for handling incoming set quota messages. + * + * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` + * @param msg message received + */ +static void +handle_set_quota (void *cls, + const struct QuotaSetMessage *qm) +{ + struct GNUNET_TRANSPORT_CoreHandle *h = cls; + struct Neighbour *n; + + n = neighbour_find (h, + &qm->peer); + if (NULL == n) + { + GNUNET_break (0); + disconnect_and_schedule_reconnect (h); + return; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Receiving SET_QUOTA message for `%s' with quota %u\n", + GNUNET_i2s (&qm->peer), + ntohl (qm->quota.value__)); + GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, + qm->quota); +} + + +/** + * Try again to connect to transport service. + * + * @param cls the handle to the transport service + */ +static void +reconnect (void *cls) +{ + struct GNUNET_TRANSPORT_CoreHandle *h = cls; + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_var_size (hello, + GNUNET_MESSAGE_TYPE_HELLO, + struct GNUNET_MessageHeader, + h), + GNUNET_MQ_hd_fixed_size (connect, + GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT, + struct ConnectInfoMessage, + h), + GNUNET_MQ_hd_fixed_size (disconnect, + GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT, + struct DisconnectInfoMessage, + h), + GNUNET_MQ_hd_fixed_size (send_ok, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK, + struct SendOkMessage, + h), + GNUNET_MQ_hd_var_size (recv, + GNUNET_MESSAGE_TYPE_TRANSPORT_RECV, + struct InboundMessage, + h), + GNUNET_MQ_hd_fixed_size (set_quota, + GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA, + struct QuotaSetMessage, + h), + GNUNET_MQ_handler_end () + }; + struct GNUNET_MQ_Envelope *env; + struct StartMessage *s; + uint32_t options; + + h->reconnect_task = NULL; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Connecting to transport service.\n"); + GNUNET_assert (NULL == h->mq); + h->mq = GNUNET_CLIENT_connect (h->cfg, + "transport", + handlers, + &mq_error_handler, + h); + if (NULL == h->mq) + return; + env = GNUNET_MQ_msg (s, + GNUNET_MESSAGE_TYPE_TRANSPORT_START); + options = 0; + if (h->check_self) + options |= 1; + if (NULL != h->handlers) + options |= 2; + s->options = htonl (options); + s->self = h->self; + GNUNET_MQ_send (h->mq, + env); +} + + +/** + * Function that will schedule the job that will try + * to connect us again to the client. + * + * @param h transport service to reconnect + */ +static void +disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h) +{ + GNUNET_assert (NULL == h->reconnect_task); + /* Forget about all neighbours that we used to be connected to */ + GNUNET_CONTAINER_multipeermap_iterate (h->neighbours, + &neighbour_delete, + h); + if (NULL != h->mq) + { + GNUNET_MQ_destroy (h->mq); + h->mq = NULL; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Scheduling task to reconnect to transport service in %s.\n", + GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, + GNUNET_YES)); + h->reconnect_task = + GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, + &reconnect, + h); + h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); +} + + +/** + * Checks if a given peer is connected to us and get the message queue. + * + * @param handle connection to transport service + * @param peer the peer to check + * @return NULL if disconnected, otherwise message queue for @a peer + */ +struct GNUNET_MQ_Handle * +GNUNET_TRANSPORT_core_get_mq (struct GNUNET_TRANSPORT_CoreHandle *handle, + const struct GNUNET_PeerIdentity *peer) +{ + struct Neighbour *n; + + n = neighbour_find (handle, + peer); + if (NULL == n) + return NULL; + return n->mq; +} + + +/** + * Connect to the transport service. Note that the connection may + * complete (or fail) asynchronously. + * + * @param cfg configuration to use + * @param self our own identity (API should check that it matches + * the identity found by transport), or NULL (no check) + * @param cls closure for the callbacks + * @param rec receive function to call + * @param nc function to call on connect events + * @param nd function to call on disconnect events + * @param neb function to call if we have excess bandwidth to a peer + * @return NULL on error + */ +struct GNUNET_TRANSPORT_CoreHandle * +GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_PeerIdentity *self, + const struct GNUNET_MQ_MessageHandler *handlers, + void *cls, + GNUNET_TRANSPORT_NotifyConnecT nc, + GNUNET_TRANSPORT_NotifyDisconnecT nd, + GNUNET_TRANSPORT_NotifyExcessBandwidtH neb) +{ + struct GNUNET_TRANSPORT_CoreHandle *h; + unsigned int i; + + h = GNUNET_new (struct GNUNET_TRANSPORT_CoreHandle); + if (NULL != self) + { + h->self = *self; + h->check_self = GNUNET_YES; + } + h->cfg = cfg; + h->cls = cls; + h->nc_cb = nc; + h->nd_cb = nd; + h->neb_cb = neb; + h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; + if (NULL != handlers) + { + for (i=0;NULL != handlers[i].cb; i++) ; + h->handlers = GNUNET_new_array (i + 1, + struct GNUNET_MQ_MessageHandler); + GNUNET_memcpy (h->handlers, + handlers, + i * sizeof (struct GNUNET_MQ_MessageHandler)); + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Connecting to transport service\n"); + reconnect (h); + if (NULL == h->mq) + { + GNUNET_free_non_null (h->handlers); + GNUNET_free (h); + return NULL; + } + h->neighbours = + GNUNET_CONTAINER_multipeermap_create (STARTING_NEIGHBOURS_SIZE, + GNUNET_YES); + return h; +} + + +/** + * Disconnect from the transport service. + * + * @param handle handle to the service as returned from #GNUNET_TRANSPORT_core_connect() + */ +void +GNUNET_TRANSPORT_core_disconnect (struct GNUNET_TRANSPORT_CoreHandle *handle) +{ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Transport disconnect called!\n"); + /* this disconnects all neighbours... */ + if (NULL == handle->reconnect_task) + disconnect_and_schedule_reconnect (handle); + /* and now we stop trying to connect again... */ + if (NULL != handle->reconnect_task) + { + GNUNET_SCHEDULER_cancel (handle->reconnect_task); + handle->reconnect_task = NULL; + } + GNUNET_CONTAINER_multipeermap_destroy (handle->neighbours); + handle->neighbours = NULL; + GNUNET_free_non_null (handle->handlers); + handle->handlers = NULL; + GNUNET_free (handle); +} + + +/* end of transport_api_core.c */ -- cgit v1.2.3 From 478a4c062b7d12b5d75d10667aa7739bd15b6405 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 13:56:40 +0100 Subject: get gnunet-service-tng to build --- src/include/gnunet_transport_core_service.h | 12 +-- src/transport/Makefile.am | 20 +++++ src/transport/gnunet-service-tng.c | 59 +------------ src/transport/transport-testing.c | 4 +- src/transport/transport-testing.h | 8 +- src/transport/transport_api2_core.c | 128 +++++++++++----------------- src/transport/transport_api_core.c | 12 +-- 7 files changed, 89 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_transport_core_service.h b/src/include/gnunet_transport_core_service.h index 5fbfcee21..b52dbe5f8 100644 --- a/src/include/gnunet_transport_core_service.h +++ b/src/include/gnunet_transport_core_service.h @@ -66,7 +66,7 @@ struct GNUNET_TRANSPORT_CoreHandle; * @return closure to use in MQ handlers */ typedef void * -(*GNUNET_TRANSPORT_NotifyConnecT) (void *cls, +(*GNUNET_TRANSPORT_NotifyConnect) (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq); @@ -83,7 +83,7 @@ typedef void * * connect notification callback */ typedef void -(*GNUNET_TRANSPORT_NotifyDisconnecT) (void *cls, +(*GNUNET_TRANSPORT_NotifyDisconnect) (void *cls, const struct GNUNET_PeerIdentity *peer, void *handler_cls); @@ -105,7 +105,7 @@ typedef void * connect notification callback */ typedef void -(*GNUNET_TRANSPORT_NotifyExcessBandwidtH)(void *cls, +(*GNUNET_TRANSPORT_NotifyExcessBandwidth)(void *cls, const struct GNUNET_PeerIdentity *neighbour, void *handlers_cls); @@ -133,9 +133,9 @@ GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, const struct GNUNET_MQ_MessageHandler *handlers, void *cls, - GNUNET_TRANSPORT_NotifyConnecT nc, - GNUNET_TRANSPORT_NotifyDisconnecT nd, - GNUNET_TRANSPORT_NotifyExcessBandwidtH neb); + GNUNET_TRANSPORT_NotifyConnect nc, + GNUNET_TRANSPORT_NotifyDisconnect nd, + GNUNET_TRANSPORT_NotifyExcessBandwidth neb); /** diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 2a549d413..ad39abe6a 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -141,6 +141,7 @@ endif noinst_PROGRAMS = \ gnunet-transport-profiler \ gnunet-communicator-unix \ + gnunet-service-tng \ $(WLAN_BIN_SENDER) \ $(WLAN_BIN_RECEIVER) @@ -150,6 +151,7 @@ endif lib_LTLIBRARIES = \ libgnunettransport.la \ + libgnunettransportcore.la \ libgnunettransportcommunicator.la \ libgnunettransportmonitor.la \ $(TESTING_LIBS) @@ -192,6 +194,15 @@ libgnunettransport_la_LDFLAGS = \ +libgnunettransportcore_la_SOURCES = \ + transport_api2_core.c +libgnunettransportcore_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +libgnunettransportcore_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) $(WINFLAGS) \ + -version-info 0:0:0 + libgnunettransportcommunicator_la_SOURCES = \ transport_api2_communication.c libgnunettransportcommunicator_la_LIBADD = \ @@ -311,6 +322,15 @@ gnunet_service_transport_CFLAGS = \ $(CFLAGS) # -DANALYZE + +gnunet_service_tng_SOURCES = \ + gnunet-service-tng.c +gnunet_service_tng_LDADD = \ + $(top_builddir)/src/ats/libgnunetats.la \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + plugin_LTLIBRARIES = \ libgnunet_plugin_transport_tcp.la \ libgnunet_plugin_transport_udp.la \ diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index d92964654..73b295442 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -233,7 +233,6 @@ handle_client_start (void *cls, const struct StartMessage *start) { struct TransportClient *tc = cls; - const struct GNUNET_MessageHeader *hello; uint32_t options; options = ntohl (start->options); @@ -255,46 +254,6 @@ handle_client_start (void *cls, return; } tc->type = CT_CORE; -#if 0 - hello = GST_hello_get (); - if (NULL != hello) - unicast (tc, - hello, - GNUNET_NO); -#endif - GNUNET_SERVICE_client_continue (tc->client); -} - - -/** - * Client sent us a HELLO. Check the request. - * - * @param cls the client - * @param message the HELLO message - */ -static int -check_client_hello (void *cls, - const struct GNUNET_MessageHeader *message) -{ - (void) cls; - return GNUNET_OK; /* FIXME: check here? */ -} - - -/** - * Client sent us a HELLO. Process the request. - * - * @param cls the client - * @param message the HELLO message - */ -static void -handle_client_hello (void *cls, - const struct GNUNET_MessageHeader *message) -{ - struct TransportClient *tc = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received HELLO message\n"); GNUNET_SERVICE_client_continue (tc->client); } @@ -395,7 +354,7 @@ handle_communicator_available (void *cls, tc->type = CT_COMMUNICATOR; size = ntohs (cam->header.size) - sizeof (*cam); if (0 == size) - return GNUNET_OK; /* receive-only communicator */ + return; /* receive-only communicator */ tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]); GNUNET_SERVICE_client_continue (tc->client); } @@ -421,7 +380,7 @@ check_add_address (void *cls, GNUNET_break (0); return GNUNET_SYSERR; } - addr = (const char *) &cam[1]; + addr = (const char *) &aam[1]; if ('\0' != addr[size-1]) { GNUNET_break (0); @@ -651,15 +610,7 @@ run (void *cls, { /* setup globals */ GST_cfg = c; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (c, - "transport", - "HELLO_EXPIRATION", - &hello_expiration)) - { - hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; - } - GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); + GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg); if (NULL == GST_my_private_key) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, @@ -696,10 +647,6 @@ GNUNET_SERVICE_MAIN GNUNET_MESSAGE_TYPE_TRANSPORT_START, struct StartMessage, NULL), - GNUNET_MQ_hd_var_size (client_hello, - GNUNET_MESSAGE_TYPE_HELLO, - struct GNUNET_MessageHeader, - NULL), GNUNET_MQ_hd_var_size (client_send, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, struct OutboundMessage, diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c index e3d4b7a9b..4295446d2 100644 --- a/src/transport/transport-testing.c +++ b/src/transport/transport-testing.c @@ -374,8 +374,8 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth const char *cfgname, int peer_id, const struct GNUNET_MQ_MessageHandler *handlers, - GNUNET_TRANSPORT_NotifyConnecT nc, - GNUNET_TRANSPORT_NotifyDisconnecT nd, + GNUNET_TRANSPORT_NotifyConnect nc, + GNUNET_TRANSPORT_NotifyDisconnect nd, void *cb_cls, GNUNET_SCHEDULER_TaskCallback start_cb, void *start_cb_cls) diff --git a/src/transport/transport-testing.h b/src/transport/transport-testing.h index a4cfd89f6..3a638580d 100644 --- a/src/transport/transport-testing.h +++ b/src/transport/transport-testing.h @@ -115,12 +115,12 @@ struct GNUNET_TRANSPORT_TESTING_PeerContext /** * Notify connect callback */ - GNUNET_TRANSPORT_NotifyConnecT nc; + GNUNET_TRANSPORT_NotifyConnect nc; /** * Notify disconnect callback */ - GNUNET_TRANSPORT_NotifyDisconnecT nd; + GNUNET_TRANSPORT_NotifyDisconnect nd; /** * Startup completed callback @@ -291,8 +291,8 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_Handle *tth const char *cfgname, int peer_id, const struct GNUNET_MQ_MessageHandler *handlers, - GNUNET_TRANSPORT_NotifyConnecT nc, - GNUNET_TRANSPORT_NotifyDisconnecT nd, + GNUNET_TRANSPORT_NotifyConnect nc, + GNUNET_TRANSPORT_NotifyDisconnect nd, void *cb_cls, GNUNET_SCHEDULER_TaskCallback start_cb, void *start_cb_cls); diff --git a/src/transport/transport_api2_core.c b/src/transport/transport_api2_core.c index b7edc3cc1..78d8dcce0 100644 --- a/src/transport/transport_api2_core.c +++ b/src/transport/transport_api2_core.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2009-2013, 2016 GNUnet e.V. + Copyright (C) 2009-2013, 2016, 2018 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published @@ -32,12 +32,6 @@ #define LOG(kind,...) GNUNET_log_from (kind, "transport-api-core",__VA_ARGS__) -/** - * If we could not send any payload to a peer for this amount of - * time, we print a warning. - */ -#define UNREADY_WARN_TIME GNUNET_TIME_UNIT_MINUTES - /** * How large to start with for the hashmap of neighbours. */ @@ -49,6 +43,12 @@ */ struct Neighbour { + + /** + * Identity of this neighbour. + */ + struct GNUNET_PeerIdentity id; + /** * Overall transport handle. */ @@ -69,16 +69,6 @@ struct Neighbour */ void *handlers_cls; - /** - * Identity of this neighbour. - */ - struct GNUNET_PeerIdentity id; - - /** - * Outbound bandwidh tracker. - */ - struct GNUNET_BANDWIDTH_Tracker out_tracker; - /** * Entry in our readyness heap (which is sorted by @e next_ready * value). NULL if there is no pending transmission request for @@ -95,6 +85,11 @@ struct Neighbour */ struct GNUNET_SCHEDULER_Task *timeout_task; + /** + * Outbound bandwidh tracker. + */ + struct GNUNET_BANDWIDTH_Tracker out_tracker; + /** * Sending consumed more bytes on wire than payload was announced * This overhead is added to the delay of next sending operation @@ -136,17 +131,17 @@ struct GNUNET_TRANSPORT_CoreHandle /** * function to call on connect events */ - GNUNET_TRANSPORT_NotifyConnecT nc_cb; + GNUNET_TRANSPORT_NotifyConnect nc_cb; /** * function to call on disconnect events */ - GNUNET_TRANSPORT_NotifyDisconnecT nd_cb; + GNUNET_TRANSPORT_NotifyDisconnect nd_cb; /** * function to call on excess bandwidth events */ - GNUNET_TRANSPORT_NotifyExcessBandwidtH neb_cb; + GNUNET_TRANSPORT_NotifyExcessBandwidth neb_cb; /** * My client connection to the transport service. @@ -305,44 +300,6 @@ mq_error_handler (void *cls, } -/** - * Function we use for checking incoming HELLO messages. - * - * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` - * @param msg message received - * @return #GNUNET_OK if message is well-formed - */ -static int -check_hello (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_PeerIdentity me; - - if (GNUNET_OK != - GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg, - &me)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Function we use for handling incoming HELLO messages. - * - * @param cls closure, a `struct GNUNET_TRANSPORT_CoreHandle *` - * @param msg message received - */ -static void -handle_hello (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - /* we do not care => FIXME: signal in options to NEVER send HELLOs! */ -} - - /** * A message from the handler's message queue to a neighbour was * transmitted. Now trigger (possibly delayed) notification of the @@ -551,7 +508,8 @@ handle_connect (void *cls, "Receiving CONNECT message for `%s' with quota %u\n", GNUNET_i2s (&cim->id), ntohl (cim->quota_out.value__)); - n = neighbour_find (h, &cim->id); + n = neighbour_find (h, + &cim->id); if (NULL != n) { GNUNET_break (0); @@ -613,7 +571,8 @@ handle_disconnect (void *cls, LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving DISCONNECT message for `%s'.\n", GNUNET_i2s (&dim->peer)); - n = neighbour_find (h, &dim->peer); + n = neighbour_find (h, + &dim->peer); if (NULL == n) { GNUNET_break (0); @@ -647,7 +606,9 @@ handle_send_ok (void *cls, LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving SEND_OK message, transmission to %s %s.\n", GNUNET_i2s (&okm->peer), - ntohl (okm->success) == GNUNET_OK ? "succeeded" : "failed"); + (GNUNET_OK == ntohl (okm->success)) + ? "succeeded" + : "failed"); n = neighbour_find (h, &okm->peer); if (NULL == n) @@ -662,8 +623,8 @@ handle_send_ok (void *cls, { LOG (GNUNET_ERROR_TYPE_DEBUG, "Overhead for %u byte message was %u\n", - bytes_msg, - bytes_physical - bytes_msg); + (unsigned int) bytes_msg, + (unsigned int) (bytes_physical - bytes_msg)); n->traffic_overhead += bytes_physical - bytes_msg; } } @@ -677,7 +638,7 @@ handle_send_ok (void *cls, */ static int check_recv (void *cls, - const struct InboundMessage *im) + const struct InboundMessage *im) { const struct GNUNET_MessageHeader *imm; uint16_t size; @@ -718,7 +679,8 @@ handle_recv (void *cls, (unsigned int) ntohs (imm->type), (unsigned int) ntohs (imm->size), GNUNET_i2s (&im->peer)); - n = neighbour_find (h, &im->peer); + n = neighbour_find (h, + &im->peer); if (NULL == n) { GNUNET_break (0); @@ -754,7 +716,7 @@ handle_set_quota (void *cls, LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving SET_QUOTA message for `%s' with quota %u\n", GNUNET_i2s (&qm->peer), - ntohl (qm->quota.value__)); + (unsigned int) ntohl (qm->quota.value__)); GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, qm->quota); } @@ -770,10 +732,6 @@ reconnect (void *cls) { struct GNUNET_TRANSPORT_CoreHandle *h = cls; struct GNUNET_MQ_MessageHandler handlers[] = { - GNUNET_MQ_hd_var_size (hello, - GNUNET_MESSAGE_TYPE_HELLO, - struct GNUNET_MessageHeader, - h), GNUNET_MQ_hd_fixed_size (connect, GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT, struct ConnectInfoMessage, @@ -826,16 +784,13 @@ reconnect (void *cls) /** - * Function that will schedule the job that will try - * to connect us again to the client. + * Disconnect from the transport service. * * @param h transport service to reconnect */ static void -disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h) +disconnect (struct GNUNET_TRANSPORT_CoreHandle *h) { - GNUNET_assert (NULL == h->reconnect_task); - /* Forget about all neighbours that we used to be connected to */ GNUNET_CONTAINER_multipeermap_iterate (h->neighbours, &neighbour_delete, h); @@ -844,6 +799,20 @@ disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h) GNUNET_MQ_destroy (h->mq); h->mq = NULL; } +} + + +/** + * Function that will schedule the job that will try + * to connect us again to the client. + * + * @param h transport service to reconnect + */ +static void +disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_CoreHandle *h) +{ + GNUNET_assert (NULL == h->reconnect_task); + disconnect (h); LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to transport service in %s.\n", GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, @@ -896,9 +865,9 @@ GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, const struct GNUNET_MQ_MessageHandler *handlers, void *cls, - GNUNET_TRANSPORT_NotifyConnecT nc, - GNUNET_TRANSPORT_NotifyDisconnecT nd, - GNUNET_TRANSPORT_NotifyExcessBandwidtH neb) + GNUNET_TRANSPORT_NotifyConnect nc, + GNUNET_TRANSPORT_NotifyDisconnect nd, + GNUNET_TRANSPORT_NotifyExcessBandwidth neb) { struct GNUNET_TRANSPORT_CoreHandle *h; unsigned int i; @@ -951,8 +920,7 @@ GNUNET_TRANSPORT_core_disconnect (struct GNUNET_TRANSPORT_CoreHandle *handle) LOG (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); /* this disconnects all neighbours... */ - if (NULL == handle->reconnect_task) - disconnect_and_schedule_reconnect (handle); + disconnect (handle); /* and now we stop trying to connect again... */ if (NULL != handle->reconnect_task) { diff --git a/src/transport/transport_api_core.c b/src/transport/transport_api_core.c index b7edc3cc1..5310054fd 100644 --- a/src/transport/transport_api_core.c +++ b/src/transport/transport_api_core.c @@ -136,17 +136,17 @@ struct GNUNET_TRANSPORT_CoreHandle /** * function to call on connect events */ - GNUNET_TRANSPORT_NotifyConnecT nc_cb; + GNUNET_TRANSPORT_NotifyConnect nc_cb; /** * function to call on disconnect events */ - GNUNET_TRANSPORT_NotifyDisconnecT nd_cb; + GNUNET_TRANSPORT_NotifyDisconnect nd_cb; /** * function to call on excess bandwidth events */ - GNUNET_TRANSPORT_NotifyExcessBandwidtH neb_cb; + GNUNET_TRANSPORT_NotifyExcessBandwidth neb_cb; /** * My client connection to the transport service. @@ -896,9 +896,9 @@ GNUNET_TRANSPORT_core_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, const struct GNUNET_MQ_MessageHandler *handlers, void *cls, - GNUNET_TRANSPORT_NotifyConnecT nc, - GNUNET_TRANSPORT_NotifyDisconnecT nd, - GNUNET_TRANSPORT_NotifyExcessBandwidtH neb) + GNUNET_TRANSPORT_NotifyConnect nc, + GNUNET_TRANSPORT_NotifyDisconnect nd, + GNUNET_TRANSPORT_NotifyExcessBandwidth neb) { struct GNUNET_TRANSPORT_CoreHandle *h; unsigned int i; -- cgit v1.2.3 From c359c3f7d928abf47a0c29d735bb7e30fb55e4dc Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 14:08:31 +0100 Subject: fix double-read task in communicator-unix --- src/transport/Makefile.am | 3 ++- src/transport/gnunet-communicator-unix.c | 9 ++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index ad39abe6a..deeb39b48 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -8,7 +8,8 @@ pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ - transport.conf + transport.conf \ + communicator-unix.conf if HAVE_MHD GN_LIBMHD = -lmicrohttpd diff --git a/src/transport/gnunet-communicator-unix.c b/src/transport/gnunet-communicator-unix.c index cd3ae5dce..b2eebbe20 100644 --- a/src/transport/gnunet-communicator-unix.c +++ b/src/transport/gnunet-communicator-unix.c @@ -533,6 +533,7 @@ mq_send (struct GNUNET_MQ_Handle *mq, GNUNET_CONTAINER_DLL_insert (queue_head, queue_tail, queue); + GNUNET_assert (NULL != unix_sock); if (NULL == write_task) write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, @@ -708,6 +709,7 @@ receive_complete_cb (void *cls, "# transport transmission failures", 1, GNUNET_NO); + GNUNET_assert (NULL != unix_sock); if ( (NULL == read_task) && (delivering_messages < max_queue_length) ) read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, @@ -735,6 +737,7 @@ select_read_cb (void *cls) ssize_t ret; uint16_t msize; + GNUNET_assert (NULL != unix_sock); read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, unix_sock, &select_read_cb, @@ -1083,16 +1086,12 @@ run (void *cls, "%s-%s", COMMUNICATOR_ADDRESS_PREFIX, unix_socket_path); + GNUNET_free (unix_socket_path); ai = GNUNET_TRANSPORT_communicator_address_add (ch, my_addr, GNUNET_ATS_NET_LOOPBACK, GNUNET_TIME_UNIT_FOREVER_REL); GNUNET_free (my_addr); - GNUNET_free (unix_socket_path); - read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - unix_sock, - &select_read_cb, - NULL); } -- cgit v1.2.3 From 700359ed8ce18fd6ddfc0940a5d0e5ba145c1fd1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 15:43:41 +0100 Subject: getting data structures in place for gnunet-service-tng --- src/transport/gnunet-service-tng.c | 518 +++++++++++++++++++++++++++++++++++-- 1 file changed, 491 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 73b295442..1e638377a 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -72,6 +72,147 @@ enum ClientType }; +/** + * Client connected to the transport service. + */ +struct TransportClient; + + +/** + * A neighbour that at least one communicator is connected to. + */ +struct Neighbour; + + +/** + * List of available queues for a particular neighbour. + */ +struct Queue +{ + /** + * Kept in a MDLL. + */ + struct Queue *next_neighbour; + + /** + * Kept in a MDLL. + */ + struct Queue *prev_neighbour; + + /** + * Kept in a MDLL. + */ + struct Queue *prev_client; + + /** + * Kept in a MDLL. + */ + struct Queue *next_client; + + /** + * Which neighbour is this queue for? + */ + struct Neighbour *neighbour; + + /** + * Which communicator offers this queue? + */ + struct TransportClient *tc; + + /** + * Unique identifier of this queue with the communicator. + */ + uint32_t qid; + + /** + * Network type offered by this queue. + */ + enum GNUNET_ATS_Network_Type nt; + + /** + * Address served by the queue. + */ + const char *address; +}; + + +/** + * A neighbour that at least one communicator is connected to. + */ +struct Neighbour +{ + + /** + * Which peer is this about? + */ + struct GNUNET_PeerIdentity pid; + + /** + * Head of list of messages pending for this neighbour. + */ + struct PendingMessage *pending_msg_head; + + /** + * Tail of list of messages pending for this neighbour. + */ + struct PendingMessage *pending_msg_tail; + + /** + * Head of DLL of queues to this peer. + */ + struct Queue *queue_head; + + /** + * Tail of DLL of queues to this peer. + */ + struct Queue *queue_tail; + +}; + + +/** + * Transmission request from CORE that is awaiting delivery. + */ +struct PendingMessage +{ + /** + * Kept in a MDLL of messages for this @a target. + */ + struct PendingMessage *next_neighbour; + + /** + * Kept in a MDLL of messages for this @a target. + */ + struct PendingMessage *prev_neighbour; + + /** + * Kept in a MDLL of messages from this @a client. + */ + struct PendingMessage *next_client; + + /** + * Kept in a MDLL of messages from this @a client. + */ + struct PendingMessage *prev_client; + + /** + * Target of the request. + */ + struct Neighbour *target; + + /** + * Client that issued the transmission request. + */ + struct TransportClient *client; + + /** + * Size of the original message. + */ + uint32_t bytes_msg; + +}; + + /** * Client connected to the transport service. */ @@ -107,17 +248,63 @@ struct TransportClient { /** - * Peer identity to monitor the addresses of. - * Zero to monitor all neighbours. Valid if - * @e type is #CT_MONITOR. + * Information for @e type #CT_CORE. */ - struct GNUNET_PeerIdentity monitor_peer; + struct { + + /** + * Head of list of messages pending for this client. + */ + struct PendingMessage *pending_msg_head; + + /** + * Tail of list of messages pending for this client. + */ + struct PendingMessage *pending_msg_tail; + + } core; + + /** + * Information for @e type #CT_MONITOR. + */ + struct { + + /** + * Peer identity to monitor the addresses of. + * Zero to monitor all neighbours. Valid if + * @e type is #CT_MONITOR. + */ + struct GNUNET_PeerIdentity peer; + + /** + * Is this a one-shot monitor? + */ + int one_shot; + + } monitor; + /** - * If @e type is #CT_COMMUNICATOR, this communicator - * supports communicating using these addresses. + * Information for @e type #CT_COMMUNICATOR. */ - const char *address_prefix; + struct { + /** + * If @e type is #CT_COMMUNICATOR, this communicator + * supports communicating using these addresses. + */ + char *address_prefix; + + /** + * Head of DLL of queues offered by this communicator. + */ + struct Queue *queue_head; + + /** + * Tail of DLL of queues offered by this communicator. + */ + struct Queue *queue_tail; + + } communicator; } details; @@ -154,6 +341,26 @@ struct GNUNET_PeerIdentity GST_my_identity; */ struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; +/** + * Map from PIDs to `struct Neighbour` entries. A peer is + * a neighbour if we have an MQ to it from some communicator. + */ +static struct GNUNET_CONTAINER_MultiPeerMap *neighbours; + + +/** + * Lookup neighbour record for peer @a pid. + * + * @param pid neighbour to look for + * @return NULL if we do not have this peer as a neighbour + */ +static struct Neighbour * +lookup_neighbour (const struct GNUNET_PeerIdentity *pid) +{ + return GNUNET_CONTAINER_multipeermap_get (neighbours, + pid); +} + /** * Called whenever a client connects. Allocates our @@ -210,10 +417,23 @@ client_disconnect_cb (void *cls, case CT_NONE: break; case CT_CORE: + { + struct PendingMessage *pm; + + while (NULL != (pm = tc->details.core.pending_msg_head)) + { + GNUNET_CONTAINER_MDLL_remove (client, + tc->details.core.pending_msg_head, + tc->details.core.pending_msg_tail, + pm); + pm->client = NULL; + } + } break; case CT_MONITOR: break; case CT_COMMUNICATOR: + GNUNET_free (tc->details.communicator.address_prefix); break; } GNUNET_free (tc); @@ -268,10 +488,15 @@ static int check_client_send (void *cls, const struct OutboundMessage *obm) { + struct TransportClient *tc = cls; uint16_t size; const struct GNUNET_MessageHeader *obmm; - - (void) cls; + + if (CT_CORE != tc->type) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } size = ntohs (obm->header.size) - sizeof (struct OutboundMessage); if (size < sizeof (struct GNUNET_MessageHeader)) { @@ -288,6 +513,51 @@ check_client_send (void *cls, } +/** + * Send a response to the @a pm that we have processed a + * "send" request with status @a success. We + * transmitted @a bytes_physical on the actual wire. + * Sends a confirmation to the "core" client responsible + * for the original request and free's @a pm. + * + * @param pm handle to the original pending message + * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR + * for transmission failure + * @param bytes_physical amount of bandwidth consumed + */ +static void +client_send_response (struct PendingMessage *pm, + int success, + uint32_t bytes_physical) +{ + struct TransportClient *tc = pm->client; + struct Neighbour *target = pm->target; + struct GNUNET_MQ_Envelope *env; + struct SendOkMessage *som; + + if (NULL != tc) + { + env = GNUNET_MQ_msg (som, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); + som->success = htonl ((uint32_t) success); + som->bytes_msg = htonl (pm->bytes_msg); + som->bytes_physical = htonl (bytes_physical); + som->peer = target->pid; + GNUNET_MQ_send (tc->mq, + env); + GNUNET_CONTAINER_MDLL_remove (client, + tc->details.core.pending_msg_head, + tc->details.core.pending_msg_tail, + pm); + } + GNUNET_CONTAINER_MDLL_remove (neighbour, + target->pending_msg_head, + target->pending_msg_tail, + pm); + GNUNET_free (pm); +} + + /** * Client asked for transmission to a peer. Process the request. * @@ -299,9 +569,55 @@ handle_client_send (void *cls, const struct OutboundMessage *obm) { struct TransportClient *tc = cls; + struct PendingMessage *pm; const struct GNUNET_MessageHeader *obmm; + struct Neighbour *target; + uint32_t bytes_msg; + GNUNET_assert (CT_CORE == tc->type); obmm = (const struct GNUNET_MessageHeader *) &obm[1]; + bytes_msg = ntohs (obmm->size); + target = lookup_neighbour (&obm->peer); + if (NULL == target) + { + /* Failure: don't have this peer as a neighbour (anymore). + Might have gone down asynchronously, so this is NOT + a protocol violation by CORE. Still count the event, + as this should be rare. */ + struct GNUNET_MQ_Envelope *env; + struct SendOkMessage *som; + + env = GNUNET_MQ_msg (som, + GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); + som->success = htonl (GNUNET_SYSERR); + som->bytes_msg = htonl (bytes_msg); + som->bytes_physical = htonl (0); + som->peer = obm->peer; + GNUNET_MQ_send (tc->mq, + env); + GNUNET_SERVICE_client_continue (tc->client); + GNUNET_STATISTICS_update (GST_stats, + "# messages dropped (neighbour unknown)", + 1, + GNUNET_NO); + return; + } + pm = GNUNET_new (struct PendingMessage); + pm->client = tc; + pm->target = target; + pm->bytes_msg = bytes_msg; + GNUNET_CONTAINER_MDLL_insert (neighbour, + target->pending_msg_head, + target->pending_msg_tail, + pm); + GNUNET_CONTAINER_MDLL_insert (client, + tc->details.core.pending_msg_head, + tc->details.core.pending_msg_tail, + pm); + // FIXME: do the work, continuation with: + client_send_response (pm, + GNUNET_NO, + 0); } @@ -315,10 +631,16 @@ static int check_communicator_available (void *cls, const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam) { + struct TransportClient *tc = cls; const char *addr; uint16_t size; - (void) cls; + if (CT_NONE != tc->type) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + tc->type = CT_COMMUNICATOR; size = ntohs (cam->header.size) - sizeof (*cam); if (0 == size) return GNUNET_OK; /* receive-only communicator */ @@ -345,17 +667,10 @@ handle_communicator_available (void *cls, struct TransportClient *tc = cls; uint16_t size; - if (CT_NONE != tc->type) - { - GNUNET_break (0); - GNUNET_SERVICE_client_drop (tc->client); - return; - } - tc->type = CT_COMMUNICATOR; size = ntohs (cam->header.size) - sizeof (*cam); if (0 == size) return; /* receive-only communicator */ - tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]); + tc->details.communicator.address_prefix = GNUNET_strdup ((const char *) &cam[1]); GNUNET_SERVICE_client_continue (tc->client); } @@ -370,10 +685,15 @@ static int check_add_address (void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam) { + struct TransportClient *tc = cls; const char *addr; uint16_t size; - (void) cls; + if (CT_COMMUNICATOR != tc->type) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } size = ntohs (aam->header.size) - sizeof (*aam); if (0 == size) { @@ -418,12 +738,19 @@ handle_del_address (void *cls, { struct TransportClient *tc = cls; + if (CT_COMMUNICATOR != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + GNUNET_SERVICE_client_continue (tc->client); } /** - * Client asked for transmission to a peer. Process the request. + * Client notified us about transmission from a peer. Process the request. * * @param cls the client * @param obm the send message that was sent @@ -432,10 +759,15 @@ static int check_incoming_msg (void *cls, const struct GNUNET_TRANSPORT_IncomingMessage *im) { + struct TransportClient *tc = cls; uint16_t size; const struct GNUNET_MessageHeader *obmm; - (void) cls; + if (CT_COMMUNICATOR != tc->type) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } size = ntohs (im->header.size) - sizeof (*im); if (size < sizeof (struct GNUNET_MessageHeader)) { @@ -478,10 +810,15 @@ static int check_add_queue_message (void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) { + struct TransportClient *tc = cls; const char *addr; uint16_t size; - (void) cls; + if (CT_COMMUNICATOR != tc->type) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } size = ntohs (aqm->header.size) - sizeof (*aqm); if (0 == size) { @@ -509,11 +846,65 @@ handle_add_queue_message (void *cls, const struct GNUNET_TRANSPORT_AddQueueMessage *aqm) { struct TransportClient *tc = cls; + struct Queue *queue; + struct Neighbour *neighbour; + const char *addr; + uint16_t addr_len; + neighbour = lookup_neighbour (&aqm->receiver); + if (NULL == neighbour) + { + neighbour = GNUNET_new (struct Neighbour); + neighbour->pid = aqm->receiver; + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multipeermap_put (neighbours, + &neighbour->pid, + neighbour, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + // FIXME: notify cores/monitors! + } + addr_len = ntohs (aqm->header.size) - sizeof (*aqm); + addr = (const char *) &aqm[1]; + + queue = GNUNET_malloc (sizeof (struct Queue) + addr_len); + queue->qid = aqm->qid; + queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt); + queue->tc = tc; + queue->neighbour = neighbour; + queue->address = (const char *) &queue[1]; + memcpy (&queue[1], + addr, + addr_len); + GNUNET_CONTAINER_MDLL_insert (neighbour, + neighbour->queue_head, + neighbour->queue_tail, + queue); + GNUNET_CONTAINER_MDLL_insert (client, + tc->details.communicator.queue_head, + tc->details.communicator.queue_tail, + queue); + // FIXME: possibly transmit queued messages? GNUNET_SERVICE_client_continue (tc->client); } +/** + * Release memory used by @a neighbour. + * + * @param neighbour neighbour entry to free + */ +static void +free_neighbour (struct Neighbour *neighbour) +{ + GNUNET_assert (NULL == neighbour->queue_head); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (neighbours, + &neighbour->pid, + neighbour)); + GNUNET_free (neighbour); +} + + /** * Queue to a peer went down. Process the request. * @@ -526,7 +917,42 @@ handle_del_queue_message (void *cls, { struct TransportClient *tc = cls; - GNUNET_SERVICE_client_continue (tc->client); + if (CT_COMMUNICATOR != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } + for (struct Queue *queue = tc->details.communicator.queue_head; + NULL != queue; + queue = queue->next_client) + { + struct Neighbour *neighbour = queue->neighbour; + + if ( (dqm->qid != queue->qid) || + (0 != memcmp (&dqm->receiver, + &neighbour->pid, + sizeof (struct GNUNET_PeerIdentity))) ) + continue; + GNUNET_CONTAINER_MDLL_remove (neighbour, + neighbour->queue_head, + neighbour->queue_tail, + queue); + GNUNET_CONTAINER_MDLL_remove (client, + tc->details.communicator.queue_head, + tc->details.communicator.queue_tail, + queue); + GNUNET_free (queue); + if (NULL == neighbour->queue_head) + { + // FIXME: notify cores/monitors! + free_neighbour (neighbour); + } + GNUNET_SERVICE_client_continue (tc->client); + return; + } + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); } @@ -542,6 +968,12 @@ handle_send_message_ack (void *cls, { struct TransportClient *tc = cls; + if (CT_COMMUNICATOR != tc->type) + { + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); + return; + } GNUNET_SERVICE_client_continue (tc->client); } @@ -565,12 +997,37 @@ handle_monitor_start (void *cls, return; } tc->type = CT_MONITOR; - tc->details.monitor_peer = start->peer; - // FIXME: remember also the one_shot flag! + tc->details.monitor.peer = start->peer; + tc->details.monitor.one_shot = ntohl (start->one_shot); + // FIXME: do work! GNUNET_SERVICE_client_continue (tc->client); } +/** + * Free neighbour entry. + * + * @param cls NULL + * @param pid unused + * @param value a `struct Neighbour` + * @return #GNUNET_OK (always) + */ +static int +free_neighbour_cb (void *cls, + const struct GNUNET_PeerIdentity *pid, + void *value) +{ + struct Neighbour *neighbour = value; + + (void) cls; + (void) pid; + GNUNET_break (0); // should this ever happen? + free_neighbour (neighbour); + + return GNUNET_OK; +} + + /** * Function called when the service shuts down. Unloads our plugins * and cancels pending validations. @@ -578,7 +1035,7 @@ handle_monitor_start (void *cls, * @param cls closure, unused */ static void -shutdown_task (void *cls) +do_shutdown (void *cls) { (void) cls; @@ -593,6 +1050,10 @@ shutdown_task (void *cls) GNUNET_free (GST_my_private_key); GST_my_private_key = NULL; } + GNUNET_CONTAINER_multipeermap_iterate (neighbours, + &free_neighbour_cb, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (neighbours); } @@ -608,8 +1069,11 @@ run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service) { + (void) cls; /* setup globals */ GST_cfg = c; + neighbours = GNUNET_CONTAINER_multipeermap_create (1024, + GNUNET_YES); GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg); if (NULL == GST_my_private_key) { @@ -626,7 +1090,7 @@ run (void *cls, GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg); - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); /* start subsystems */ } -- cgit v1.2.3 From 92b7e711f94b4cba262992965a59c67d1fffb046 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 21:41:19 +0100 Subject: add missing file --- po/POTFILES.in | 2 ++ src/transport/communicator-unix.conf | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 src/transport/communicator-unix.conf (limited to 'src') diff --git a/po/POTFILES.in b/po/POTFILES.in index 54fe7b4e7..129c43cdd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -432,6 +432,8 @@ src/transport/tcp_server_legacy.c src/transport/tcp_server_mst_legacy.c src/transport/tcp_service_legacy.c src/transport/transport_api2_communication.c +src/transport/transport_api2_core.c +src/transport/transport_api2_monitor.c src/transport/transport_api_address_to_string.c src/transport/transport_api_blacklist.c src/transport/transport_api_core.c diff --git a/src/transport/communicator-unix.conf b/src/transport/communicator-unix.conf new file mode 100644 index 000000000..ad92616c6 --- /dev/null +++ b/src/transport/communicator-unix.conf @@ -0,0 +1,2 @@ +[communicator-unix] +UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-communicator-unix.sock -- cgit v1.2.3 From 84d51248d563d4187fc5414fbe795a5a4e284262 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 23:24:08 +0100 Subject: handle addr add/remove messages --- src/transport/gnunet-service-tng.c | 143 +++++++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 1e638377a..555210585 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -119,6 +119,11 @@ struct Queue */ struct TransportClient *tc; + /** + * Address served by the queue. + */ + const char *address; + /** * Unique identifier of this queue with the communicator. */ @@ -128,11 +133,6 @@ struct Queue * Network type offered by this queue. */ enum GNUNET_ATS_Network_Type nt; - - /** - * Address served by the queue. - */ - const char *address; }; @@ -166,7 +166,7 @@ struct Neighbour * Tail of DLL of queues to this peer. */ struct Queue *queue_tail; - + }; @@ -209,7 +209,52 @@ struct PendingMessage * Size of the original message. */ uint32_t bytes_msg; - + +}; + + +/** + * One of the addresses of this peer. + */ +struct AddressListEntry +{ + + /** + * Kept in a DLL. + */ + struct AddressListEntry *next; + + /** + * Kept in a DLL. + */ + struct AddressListEntry *prev; + + /** + * Which communicator provides this address? + */ + struct TransportClient *tc; + + /** + * The actual address. + */ + const char *address; + + /** + * What is a typical lifetime the communicator expects this + * address to have? (Always from now.) + */ + struct GNUNET_TIME_Relative expiration; + + /** + * Address identifier used by the communicator. + */ + uint32_t aid; + + /** + * Network type offered by this address. + */ + enum GNUNET_ATS_Network_Type nt; + }; @@ -261,14 +306,14 @@ struct TransportClient * Tail of list of messages pending for this client. */ struct PendingMessage *pending_msg_tail; - + } core; /** * Information for @e type #CT_MONITOR. */ struct { - + /** * Peer identity to monitor the addresses of. * Zero to monitor all neighbours. Valid if @@ -280,30 +325,40 @@ struct TransportClient * Is this a one-shot monitor? */ int one_shot; - + } monitor; - + /** * Information for @e type #CT_COMMUNICATOR. */ - struct { + struct { /** * If @e type is #CT_COMMUNICATOR, this communicator * supports communicating using these addresses. */ char *address_prefix; - + /** * Head of DLL of queues offered by this communicator. */ struct Queue *queue_head; - + /** * Tail of DLL of queues offered by this communicator. */ struct Queue *queue_tail; - + + /** + * Head of list of the addresses of this peer offered by this communicator. + */ + struct AddressListEntry *addr_head; + + /** + * Tail of list of the addresses of this peer offered by this communicator. + */ + struct AddressListEntry *addr_tail; + } communicator; } details; @@ -491,7 +546,7 @@ check_client_send (void *cls, struct TransportClient *tc = cls; uint16_t size; const struct GNUNET_MessageHeader *obmm; - + if (CT_CORE != tc->type) { GNUNET_break (0); @@ -514,7 +569,7 @@ check_client_send (void *cls, /** - * Send a response to the @a pm that we have processed a + * Send a response to the @a pm that we have processed a * "send" request with status @a success. We * transmitted @a bytes_physical on the actual wire. * Sends a confirmation to the "core" client responsible @@ -586,7 +641,7 @@ handle_client_send (void *cls, as this should be rare. */ struct GNUNET_MQ_Envelope *env; struct SendOkMessage *som; - + env = GNUNET_MQ_msg (som, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); som->success = htonl (GNUNET_SYSERR); @@ -601,7 +656,7 @@ handle_client_send (void *cls, 1, GNUNET_NO); return; - } + } pm = GNUNET_new (struct PendingMessage); pm->client = tc; pm->target = target; @@ -721,7 +776,23 @@ handle_add_address (void *cls, const struct GNUNET_TRANSPORT_AddAddressMessage *aam) { struct TransportClient *tc = cls; - + struct AddressListEntry *ale; + size_t slen; + + slen = ntohs (aam->header.size) - sizeof (*aam); + ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen); + ale->tc = tc; + ale->address = (const char *) &ale[1]; + ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration); + ale->aid = aam->aid; + ale->nt = (enum GNUNET_ATS_Network_Type) ntohl (aam->nt); + memcpy (&ale[1], + &aam[1], + slen); + GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head, + tc->details.communicator.addr_tail, + ale); + // FIXME: notify somebody?! GNUNET_SERVICE_client_continue (tc->client); } @@ -744,8 +815,22 @@ handle_del_address (void *cls, GNUNET_SERVICE_client_drop (tc->client); return; } - - GNUNET_SERVICE_client_continue (tc->client); + for (struct AddressListEntry *ale = tc->details.communicator.addr_head; + NULL != ale; + ale = ale->next) + { + if (dam->aid != ale->aid) + continue; + GNUNET_assert (ale->tc == tc); + GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head, + tc->details.communicator.addr_tail, + ale); + // FIXME: notify somebody? + GNUNET_free (ale); + GNUNET_SERVICE_client_continue (tc->client); + } + GNUNET_break (0); + GNUNET_SERVICE_client_drop (tc->client); } @@ -861,11 +946,11 @@ handle_add_queue_message (void *cls, &neighbour->pid, neighbour, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - // FIXME: notify cores/monitors! + // FIXME: notify ATS/COREs/monitors! } addr_len = ntohs (aqm->header.size) - sizeof (*aqm); addr = (const char *) &aqm[1]; - + queue = GNUNET_malloc (sizeof (struct Queue) + addr_len); queue->qid = aqm->qid; queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt); @@ -948,7 +1033,7 @@ handle_del_queue_message (void *cls, // FIXME: notify cores/monitors! free_neighbour (neighbour); } - GNUNET_SERVICE_client_continue (tc->client); + GNUNET_SERVICE_client_continue (tc->client); return; } GNUNET_break (0); @@ -1020,10 +1105,10 @@ free_neighbour_cb (void *cls, struct Neighbour *neighbour = value; (void) cls; - (void) pid; + (void) pid; GNUNET_break (0); // should this ever happen? free_neighbour (neighbour); - + return GNUNET_OK; } @@ -1077,8 +1162,8 @@ run (void *cls, GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg); if (NULL == GST_my_private_key) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - _("Transport service is lacking key configuration settings. Exiting.\n")); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Transport service is lacking key configuration settings. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } -- cgit v1.2.3 From 196a0bf9699d9ecead4b50819bd64d3174795296 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 23:26:24 +0100 Subject: remove dead field quota_in --- src/transport/gnunet-service-transport.c | 1 - src/transport/gnunet-service-transport_neighbours.c | 3 +-- src/transport/transport.h | 13 ++++--------- src/transport/transport_api_core.c | 5 +++-- 4 files changed, 8 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index 8c4f33fd0..2d9803651 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -602,7 +602,6 @@ notify_client_about_neighbour (void *cls, cim.header.size = htons (sizeof (struct ConnectInfoMessage)); cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); cim.id = *peer; - cim.quota_in = bandwidth_in; cim.quota_out = bandwidth_out; unicast (tc, &cim.header, diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c index 3965bc13e..68344bcf4 100644 --- a/src/transport/gnunet-service-transport_neighbours.c +++ b/src/transport/gnunet-service-transport_neighbours.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -571,7 +571,6 @@ neighbours_connect_notification (struct NeighbourMapEntry *n) connect_msg->header.size = htons (sizeof(buf)); connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); connect_msg->id = n->id; - connect_msg->quota_in = n->primary_address.bandwidth_in; connect_msg->quota_out = bandwidth_min; GST_clients_broadcast (&connect_msg->header, GNUNET_NO); diff --git a/src/transport/transport.h b/src/transport/transport.h index c5191a5ce..129b1ce15 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -121,19 +121,14 @@ struct ConnectInfoMessage struct GNUNET_MessageHeader header; /** - * Identity of the new neighbour. - */ - struct GNUNET_PeerIdentity id; - - /** - * Current inbound quota for this peer + * Current outbound quota for this peer */ - struct GNUNET_BANDWIDTH_Value32NBO quota_in; + struct GNUNET_BANDWIDTH_Value32NBO quota_out; /** - * Current outbound quota for this peer + * Identity of the new neighbour. */ - struct GNUNET_BANDWIDTH_Value32NBO quota_out; + struct GNUNET_PeerIdentity id; }; diff --git a/src/transport/transport_api_core.c b/src/transport/transport_api_core.c index 5310054fd..2e897d94a 100644 --- a/src/transport/transport_api_core.c +++ b/src/transport/transport_api_core.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -551,7 +551,8 @@ handle_connect (void *cls, "Receiving CONNECT message for `%s' with quota %u\n", GNUNET_i2s (&cim->id), ntohl (cim->quota_out.value__)); - n = neighbour_find (h, &cim->id); + n = neighbour_find (h, + &cim->id); if (NULL != n) { GNUNET_break (0); -- cgit v1.2.3 From 35e5be0b0b4c7aea5a56d6a62333ab3a964a2972 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Nov 2018 23:36:28 +0100 Subject: notes --- src/include/gnunet_bandwidth_lib.h | 2 +- src/transport/gnunet-service-tng.c | 23 +++++++++++++++++++++++ src/transport/transport.h | 2 ++ 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/include/gnunet_bandwidth_lib.h b/src/include/gnunet_bandwidth_lib.h index 78610c48b..4395b878b 100644 --- a/src/include/gnunet_bandwidth_lib.h +++ b/src/include/gnunet_bandwidth_lib.h @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 555210585..c7bdfd77c 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -19,6 +19,15 @@ * @file transport/gnunet-service-transport.c * @brief main for gnunet-service-transport * @author Christian Grothoff + * + * TODO: + * - make *our* collected addresses available somehow somewhere + * => Choices: in peerstore or revive/keep peerinfo? + * - MTU information is missing for queues! + * - start supporting monitor logic (add functions to signal monitors!) + * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc. + * - ask ATS about bandwidth allocation + * - */ #include "platform.h" #include "gnunet_util_lib.h" @@ -133,6 +142,8 @@ struct Queue * Network type offered by this queue. */ enum GNUNET_ATS_Network_Type nt; + + // FIXME: add ATS-specific fields here! }; @@ -167,6 +178,18 @@ struct Neighbour */ struct Queue *queue_tail; + /** + * Quota at which CORE is allowed to transmit to this peer + * according to ATS. + * + * FIXME: not yet used, tricky to get right given multiple queues! + * (=> Idea: let ATS set a quota per queue and we add them up here?) + * FIXME: how do we set this value initially when we tell CORE? + * Options: start at a minimum value or at literally zero (before ATS?) + * (=> Current thought: clean would be zero!) + */ + struct GNUNET_BANDWIDTH_Value32NBO quota_out; + }; diff --git a/src/transport/transport.h b/src/transport/transport.h index 129b1ce15..423d3cefa 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -800,6 +800,8 @@ struct GNUNET_TRANSPORT_AddQueueMessage */ uint32_t nt; + // FIXME: add MTU? + /* followed by UTF-8 encoded, 0-terminated human-readable address */ }; -- cgit v1.2.3