GNUnet  0.10.x
gnunet-service-regex.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "regex_internal_lib.h"
30 #include "regex_ipc.h"
31 
32 
37 {
38 
43 
48 
53 
58 
63 
68 
69 };
70 
71 
75 static struct GNUNET_DHT_Handle *dht;
76 
81 
86 
87 
93 static void
94 cleanup_task (void *cls)
95 {
97  dht = NULL;
99  GNUNET_NO);
100  stats = NULL;
101  GNUNET_free (my_private_key);
102  my_private_key = NULL;
103 }
104 
105 
112 static void
113 reannounce (void *cls)
114 {
115  struct ClientEntry *ce = cls;
116 
119  &reannounce,
120  ce);
121 }
122 
123 
131 static int
132 check_announce (void *cls,
133  const struct AnnounceMessage *am)
134 {
135  struct ClientEntry *ce = cls;
136 
138  if (NULL != ce->ah)
139  {
140  /* only one announcement per client allowed */
141  GNUNET_break (0);
142  return GNUNET_SYSERR;
143  }
144  return GNUNET_OK;
145 }
146 
147 
154 static void
155 handle_announce (void *cls,
156  const struct AnnounceMessage *am)
157 {
158  struct ClientEntry *ce = cls;
159  const char *regex;
160 
161  regex = (const char *) &am[1];
164  &reannounce,
165  ce);
167  "Starting to announce regex `%s' every %s\n",
168  regex,
170  GNUNET_NO));
171  ce->ah = REGEX_INTERNAL_announce (dht,
172  my_private_key,
173  regex,
174  ntohs (am->compression),
175  stats);
176  if (NULL == ce->ah)
177  {
178  GNUNET_break (0);
180  ce->refresh_task = NULL;
182  return;
183  }
185 }
186 
187 
198 static void
200  const struct GNUNET_PeerIdentity *id,
201  const struct GNUNET_PeerIdentity *get_path,
202  unsigned int get_path_length,
203  const struct GNUNET_PeerIdentity *put_path,
204  unsigned int put_path_length)
205 {
206  struct ClientEntry *ce = cls;
207  struct GNUNET_MQ_Envelope *env;
208  struct ResultMessage *result;
209  struct GNUNET_PeerIdentity *gp;
210  uint16_t size;
211 
212  if ( (get_path_length >= 65536) ||
213  (put_path_length >= 65536) ||
214  ( (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity))
215  + sizeof (struct ResultMessage) >= GNUNET_MAX_MESSAGE_SIZE)
216  {
217  GNUNET_break (0);
218  return;
219  }
220  size = (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity);
221  env = GNUNET_MQ_msg_extra (result,
222  size,
224  result->get_path_length = htons ((uint16_t) get_path_length);
225  result->put_path_length = htons ((uint16_t) put_path_length);
226  result->id = *id;
227  gp = &result->id;
228  GNUNET_memcpy (&gp[1],
229  get_path,
230  get_path_length * sizeof (struct GNUNET_PeerIdentity));
231  GNUNET_memcpy (&gp[1 + get_path_length],
232  put_path,
233  put_path_length * sizeof (struct GNUNET_PeerIdentity));
234  GNUNET_MQ_send (ce->mq,
235  env);
236 }
237 
238 
245 static int
246 check_search (void *cls,
247  const struct RegexSearchMessage *sm)
248 {
249  struct ClientEntry *ce = cls;
250  const char *string;
251  uint16_t size;
252 
253  size = ntohs (sm->header.size) - sizeof (*sm);
254  string = (const char *) &sm[1];
255  if ('\0' != string[size - 1])
256  {
257  GNUNET_break (0);
258  return GNUNET_SYSERR;
259  }
260  if (NULL != ce->sh)
261  {
262  /* only one search allowed per client */
263  GNUNET_break (0);
264  return GNUNET_SYSERR;
265  }
266  return GNUNET_OK;
267 }
268 
269 
276 static void
277 handle_search (void *cls,
278  const struct RegexSearchMessage *sm)
279 {
280  struct ClientEntry *ce = cls;
281  const char *string;
282 
283  string = (const char *) &sm[1];
285  "Starting to search for `%s'\n",
286  string);
287  ce->sh = REGEX_INTERNAL_search (dht,
288  string,
290  ce,
291  stats);
292  if (NULL == ce->sh)
293  {
294  GNUNET_break (0);
296  return;
297  }
299 }
300 
301 
309 static void
310 run (void *cls,
311  const struct GNUNET_CONFIGURATION_Handle *cfg,
313 {
315  if (NULL == my_private_key)
316  {
318  return;
319  }
320  dht = GNUNET_DHT_connect (cfg, 1024);
321  if (NULL == dht)
322  {
323  GNUNET_free (my_private_key);
324  my_private_key = NULL;
326  return;
327  }
329  NULL);
330  stats = GNUNET_STATISTICS_create ("regex", cfg);
331 }
332 
333 
342 static void *
343 client_connect_cb (void *cls,
344  struct GNUNET_SERVICE_Client *c,
345  struct GNUNET_MQ_Handle *mq)
346 {
347  struct ClientEntry *ce;
348 
349  ce = GNUNET_new (struct ClientEntry);
350  ce->client = c;
351  ce->mq = mq;
352  return ce;
353 }
354 
355 
363 static void
365  struct GNUNET_SERVICE_Client *c,
366  void *internal_cls)
367 {
368  struct ClientEntry *ce = internal_cls;
369 
370  if (NULL != ce->refresh_task)
371  {
373  ce->refresh_task = NULL;
374  }
375  if (NULL != ce->ah)
376  {
378  ce->ah = NULL;
379  }
380  if (NULL != ce->sh)
381  {
383  ce->sh = NULL;
384  }
385  GNUNET_free (ce);
386 }
387 
388 
393 ("regex",
395  &run,
398  NULL,
399  GNUNET_MQ_hd_var_size (announce,
401  struct AnnounceMessage,
402  NULL),
403  GNUNET_MQ_hd_var_size (search,
405  struct RegexSearchMessage,
406  NULL),
408 
409 
410 /* end of gnunet-service-regex.c */
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
uint16_t compression
How many characters can we squeeze per edge?
Definition: regex_ipc.h:45
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
Message to initiate regex search.
Definition: regex_ipc.h:64
static void handle_announce(void *cls, const struct AnnounceMessage *am)
Handle ANNOUNCE message.
Handle to a service.
Definition: service.c:116
#define GNUNET_MESSAGE_TYPE_REGEX_SEARCH
Search for peer with matching capability.
Result from regex search.
Definition: regex_ipc.h:79
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
static void handle_search_result(void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length)
Handle result, pass it back to the client.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_REGEX_SEARCH.
Definition: regex_ipc.h:69
#define GNUNET_NO
Definition: gnunet_common.h:81
void REGEX_INTERNAL_announce_cancel(struct REGEX_INTERNAL_Announcement *h)
Clear all cached data used by a regex announce.
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
struct REGEX_INTERNAL_Announcement * ah
Announcement handle (if this client is announcing).
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_TIME_Relative frequency
Refresh frequency for announcements.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
Handle for the service.
struct REGEX_INTERNAL_Search * sh
Search handle (if this client is searching).
struct GNUNET_SERVICE_Client * client
Handle identifying the client.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_MESSAGE_TYPE_REGEX_RESULT
Result in response to regex search.
Connection to the DHT service.
Definition: dht_api.c:205
Handle to a client that is connected to a service.
Definition: service.c:249
static void handle_search(void *cls, const struct RegexSearchMessage *sm)
Handle SEARCH message.
regex IPC messages (not called &#39;regex.h&#39; due to conflict with system headers)
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
GNUNET_SERVICE_MAIN("regex", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(announce, GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE, struct AnnounceMessage, NULL), GNUNET_MQ_hd_var_size(search, GNUNET_MESSAGE_TYPE_REGEX_SEARCH, struct RegexSearchMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
uint16_t put_path_length
Number of entries in the PUT path.
Definition: regex_ipc.h:94
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
Request for regex service to announce capability.
Definition: regex_ipc.h:34
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_memcpy(dst, src, n)
library to parse regular expressions into dfa
Information about one of our clients.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
static void reannounce(void *cls)
Periodic task to refresh our announcement of the regex.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:727
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
static struct GNUNET_STATISTICS_Handle * stats
Handle for doing statistics.
struct GNUNET_SCHEDULER_Task * refresh_task
Task for re-announcing.
static int result
Global testing status.
Handle to store cached data about a regex announce.
void REGEX_INTERNAL_search_cancel(struct REGEX_INTERNAL_Search *h)
Cancel an ongoing regex search in the DHT and free all resources.
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
Private key for this peer.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition: time.c:638
static int check_announce(void *cls, const struct AnnounceMessage *am)
Check ANNOUNCE message.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2618
static struct GNUNET_DHT_Handle * dht
Connection to the DHT.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct REGEX_INTERNAL_Search * REGEX_INTERNAL_search(struct GNUNET_DHT_Handle *dht, const char *string, REGEX_INTERNAL_Found callback, void *callback_cls, struct GNUNET_STATISTICS_Handle *stats)
Search for a peer offering a regex matching certain string in the DHT.
struct GNUNET_DHT_Handle * GNUNET_DHT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len)
Initialize the connection with the DHT service.
Definition: dht_api.c:895
struct REGEX_INTERNAL_Announcement * REGEX_INTERNAL_announce(struct GNUNET_DHT_Handle *dht, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const char *regex, uint16_t compression, struct GNUNET_STATISTICS_Handle *stats)
Announce a regular expression: put all states of the automaton in the DHT.
struct GNUNET_MQ_Handle * mq
Queue for transmissions to client.
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition: dht_api.c:923
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static int check_search(void *cls, const struct RegexSearchMessage *sm)
Check SEARCH message.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
Struct to keep information of searches of services described by a regex using a user-provided string ...
void REGEX_INTERNAL_reannounce(struct REGEX_INTERNAL_Announcement *h)
Announce again a regular expression previously announced.
struct GNUNET_PeerIdentity id
Identity of the peer that was found.
Definition: regex_ipc.h:99
Handle to a message queue.
Definition: mq.c:85
Private ECC key encoded for transmission.
static void cleanup_task(void *cls)
Task run during shutdown.
The identity of the host (wraps the signing key of the peer).
#define GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE
Advertise regex capability.
configuration data
Definition: configuration.c:85
uint16_t get_path_length
Number of entries in the GET path.
Definition: regex_ipc.h:89
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer&#39;s key from the file specified in the configuration...
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2533
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
struct GNUNET_TIME_RelativeNBO refresh_delay
Delay between repeated announcements.
Definition: regex_ipc.h:55
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
Process regex requests.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965