aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <grothoff@gnunet.org>2021-07-06 21:04:08 +0200
committerChristian Grothoff <grothoff@gnunet.org>2021-07-06 21:04:08 +0200
commit7d384a118326f5ce8237281c5b5ffa36c32662fe (patch)
tree23bd230a730a127c8155a10a0dd4463faec04753
parenta8cbc99928e0a83e249e97707b12d3ca38a81ca0 (diff)
downloadgnunet-7d384a118326f5ce8237281c5b5ffa36c32662fe.tar.gz
gnunet-7d384a118326f5ce8237281c5b5ffa36c32662fe.zip
-work on receive logic
-rw-r--r--src/dhtu/plugin_dhtu_ip.c390
1 files changed, 347 insertions, 43 deletions
diff --git a/src/dhtu/plugin_dhtu_ip.c b/src/dhtu/plugin_dhtu_ip.c
index c76744d9a..19fe19192 100644
--- a/src/dhtu/plugin_dhtu_ip.c
+++ b/src/dhtu/plugin_dhtu_ip.c
@@ -167,9 +167,14 @@ struct Plugin
167 struct GNUNET_SCHEDULER_Task *scan_task; 167 struct GNUNET_SCHEDULER_Task *scan_task;
168 168
169 /** 169 /**
170 * Port we bind to. FIXME: initialize... 170 * Task that reads incoming UDP packets.
171 */ 171 */
172 char *my_port; 172 struct GNUNET_SCHEDULER_Task *read_task;
173
174 /**
175 * Port we bind to.
176 */
177 char *port;
173 178
174 /** 179 /**
175 * How often have we scanned for IPs? 180 * How often have we scanned for IPs?
@@ -179,7 +184,7 @@ struct Plugin
179 /** 184 /**
180 * My UDP socket. 185 * My UDP socket.
181 */ 186 */
182 int sock; 187 struct GNUNET_NETWORK_Handle *sock;
183}; 188};
184 189
185 190
@@ -266,7 +271,7 @@ ip_try_connect (void *cls,
266 colon = strchr (addr, ':'); 271 colon = strchr (addr, ':');
267 if (NULL == colon) 272 if (NULL == colon)
268 { 273 {
269 port = plugin->my_port; 274 port = plugin->port;
270 } 275 }
271 else 276 else
272 { 277 {
@@ -359,17 +364,93 @@ ip_send (void *cls,
359{ 364{
360 struct Plugin *plugin = cls; 365 struct Plugin *plugin = cls;
361 366
362 sendto (plugin->sock, 367 GNUNET_NETWORK_socket_sendto (plugin->sock,
363 msg, 368 msg,
364 msg_size, 369 msg_size,
365 0, 370 (const struct sockaddr *) &target->addr,
366 (const struct sockaddr *) &target->addr, 371 target->addrlen);
367 target->addrlen);
368 finished_cb (finished_cb_cls); 372 finished_cb (finished_cb_cls);
369} 373}
370 374
371 375
372/** 376/**
377 * Create a new source on which we may be receiving traffic.
378 *
379 * @param plugin our plugin
380 * @param addr our address
381 * @param addrlen number of bytes in @a addr
382 * @return new source object
383 */
384static struct GNUNET_DHTU_Source *
385create_source (struct Plugin *plugin,
386 const struct sockaddr *addr,
387 socklen_t addrlen)
388{
389 struct GNUNET_DHTU_Source *src;
390
391 src = GNUNET_new (struct GNUNET_DHTU_Source);
392 src->addrlen = addrlen;
393 memcpy (&src->addr,
394 addr,
395 addrlen);
396 src->scan_generation = plugin->scan_generation;
397 switch (addr->sa_family)
398 {
399 case AF_INET:
400 {
401 const struct sockaddr_in *s4 = (const struct sockaddr_in *) addr;
402 char buf[INET_ADDRSTRLEN];
403
404 GNUNET_assert (sizeof (struct sockaddr_in) == addrlen);
405 GNUNET_CRYPTO_hash (&s4->sin_addr,
406 sizeof (struct in_addr),
407 &src->id.hc);
408 GNUNET_asprintf (&src->address,
409 "ip+udp://%s:%u",
410 inet_ntop (AF_INET,
411 &s4->sin_addr,
412 buf,
413 sizeof (buf)),
414 ntohs (s4->sin_port));
415 }
416 break;
417 case AF_INET6:
418 {
419 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) addr;
420 char buf[INET6_ADDRSTRLEN];
421
422 GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen);
423 GNUNET_CRYPTO_hash (&s6->sin6_addr,
424 sizeof (struct in6_addr),
425 &src->id.hc);
426 GNUNET_asprintf (&src->address,
427 "ip+udp://[%s]:%u",
428 inet_ntop (AF_INET6,
429 &s6->sin6_addr,
430 buf,
431 sizeof (buf)),
432 ntohs (s6->sin6_port));
433 }
434 break;
435 default:
436 GNUNET_break (0);
437 GNUNET_free (src);
438 return NULL;
439 }
440 GNUNET_CONTAINER_DLL_insert (plugin->src_head,
441 plugin->src_tail,
442 src);
443 plugin->env->address_add_cb (plugin->env->cls,
444 &src->id,
445 NULL, /* no key */
446 src->address,
447 src,
448 &src->app_ctx);
449 return src;
450}
451
452
453/**
373 * Callback function invoked for each interface found. 454 * Callback function invoked for each interface found.
374 * 455 *
375 * @param cls closure 456 * @param cls closure
@@ -406,36 +487,9 @@ process_ifcs (void *cls,
406 return GNUNET_OK; 487 return GNUNET_OK;
407 } 488 }
408 } 489 }
409 src = GNUNET_new (struct GNUNET_DHTU_Source); 490 (void) create_source (plugin,
410 src->addrlen = addrlen; 491 addr,
411 memcpy (&src->addr, 492 addrlen);
412 addr,
413 addrlen);
414 src->scan_generation = plugin->scan_generation;
415 switch (addr->sa_family)
416 {
417 case AF_INET:
418 // hash v4 address
419 // convert address to src->address
420 break;
421 case AF_INET6:
422 // hash v6 address
423 // convert address to src->address
424 break;
425 default:
426 GNUNET_break (0);
427 GNUNET_free (src);
428 return GNUNET_OK;
429 }
430 GNUNET_CONTAINER_DLL_insert (plugin->src_head,
431 plugin->src_tail,
432 src);
433 plugin->env->address_add_cb (plugin->env->cls,
434 &src->id,
435 NULL, /* no key */
436 src->address,
437 src,
438 &src->app_ctx);
439 return GNUNET_OK; 493 return GNUNET_OK;
440} 494}
441 495
@@ -475,6 +529,186 @@ scan (void *cls)
475 529
476 530
477/** 531/**
532 * Find our source matching @a addr. If none exists,
533 * create one!
534 *
535 * @param plugin the plugin handle
536 * @param addr IP address to find
537 * @param addrlen number of bytes in @a addr
538 * @return matching source object
539 */
540static struct GNUNET_DHTU_Source *
541find_source (struct Plugin *plugin,
542 const void *addr,
543 size_t addrlen)
544{
545 for (struct GNUNET_DHTU_Source *src = plugin->src_head;
546 NULL != src;
547 src = src->next)
548 {
549 if ( (addrlen == sizeof (struct in_addr)) &&
550 (src->addrlen == sizeof (struct sockaddr_in)) )
551 {
552 const struct sockaddr_in *sa =
553 (const struct sockaddr_in *) &src->addr;
554 if (0 == memcmp (addr,
555 &sa->sin_addr,
556 addrlen))
557 return src;
558 }
559 if ( (addrlen == sizeof (struct in6_addr)) &&
560 (src->addrlen == sizeof (struct sockaddr_in6)) )
561 {
562 const struct sockaddr_in6 *sa =
563 (const struct sockaddr_in6 *) &src->addr;
564 if (0 == memcmp (addr,
565 &sa->sin6_addr,
566 addrlen))
567 return src;
568 }
569 }
570
571 {
572 struct sockaddr_storage sa;
573 socklen_t salen;
574
575 memset (&sa,
576 0,
577 sizeof (sa));
578 if (addrlen == sizeof (struct in_addr))
579 {
580 struct sockaddr_in *s4 =
581 (struct sockaddr_in *) &sa;
582
583 s4->sin_family = AF_INET;
584 memcpy (&s4->sin_addr,
585 addr,
586 addrlen);
587 salen = sizeof (*s4);
588 }
589 if (addrlen == sizeof (struct in6_addr))
590 {
591 struct sockaddr_in6 *s6 =
592 (struct sockaddr_in6 *) &sa;
593
594 s6->sin6_family = AF_INET6;
595 memcpy (&s6->sin6_addr,
596 addr,
597 addrlen);
598 salen = sizeof (*s6);
599 }
600 return create_source (plugin,
601 (const struct sockaddr *) &sa,
602 salen);
603 }
604}
605
606
607/**
608 * UDP socket is ready to receive. Read.
609 *
610 * @param cls our `struct Plugin *`
611 */
612static void
613read_cb (void *cls)
614{
615 struct Plugin *plugin = cls;
616 ssize_t ret;
617 char buf[65536];
618 struct sockaddr_storage sa;
619 struct iovec iov = {
620 .iov_base = buf,
621 .iov_len = sizeof (buf)
622 };
623 char ctl[1024];
624 struct msghdr mh = {
625 .msg_name = &sa,
626 .msg_namelen = sizeof (sa),
627 .msg_iov = &iov,
628 .msg_iovlen = 1,
629 .msg_control = ctl,
630 .msg_controllen = sizeof (ctl)
631 };
632
633 ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock),
634 &mh,
635 MSG_DONTWAIT);
636 if (ret >= 0)
637 {
638 struct GNUNET_DHTU_Target *dst = NULL;
639 struct GNUNET_DHTU_Source *src = NULL;
640 struct cmsghdr *cmsg;
641 struct msghdr *msh = mh.msg_control;
642
643 /* find IP where we received message */
644 for (cmsg = CMSG_FIRSTHDR (msh);
645 NULL != cmsg;
646 cmsg = CMSG_NXTHDR (msh,
647 cmsg))
648 {
649 if ( (cmsg->cmsg_level == IPPROTO_IP) &&
650 (cmsg->cmsg_type == IP_ORIGDSTADDR) )
651 {
652 if (CMSG_LEN (sizeof (struct in_addr)) ==
653 cmsg->cmsg_len)
654 {
655 struct in6_addr ia;
656
657 memcpy (&ia,
658 CMSG_DATA (cmsg),
659 sizeof (ia));
660 src = find_source (plugin,
661 &ia,
662 sizeof (ia));
663 break;
664 }
665 else
666 GNUNET_break (0);
667 }
668 if ( (cmsg->cmsg_level == IPPROTO_IPV6) &&
669 (cmsg->cmsg_type == IP_ORIGDSTADDR) )
670 {
671 if (CMSG_LEN (sizeof (struct in6_addr)) ==
672 cmsg->cmsg_len)
673 {
674 struct in6_addr ia;
675
676 memcpy (&ia,
677 CMSG_DATA (cmsg),
678 sizeof (ia));
679 src = find_source (plugin,
680 &ia,
681 sizeof (ia));
682 break;
683 }
684 else
685 GNUNET_break (0);
686 }
687 }
688 // FIXME: find or create 'dst'!
689 if ( (NULL == src) ||
690 (NULL == dst) )
691 {
692 GNUNET_break (0);
693 }
694 else
695 {
696 plugin->env->receive_cb (plugin->env->cls,
697 dst->app_ctx,
698 src->app_ctx,
699 buf,
700 ret);
701 }
702 }
703 plugin->read_task = GNUNET_SCHEDULER_add_read_net (
704 GNUNET_TIME_UNIT_FOREVER_REL,
705 plugin->sock,
706 &read_cb,
707 plugin);
708}
709
710
711/**
478 * Entry point for the plugin. 712 * Entry point for the plugin.
479 * 713 *
480 * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`) 714 * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`)
@@ -486,14 +720,81 @@ libgnunet_plugin_dhtu_ip_init (void *cls)
486 struct GNUNET_DHTU_PluginEnvironment *env = cls; 720 struct GNUNET_DHTU_PluginEnvironment *env = cls;
487 struct GNUNET_DHTU_PluginFunctions *api; 721 struct GNUNET_DHTU_PluginFunctions *api;
488 struct Plugin *plugin; 722 struct Plugin *plugin;
723 char *port;
724 unsigned int nport;
725 int sock;
489 726
727 if (GNUNET_OK !=
728 GNUNET_CONFIGURATION_get_value_string (env->cfg,
729 "DHTU-IP",
730 "UDP_PORT",
731 &port))
732 {
733 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
734 "DHTU-IP",
735 "UDP_PORT");
736 return NULL;
737 }
738 {
739 char dummy;
740
741 if ( (1 != sscanf (port,
742 "%u%c",
743 &nport,
744 &dummy)) ||
745 (nport > UINT16_MAX) )
746 {
747 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
748 "DHTU-IP",
749 "UDP_PORT",
750 "must be number below 65536");
751 GNUNET_free (port);
752 return NULL;
753 }
754 }
490 plugin = GNUNET_new (struct Plugin); 755 plugin = GNUNET_new (struct Plugin);
491 plugin->env = env; 756 plugin->env = env;
492 // FIXME: get port configuration! 757 plugin->port = port;
758 sock = socket (AF_INET6,
759 SOCK_DGRAM,
760 IPPROTO_UDP);
761 if (-1 == sock)
762 {
763 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
764 "socket");
765 GNUNET_free (plugin->port);
766 GNUNET_free (plugin);
767 return NULL;
768 }
769 {
770 struct sockaddr_in6 sa = {
771 .sin6_family = AF_INET6,
772 .sin6_port = htons ((uint16_t) nport)
773 };
774
775 if (0 !=
776 bind (sock,
777 &sa,
778 sizeof (sa)))
779 {
780 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
781 "socket");
782 GNUNET_break (0 ==
783 close (sock));
784 GNUNET_free (plugin->port);
785 GNUNET_free (plugin);
786 return NULL;
787 }
788 }
789 plugin->sock = GNUNET_NETWORK_socket_box_native (sock);
790 plugin->read_task = GNUNET_SCHEDULER_add_read_net (
791 GNUNET_TIME_UNIT_FOREVER_REL,
792 plugin->sock,
793 &read_cb,
794 plugin);
795 // FIXME: deal with NSE callback...
493 plugin->scan_task = GNUNET_SCHEDULER_add_now (&scan, 796 plugin->scan_task = GNUNET_SCHEDULER_add_now (&scan,
494 plugin); 797 plugin);
495 // FIXME: bind, start receive loop
496 // FIXME: deal with NSE callback...
497 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions); 798 api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions);
498 api->cls = plugin; 799 api->cls = plugin;
499 api->sign = &ip_sign; 800 api->sign = &ip_sign;
@@ -519,6 +820,9 @@ libgnunet_plugin_dhtu_ip_done (void *cls)
519 struct Plugin *plugin = api->cls; 820 struct Plugin *plugin = api->cls;
520 821
521 GNUNET_SCHEDULER_cancel (plugin->scan_task); 822 GNUNET_SCHEDULER_cancel (plugin->scan_task);
823 GNUNET_break (0 ==
824 GNUNET_NETWORK_socket_close (plugin->sock));
825 GNUNET_free (plugin->port);
522 GNUNET_free (plugin); 826 GNUNET_free (plugin);
523 GNUNET_free (api); 827 GNUNET_free (api);
524 return NULL; 828 return NULL;