GNUnet  0.11.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 {
42 
47 
52 
57 
62 
67 };
68 
69 
73 static struct GNUNET_DHT_Handle *dht;
74 
79 
84 
85 
91 static void
92 cleanup_task (void *cls)
93 {
95  dht = NULL;
97  GNUNET_NO);
98  stats = NULL;
100  my_private_key = NULL;
101 }
102 
103 
110 static void
111 reannounce (void *cls)
112 {
113  struct ClientEntry *ce = cls;
114 
117  &reannounce,
118  ce);
119 }
120 
121 
129 static int
130 check_announce (void *cls,
131  const struct AnnounceMessage *am)
132 {
133  struct ClientEntry *ce = cls;
134 
136  if (NULL != ce->ah)
137  {
138  /* only one announcement per client allowed */
139  GNUNET_break (0);
140  return GNUNET_SYSERR;
141  }
142  return GNUNET_OK;
143 }
144 
145 
152 static void
153 handle_announce (void *cls,
154  const struct AnnounceMessage *am)
155 {
156  struct ClientEntry *ce = cls;
157  const char *regex;
158 
159  regex = (const char *) &am[1];
162  &reannounce,
163  ce);
165  "Starting to announce regex `%s' every %s\n",
166  regex,
168  GNUNET_NO));
171  regex,
172  ntohs (am->compression),
173  stats);
174  if (NULL == ce->ah)
175  {
176  GNUNET_break (0);
178  ce->refresh_task = NULL;
180  return;
181  }
183 }
184 
185 
196 static void
198  const struct GNUNET_PeerIdentity *id,
199  const struct GNUNET_PeerIdentity *get_path,
200  unsigned int get_path_length,
201  const struct GNUNET_PeerIdentity *put_path,
202  unsigned int put_path_length)
203 {
204  struct ClientEntry *ce = cls;
205  struct GNUNET_MQ_Envelope *env;
206  struct ResultMessage *result;
207  struct GNUNET_PeerIdentity *gp;
208  uint16_t size;
209 
210  if ((get_path_length >= 65536) ||
211  (put_path_length >= 65536) ||
212  ( ((get_path_length + put_path_length) * sizeof(struct
214  + sizeof(struct ResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) )
215  {
216  GNUNET_break (0);
217  return;
218  }
219  size = (get_path_length + put_path_length) * sizeof(struct
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);
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  {
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 */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
static int result
Global testing status.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_DHT_Handle * dht
Connection to the DHT.
static int check_announce(void *cls, const struct AnnounceMessage *am)
Check ANNOUNCE message.
static void handle_announce(void *cls, const struct AnnounceMessage *am)
Handle ANNOUNCE message.
static void handle_search(void *cls, const struct RegexSearchMessage *sm)
Handle SEARCH message.
static struct GNUNET_STATISTICS_Handle * stats
Handle for doing statistics.
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 void cleanup_task(void *cls)
Task run during shutdown.
static int check_search(void *cls, const struct RegexSearchMessage *sm)
Check SEARCH message.
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.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
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.
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
Private key for this peer.
static void reannounce(void *cls)
Periodic task to refresh our announcement of the regex.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
Process regex requests.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
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's key from the file specified in the configuration.
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:890
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition: dht_api.c:918
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
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:355
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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_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
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE
Advertise regex capability.
#define GNUNET_MESSAGE_TYPE_REGEX_SEARCH
Search for peer with matching capability.
#define GNUNET_MESSAGE_TYPE_REGEX_RESULT
Result in response to regex search.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
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,...
Definition: scheduler.c:1331
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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:1269
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2325
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2244
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition: time.c:454
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:557
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.
void REGEX_INTERNAL_search_cancel(struct REGEX_INTERNAL_Search *h)
Cancel an ongoing regex search in the DHT and free all resources.
void REGEX_INTERNAL_announce_cancel(struct REGEX_INTERNAL_Announcement *h)
Clear all cached data used by a regex announce.
void REGEX_INTERNAL_reannounce(struct REGEX_INTERNAL_Announcement *h)
Announce again a regular expression previously announced.
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.
library to parse regular expressions into dfa
regex IPC messages (not called 'regex.h' due to conflict with system headers)
Request for regex service to announce capability.
Definition: regex_ipc.h:35
struct GNUNET_TIME_RelativeNBO refresh_delay
Delay between repeated announcements.
Definition: regex_ipc.h:54
uint16_t compression
How many characters can we squeeze per edge?
Definition: regex_ipc.h:44
Information about one of our clients.
struct GNUNET_SERVICE_Client * client
Handle identifying the client.
struct REGEX_INTERNAL_Announcement * ah
Announcement handle (if this client is announcing).
struct GNUNET_TIME_Relative frequency
Refresh frequency for announcements.
struct REGEX_INTERNAL_Search * sh
Search handle (if this client is searching).
struct GNUNET_MQ_Handle * mq
Queue for transmissions to client.
struct GNUNET_SCHEDULER_Task * refresh_task
Task for re-announcing.
Private ECC key encoded for transmission.
Connection to the DHT service.
Definition: dht_api.c:202
Handle to a message queue.
Definition: mq.c:86
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:135
Handle to a client that is connected to a service.
Definition: service.c:251
Handle to a service.
Definition: service.c:117
Handle for the service.
Time for relative time used by GNUnet, in microseconds.
Handle to store cached data about a regex announce.
Struct to keep information of searches of services described by a regex using a user-provided string ...
Message to initiate regex search.
Definition: regex_ipc.h:64
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_REGEX_SEARCH.
Definition: regex_ipc.h:68
Result from regex search.
Definition: regex_ipc.h:78