From 8590cba90ab53a070d5ce3d8ec8f1a7f4fb4ee23 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 31 May 2013 14:06:52 +0000 Subject: [PATCH] -hacking up new regex client library --- src/include/gnunet_client_lib.h | 2 +- src/include/gnunet_protocols.h | 18 +- src/include/gnunet_regex_service.h | 14 +- src/regex/Makefile.am | 12 +- src/regex/regex_api.c | 333 +++++++++++++++++++++++++++++ src/regex/regex_ipc.h | 112 ++++++++++ 6 files changed, 483 insertions(+), 8 deletions(-) create mode 100644 src/regex/regex_api.c create mode 100644 src/regex/regex_ipc.h diff --git a/src/include/gnunet_client_lib.h b/src/include/gnunet_client_lib.h index 51da46de6..8642dd941 100644 --- a/src/include/gnunet_client_lib.h +++ b/src/include/gnunet_client_lib.h @@ -84,7 +84,7 @@ GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client); */ typedef void (*GNUNET_CLIENT_MessageHandler) (void *cls, const struct GNUNET_MessageHeader - * msg); + *msg); /** diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 9325416ec..15bbae2e8 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -1881,7 +1881,23 @@ extern "C" #define GNUNET_MESSAGE_TYPE_EXPERIMENTATION_RESPONSE 611 /** - * Next available: 620 + * Advertise regex capability. + */ +#define GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE 620 + +/** + * Search for peer with matching capability. + */ +#define GNUNET_MESSAGE_TYPE_REGEX_SEARCH 621 + +/** + * Result in response to regex search. + */ +#define GNUNET_MESSAGE_TYPE_REGEX_RESULT 622 + + +/** + * Next available: 624 */ diff --git a/src/include/gnunet_regex_service.h b/src/include/gnunet_regex_service.h index 57f98b19f..2a176f401 100644 --- a/src/include/gnunet_regex_service.h +++ b/src/include/gnunet_regex_service.h @@ -60,6 +60,7 @@ struct GNUNET_REGEX_Search; * not free resources, must call GNUNET_REGEX_announce_cancel for * that. * + * @param cfg configuration to use * @param id ID to announce as provider of regex. Own ID in most cases. * @param regex Regular expression to announce. * @param refresh_delay after what delay should the announcement be repeated? @@ -68,7 +69,8 @@ struct GNUNET_REGEX_Search; * Must be freed by calling GNUNET_REGEX_announce_cancel. */ struct GNUNET_REGEX_Announcement * -GNUNET_REGEX_announce (const struct GNUNET_PeerIdentity *id, +GNUNET_REGEX_announce (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_PeerIdentity *id, const char *regex, struct GNUNET_TIME_Relative refresh_delay, uint16_t compression); @@ -77,10 +79,10 @@ GNUNET_REGEX_announce (const struct GNUNET_PeerIdentity *id, /** * Stop announcing the regex specified by the given handle. * - * @param h handle returned by a previous GNUNET_REGEX_announce call. + * @param a handle returned by a previous GNUNET_REGEX_announce call. */ void -GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_Announcement *h); +GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_Announcement *a); /** @@ -106,6 +108,7 @@ typedef void (*GNUNET_REGEX_Found)(void *cls, * The search runs until GNUNET_REGEX_search_cancel is called, even if results * are returned. * + * @param cfg configuration to use * @param string String to match against the regexes in the DHT. * @param callback Callback for found peers. * @param callback_cls Closure for @c callback. @@ -113,7 +116,8 @@ typedef void (*GNUNET_REGEX_Found)(void *cls, * Must be freed by calling GNUNET_REGEX_search_cancel. */ struct GNUNET_REGEX_Search * -GNUNET_REGEX_search (const char *string, +GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *string, GNUNET_REGEX_Found callback, void *callback_cls); @@ -124,7 +128,7 @@ GNUNET_REGEX_search (const char *string, * @param h Handle returned by a previous GNUNET_REGEX_search call. */ void -GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *h); +GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s); #if 0 /* keep Emacsens' auto-indent happy */ diff --git a/src/regex/Makefile.am b/src/regex/Makefile.am index 4900e5e91..e88938054 100644 --- a/src/regex/Makefile.am +++ b/src/regex/Makefile.am @@ -9,7 +9,8 @@ if USE_COVERAGE endif lib_LTLIBRARIES = libgnunetregexblock.la \ - libgnunetregex.la + libgnunetregex.la \ + libgnunetregexnew.la libgnunetregexblock_la_SOURCES = \ @@ -38,6 +39,15 @@ libgnunetregex_la_LDFLAGS = \ -version-info 2:0:1 +libgnunetregexnew_la_SOURCES = \ + regex_api.c regex_ipc.h +libgnunetregexnew_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la +libgnunetregexnew_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) \ + -version-info 3:0:0 + + plugindir = $(libdir)/gnunet plugin_LTLIBRARIES = \ diff --git a/src/regex/regex_api.c b/src/regex/regex_api.c new file mode 100644 index 000000000..ec9ee0de8 --- /dev/null +++ b/src/regex/regex_api.c @@ -0,0 +1,333 @@ +/* + This file is part of GNUnet + (C) 2012, 2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file include/gnunet_regex_service.h + * @brief access regex service to advertise capabilities via regex and discover + * respective peers using matching strings + * @author Maximilian Szengel + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_protocols.h" +#include "gnunet_util_lib.h" +#include "gnunet_regex_service.h" +#include "regex_ipc.h" + +/** + * Handle to store cached data about a regex announce. + */ +struct GNUNET_REGEX_Announcement +{ + /** + * Connection to the regex service. + */ + struct GNUNET_CLIENT_Connection *client; + + /** + * Our configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Message we're sending to the service. + */ + struct AnnounceMessage msg; +}; + + +/** + * We got a response (!?) or disconnect after asking regex + * to do the announcement. Retry. + * + * @param cls the 'struct GNUNET_REGEX_Announcement' to retry + * @param msg NULL on disconnect + */ +static void +handle_a_reconnect (void *cls, + const struct GNUNET_MessageHeader *msg); + + +/** + * Try sending the announcement request to regex. On + * errors (i.e. regex died), try again. + * + * @param a the announcement to retry + */ +static void +retry_announcement (struct GNUNET_REGEX_Announcement *a) +{ + GNUNET_assert (NULL != a->client); + GNUNET_assert (GNUNET_OK == + GNUNET_CLIENT_transmit_and_get_response (a->client, + &a->msg.header, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, + &handle_a_reconnect, + a)); +} + + +/** + * We got a response (!?) or disconnect after asking regex + * to do the announcement. Retry. + * + * @param cls the 'struct GNUNET_REGEX_Announcement' to retry + * @param msg NULL on disconnect + */ +static void +handle_a_reconnect (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + struct GNUNET_REGEX_Announcement *a = cls; + + GNUNET_CLIENT_disconnect (a->client); + a->client = GNUNET_CLIENT_connect ("regex", a->cfg); + retry_announcement (a); +} + + +/** + * Announce the given peer under the given regular expression. Does + * not free resources, must call GNUNET_REGEX_announce_cancel for + * that. + * + * @param cfg configuration to use + * @param id ID to announce as provider of regex. Own ID in most cases. + * @param regex Regular expression to announce. + * @param refresh_delay after what delay should the announcement be repeated? + * @param compression How many characters per edge can we squeeze? + * @return Handle to reuse o free cached resources. + * Must be freed by calling GNUNET_REGEX_announce_cancel. + */ +struct GNUNET_REGEX_Announcement * +GNUNET_REGEX_announce (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_PeerIdentity *id, + const char *regex, + struct GNUNET_TIME_Relative refresh_delay, + uint16_t compression) +{ + struct GNUNET_REGEX_Announcement *a; + size_t slen; + + slen = strlen (regex) + 1; + if (slen + sizeof (struct AnnounceMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_break (0); + return NULL; + } + a = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Announcement) + slen); + a->cfg = cfg; + a->client = GNUNET_CLIENT_connect ("regex", cfg); + if (NULL == a->client) + return NULL; + a->msg.header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE); + a->msg.header.size = htons (slen + sizeof (struct AnnounceMessage)); + a->msg.compression = htons (compression); + a->msg.reserved = htons (0); + a->msg.refresh_delay = GNUNET_TIME_relative_hton (refresh_delay); + a->msg.pid = *id; + memcpy (&a[1], regex, slen); + retry_announcement (a); + return a; +} + + +/** + * Stop announcing the regex specified by the given handle. + * + * @param a handle returned by a previous GNUNET_REGEX_announce call. + */ +void +GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_Announcement *a) +{ + GNUNET_CLIENT_disconnect (a->client); + GNUNET_free (a); +} + + +/** + * Handle to store data about a regex search. + */ +struct GNUNET_REGEX_Search +{ + /** + * Connection to the regex service. + */ + struct GNUNET_CLIENT_Connection *client; + + /** + * Our configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Function to call with results. + */ + GNUNET_REGEX_Found callback; + + /** + * Closure for 'callback'. + */ + void *callback_cls; + + /** + * Search message to transmit to the service. + */ + struct SearchMessage msg; +}; + + +/** + * We got a response or disconnect after asking regex + * to do the search. Handle it. + * + * @param cls the 'struct GNUNET_REGEX_Search' to retry + * @param msg NULL on disconnect + */ +static void +handle_search_response (void *cls, + const struct GNUNET_MessageHeader *msg); + + +/** + * Try sending the search request to regex. On + * errors (i.e. regex died), try again. + * + * @param s the search to retry + */ +static void +retry_search (struct GNUNET_REGEX_Search *s) +{ + GNUNET_assert (NULL != s->client); + GNUNET_assert (GNUNET_OK == + GNUNET_CLIENT_transmit_and_get_response (s->client, + &s->msg.header, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, + &handle_search_response, + s)); +} + + +/** + * We got a response or disconnect after asking regex + * to do the search. Handle it. + * + * @param cls the 'struct GNUNET_REGEX_Search' to retry + * @param msg NULL on disconnect, otherwise presumably a response + */ +static void +handle_search_response (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + struct GNUNET_REGEX_Search *s = cls; + const struct ResultMessage *result; + uint16_t size; + uint16_t gpl; + uint16_t ppl; + + if (NULL == msg) + { + GNUNET_CLIENT_disconnect (s->client); + s->client = GNUNET_CLIENT_connect ("regex", s->cfg); + retry_search (s); + return; + } + size = ntohs (msg->size); + if ( (GNUNET_MESSAGE_TYPE_REGEX_RESULT == ntohs (msg->type)) && + (size >= sizeof (struct ResultMessage)) ) + { + result = (const struct ResultMessage *) msg; + gpl = ntohs (result->get_path_length); + ppl = ntohs (result->put_path_length); + if (size == (sizeof (struct ResultMessage) + + (gpl + ppl) * sizeof (struct GNUNET_PeerIdentity))) + { + const struct GNUNET_PeerIdentity *pid; + + GNUNET_CLIENT_receive (s->client, + &handle_search_response, s, + GNUNET_TIME_UNIT_FOREVER_REL); + pid = &result->id; + s->callback (s->callback_cls, + pid, + &pid[1], gpl, + &pid[1 + gpl], ppl); + return; + } + } + GNUNET_break (0); + GNUNET_CLIENT_disconnect (s->client); + s->client = GNUNET_CLIENT_connect ("regex", s->cfg); + retry_search (s); +} + + +/** + * Search for a peer offering a regex matching certain string in the DHT. + * The search runs until GNUNET_REGEX_search_cancel is called, even if results + * are returned. + * + * @param cfg configuration to use + * @param string String to match against the regexes in the DHT. + * @param callback Callback for found peers. + * @param callback_cls Closure for @c callback. + * @return Handle to stop search and free resources. + * Must be freed by calling GNUNET_REGEX_search_cancel. + */ +struct GNUNET_REGEX_Search * +GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *string, + GNUNET_REGEX_Found callback, + void *callback_cls) +{ + struct GNUNET_REGEX_Search *s; + size_t slen; + + slen = strlen (string) + 1; + s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Announcement) + slen); + s->cfg = cfg; + s->client = GNUNET_CLIENT_connect ("regex", cfg); + if (NULL == s->client) + return NULL; + s->callback = callback; + s->callback_cls = callback_cls; + s->msg.header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH); + s->msg.header.size = htons (sizeof (struct SearchMessage) + slen); + memcpy (&s[1], string, slen); + retry_search (s); + return s; +} + + +/** + * Stop search and free all data used by a GNUNET_REGEX_search call. + * + * @param s Handle returned by a previous GNUNET_REGEX_search call. + */ +void +GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s) +{ + GNUNET_CLIENT_disconnect (s->client); + GNUNET_free (s); +} + + +/* end of regex_api.c */ diff --git a/src/regex/regex_ipc.h b/src/regex/regex_ipc.h new file mode 100644 index 000000000..b94fceb86 --- /dev/null +++ b/src/regex/regex_ipc.h @@ -0,0 +1,112 @@ +/* + This file is part of GNUnet + (C) 2012, 2013 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file regex/regex_ipc.h + * @brief regex IPC messages (not called 'regex.h' due to conflict with + * system headers) + * @author Christian Grothoff + */ +#ifndef REGEX_IPC_H +#define REGEX_IPC_H + +#include "gnunet_util_lib.h" + +/** + * Request for regex service to announce capability. + */ +struct AnnounceMessage +{ + + /** + * Type is GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE + */ + struct GNUNET_MessageHeader header; + + /** + * How many characters can we squeeze per edge? + */ + uint16_t compression; + + /** + * Always zero. + */ + uint16_t reserved; + + /** + * Delay between repeated announcements. + */ + struct GNUNET_TIME_RelativeNBO refresh_delay; + + /** + * Which PID to announce as the provider? + */ + struct GNUNET_PeerIdentity pid; + + /* followed by 0-terminated regex as string */ +}; + + +/** + * Message to initiate regex search. + */ +struct SearchMessage +{ + /** + * Type is GNUNET_MESSAGE_TYPE_REGEX_SEARCH + */ + struct GNUNET_MessageHeader header; + + /* followed by 0-terminated search string */ + +}; + + +/** + * Result from regex search. + */ +struct ResultMessage +{ + /** + * Type is GNUNET_MESSAGE_TYPE_REGEX_RESULT + */ + struct GNUNET_MessageHeader header; + + /** + * Number of entries in the GET path. + */ + uint16_t get_path_length; + + /** + * Number of entries in the PUT path. + */ + uint16_t put_path_length; + + /** + * Identity of the peer that was found. + */ + struct GNUNET_PeerIdentity id; + + /* followed by GET path and PUT path arrays */ + +}; + + +/* end of regex_ipc.h */ +#endif -- 2.25.1