migrate first half of regex API to MQ lib
authorChristian Grothoff <christian@grothoff.org>
Thu, 23 Jun 2016 17:48:40 +0000 (17:48 +0000)
committerChristian Grothoff <christian@grothoff.org>
Thu, 23 Jun 2016 17:48:40 +0000 (17:48 +0000)
src/regex/Makefile.am
src/regex/regex_api.c [deleted file]
src/regex/regex_api_announce.c [new file with mode: 0644]
src/regex/regex_api_search.c [new file with mode: 0644]

index 43555cf722b5a7209c556cd62bcbd99482f77d6c..6204a47d8e3dd00104cc6edf0135a67832104cab 100644 (file)
@@ -62,7 +62,9 @@ libgnunetregex_internal_a_DEPENDENCIES = \
 
 
 libgnunetregex_la_SOURCES = \
-  regex_api.c regex_ipc.h
+  regex_api_announce.c \
+  regex_api_search.c \
+  regex_ipc.h
 libgnunetregex_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la
 libgnunetregex_la_LDFLAGS = \
diff --git a/src/regex/regex_api.c b/src/regex/regex_api.c
deleted file mode 100644 (file)
index c3be202..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
-     This file is part of GNUnet
-     Copyright (C) 2012, 2013 GNUnet e.V.
-
-     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., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
-*/
-/**
- * @file regex/regex_api.c
- * @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"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "regex-api",__VA_ARGS__)
-
-/**
- * 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.
- *
- * @param cfg configuration to use
- * @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 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_log (GNUNET_ERROR_TYPE_WARNING,
-                _("Regex `%s' is too long!\n"),
-                regex);
-    GNUNET_break (0);
-    return NULL;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Starting REGEX announcement %s\n",
-       regex);
-  a = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Announcement) + slen);
-  a->cfg = cfg;
-  a->client = GNUNET_CLIENT_connect ("regex", cfg);
-  if (NULL == a->client)
-  {
-    GNUNET_free (a);
-    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);
-  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 @e callback.
-   */
-  void *callback_cls;
-
-  /**
-   * Search message to transmit to the service.
-   */
-  struct RegexSearchMessage *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 handle reply for
- * @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;
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Got regex result %s\n",
-           GNUNET_i2s (pid));
-      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;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Starting regex search for %s\n",
-       string);
-  slen = strlen (string) + 1;
-  s = GNUNET_new (struct GNUNET_REGEX_Search);
-  s->cfg = cfg;
-  s->client = GNUNET_CLIENT_connect ("regex", cfg);
-  if (NULL == s->client)
-  {
-    GNUNET_free (s);
-    return NULL;
-  }
-  s->callback = callback;
-  s->callback_cls = callback_cls;
-  s->msg = GNUNET_malloc (sizeof (struct RegexSearchMessage) + slen);
-  s->msg->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH);
-  s->msg->header.size = htons (sizeof (struct RegexSearchMessage) + slen);
-  memcpy (&s->msg[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->msg);
-  GNUNET_free (s);
-}
-
-
-/* end of regex_api.c */
diff --git a/src/regex/regex_api_announce.c b/src/regex/regex_api_announce.c
new file mode 100644 (file)
index 0000000..8953436
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2012, 2013, 2016 GNUnet e.V.
+
+     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., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file regex/regex_api_announce.c
+ * @brief access regex service to advertise capabilities via regex
+ * @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"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "regex-api",__VA_ARGS__)
+
+/**
+ * Handle to store cached data about a regex announce.
+ */
+struct GNUNET_REGEX_Announcement
+{
+  /**
+   * Connection to the regex service.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Our configuration.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Message we're sending to the service.
+   */
+  char *regex;
+
+  /**
+   * Frequency of announcements.
+   */
+  struct GNUNET_TIME_Relative refresh_delay;
+
+  /**
+   * Number of characters per edge.
+   */
+  uint16_t compression;
+};
+
+
+
+/**
+ * (Re)connect to the REGEX service with the given announcement @a a.
+ *
+ * @param a REGEX to announce.
+ */
+static void
+announce_reconnect (struct GNUNET_REGEX_Announcement *a);
+
+
+/**
+ * We got a disconnect after asking regex to do the announcement.
+ * Retry.
+ *
+ * @param cls the `struct GNUNET_REGEX_Announcement` to retry
+ * @param error error code
+ */
+static void
+announce_mq_error_handler (void *cls,
+                           enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_REGEX_Announcement *a = cls;
+
+  GNUNET_MQ_destroy (a->mq);
+  a->mq = NULL;
+  announce_reconnect (a);
+}
+
+
+/**
+ * (Re)connect to the REGEX service with the given announcement @a a.
+ *
+ * @param a REGEX to announce.
+ */
+static void
+announce_reconnect (struct GNUNET_REGEX_Announcement *a)
+{
+  struct GNUNET_MQ_Envelope *env;
+  struct AnnounceMessage *am;
+  size_t slen;
+
+  a->mq = GNUNET_CLIENT_connecT (a->cfg,
+                                 "regex",
+                                 NULL,
+                                 &announce_mq_error_handler,
+                                 a);
+  if (NULL == a->mq)
+    return;
+  slen = strlen (a->regex) + 1;
+  env = GNUNET_MQ_msg_extra (am,
+                             slen,
+                             GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE);
+  am->compression = htons (a->compression);
+  am->reserved = htons (0);
+  am->refresh_delay = GNUNET_TIME_relative_hton (a->refresh_delay);
+  memcpy (&am[1],
+          a->regex,
+          slen);
+  GNUNET_MQ_send (a->mq,
+                  env);
+}
+
+
+/**
+ * Announce the given peer under the given regular expression.
+ *
+ * @param cfg configuration to use
+ * @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 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_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Regex `%s' is too long!\n"),
+                regex);
+    GNUNET_break (0);
+    return NULL;
+  }
+  a = GNUNET_new (struct GNUNET_REGEX_Announcement);
+  a->cfg = cfg;
+  a->refresh_delay = refresh_delay;
+  a->compression = compression;
+  a->regex = GNUNET_strdup (regex);
+  announce_reconnect (a);
+  if (NULL == a->mq)
+  {
+    GNUNET_free (a->regex);
+    GNUNET_free (a);
+    return NULL;
+  }
+  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_MQ_destroy (a->mq);
+  GNUNET_free (a->regex);
+  GNUNET_free (a);
+}
+
+/* end of regex_api_announce.c */
diff --git a/src/regex/regex_api_search.c b/src/regex/regex_api_search.c
new file mode 100644 (file)
index 0000000..728e12b
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2012, 2013, 2016 GNUnet e.V.
+
+     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., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file regex/regex_api_search.c
+ * @brief access regex service to discover
+ *        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"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "regex-api",__VA_ARGS__)
+
+
+/**
+ * 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 @e callback.
+   */
+  void *callback_cls;
+
+  /**
+   * Search message to transmit to the service.
+   */
+  struct RegexSearchMessage *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 handle reply for
+ * @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;
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Got regex result %s\n",
+           GNUNET_i2s (pid));
+      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;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Starting regex search for %s\n",
+       string);
+  slen = strlen (string) + 1;
+  s = GNUNET_new (struct GNUNET_REGEX_Search);
+  s->cfg = cfg;
+  s->client = GNUNET_CLIENT_connect ("regex", cfg);
+  if (NULL == s->client)
+  {
+    GNUNET_free (s);
+    return NULL;
+  }
+  s->callback = callback;
+  s->callback_cls = callback_cls;
+  s->msg = GNUNET_malloc (sizeof (struct RegexSearchMessage) + slen);
+  s->msg->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH);
+  s->msg->header.size = htons (sizeof (struct RegexSearchMessage) + slen);
+  memcpy (&s->msg[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->msg);
+  GNUNET_free (s);
+}
+
+
+/* end of regex_api.c */