aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/regex/gnunet-service-regex.c321
1 files changed, 163 insertions, 158 deletions
diff --git a/src/regex/gnunet-service-regex.c b/src/regex/gnunet-service-regex.c
index 294670be6..e763bf08d 100644
--- a/src/regex/gnunet-service-regex.c
+++ b/src/regex/gnunet-service-regex.c
@@ -37,19 +37,14 @@ struct ClientEntry
37{ 37{
38 38
39 /** 39 /**
40 * Kept in DLL. 40 * Queue for transmissions to @e client.
41 */ 41 */
42 struct ClientEntry *next; 42 struct GNUNET_MQ_Handle *mq;
43
44 /**
45 * Kept in DLL.
46 */
47 struct ClientEntry *prev;
48 43
49 /** 44 /**
50 * Handle identifying the client. 45 * Handle identifying the client.
51 */ 46 */
52 struct GNUNET_SERVER_Client *client; 47 struct GNUNET_SERVICE_Client *client;
53 48
54 /** 49 /**
55 * Search handle (if this client is searching). 50 * Search handle (if this client is searching).
@@ -69,7 +64,7 @@ struct ClientEntry
69 /** 64 /**
70 * Task for re-announcing. 65 * Task for re-announcing.
71 */ 66 */
72 struct GNUNET_SCHEDULER_Task * refresh_task; 67 struct GNUNET_SCHEDULER_Task *refresh_task;
73 68
74}; 69};
75 70
@@ -85,70 +80,12 @@ static struct GNUNET_DHT_Handle *dht;
85static struct GNUNET_STATISTICS_Handle *stats; 80static struct GNUNET_STATISTICS_Handle *stats;
86 81
87/** 82/**
88 * Head of list of clients.
89 */
90static struct ClientEntry *client_head;
91
92/**
93 * End of list of clients.
94 */
95static struct ClientEntry *client_tail;
96
97/**
98 * Our notification context, used to send back results to the client.
99 */
100static struct GNUNET_SERVER_NotificationContext *nc;
101
102/**
103 * Private key for this peer. 83 * Private key for this peer.
104 */ 84 */
105static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; 85static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
106 86
107 87
108/** 88/**
109 * A client disconnected. Remove all of its data structure entries.
110 *
111 * @param cls closure, NULL
112 * @param client identification of the client
113 */
114static void
115handle_client_disconnect (void *cls,
116 struct GNUNET_SERVER_Client *client)
117{
118 struct ClientEntry *ce;
119 struct ClientEntry *nx;
120
121 nx = client_head;
122 for (ce = nx; NULL != ce; ce = nx)
123 {
124 nx = ce->next;
125 if (ce->client == client)
126 {
127 if (NULL != ce->refresh_task)
128 {
129 GNUNET_SCHEDULER_cancel (ce->refresh_task);
130 ce->refresh_task = NULL;
131 }
132 if (NULL != ce->ah)
133 {
134 REGEX_INTERNAL_announce_cancel (ce->ah);
135 ce->ah = NULL;
136 }
137 if (NULL != ce->sh)
138 {
139 REGEX_INTERNAL_search_cancel (ce->sh);
140 ce->sh = NULL;
141 }
142 GNUNET_CONTAINER_DLL_remove (client_head,
143 client_tail,
144 ce);
145 GNUNET_free (ce);
146 }
147 }
148}
149
150
151/**
152 * Task run during shutdown. 89 * Task run during shutdown.
153 * 90 *
154 * @param cls unused 91 * @param cls unused
@@ -156,17 +93,11 @@ handle_client_disconnect (void *cls,
156static void 93static void
157cleanup_task (void *cls) 94cleanup_task (void *cls)
158{ 95{
159 struct ClientEntry *ce;
160
161 while (NULL != (ce = client_head))
162 handle_client_disconnect (NULL,
163 ce->client);
164 GNUNET_DHT_disconnect (dht); 96 GNUNET_DHT_disconnect (dht);
165 dht = NULL; 97 dht = NULL;
166 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 98 GNUNET_STATISTICS_destroy (stats,
99 GNUNET_NO);
167 stats = NULL; 100 stats = NULL;
168 GNUNET_SERVER_notification_context_destroy (nc);
169 nc = NULL;
170 GNUNET_free (my_private_key); 101 GNUNET_free (my_private_key);
171 my_private_key = NULL; 102 my_private_key = NULL;
172} 103}
@@ -191,35 +122,51 @@ reannounce (void *cls)
191 122
192 123
193/** 124/**
194 * Handle ANNOUNCE message. 125 * Check ANNOUNCE message.
195 * 126 *
196 * @param cls closure 127 * @param cls identification of the client
197 * @param client identification of the client 128 * @param am the actual message
198 * @param message the actual message 129 * @return #GNUNET_OK if @am is well-formed
199 */ 130 */
200static void 131static int
201handle_announce (void *cls, 132check_announce (void *cls,
202 struct GNUNET_SERVER_Client *client, 133 const struct AnnounceMessage *am)
203 const struct GNUNET_MessageHeader *message)
204{ 134{
205 const struct AnnounceMessage *am; 135 struct ClientEntry *ce = cls;
206 const char *regex; 136 const char *regex;
207 struct ClientEntry *ce;
208 uint16_t size; 137 uint16_t size;
209 138
210 size = ntohs (message->size); 139 size = ntohs (am->header.size) - sizeof (*am);
211 am = (const struct AnnounceMessage *) message;
212 regex = (const char *) &am[1]; 140 regex = (const char *) &am[1];
213 if ( (size <= sizeof (struct AnnounceMessage)) || 141 if ('\0' != regex[size - 1])
214 ('\0' != regex[size - sizeof (struct AnnounceMessage) - 1]) )
215 { 142 {
216 GNUNET_break (0); 143 GNUNET_break (0);
217 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 144 return GNUNET_SYSERR;
218 return; 145 }
146 if (NULL != ce->ah)
147 {
148 /* only one announcement per client allowed */
149 GNUNET_break (0);
150 return GNUNET_SYSERR;
219 } 151 }
152 return GNUNET_OK;
153}
220 154
221 ce = GNUNET_new (struct ClientEntry); 155
222 ce->client = client; 156/**
157 * Handle ANNOUNCE message.
158 *
159 * @param cls identification of the client
160 * @param am the actual message
161 */
162static void
163handle_announce (void *cls,
164 const struct AnnounceMessage *am)
165{
166 struct ClientEntry *ce = cls;
167 const char *regex;
168
169 regex = (const char *) &am[1];
223 ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay); 170 ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay);
224 ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency, 171 ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency,
225 &reannounce, 172 &reannounce,
@@ -238,14 +185,11 @@ handle_announce (void *cls,
238 { 185 {
239 GNUNET_break (0); 186 GNUNET_break (0);
240 GNUNET_SCHEDULER_cancel (ce->refresh_task); 187 GNUNET_SCHEDULER_cancel (ce->refresh_task);
241 GNUNET_free (ce); 188 ce->refresh_task = NULL;
242 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 189 GNUNET_SERVICE_client_drop (ce->client);
243 return; 190 return;
244 } 191 }
245 GNUNET_CONTAINER_DLL_insert (client_head, 192 GNUNET_SERVICE_client_continue (ce->client);
246 client_tail,
247 ce);
248 GNUNET_SERVER_receive_done (client, GNUNET_OK);
249} 193}
250 194
251 195
@@ -268,6 +212,7 @@ handle_search_result (void *cls,
268 unsigned int put_path_length) 212 unsigned int put_path_length)
269{ 213{
270 struct ClientEntry *ce = cls; 214 struct ClientEntry *ce = cls;
215 struct GNUNET_MQ_Envelope *env;
271 struct ResultMessage *result; 216 struct ResultMessage *result;
272 struct GNUNET_PeerIdentity *gp; 217 struct GNUNET_PeerIdentity *gp;
273 uint16_t size; 218 uint16_t size;
@@ -280,59 +225,73 @@ handle_search_result (void *cls,
280 GNUNET_break (0); 225 GNUNET_break (0);
281 return; 226 return;
282 } 227 }
283 size = (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity) + sizeof (struct ResultMessage); 228 size = (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity);
284 result = GNUNET_malloc (size); 229 env = GNUNET_MQ_msg_extra (result,
285 result->header.size = htons (size); 230 size,
286 result->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_RESULT); 231 GNUNET_MESSAGE_TYPE_REGEX_RESULT);
287 result->get_path_length = htons ((uint16_t) get_path_length); 232 result->get_path_length = htons ((uint16_t) get_path_length);
288 result->put_path_length = htons ((uint16_t) put_path_length); 233 result->put_path_length = htons ((uint16_t) put_path_length);
289 result->id = *id; 234 result->id = *id;
290 gp = &result->id; 235 gp = &result->id;
291 GNUNET_memcpy (&gp[1], 236 GNUNET_memcpy (&gp[1],
292 get_path, 237 get_path,
293 get_path_length * sizeof (struct GNUNET_PeerIdentity)); 238 get_path_length * sizeof (struct GNUNET_PeerIdentity));
294 GNUNET_memcpy (&gp[1 + get_path_length], 239 GNUNET_memcpy (&gp[1 + get_path_length],
295 put_path, 240 put_path,
296 put_path_length * sizeof (struct GNUNET_PeerIdentity)); 241 put_path_length * sizeof (struct GNUNET_PeerIdentity));
297 GNUNET_SERVER_notification_context_unicast (nc, 242 GNUNET_MQ_send (ce->mq,
298 ce->client, 243 env);
299 &result->header, GNUNET_NO);
300 GNUNET_free (result);
301} 244}
302 245
303 246
304/** 247/**
305 * Handle SEARCH message. 248 * Check SEARCH message.
306 * 249 *
307 * @param cls closure 250 * @param cls identification of the client
308 * @param client identification of the client
309 * @param message the actual message 251 * @param message the actual message
310 */ 252 */
311static void 253static int
312handle_search (void *cls, 254check_search (void *cls,
313 struct GNUNET_SERVER_Client *client, 255 const struct RegexSearchMessage *sm)
314 const struct GNUNET_MessageHeader *message)
315{ 256{
316 const struct RegexSearchMessage *sm; 257 struct ClientEntry *ce = cls;
317 const char *string; 258 const char *string;
318 struct ClientEntry *ce;
319 uint16_t size; 259 uint16_t size;
320 260
321 size = ntohs (message->size); 261 size = ntohs (sm->header.size) - sizeof (*sm);
322 sm = (const struct RegexSearchMessage *) message;
323 string = (const char *) &sm[1]; 262 string = (const char *) &sm[1];
324 if ( (size <= sizeof (struct RegexSearchMessage)) || 263 if ('\0' != string[size - 1])
325 ('\0' != string[size - sizeof (struct RegexSearchMessage) - 1]) )
326 { 264 {
327 GNUNET_break (0); 265 GNUNET_break (0);
328 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 266 return GNUNET_SYSERR;
329 return;
330 } 267 }
268 if (NULL != ce->sh)
269 {
270 /* only one search allowed per client */
271 GNUNET_break (0);
272 return GNUNET_SYSERR;
273 }
274 return GNUNET_OK;
275}
276
277
278/**
279 * Handle SEARCH message.
280 *
281 * @param cls identification of the client
282 * @param message the actual message
283 */
284static void
285handle_search (void *cls,
286 const struct RegexSearchMessage *sm)
287{
288 struct ClientEntry *ce = cls;
289 const char *string;
290
291 string = (const char *) &sm[1];
331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
332 "Starting to search for `%s'\n", 293 "Starting to search for `%s'\n",
333 string); 294 string);
334 ce = GNUNET_new (struct ClientEntry);
335 ce->client = client;
336 ce->sh = REGEX_INTERNAL_search (dht, 295 ce->sh = REGEX_INTERNAL_search (dht,
337 string, 296 string,
338 &handle_search_result, 297 &handle_search_result,
@@ -341,15 +300,10 @@ handle_search (void *cls,
341 if (NULL == ce->sh) 300 if (NULL == ce->sh)
342 { 301 {
343 GNUNET_break (0); 302 GNUNET_break (0);
344 GNUNET_free (ce); 303 GNUNET_SERVICE_client_drop (ce->client);
345 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
346 return; 304 return;
347 } 305 }
348 GNUNET_CONTAINER_DLL_insert (client_head, 306 GNUNET_SERVICE_client_continue (ce->client);
349 client_tail,
350 ce);
351 GNUNET_SERVER_notification_context_add (nc, client);
352 GNUNET_SERVER_receive_done (client, GNUNET_OK);
353} 307}
354 308
355 309
@@ -357,19 +311,14 @@ handle_search (void *cls,
357 * Process regex requests. 311 * Process regex requests.
358 * 312 *
359 * @param cls closure 313 * @param cls closure
360 * @param server the initialized server
361 * @param cfg configuration to use 314 * @param cfg configuration to use
315 * @param service the initialized service
362 */ 316 */
363static void 317static void
364run (void *cls, struct GNUNET_SERVER_Handle *server, 318run (void *cls,
365 const struct GNUNET_CONFIGURATION_Handle *cfg) 319 const struct GNUNET_CONFIGURATION_Handle *cfg,
320 struct GNUNET_SERVICE_Handle *service)
366{ 321{
367 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
368 {&handle_announce, NULL, GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE, 0},
369 {&handle_search, NULL, GNUNET_MESSAGE_TYPE_REGEX_SEARCH, 0},
370 {NULL, NULL, 0, 0}
371 };
372
373 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); 322 my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
374 if (NULL == my_private_key) 323 if (NULL == my_private_key)
375 { 324 {
@@ -386,28 +335,84 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
386 } 335 }
387 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, 336 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
388 NULL); 337 NULL);
389 nc = GNUNET_SERVER_notification_context_create (server, 1);
390 stats = GNUNET_STATISTICS_create ("regex", cfg); 338 stats = GNUNET_STATISTICS_create ("regex", cfg);
391 GNUNET_SERVER_add_handlers (server, handlers);
392 GNUNET_SERVER_disconnect_notify (server,
393 &handle_client_disconnect,
394 NULL);
395} 339}
396 340
397 341
398/** 342/**
399 * The main function for the regex service. 343 * Callback called when a client connects to the service.
400 * 344 *
401 * @param argc number of arguments from the command line 345 * @param cls closure for the service
402 * @param argv command line arguments 346 * @param c the new client that connected to the service
403 * @return 0 ok, 1 on error 347 * @param mq the message queue used to send messages to the client
348 * @return @a c
404 */ 349 */
405int 350static void *
406main (int argc, char *const *argv) 351client_connect_cb (void *cls,
352 struct GNUNET_SERVICE_Client *c,
353 struct GNUNET_MQ_Handle *mq)
407{ 354{
408 return (GNUNET_OK == 355 struct ClientEntry *ce;
409 GNUNET_SERVICE_run (argc, argv, "regex", 356
410 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; 357 ce = GNUNET_new (struct ClientEntry);
358 ce->client = c;
359 ce->mq = mq;
360 return ce;
411} 361}
412 362
363
364/**
365 * Callback called when a client disconnected from the service
366 *
367 * @param cls closure for the service
368 * @param c the client that disconnected
369 * @param internal_cls should be equal to @a c
370 */
371static void
372client_disconnect_cb (void *cls,
373 struct GNUNET_SERVICE_Client *c,
374 void *internal_cls)
375{
376 struct ClientEntry *ce = internal_cls;
377
378 if (NULL != ce->refresh_task)
379 {
380 GNUNET_SCHEDULER_cancel (ce->refresh_task);
381 ce->refresh_task = NULL;
382 }
383 if (NULL != ce->ah)
384 {
385 REGEX_INTERNAL_announce_cancel (ce->ah);
386 ce->ah = NULL;
387 }
388 if (NULL != ce->sh)
389 {
390 REGEX_INTERNAL_search_cancel (ce->sh);
391 ce->sh = NULL;
392 }
393 GNUNET_free (ce);
394}
395
396
397/**
398 * Define "main" method using service macro.
399 */
400GNUNET_SERVICE_MAIN
401("regex",
402 GNUNET_SERVICE_OPTION_NONE,
403 &run,
404 &client_connect_cb,
405 &client_disconnect_cb,
406 NULL,
407 GNUNET_MQ_hd_var_size (announce,
408 GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE,
409 struct AnnounceMessage,
410 NULL),
411 GNUNET_MQ_hd_var_size (search,
412 GNUNET_MESSAGE_TYPE_REGEX_SEARCH,
413 struct RegexSearchMessage,
414 NULL),
415 GNUNET_MQ_handler_end ());
416
417
413/* end of gnunet-service-regex.c */ 418/* end of gnunet-service-regex.c */