aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-09-19 13:26:44 +0000
committerChristian Grothoff <christian@grothoff.org>2016-09-19 13:26:44 +0000
commit64fda257bdaf166ed3d96dce3a01ea14017a2a3e (patch)
treee33c077dcb46d06755fb4d0b37f829d7f6a0731e /src
parent08f1726b6552ac29830637e9f7be4d42e2ea4294 (diff)
downloadgnunet-64fda257bdaf166ed3d96dce3a01ea14017a2a3e.tar.gz
gnunet-64fda257bdaf166ed3d96dce3a01ea14017a2a3e.zip
misc minor fixes for new service MQ API, implementing resolver using new service API
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_mq_lib.h8
-rw-r--r--src/include/gnunet_scheduler_lib.h2
-rw-r--r--src/include/gnunet_service_lib.h36
-rw-r--r--src/statistics/statistics_api.c33
-rw-r--r--src/util/gnunet-service-resolver.c410
-rw-r--r--src/util/mq.c13
6 files changed, 337 insertions, 165 deletions
diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h
index 86144abca..999ee4134 100644
--- a/src/include/gnunet_mq_lib.h
+++ b/src/include/gnunet_mq_lib.h
@@ -171,7 +171,13 @@ enum GNUNET_MQ_Error
171 * We received a message that was malformed and thus 171 * We received a message that was malformed and thus
172 * could not be passed to its handler. 172 * could not be passed to its handler.
173 */ 173 */
174 GNUNET_MQ_ERROR_MALFORMED = 8 174 GNUNET_MQ_ERROR_MALFORMED = 8,
175
176 /**
177 * We received a message for which we have no matching
178 * handler.
179 */
180 GNUNET_MQ_ERROR_NO_MATCH = 16
175}; 181};
176 182
177 183
diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h
index 87cb3b6f1..1a0438bed 100644
--- a/src/include/gnunet_scheduler_lib.h
+++ b/src/include/gnunet_scheduler_lib.h
@@ -346,7 +346,7 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay,
346 * scheduled for execution once either the delay has expired or the 346 * scheduled for execution once either the delay has expired or the
347 * socket operation is ready. It will be run with the DEFAULT priority. 347 * socket operation is ready. It will be run with the DEFAULT priority.
348 * 348 *
349 * * @param delay when should this operation time out? 349 * @param delay when should this operation time out?
350 * @param rfd read file-descriptor 350 * @param rfd read file-descriptor
351 * @param task main function of the task 351 * @param task main function of the task
352 * @param task_cls closure of @a task 352 * @param task_cls closure of @a task
diff --git a/src/include/gnunet_service_lib.h b/src/include/gnunet_service_lib.h
index 797857ed8..9c7009ef4 100644
--- a/src/include/gnunet_service_lib.h
+++ b/src/include/gnunet_service_lib.h
@@ -336,16 +336,36 @@ GNUNET_SERVICE_ruN_ (int argc,
336 * @param connect_cb function to call whenever a client connects 336 * @param connect_cb function to call whenever a client connects
337 * @param disconnect_cb function to call whenever a client disconnects 337 * @param disconnect_cb function to call whenever a client disconnects
338 * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb 338 * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
339 * @param handlers NULL-terminated array of message handlers for the service, 339 * @param ... array of message handlers for the service, terminated
340 * by #GNUNET_MQ_handler_end();
340 * the closure will be set to the value returned by 341 * the closure will be set to the value returned by
341 * the @a connect_cb for the respective connection 342 * the @a connect_cb for the respective connection
342 * @return 0 on success, non-zero on error 343 * @return 0 on success, non-zero on error
344 *
345 * Sample invocation:
346 * <code>
347 * GNUNET_SERVICE_MAIN
348 * ("resolver",
349 * GNUNET_SERVICE_OPTION_NONE,
350 * &init_cb,
351 * &connect_cb,
352 * &disconnect_cb,
353 * closure_for_cb,
354 * GNUNET_MQ_hd_var_size (get,
355 * GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST,
356 * struct GNUNET_RESOLVER_GetMessage,
357 * NULL),
358 * GNUNET_MQ_handler_end ());
359 * </code>
343 */ 360 */
344#define GNUNET_SERVICE_MAIN(service_name,service_options,init_cb,connect_cb,disconnect_cb,cls,handlers) \ 361#define GNUNET_SERVICE_MAIN(service_name,service_options,init_cb,connect_cb,disconnect_cb,cls,...) \
345 int \ 362 int \
346 main (int argc,\ 363 main (int argc,\
347 char *const *argv)\ 364 char *const *argv)\
348 { \ 365 { \
366 struct GNUNET_MQ_MessageHandler mh[] = { \
367 __VA_ARGS__ \
368 }; \
349 return GNUNET_SERVICE_ruN_ (argc, \ 369 return GNUNET_SERVICE_ruN_ (argc, \
350 argv, \ 370 argv, \
351 service_name, \ 371 service_name, \
@@ -354,7 +374,7 @@ GNUNET_SERVICE_ruN_ (int argc,
354 connect_cb, \ 374 connect_cb, \
355 disconnect_cb, \ 375 disconnect_cb, \
356 cls, \ 376 cls, \
357 handlers); \ 377 mh); \
358 } 378 }
359 379
360 380
@@ -388,6 +408,16 @@ GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c);
388 408
389 409
390/** 410/**
411 * Obtain the message queue of @a c. Convenience function.
412 *
413 * @param c the client to continue receiving from
414 * @return the message queue of @a c
415 */
416struct GNUNET_MQ_Handle *
417GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c);
418
419
420/**
391 * Disable the warning the server issues if a message is not 421 * Disable the warning the server issues if a message is not
392 * acknowledged in a timely fashion. Use this call if a client is 422 * acknowledged in a timely fashion. Use this call if a client is
393 * intentionally delayed for a while. Only applies to the current 423 * intentionally delayed for a while. Only applies to the current
diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c
index c8709145b..856873d00 100644
--- a/src/statistics/statistics_api.c
+++ b/src/statistics/statistics_api.c
@@ -295,12 +295,18 @@ update_memory_statistics (struct GNUNET_STATISTICS_Handle *h)
295 if (current_heap_size > h->peak_heap_size) 295 if (current_heap_size > h->peak_heap_size)
296 { 296 {
297 h->peak_heap_size = current_heap_size; 297 h->peak_heap_size = current_heap_size;
298 GNUNET_STATISTICS_set (h, "# peak heap size", current_heap_size, GNUNET_NO); 298 GNUNET_STATISTICS_set (h,
299 "# peak heap size",
300 current_heap_size,
301 GNUNET_NO);
299 } 302 }
300 if (current_rss > h->peak_rss) 303 if (current_rss > h->peak_rss)
301 { 304 {
302 h->peak_rss = current_rss; 305 h->peak_rss = current_rss;
303 GNUNET_STATISTICS_set (h, "# peak resident set size", current_rss, GNUNET_NO); 306 GNUNET_STATISTICS_set (h,
307 "# peak resident set size",
308 current_rss,
309 GNUNET_NO);
304 } 310 }
305#endif 311#endif
306} 312}
@@ -739,7 +745,8 @@ reconnect_later (struct GNUNET_STATISTICS_Handle *h)
739 */ 745 */
740 loss = GNUNET_NO; 746 loss = GNUNET_NO;
741 for (gh = h->action_head; NULL != gh; gh = gh->next) 747 for (gh = h->action_head; NULL != gh; gh = gh->next)
742 if ( (gh->make_persistent) && (ACTION_SET == gh->type) ) 748 if ( (gh->make_persistent) &&
749 (ACTION_SET == gh->type) )
743 loss = GNUNET_YES; 750 loss = GNUNET_YES;
744 if (GNUNET_YES == loss) 751 if (GNUNET_YES == loss)
745 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 752 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -922,8 +929,7 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h,
922 GNUNET_assert (GNUNET_NO == h->do_destroy); /* Don't call twice. */ 929 GNUNET_assert (GNUNET_NO == h->do_destroy); /* Don't call twice. */
923 if ( (sync_first) && 930 if ( (sync_first) &&
924 (NULL != h->mq) && 931 (NULL != h->mq) &&
925 (0 != GNUNET_MQ_get_length (h->mq)) && 932 (0 != GNUNET_MQ_get_length (h->mq)) )
926 (GNUNET_YES == try_connect (h)) )
927 { 933 {
928 if ( (NULL != h->current) && 934 if ( (NULL != h->current) &&
929 (ACTION_GET == h->current->type) ) 935 (ACTION_GET == h->current->type) )
@@ -933,8 +939,7 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h,
933 { 939 {
934 next = pos->next; 940 next = pos->next;
935 if ( (ACTION_GET == pos->type) || 941 if ( (ACTION_GET == pos->type) ||
936 (ACTION_WATCH == pos->type) || 942 (ACTION_WATCH == pos->type) )
937 (GNUNET_NO == pos->make_persistent) )
938 { 943 {
939 GNUNET_CONTAINER_DLL_remove (h->action_head, 944 GNUNET_CONTAINER_DLL_remove (h->action_head,
940 h->action_tail, 945 h->action_tail,
@@ -1009,7 +1014,7 @@ schedule_action (void *cls)
1009 reconnect_later (h); 1014 reconnect_later (h);
1010 return; 1015 return;
1011 } 1016 }
1012 if (0 < GNUNET_MQ_get_length (h->mq) ) 1017 if (0 < GNUNET_MQ_get_length (h->mq))
1013 return; /* Wait for queue to be reduced more */ 1018 return; /* Wait for queue to be reduced more */
1014 /* schedule next action */ 1019 /* schedule next action */
1015 while (NULL == h->current) 1020 while (NULL == h->current)
@@ -1200,8 +1205,10 @@ GNUNET_STATISTICS_watch_cancel (struct GNUNET_STATISTICS_Handle *handle,
1200 continue; 1205 continue;
1201 if ( (w->proc == proc) && 1206 if ( (w->proc == proc) &&
1202 (w->proc_cls == proc_cls) && 1207 (w->proc_cls == proc_cls) &&
1203 (0 == strcmp (w->name, name)) && 1208 (0 == strcmp (w->name,
1204 (0 == strcmp (w->subsystem, subsystem)) ) 1209 name)) &&
1210 (0 == strcmp (w->subsystem,
1211 subsystem)) )
1205 { 1212 {
1206 GNUNET_free (w->name); 1213 GNUNET_free (w->name);
1207 GNUNET_free (w->subsystem); 1214 GNUNET_free (w->subsystem);
@@ -1291,8 +1298,10 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h,
1291 ai->type = type; 1298 ai->type = type;
1292 } 1299 }
1293 } 1300 }
1294 ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); 1301 ai->timeout
1295 ai->make_persistent = make_persistent; 1302 = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT);
1303 ai->make_persistent
1304 = make_persistent;
1296 return; 1305 return;
1297 } 1306 }
1298 /* no existing entry matches, create a fresh one */ 1307 /* no existing entry matches, create a fresh one */
diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c
index a87b1f5d0..12e484845 100644
--- a/src/util/gnunet-service-resolver.c
+++ b/src/util/gnunet-service-resolver.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2007-2013 GNUnet e.V. 3 Copyright (C) 2007-2016 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -197,6 +197,22 @@ cache_resolve (struct IPCache *cache)
197 197
198 198
199/** 199/**
200 * Function called after the replies for the request have all
201 * been transmitted to the client, and we can now read the next
202 * request from the client.
203 *
204 * @param cls the `struct GNUNET_SERVICE_Client` to continue with
205 */
206static void
207notify_service_client_done (void *cls)
208{
209 struct GNUNET_SERVICE_Client *client = cls;
210
211 GNUNET_SERVICE_client_continue (client);
212}
213
214
215/**
200 * Get an IP address as a string (works for both IPv4 and IPv6). Note 216 * Get an IP address as a string (works for both IPv4 and IPv6). Note
201 * that the resolution happens asynchronously and that the first call 217 * that the resolution happens asynchronously and that the first call
202 * may not immediately result in the FQN (but instead in a 218 * may not immediately result in the FQN (but instead in a
@@ -207,16 +223,19 @@ cache_resolve (struct IPCache *cache)
207 * @param ip `struct in_addr` or `struct in6_addr` 223 * @param ip `struct in_addr` or `struct in6_addr`
208 */ 224 */
209static void 225static void
210get_ip_as_string (struct GNUNET_SERVER_Client *client, 226get_ip_as_string (struct GNUNET_SERVICE_Client *client,
211 int af, 227 int af,
212 const void *ip) 228 const void *ip)
213{ 229{
214 struct IPCache *pos; 230 struct IPCache *pos;
215 struct IPCache *next; 231 struct IPCache *next;
216 struct GNUNET_TIME_Absolute now; 232 struct GNUNET_TIME_Absolute now;
217 struct GNUNET_SERVER_TransmitContext *tc; 233 struct GNUNET_MQ_Envelope *env;
234 struct GNUNET_MQ_Handle *mq;
235 struct GNUNET_MessageHeader *msg;
218 size_t ip_len; 236 size_t ip_len;
219 struct in6_addr ix; 237 struct in6_addr ix;
238 size_t alen;
220 239
221 switch (af) 240 switch (af)
222 { 241 {
@@ -267,7 +286,9 @@ get_ip_as_string (struct GNUNET_SERVER_Client *client,
267 { 286 {
268 pos = GNUNET_malloc (sizeof (struct IPCache) + ip_len); 287 pos = GNUNET_malloc (sizeof (struct IPCache) + ip_len);
269 pos->ip = &pos[1]; 288 pos->ip = &pos[1];
270 GNUNET_memcpy (&pos[1], ip, ip_len); 289 GNUNET_memcpy (&pos[1],
290 ip,
291 ip_len);
271 pos->last_request = now; 292 pos->last_request = now;
272 pos->last_refresh = now; 293 pos->last_refresh = now;
273 pos->ip_len = ip_len; 294 pos->ip_len = ip_len;
@@ -277,29 +298,41 @@ get_ip_as_string (struct GNUNET_SERVER_Client *client,
277 pos); 298 pos);
278 cache_resolve (pos); 299 cache_resolve (pos);
279 } 300 }
280 tc = GNUNET_SERVER_transmit_context_create (client);
281 if (NULL != pos->addr) 301 if (NULL != pos->addr)
282 GNUNET_SERVER_transmit_context_append_data (tc, pos->addr, 302 alen = strlen (pos->addr) + 1;
283 strlen (pos->addr) + 1,
284 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
285 else 303 else
286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 304 alen = 0;
287 "Reverse lookup failed\n"); 305 mq = GNUNET_SERVICE_client_get_mq (client);
288 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, 306 env = GNUNET_MQ_msg_extra (msg,
289 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 307 alen,
290 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 308 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
309 GNUNET_memcpy (&msg[1],
310 pos->addr,
311 alen);
312 GNUNET_MQ_send (mq,
313 env);
314 env = GNUNET_MQ_msg (msg,
315 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
316 GNUNET_MQ_notify_sent (env,
317 &notify_service_client_done,
318 client);
319 GNUNET_MQ_send (mq,
320 env);
291} 321}
292 322
293 323
294#if HAVE_GETADDRINFO 324#if HAVE_GETADDRINFO
295static int 325static int
296getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, 326getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq,
297 const char *hostname, int af) 327 const char *hostname,
328 int af)
298{ 329{
299 int s; 330 int s;
300 struct addrinfo hints; 331 struct addrinfo hints;
301 struct addrinfo *result; 332 struct addrinfo *result;
302 struct addrinfo *pos; 333 struct addrinfo *pos;
334 struct GNUNET_MessageHeader *msg;
335 struct GNUNET_MQ_Envelope *env;
303 336
304#ifdef WINDOWS 337#ifdef WINDOWS
305 /* Due to a bug, getaddrinfo will not return a mix of different families */ 338 /* Due to a bug, getaddrinfo will not return a mix of different families */
@@ -307,21 +340,32 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
307 { 340 {
308 int ret1; 341 int ret1;
309 int ret2; 342 int ret2;
310 ret1 = getaddrinfo_resolve (tc, hostname, AF_INET); 343 ret1 = getaddrinfo_resolve (mq,
311 ret2 = getaddrinfo_resolve (tc, hostname, AF_INET6); 344 hostname,
312 if ((ret1 == GNUNET_OK) || (ret2 == GNUNET_OK)) 345 AF_INET);
346 ret2 = getaddrinfo_resolve (mq,
347 hostname,
348 AF_INET6);
349 if ( (ret1 == GNUNET_OK) ||
350 (ret2 == GNUNET_OK) )
313 return GNUNET_OK; 351 return GNUNET_OK;
314 if ((ret1 == GNUNET_SYSERR) || (ret2 == GNUNET_SYSERR)) 352 if ( (ret1 == GNUNET_SYSERR) ||
353 (ret2 == GNUNET_SYSERR) )
315 return GNUNET_SYSERR; 354 return GNUNET_SYSERR;
316 return GNUNET_NO; 355 return GNUNET_NO;
317 } 356 }
318#endif 357#endif
319 358
320 memset (&hints, 0, sizeof (struct addrinfo)); 359 memset (&hints,
360 0,
361 sizeof (struct addrinfo));
321 hints.ai_family = af; 362 hints.ai_family = af;
322 hints.ai_socktype = SOCK_STREAM; /* go for TCP */ 363 hints.ai_socktype = SOCK_STREAM; /* go for TCP */
323 364
324 if (0 != (s = getaddrinfo (hostname, NULL, &hints, &result))) 365 if (0 != (s = getaddrinfo (hostname,
366 NULL,
367 &hints,
368 &result)))
325 { 369 {
326 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 370 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
327 _("Could not resolve `%s' (%s): %s\n"), 371 _("Could not resolve `%s' (%s): %s\n"),
@@ -329,13 +373,11 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
329 (af == 373 (af ==
330 AF_INET) ? "IPv4" : ((af == AF_INET6) ? "IPv6" : "any"), 374 AF_INET) ? "IPv4" : ((af == AF_INET6) ? "IPv6" : "any"),
331 gai_strerror (s)); 375 gai_strerror (s));
332 if ((s == EAI_BADFLAGS) || (s == EAI_MEMORY) 376 if ( (s == EAI_BADFLAGS) ||
333#ifndef WINDOWS 377#ifndef WINDOWS
334 || (s == EAI_SYSTEM) 378 (s == EAI_SYSTEM) ||
335#else
336 || 1
337#endif 379#endif
338 ) 380 (s == EAI_MEMORY) )
339 return GNUNET_NO; /* other function may still succeed */ 381 return GNUNET_NO; /* other function may still succeed */
340 return GNUNET_SYSERR; 382 return GNUNET_SYSERR;
341 } 383 }
@@ -346,16 +388,24 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
346 switch (pos->ai_family) 388 switch (pos->ai_family)
347 { 389 {
348 case AF_INET: 390 case AF_INET:
349 GNUNET_SERVER_transmit_context_append_data (tc, 391 env = GNUNET_MQ_msg_extra (msg,
350 &((struct sockaddr_in*) pos->ai_addr)->sin_addr, 392 sizeof (struct in_addr),
351 sizeof (struct in_addr), 393 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
352 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 394 GNUNET_memcpy (&msg[1],
395 &((struct sockaddr_in*) pos->ai_addr)->sin_addr,
396 sizeof (struct in_addr));
397 GNUNET_MQ_send (mq,
398 env);
353 break; 399 break;
354 case AF_INET6: 400 case AF_INET6:
355 GNUNET_SERVER_transmit_context_append_data (tc, 401 env = GNUNET_MQ_msg_extra (msg,
356 &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr, 402 sizeof (struct in6_addr),
357 sizeof (struct in6_addr), 403 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
358 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 404 GNUNET_memcpy (&msg[1],
405 &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr,
406 sizeof (struct in6_addr));
407 GNUNET_MQ_send (mq,
408 env);
359 break; 409 break;
360 default: 410 default:
361 /* unsupported, skip */ 411 /* unsupported, skip */
@@ -371,13 +421,15 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
371 421
372 422
373static int 423static int
374gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc, 424gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq,
375 const char *hostname, 425 const char *hostname,
376 int af) 426 int af)
377{ 427{
378 struct hostent *hp; 428 struct hostent *hp;
379 int ret1; 429 int ret1;
380 int ret2; 430 int ret2;
431 struct GNUNET_MQ_Envelope *env;
432 struct GNUNET_MessageHeader *msg;
381 433
382#ifdef WINDOWS 434#ifdef WINDOWS
383 /* gethostbyname2() in plibc is a compat dummy that calls gethostbyname(). */ 435 /* gethostbyname2() in plibc is a compat dummy that calls gethostbyname(). */
@@ -386,19 +438,27 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc,
386 438
387 if (af == AF_UNSPEC) 439 if (af == AF_UNSPEC)
388 { 440 {
389 ret1 = gethostbyname2_resolve (tc, hostname, AF_INET); 441 ret1 = gethostbyname2_resolve (mq,
390 ret2 = gethostbyname2_resolve (tc, hostname, AF_INET6); 442 hostname,
391 if ((ret1 == GNUNET_OK) || (ret2 == GNUNET_OK)) 443 AF_INET);
444 ret2 = gethostbyname2_resolve (mq,
445 hostname,
446 AF_INET6);
447 if ( (ret1 == GNUNET_OK) ||
448 (ret2 == GNUNET_OK) )
392 return GNUNET_OK; 449 return GNUNET_OK;
393 if ((ret1 == GNUNET_SYSERR) || (ret2 == GNUNET_SYSERR)) 450 if ( (ret1 == GNUNET_SYSERR) ||
451 (ret2 == GNUNET_SYSERR) )
394 return GNUNET_SYSERR; 452 return GNUNET_SYSERR;
395 return GNUNET_NO; 453 return GNUNET_NO;
396 } 454 }
397 hp = gethostbyname2 (hostname, af); 455 hp = gethostbyname2 (hostname,
456 af);
398 if (hp == NULL) 457 if (hp == NULL)
399 { 458 {
400 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 459 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
401 _("Could not find IP of host `%s': %s\n"), hostname, 460 _("Could not find IP of host `%s': %s\n"),
461 hostname,
402 hstrerror (h_errno)); 462 hstrerror (h_errno));
403 return GNUNET_SYSERR; 463 return GNUNET_SYSERR;
404 } 464 }
@@ -407,17 +467,25 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc,
407 { 467 {
408 case AF_INET: 468 case AF_INET:
409 GNUNET_assert (hp->h_length == sizeof (struct in_addr)); 469 GNUNET_assert (hp->h_length == sizeof (struct in_addr));
410 GNUNET_SERVER_transmit_context_append_data (tc, 470 env = GNUNET_MQ_msg_extra (msg,
411 hp->h_addr_list[0], 471 hp->h_length,
412 hp->h_length, 472 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
413 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 473 GNUNET_memcpy (&msg[1],
474 hp->h_addr_list[0],
475 hp->h_length);
476 GNUNET_MQ_send (mq,
477 env);
414 break; 478 break;
415 case AF_INET6: 479 case AF_INET6:
416 GNUNET_assert (hp->h_length == sizeof (struct in6_addr)); 480 GNUNET_assert (hp->h_length == sizeof (struct in6_addr));
417 GNUNET_SERVER_transmit_context_append_data (tc, 481 env = GNUNET_MQ_msg_extra (msg,
418 hp->h_addr_list[0], 482 hp->h_length,
419 hp->h_length, 483 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
420 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 484 GNUNET_memcpy (&msg[1],
485 hp->h_addr_list[0],
486 hp->h_length);
487 GNUNET_MQ_send (mq,
488 env);
421 break; 489 break;
422 default: 490 default:
423 GNUNET_break (0); 491 GNUNET_break (0);
@@ -430,10 +498,12 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc,
430 498
431 499
432static int 500static int
433gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc, 501gethostbyname_resolve (struct GNUNET_MQ_Handle *mq,
434 const char *hostname) 502 const char *hostname)
435{ 503{
436 struct hostent *hp; 504 struct hostent *hp;
505 struct GNUNET_MessageHeader *msg;
506 struct GNUNET_MQ_Envelope *env;
437 507
438 hp = GETHOSTBYNAME (hostname); 508 hp = GETHOSTBYNAME (hostname);
439 if (NULL == hp) 509 if (NULL == hp)
@@ -450,10 +520,14 @@ gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc,
450 return GNUNET_SYSERR; 520 return GNUNET_SYSERR;
451 } 521 }
452 GNUNET_assert (hp->h_length == sizeof (struct in_addr)); 522 GNUNET_assert (hp->h_length == sizeof (struct in_addr));
453 GNUNET_SERVER_transmit_context_append_data (tc, 523 env = GNUNET_MQ_msg_extra (msg,
454 hp->h_addr_list[0], 524 hp->h_length,
455 hp->h_length, 525 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
456 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 526 GNUNET_memcpy (&msg[1],
527 hp->h_addr_list[0],
528 hp->h_length);
529 GNUNET_MQ_send (mq,
530 env);
457 return GNUNET_OK; 531 return GNUNET_OK;
458} 532}
459#endif 533#endif
@@ -467,168 +541,197 @@ gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc,
467 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" 541 * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any"
468 */ 542 */
469static void 543static void
470get_ip_from_hostname (struct GNUNET_SERVER_Client *client, 544get_ip_from_hostname (struct GNUNET_SERVICE_Client *client,
471 const char *hostname, 545 const char *hostname,
472 int af) 546 int af)
473{ 547{
474 int ret; 548 int ret;
475 struct GNUNET_SERVER_TransmitContext *tc; 549 struct GNUNET_MQ_Handle *mq;
550 struct GNUNET_MQ_Envelope *env;
551 struct GNUNET_MessageHeader *msg;
476 552
477 tc = GNUNET_SERVER_transmit_context_create (client); 553 mq = GNUNET_SERVICE_client_get_mq (client);
478 ret = GNUNET_NO; 554 ret = GNUNET_NO;
479#if HAVE_GETADDRINFO 555#if HAVE_GETADDRINFO
480 if (ret == GNUNET_NO) 556 if (ret == GNUNET_NO)
481 ret = getaddrinfo_resolve (tc, hostname, af); 557 ret = getaddrinfo_resolve (mq,
558 hostname,
559 af);
482#elif HAVE_GETHOSTBYNAME2 560#elif HAVE_GETHOSTBYNAME2
483 if (ret == GNUNET_NO) 561 if (ret == GNUNET_NO)
484 ret = gethostbyname2_resolve (tc, hostname, af); 562 ret = gethostbyname2_resolve (mq,
563 hostname,
564 af);
485#elif HAVE_GETHOSTBYNAME 565#elif HAVE_GETHOSTBYNAME
486 if ((ret == GNUNET_NO) && ((af == AF_UNSPEC) || (af == PF_INET))) 566 if ( (ret == GNUNET_NO) &&
487 gethostbyname_resolve (tc, hostname); 567 ( (af == AF_UNSPEC) ||
568 (af == PF_INET) ) )
569 gethostbyname_resolve (mq,
570 hostname);
488#endif 571#endif
489 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, 572 env = GNUNET_MQ_msg (msg,
490 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); 573 GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE);
491 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 574 GNUNET_MQ_notify_sent (env,
575 &notify_service_client_done,
576 client);
577 GNUNET_MQ_send (mq,
578 env);
492} 579}
493 580
494 581
495/** 582/**
496 * Handle GET-message. 583 * Verify well-formedness of GET-message.
497 * 584 *
498 * @param cls closure 585 * @param cls closure
499 * @param client identification of the client 586 * @param get the actual message
500 * @param message the actual message 587 * @return #GNUNET_OK if @a get is well-formed
501 */ 588 */
502static void 589static int
503handle_get (void *cls, 590check_get (void *cls,
504 struct GNUNET_SERVER_Client *client, 591 const struct GNUNET_RESOLVER_GetMessage *get)
505 const struct GNUNET_MessageHeader *message)
506{ 592{
507 uint16_t msize;
508 const struct GNUNET_RESOLVER_GetMessage *msg;
509 const void *ip;
510 uint16_t size; 593 uint16_t size;
511 int direction; 594 int direction;
512 int af; 595 int af;
513 596
514 msize = ntohs (message->size); 597 size = ntohs (get->header.size) - sizeof (*get);
515 if (msize < sizeof (struct GNUNET_RESOLVER_GetMessage)) 598 direction = ntohl (get->direction);
516 {
517 GNUNET_break (0);
518 GNUNET_SERVER_receive_done (client,
519 GNUNET_SYSERR);
520 return;
521 }
522 msg = (const struct GNUNET_RESOLVER_GetMessage *) message;
523 size = msize - sizeof (struct GNUNET_RESOLVER_GetMessage);
524 direction = ntohl (msg->direction);
525 af = ntohl (msg->af);
526 if (GNUNET_NO == direction) 599 if (GNUNET_NO == direction)
527 { 600 {
528 /* IP from hostname */ 601 /* IP from hostname */
529 const char *hostname; 602 const char *hostname;
530 603
531 hostname = (const char *) &msg[1]; 604 hostname = (const char *) &get[1];
532 if (hostname[size - 1] != '\0') 605 if (hostname[size - 1] != '\0')
533 { 606 {
534 GNUNET_break (0); 607 GNUNET_break (0);
535 GNUNET_SERVER_receive_done (client, 608 return GNUNET_SYSERR;
536 GNUNET_SYSERR);
537 return;
538 } 609 }
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 610 return GNUNET_OK;
540 "Resolver asked to look up `%s'.\n",
541 hostname);
542 get_ip_from_hostname (client, hostname, af);
543 return;
544 } 611 }
545 ip = &msg[1]; 612 af = ntohl (get->af);
546 switch (af) 613 switch (af)
547 { 614 {
548 case AF_INET: 615 case AF_INET:
549 if (size != sizeof (struct in_addr)) 616 if (size != sizeof (struct in_addr))
550 { 617 {
551 GNUNET_break (0); 618 GNUNET_break (0);
552 GNUNET_SERVER_receive_done (client, 619 return GNUNET_SYSERR;
553 GNUNET_SYSERR);
554 return;
555 } 620 }
556 break; 621 break;
557 case AF_INET6: 622 case AF_INET6:
558 if (size != sizeof (struct in6_addr)) 623 if (size != sizeof (struct in6_addr))
559 { 624 {
560 GNUNET_break (0); 625 GNUNET_break (0);
561 GNUNET_SERVER_receive_done (client, 626 return GNUNET_SYSERR;
562 GNUNET_SYSERR);
563 return;
564 } 627 }
565 break; 628 break;
566 default: 629 default:
567 GNUNET_break (0); 630 GNUNET_break (0);
568 GNUNET_SERVER_receive_done (client, 631 return GNUNET_SYSERR;
569 GNUNET_SYSERR); 632 }
633 return GNUNET_OK;
634}
635
636
637/**
638 * Handle GET-message.
639 *
640 * @param cls identification of the client
641 * @param msg the actual message
642 */
643static void
644handle_get (void *cls,
645 const struct GNUNET_RESOLVER_GetMessage *msg)
646{
647 struct GNUNET_SERVICE_Client *client = cls;
648 const void *ip;
649 int direction;
650 int af;
651
652 direction = ntohl (msg->direction);
653 af = ntohl (msg->af);
654 if (GNUNET_NO == direction)
655 {
656 /* IP from hostname */
657 const char *hostname;
658
659 hostname = (const char *) &msg[1];
660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661 "Resolver asked to look up `%s'.\n",
662 hostname);
663 get_ip_from_hostname (client,
664 hostname,
665 af);
570 return; 666 return;
571 } 667 }
668 ip = &msg[1];
572 { 669 {
573 char buf[INET6_ADDRSTRLEN]; 670 char buf[INET6_ADDRSTRLEN];
574 671
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
576 "Resolver asked to look up IP address `%s'.\n", 673 "Resolver asked to look up IP address `%s'.\n",
577 inet_ntop (af, ip, buf, sizeof (buf))); 674 inet_ntop (af,
675 ip,
676 buf,
677 sizeof (buf)));
578 } 678 }
579 get_ip_as_string (client, af, ip); 679 get_ip_as_string (client,
680 af,
681 ip);
580} 682}
581 683
582 684
583/** 685/**
584 * Process resolver requests. 686 * Callback called when a client connects to the service.
585 * 687 *
586 * @param cls closure 688 * @param cls closure for the service
587 * @param server the initialized server 689 * @param c the new client that connected to the service
588 * @param cfg configuration to use 690 * @param mq the message queue used to send messages to the client
691 * @return @a c
589 */ 692 */
590static void 693static void *
591run (void *cls, struct GNUNET_SERVER_Handle *server, 694connect_cb (void *cls,
592 const struct GNUNET_CONFIGURATION_Handle *cfg) 695 struct GNUNET_SERVICE_Client *c,
696 struct GNUNET_MQ_Handle *mq)
593{ 697{
594 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 698 return c;
595 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, 0},
596 {NULL, NULL, 0, 0}
597 };
598 GNUNET_SERVER_add_handlers (server, handlers);
599} 699}
600 700
601 701
602/** 702/**
603 * The main function for the resolver service. 703 * Callback called when a client disconnected from the service
604 * 704 *
605 * @param argc number of arguments from the command line 705 * @param cls closure for the service
606 * @param argv command line arguments 706 * @param c the client that disconnected
607 * @return 0 ok, 1 on error 707 * @param internal_cls should be equal to @a c
608 */ 708 */
609int 709static void
610main (int argc, char *const *argv) 710disconnect_cb (void *cls,
711 struct GNUNET_SERVICE_Client *c,
712 void *internal_cls)
611{ 713{
612 struct IPCache *pos; 714 GNUNET_assert (c == internal_cls);
613 int ret;
614
615 ret =
616 (GNUNET_OK ==
617 GNUNET_SERVICE_run (argc, argv,
618 "resolver",
619 GNUNET_SERVICE_OPTION_NONE,
620 &run, NULL)) ? 0 : 1;
621 while (NULL != (pos = cache_head))
622 {
623 GNUNET_CONTAINER_DLL_remove (cache_head,
624 cache_tail,
625 pos);
626 GNUNET_free_non_null (pos->addr);
627 GNUNET_free (pos);
628 }
629 return ret;
630} 715}
631 716
717
718/**
719 * Define "main" method using service macro.
720 */
721GNUNET_SERVICE_MAIN
722("resolver",
723 GNUNET_SERVICE_OPTION_NONE,
724 NULL,
725 &connect_cb,
726 &disconnect_cb,
727 NULL,
728 GNUNET_MQ_hd_var_size (get,
729 GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST,
730 struct GNUNET_RESOLVER_GetMessage,
731 NULL),
732 GNUNET_MQ_handler_end ());
733
734
632#if defined(LINUX) && defined(__GLIBC__) 735#if defined(LINUX) && defined(__GLIBC__)
633#include <malloc.h> 736#include <malloc.h>
634 737
@@ -636,7 +739,7 @@ main (int argc, char *const *argv)
636 * MINIMIZE heap size (way below 128k) since this process doesn't need much. 739 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
637 */ 740 */
638void __attribute__ ((constructor)) 741void __attribute__ ((constructor))
639GNUNET_ARM_memory_init () 742GNUNET_RESOLVER_memory_init ()
640{ 743{
641 mallopt (M_TRIM_THRESHOLD, 4 * 1024); 744 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
642 mallopt (M_TOP_PAD, 1 * 1024); 745 mallopt (M_TOP_PAD, 1 * 1024);
@@ -645,4 +748,23 @@ GNUNET_ARM_memory_init ()
645#endif 748#endif
646 749
647 750
751/**
752 * Free globals on exit.
753 */
754void __attribute__ ((destructor))
755GNUNET_RESOLVER_memory_done ()
756{
757 struct IPCache *pos;
758
759 while (NULL != (pos = cache_head))
760 {
761 GNUNET_CONTAINER_DLL_remove (cache_head,
762 cache_tail,
763 pos);
764 GNUNET_free_non_null (pos->addr);
765 GNUNET_free (pos);
766 }
767}
768
769
648/* end of gnunet-service-resolver.c */ 770/* end of gnunet-service-resolver.c */
diff --git a/src/util/mq.c b/src/util/mq.c
index b22d97f59..e9dba3d9d 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -359,6 +359,7 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
359 GNUNET_assert (NULL != mq); 359 GNUNET_assert (NULL != mq);
360 GNUNET_assert (NULL == ev->parent_queue); 360 GNUNET_assert (NULL == ev->parent_queue);
361 361
362 mq->queue_length++;
362 ev->parent_queue = mq; 363 ev->parent_queue = mq;
363 /* is the implementation busy? queue it! */ 364 /* is the implementation busy? queue it! */
364 if (NULL != mq->current_envelope) 365 if (NULL != mq->current_envelope)
@@ -366,11 +367,12 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
366 GNUNET_CONTAINER_DLL_insert_tail (mq->envelope_head, 367 GNUNET_CONTAINER_DLL_insert_tail (mq->envelope_head,
367 mq->envelope_tail, 368 mq->envelope_tail,
368 ev); 369 ev);
369 mq->queue_length++;
370 return; 370 return;
371 } 371 }
372 mq->current_envelope = ev; 372 mq->current_envelope = ev;
373 mq->send_impl (mq, ev->mh, mq->impl_state); 373 mq->send_impl (mq,
374 ev->mh,
375 mq->impl_state);
374} 376}
375 377
376 378
@@ -422,6 +424,8 @@ impl_send_continue (void *cls)
422 current_envelope = mq->current_envelope; 424 current_envelope = mq->current_envelope;
423 GNUNET_assert (NULL != current_envelope); 425 GNUNET_assert (NULL != current_envelope);
424 current_envelope->parent_queue = NULL; 426 current_envelope->parent_queue = NULL;
427 GNUNET_assert (0 < mq->queue_length);
428 mq->queue_length--;
425 if (NULL == mq->envelope_head) 429 if (NULL == mq->envelope_head)
426 { 430 {
427 mq->current_envelope = NULL; 431 mq->current_envelope = NULL;
@@ -432,7 +436,6 @@ impl_send_continue (void *cls)
432 GNUNET_CONTAINER_DLL_remove (mq->envelope_head, 436 GNUNET_CONTAINER_DLL_remove (mq->envelope_head,
433 mq->envelope_tail, 437 mq->envelope_tail,
434 mq->current_envelope); 438 mq->current_envelope);
435 mq->queue_length--;
436 mq->send_impl (mq, 439 mq->send_impl (mq,
437 mq->current_envelope->mh, 440 mq->current_envelope->mh,
438 mq->impl_state); 441 mq->impl_state);
@@ -973,7 +976,6 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
973 mq->queue_length--; 976 mq->queue_length--;
974 GNUNET_MQ_discard (ev); 977 GNUNET_MQ_discard (ev);
975 } 978 }
976 GNUNET_assert (0 == mq->queue_length);
977 if (NULL != mq->current_envelope) 979 if (NULL != mq->current_envelope)
978 { 980 {
979 /* we can only discard envelopes that 981 /* we can only discard envelopes that
@@ -981,7 +983,9 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
981 mq->current_envelope->parent_queue = NULL; 983 mq->current_envelope->parent_queue = NULL;
982 GNUNET_MQ_discard (mq->current_envelope); 984 GNUNET_MQ_discard (mq->current_envelope);
983 mq->current_envelope = NULL; 985 mq->current_envelope = NULL;
986 mq->queue_length--;
984 } 987 }
988 GNUNET_assert (0 == mq->queue_length);
985 if (NULL != mq->assoc_map) 989 if (NULL != mq->assoc_map)
986 { 990 {
987 GNUNET_CONTAINER_multihashmap32_destroy (mq->assoc_map); 991 GNUNET_CONTAINER_multihashmap32_destroy (mq->assoc_map);
@@ -1039,6 +1043,7 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev)
1039 { 1043 {
1040 // complex case, we already started with transmitting 1044 // complex case, we already started with transmitting
1041 // the message 1045 // the message
1046 mq->queue_length--;
1042 mq->cancel_impl (mq, 1047 mq->cancel_impl (mq,
1043 mq->impl_state); 1048 mq->impl_state);
1044 // continue sending the next message, if any 1049 // continue sending the next message, if any