2 This file is part of GNUnet
3 Copyright (C) 2012, 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file regex/regex_api.c
22 * @brief access regex service to advertise capabilities via regex and discover
23 * respective peers using matching strings
24 * @author Maximilian Szengel
25 * @author Christian Grothoff
28 #include "gnunet_protocols.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_regex_service.h"
31 #include "regex_ipc.h"
33 #define LOG(kind,...) GNUNET_log_from (kind, "regex-api",__VA_ARGS__)
36 * Handle to store cached data about a regex announce.
38 struct GNUNET_REGEX_Announcement
41 * Connection to the regex service.
43 struct GNUNET_CLIENT_Connection *client;
48 const struct GNUNET_CONFIGURATION_Handle *cfg;
51 * Message we're sending to the service.
53 struct AnnounceMessage msg;
58 * We got a response (!?) or disconnect after asking regex
59 * to do the announcement. Retry.
61 * @param cls the 'struct GNUNET_REGEX_Announcement' to retry
62 * @param msg NULL on disconnect
65 handle_a_reconnect (void *cls,
66 const struct GNUNET_MessageHeader *msg);
70 * Try sending the announcement request to regex. On
71 * errors (i.e. regex died), try again.
73 * @param a the announcement to retry
76 retry_announcement (struct GNUNET_REGEX_Announcement *a)
78 GNUNET_assert (NULL != a->client);
79 GNUNET_assert (GNUNET_OK ==
80 GNUNET_CLIENT_transmit_and_get_response (a->client,
82 GNUNET_TIME_UNIT_FOREVER_REL,
90 * We got a response (!?) or disconnect after asking regex
91 * to do the announcement. Retry.
93 * @param cls the 'struct GNUNET_REGEX_Announcement' to retry
94 * @param msg NULL on disconnect
97 handle_a_reconnect (void *cls,
98 const struct GNUNET_MessageHeader *msg)
100 struct GNUNET_REGEX_Announcement *a = cls;
102 GNUNET_CLIENT_disconnect (a->client);
103 a->client = GNUNET_CLIENT_connect ("regex", a->cfg);
104 retry_announcement (a);
109 * Announce the given peer under the given regular expression.
111 * @param cfg configuration to use
112 * @param regex Regular expression to announce.
113 * @param refresh_delay after what delay should the announcement be repeated?
114 * @param compression How many characters per edge can we squeeze?
115 * @return Handle to reuse o free cached resources.
116 * Must be freed by calling #GNUNET_REGEX_announce_cancel().
118 struct GNUNET_REGEX_Announcement *
119 GNUNET_REGEX_announce (const struct GNUNET_CONFIGURATION_Handle *cfg,
121 struct GNUNET_TIME_Relative refresh_delay,
122 uint16_t compression)
124 struct GNUNET_REGEX_Announcement *a;
127 slen = strlen (regex) + 1;
128 if (slen + sizeof (struct AnnounceMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
130 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
131 _("Regex `%s' is too long!\n"),
136 LOG (GNUNET_ERROR_TYPE_DEBUG,
137 "Starting REGEX announcement %s\n",
139 a = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Announcement) + slen);
141 a->client = GNUNET_CLIENT_connect ("regex", cfg);
142 if (NULL == a->client)
147 a->msg.header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE);
148 a->msg.header.size = htons (slen + sizeof (struct AnnounceMessage));
149 a->msg.compression = htons (compression);
150 a->msg.reserved = htons (0);
151 a->msg.refresh_delay = GNUNET_TIME_relative_hton (refresh_delay);
152 memcpy (&a[1], regex, slen);
153 retry_announcement (a);
159 * Stop announcing the regex specified by the given handle.
161 * @param a handle returned by a previous GNUNET_REGEX_announce call.
164 GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_Announcement *a)
166 GNUNET_CLIENT_disconnect (a->client);
172 * Handle to store data about a regex search.
174 struct GNUNET_REGEX_Search
177 * Connection to the regex service.
179 struct GNUNET_CLIENT_Connection *client;
184 const struct GNUNET_CONFIGURATION_Handle *cfg;
187 * Function to call with results.
189 GNUNET_REGEX_Found callback;
192 * Closure for @e callback.
197 * Search message to transmit to the service.
199 struct RegexSearchMessage *msg;
204 * We got a response or disconnect after asking regex
205 * to do the search. Handle it.
207 * @param cls the `struct GNUNET_REGEX_Search` to retry
208 * @param msg NULL on disconnect
211 handle_search_response (void *cls,
212 const struct GNUNET_MessageHeader *msg);
216 * Try sending the search request to regex. On
217 * errors (i.e. regex died), try again.
219 * @param s the search to retry
222 retry_search (struct GNUNET_REGEX_Search *s)
224 GNUNET_assert (NULL != s->client);
225 GNUNET_assert (GNUNET_OK ==
226 GNUNET_CLIENT_transmit_and_get_response (s->client,
228 GNUNET_TIME_UNIT_FOREVER_REL,
230 &handle_search_response,
236 * We got a response or disconnect after asking regex
237 * to do the search. Handle it.
239 * @param cls the `struct GNUNET_REGEX_Search` to handle reply for
240 * @param msg NULL on disconnect, otherwise presumably a response
243 handle_search_response (void *cls,
244 const struct GNUNET_MessageHeader *msg)
246 struct GNUNET_REGEX_Search *s = cls;
247 const struct ResultMessage *result;
254 GNUNET_CLIENT_disconnect (s->client);
255 s->client = GNUNET_CLIENT_connect ("regex", s->cfg);
259 size = ntohs (msg->size);
260 if ( (GNUNET_MESSAGE_TYPE_REGEX_RESULT == ntohs (msg->type)) &&
261 (size >= sizeof (struct ResultMessage)) )
263 result = (const struct ResultMessage *) msg;
264 gpl = ntohs (result->get_path_length);
265 ppl = ntohs (result->put_path_length);
266 if (size == (sizeof (struct ResultMessage) +
267 (gpl + ppl) * sizeof (struct GNUNET_PeerIdentity)))
269 const struct GNUNET_PeerIdentity *pid;
271 GNUNET_CLIENT_receive (s->client,
272 &handle_search_response, s,
273 GNUNET_TIME_UNIT_FOREVER_REL);
275 LOG (GNUNET_ERROR_TYPE_DEBUG,
276 "Got regex result %s\n",
278 s->callback (s->callback_cls,
282 LOG (GNUNET_ERROR_TYPE_DEBUG,
283 "Returned from regex CB\n",
289 GNUNET_CLIENT_disconnect (s->client);
290 s->client = GNUNET_CLIENT_connect ("regex", s->cfg);
296 * Search for a peer offering a regex matching certain string in the DHT.
297 * The search runs until #GNUNET_REGEX_search_cancel() is called, even if results
300 * @param cfg configuration to use
301 * @param string String to match against the regexes in the DHT.
302 * @param callback Callback for found peers.
303 * @param callback_cls Closure for @c callback.
304 * @return Handle to stop search and free resources.
305 * Must be freed by calling #GNUNET_REGEX_search_cancel().
307 struct GNUNET_REGEX_Search *
308 GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg,
310 GNUNET_REGEX_Found callback,
313 struct GNUNET_REGEX_Search *s;
316 LOG (GNUNET_ERROR_TYPE_DEBUG,
317 "Starting regex search for %s\n",
319 slen = strlen (string) + 1;
320 s = GNUNET_new (struct GNUNET_REGEX_Search);
322 s->client = GNUNET_CLIENT_connect ("regex", cfg);
323 if (NULL == s->client)
328 s->callback = callback;
329 s->callback_cls = callback_cls;
330 s->msg = GNUNET_malloc (sizeof (struct RegexSearchMessage) + slen);
331 s->msg->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH);
332 s->msg->header.size = htons (sizeof (struct RegexSearchMessage) + slen);
333 memcpy (&s->msg[1], string, slen);
340 * Stop search and free all data used by a #GNUNET_REGEX_search() call.
342 * @param s Handle returned by a previous #GNUNET_REGEX_search() call.
345 GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s)
347 GNUNET_CLIENT_disconnect (s->client);
348 GNUNET_free (s->msg);
353 /* end of regex_api.c */