diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-01-28 12:43:09 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-01-28 12:43:09 +0100 |
commit | 07533eec5c7b1637374ea1496595918861ac8b6d (patch) | |
tree | fe97a71907b96fe28c477526901895f9eaffcc87 /src/transport | |
parent | cadf559899f7dfaf24ed27cab923414058f207b3 (diff) | |
download | gnunet-07533eec5c7b1637374ea1496595918861ac8b6d.tar.gz gnunet-07533eec5c7b1637374ea1496595918861ac8b6d.zip |
more work on TCP communicator, almost there
Diffstat (limited to 'src/transport')
-rw-r--r-- | src/transport/Makefile.am | 1 | ||||
-rw-r--r-- | src/transport/gnunet-communicator-tcp.c | 498 |
2 files changed, 438 insertions, 61 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 0df3e4e27..ead9beeec 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am | |||
@@ -256,6 +256,7 @@ gnunet_communicator_tcp_SOURCES = \ | |||
256 | gnunet-communicator-tcp.c | 256 | gnunet-communicator-tcp.c |
257 | gnunet_communicator_tcp_LDADD = \ | 257 | gnunet_communicator_tcp_LDADD = \ |
258 | libgnunettransportcommunicator.la \ | 258 | libgnunettransportcommunicator.la \ |
259 | $(top_builddir)/src/nat/libgnunetnatnew.la \ | ||
259 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 260 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
260 | $(top_builddir)/src/util/libgnunetutil.la \ | 261 | $(top_builddir)/src/util/libgnunetutil.la \ |
261 | $(LIBGCRYPT_LIBS) | 262 | $(LIBGCRYPT_LIBS) |
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c index a94559bd2..050a5f225 100644 --- a/src/transport/gnunet-communicator-tcp.c +++ b/src/transport/gnunet-communicator-tcp.c | |||
@@ -24,14 +24,8 @@ | |||
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | 25 | * |
26 | * TODO: | 26 | * TODO: |
27 | * - lots of basic adaptations (see FIXMEs), need NAT service | 27 | * - NAT service API change to handle address stops! |
28 | * to determine our own listen IPs! Parsing of bindto spec! | 28 | * - handling of rekeys! |
29 | * - actual decryption and handling of boxes and rekeys! | ||
30 | * - message queue management: flow control towards CORE! | ||
31 | * (stop reading from socket until MQ send to core is done; | ||
32 | * will need a counter as ONE read from socket may generate | ||
33 | * multiple messages en route to CORE; tricky bit: queue | ||
34 | * may die before we get MQ sent-done callbacks!) | ||
35 | */ | 29 | */ |
36 | #include "platform.h" | 30 | #include "platform.h" |
37 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
@@ -39,6 +33,7 @@ | |||
39 | #include "gnunet_signatures.h" | 33 | #include "gnunet_signatures.h" |
40 | #include "gnunet_constants.h" | 34 | #include "gnunet_constants.h" |
41 | #include "gnunet_nt_lib.h" | 35 | #include "gnunet_nt_lib.h" |
36 | #include "gnunet_nat_service.h" | ||
42 | #include "gnunet_statistics_service.h" | 37 | #include "gnunet_statistics_service.h" |
43 | #include "gnunet_transport_communication_service.h" | 38 | #include "gnunet_transport_communication_service.h" |
44 | 39 | ||
@@ -391,10 +386,19 @@ struct Queue | |||
391 | struct GNUNET_TIME_Absolute timeout; | 386 | struct GNUNET_TIME_Absolute timeout; |
392 | 387 | ||
393 | /** | 388 | /** |
389 | * How may messages did we pass from this queue to CORE for which we | ||
390 | * have yet to receive an acknoweldgement that CORE is done with | ||
391 | * them? If "large" (or even just non-zero), we should throttle | ||
392 | * reading to provide flow control. See also #DEFAULT_MAX_QUEUE_LENGTH | ||
393 | * and #max_queue_length. | ||
394 | */ | ||
395 | unsigned int backpressure; | ||
396 | |||
397 | /** | ||
394 | * Which network type does this queue use? | 398 | * Which network type does this queue use? |
395 | */ | 399 | */ |
396 | enum GNUNET_NetworkType nt; | 400 | enum GNUNET_NetworkType nt; |
397 | 401 | ||
398 | /** | 402 | /** |
399 | * Is MQ awaiting a #GNUNET_MQ_impl_send_continue() call? | 403 | * Is MQ awaiting a #GNUNET_MQ_impl_send_continue() call? |
400 | */ | 404 | */ |
@@ -406,6 +410,14 @@ struct Queue | |||
406 | int finishing; | 410 | int finishing; |
407 | 411 | ||
408 | /** | 412 | /** |
413 | * Did we technically destroy this queue, but kept the allocation | ||
414 | * around because of @e backpressure not being zero yet? Used | ||
415 | * simply to delay the final #GNUNET_free() operation until | ||
416 | * #core_read_finished_cb() has been called. | ||
417 | */ | ||
418 | int destroyed; | ||
419 | |||
420 | /** | ||
409 | * #GNUNET_YES after #inject_key() placed the rekey message into the | 421 | * #GNUNET_YES after #inject_key() placed the rekey message into the |
410 | * plaintext buffer. Once the plaintext buffer is drained, this | 422 | * plaintext buffer. Once the plaintext buffer is drained, this |
411 | * means we must switch to the new key material. | 423 | * means we must switch to the new key material. |
@@ -475,11 +487,6 @@ struct ProtoQueue | |||
475 | static struct GNUNET_SCHEDULER_Task *listen_task; | 487 | static struct GNUNET_SCHEDULER_Task *listen_task; |
476 | 488 | ||
477 | /** | 489 | /** |
478 | * Number of messages we currently have in our queues towards the transport service. | ||
479 | */ | ||
480 | static unsigned long long delivering_messages; | ||
481 | |||
482 | /** | ||
483 | * Maximum queue length before we stop reading towards the transport service. | 490 | * Maximum queue length before we stop reading towards the transport service. |
484 | */ | 491 | */ |
485 | static unsigned long long max_queue_length; | 492 | static unsigned long long max_queue_length; |
@@ -505,11 +512,6 @@ static struct GNUNET_CONTAINER_MultiPeerMap *queue_map; | |||
505 | static struct GNUNET_NETWORK_Handle *listen_sock; | 512 | static struct GNUNET_NETWORK_Handle *listen_sock; |
506 | 513 | ||
507 | /** | 514 | /** |
508 | * Handle to the operation that publishes our address. | ||
509 | */ | ||
510 | static struct GNUNET_TRANSPORT_AddressIdentifier *ai; | ||
511 | |||
512 | /** | ||
513 | * Our public key. | 515 | * Our public key. |
514 | */ | 516 | */ |
515 | static struct GNUNET_PeerIdentity my_identity; | 517 | static struct GNUNET_PeerIdentity my_identity; |
@@ -525,6 +527,11 @@ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | |||
525 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 527 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
526 | 528 | ||
527 | /** | 529 | /** |
530 | * Connection to NAT service. | ||
531 | */ | ||
532 | static struct GNUNET_NAT_Handle *nat; | ||
533 | |||
534 | /** | ||
528 | * Protoqueues DLL head. | 535 | * Protoqueues DLL head. |
529 | */ | 536 | */ |
530 | static struct ProtoQueue *proto_head; | 537 | static struct ProtoQueue *proto_head; |
@@ -588,7 +595,10 @@ queue_destroy (struct Queue *queue) | |||
588 | gcry_cipher_close (queue->in_cipher); | 595 | gcry_cipher_close (queue->in_cipher); |
589 | gcry_cipher_close (queue->out_cipher); | 596 | gcry_cipher_close (queue->out_cipher); |
590 | GNUNET_free (queue->address); | 597 | GNUNET_free (queue->address); |
591 | GNUNET_free (queue); | 598 | if (0 != queue->backpressure) |
599 | queue->destroyed = GNUNET_YES; | ||
600 | else | ||
601 | GNUNET_free (queue); | ||
592 | if (NULL == listen_task) | 602 | if (NULL == listen_task) |
593 | listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 603 | listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
594 | listen_sock, | 604 | listen_sock, |
@@ -685,6 +695,213 @@ reschedule_queue_timeout (struct Queue *queue) | |||
685 | * @param cls the `struct Queue *` to disconnect | 695 | * @param cls the `struct Queue *` to disconnect |
686 | */ | 696 | */ |
687 | static void | 697 | static void |
698 | queue_read (void *cls); | ||
699 | |||
700 | |||
701 | /** | ||
702 | * Core tells us it is done processing a message that transport | ||
703 | * received on a queue with status @a success. | ||
704 | * | ||
705 | * @param cls a `struct Queue *` where the message originally came from | ||
706 | * @param success #GNUNET_OK on success | ||
707 | */ | ||
708 | static void | ||
709 | core_read_finished_cb (void *cls, | ||
710 | int success) | ||
711 | { | ||
712 | struct Queue *queue = cls; | ||
713 | |||
714 | if (GNUNET_OK != success) | ||
715 | GNUNET_STATISTICS_update (stats, | ||
716 | "# messages lost in communicator API towards CORE", | ||
717 | 1, | ||
718 | GNUNET_NO); | ||
719 | queue->backpressure--; | ||
720 | /* handle deferred queue destruction */ | ||
721 | if ( (queue->destroyed) && | ||
722 | (0 == queue->backpressure) ) | ||
723 | { | ||
724 | GNUNET_free (queue); | ||
725 | return; | ||
726 | } | ||
727 | reschedule_queue_timeout (queue); | ||
728 | /* possibly unchoke reading, now that CORE made progress */ | ||
729 | if (NULL == queue->read_task) | ||
730 | queue->read_task | ||
731 | = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (queue->timeout), | ||
732 | queue->sock, | ||
733 | &queue_read, | ||
734 | queue); | ||
735 | } | ||
736 | |||
737 | |||
738 | /** | ||
739 | * We received @a plaintext_len bytes of @a plaintext on @a queue. | ||
740 | * Pass it on to CORE. If transmission is actually happening, | ||
741 | * increase backpressure counter. | ||
742 | * | ||
743 | * @param queue the queue that received the plaintext | ||
744 | * @param plaintext the plaintext that was received | ||
745 | * @param plaintext_len number of bytes of plaintext received | ||
746 | */ | ||
747 | static void | ||
748 | pass_plaintext_to_core (struct Queue *queue, | ||
749 | const void *plaintext, | ||
750 | size_t plaintext_len) | ||
751 | { | ||
752 | const struct GNUNET_MessageHeader *hdr = plaintext; | ||
753 | int ret; | ||
754 | |||
755 | if (ntohs (hdr->size) != plaintext_len) | ||
756 | { | ||
757 | /* NOTE: If we ever allow multiple CORE messages in one | ||
758 | BOX, this will have to change! */ | ||
759 | GNUNET_break (0); | ||
760 | return; | ||
761 | } | ||
762 | ret = GNUNET_TRANSPORT_communicator_receive (ch, | ||
763 | &queue->target, | ||
764 | hdr, | ||
765 | &core_read_finished_cb, | ||
766 | queue); | ||
767 | if (GNUNET_OK == ret) | ||
768 | queue->backpressure++; | ||
769 | GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */ | ||
770 | if (GNUNET_SYSERR == ret) | ||
771 | GNUNET_STATISTICS_update (stats, | ||
772 | "# bytes lost due to CORE not running", | ||
773 | plaintext_len, | ||
774 | GNUNET_NO); | ||
775 | } | ||
776 | |||
777 | |||
778 | /** | ||
779 | * Test if we have received a full message in plaintext. | ||
780 | * If so, handle it. | ||
781 | * | ||
782 | * @param queue queue to process inbound plaintext for | ||
783 | */ | ||
784 | static void | ||
785 | try_handle_plaintext (struct Queue *queue) | ||
786 | { | ||
787 | const struct GNUNET_MessageHeader *hdr | ||
788 | = (const struct GNUNET_MessageHeader *) queue->pread_buf; | ||
789 | const struct TCPBox *box | ||
790 | = (const struct TCPBox *) queue->pread_buf; | ||
791 | const struct TCPRekey *rekey | ||
792 | = (const struct TCPRekey *) queue->pread_buf; | ||
793 | const struct TCPFinish *fin | ||
794 | = (const struct TCPFinish *) queue->pread_buf; | ||
795 | struct TCPRekey rekeyz; | ||
796 | struct TCPFinish finz; | ||
797 | struct GNUNET_ShortHashCode tmac; | ||
798 | uint16_t type; | ||
799 | size_t size = 0; /* make compiler happy */ | ||
800 | |||
801 | if (sizeof (*hdr) > queue->pread_off) | ||
802 | return; /* not even a header */ | ||
803 | type = ntohs (hdr->type); | ||
804 | switch (type) | ||
805 | { | ||
806 | case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX: | ||
807 | /* Special case: header size excludes box itself! */ | ||
808 | if (ntohs (hdr->size) + sizeof (struct TCPBox) > queue->pread_off) | ||
809 | return; | ||
810 | hmac (&queue->in_hmac, | ||
811 | &box[1], | ||
812 | ntohs (hdr->size), | ||
813 | &tmac); | ||
814 | if (0 != memcmp (&tmac, | ||
815 | &box->hmac, | ||
816 | sizeof (tmac))) | ||
817 | { | ||
818 | GNUNET_break_op (0); | ||
819 | queue_finish (queue); | ||
820 | return; | ||
821 | } | ||
822 | pass_plaintext_to_core (queue, | ||
823 | (const void *) &box[1], | ||
824 | ntohs (hdr->size)); | ||
825 | size = ntohs (hdr->size) + sizeof (*box); | ||
826 | break; | ||
827 | case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY: | ||
828 | if (sizeof (*rekey) > queue->pread_off) | ||
829 | return; | ||
830 | if (ntohs (hdr->size) != sizeof (*rekey)) | ||
831 | { | ||
832 | GNUNET_break_op (0); | ||
833 | queue_finish (queue); | ||
834 | return; | ||
835 | } | ||
836 | rekeyz = *rekey; | ||
837 | memset (&rekeyz.hmac, | ||
838 | 0, | ||
839 | sizeof (rekeyz.hmac)); | ||
840 | hmac (&queue->in_hmac, | ||
841 | &rekeyz, | ||
842 | sizeof (rekeyz), | ||
843 | &tmac); | ||
844 | if (0 != memcmp (&tmac, | ||
845 | &box->hmac, | ||
846 | sizeof (tmac))) | ||
847 | { | ||
848 | GNUNET_break_op (0); | ||
849 | queue_finish (queue); | ||
850 | return; | ||
851 | } | ||
852 | // FIXME: handle rekey! | ||
853 | |||
854 | size = ntohs (hdr->size); | ||
855 | break; | ||
856 | case GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH: | ||
857 | if (sizeof (*fin) > queue->pread_off) | ||
858 | return; | ||
859 | if (ntohs (hdr->size) != sizeof (*fin)) | ||
860 | { | ||
861 | GNUNET_break_op (0); | ||
862 | queue_finish (queue); | ||
863 | return; | ||
864 | } | ||
865 | finz = *fin; | ||
866 | memset (&finz.hmac, | ||
867 | 0, | ||
868 | sizeof (finz.hmac)); | ||
869 | hmac (&queue->in_hmac, | ||
870 | &rekeyz, | ||
871 | sizeof (rekeyz), | ||
872 | &tmac); | ||
873 | if (0 != memcmp (&tmac, | ||
874 | &fin->hmac, | ||
875 | sizeof (tmac))) | ||
876 | { | ||
877 | GNUNET_break_op (0); | ||
878 | queue_finish (queue); | ||
879 | return; | ||
880 | } | ||
881 | /* handle FINISH by destroying queue */ | ||
882 | queue_destroy (queue); | ||
883 | break; | ||
884 | default: | ||
885 | GNUNET_break_op (0); | ||
886 | queue_finish (queue); | ||
887 | return; | ||
888 | } | ||
889 | GNUNET_assert (0 != size); | ||
890 | /* 'size' bytes of plaintext were used, shift buffer */ | ||
891 | GNUNET_assert (size <= queue->pread_off); | ||
892 | memmove (queue->pread_buf, | ||
893 | &queue->pread_buf[size], | ||
894 | queue->pread_off - size); | ||
895 | queue->pread_off -= size; | ||
896 | } | ||
897 | |||
898 | |||
899 | /** | ||
900 | * Queue read task. If we hit the timeout, disconnect it | ||
901 | * | ||
902 | * @param cls the `struct Queue *` to disconnect | ||
903 | */ | ||
904 | static void | ||
688 | queue_read (void *cls) | 905 | queue_read (void *cls) |
689 | { | 906 | { |
690 | struct Queue *queue = cls; | 907 | struct Queue *queue = cls; |
@@ -718,10 +935,20 @@ queue_read (void *cls) | |||
718 | queue->cread_off += rcvd; | 935 | queue->cread_off += rcvd; |
719 | if (queue->pread_off < sizeof (queue->pread_buf)) | 936 | if (queue->pread_off < sizeof (queue->pread_buf)) |
720 | { | 937 | { |
721 | /* FIXME: decrypt */ | 938 | size_t max = GNUNET_MIN (sizeof (queue->pread_buf) - queue->pread_off, |
722 | 939 | queue->cread_off); | |
723 | /* FIXME: check plaintext for complete messages, if complete, hand to CORE */ | 940 | GNUNET_assert (0 == |
724 | /* FIXME: CORE flow control: suspend doing more until CORE has ACKed */ | 941 | gcry_cipher_decrypt (queue->in_cipher, |
942 | &queue->pread_buf[queue->pread_off], | ||
943 | max, | ||
944 | queue->cread_buf, | ||
945 | max)); | ||
946 | queue->pread_off += max; | ||
947 | memmove (queue->cread_buf, | ||
948 | &queue->cread_buf[max], | ||
949 | queue->cread_off - max); | ||
950 | queue->cread_off -= max; | ||
951 | try_handle_plaintext (queue); | ||
725 | } | 952 | } |
726 | 953 | ||
727 | if (BUF_SIZE == queue->cread_off) | 954 | if (BUF_SIZE == queue->cread_off) |
@@ -729,14 +956,15 @@ queue_read (void *cls) | |||
729 | left = GNUNET_TIME_absolute_get_remaining (queue->timeout); | 956 | left = GNUNET_TIME_absolute_get_remaining (queue->timeout); |
730 | if (0 != left.rel_value_us) | 957 | if (0 != left.rel_value_us) |
731 | { | 958 | { |
732 | /* not actually our turn yet, but let's at least update | 959 | if (max_queue_length < queue->backpressure) |
733 | the monitor, it may think we're about to die ... */ | 960 | { |
734 | queue->read_task | 961 | /* continue reading */ |
735 | = GNUNET_SCHEDULER_add_read_net (left, | 962 | queue->read_task |
736 | queue->sock, | 963 | = GNUNET_SCHEDULER_add_read_net (left, |
737 | &queue_read, | 964 | queue->sock, |
738 | queue); | 965 | &queue_read, |
739 | 966 | queue); | |
967 | } | ||
740 | return; | 968 | return; |
741 | } | 969 | } |
742 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 970 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -760,9 +988,119 @@ tcp_address_to_sockaddr (const char *bindto, | |||
760 | socklen_t *sock_len) | 988 | socklen_t *sock_len) |
761 | { | 989 | { |
762 | struct sockaddr *in; | 990 | struct sockaddr *in; |
763 | size_t slen; | 991 | unsigned int port; |
992 | char dummy[2]; | ||
993 | char *colon; | ||
994 | char *cp; | ||
995 | |||
996 | if (1 == SSCANF (bindto, | ||
997 | "%u%1s", | ||
998 | &port, | ||
999 | dummy)) | ||
1000 | { | ||
1001 | /* interpreting value as just a PORT number */ | ||
1002 | if (port > UINT16_MAX) | ||
1003 | { | ||
1004 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1005 | "BINDTO specification `%s' invalid: value too large for port\n", | ||
1006 | bindto); | ||
1007 | return NULL; | ||
1008 | } | ||
1009 | if (GNUNET_YES == | ||
1010 | GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
1011 | COMMUNICATOR_CONFIG_SECTION, | ||
1012 | "DISABLE_V6")) | ||
1013 | { | ||
1014 | struct sockaddr_in *i4; | ||
1015 | |||
1016 | i4 = GNUNET_malloc (sizeof (struct sockaddr_in)); | ||
1017 | i4->sin_family = AF_INET; | ||
1018 | i4->sin_port = htons ((uint16_t) port); | ||
1019 | *sock_len = sizeof (struct sockaddr_in); | ||
1020 | in = (struct sockaddr *) i4; | ||
1021 | } | ||
1022 | else | ||
1023 | { | ||
1024 | struct sockaddr_in6 *i6; | ||
1025 | |||
1026 | i6 = GNUNET_malloc (sizeof (struct sockaddr_in6)); | ||
1027 | i6->sin6_family = AF_INET6; | ||
1028 | i6->sin6_port = htons ((uint16_t) port); | ||
1029 | *sock_len = sizeof (struct sockaddr_in6); | ||
1030 | in = (struct sockaddr *) i6; | ||
1031 | } | ||
1032 | return in; | ||
1033 | } | ||
1034 | cp = GNUNET_strdup (bindto); | ||
1035 | colon = strrchr (cp, ':'); | ||
1036 | if (NULL != colon) | ||
1037 | { | ||
1038 | /* interpet value after colon as port */ | ||
1039 | *colon = '\0'; | ||
1040 | colon++; | ||
1041 | if (1 == SSCANF (colon, | ||
1042 | "%u%1s", | ||
1043 | &port, | ||
1044 | dummy)) | ||
1045 | { | ||
1046 | /* interpreting value as just a PORT number */ | ||
1047 | if (port > UINT16_MAX) | ||
1048 | { | ||
1049 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1050 | "BINDTO specification `%s' invalid: value too large for port\n", | ||
1051 | bindto); | ||
1052 | GNUNET_free (cp); | ||
1053 | return NULL; | ||
1054 | } | ||
1055 | } | ||
1056 | else | ||
1057 | { | ||
1058 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1059 | "BINDTO specification `%s' invalid: last ':' not followed by number\n", | ||
1060 | bindto); | ||
1061 | GNUNET_free (cp); | ||
1062 | return NULL; | ||
1063 | } | ||
1064 | } | ||
1065 | else | ||
1066 | { | ||
1067 | /* interpret missing port as 0, aka pick any free one */ | ||
1068 | port = 0; | ||
1069 | } | ||
1070 | { | ||
1071 | /* try IPv4 */ | ||
1072 | struct sockaddr_in v4; | ||
764 | 1073 | ||
765 | /* FIXME: parse, allocate, return! */ | 1074 | if (1 == inet_pton (AF_INET, |
1075 | cp, | ||
1076 | &v4)) | ||
1077 | { | ||
1078 | v4.sin_port = htons ((uint16_t) port); | ||
1079 | in = GNUNET_memdup (&v4, | ||
1080 | sizeof (v4)); | ||
1081 | *sock_len = sizeof (v4); | ||
1082 | GNUNET_free (cp); | ||
1083 | return in; | ||
1084 | } | ||
1085 | } | ||
1086 | { | ||
1087 | /* try IPv6 */ | ||
1088 | struct sockaddr_in6 v6; | ||
1089 | |||
1090 | if (1 == inet_pton (AF_INET6, | ||
1091 | cp, | ||
1092 | &v6)) | ||
1093 | { | ||
1094 | v6.sin6_port = htons ((uint16_t) port); | ||
1095 | in = GNUNET_memdup (&v6, | ||
1096 | sizeof (v6)); | ||
1097 | *sock_len = sizeof (v6); | ||
1098 | GNUNET_free (cp); | ||
1099 | return in; | ||
1100 | } | ||
1101 | } | ||
1102 | /* FIXME (feature!): maybe also try getnameinfo()? */ | ||
1103 | GNUNET_free (cp); | ||
766 | return NULL; | 1104 | return NULL; |
767 | } | 1105 | } |
768 | 1106 | ||
@@ -966,8 +1304,8 @@ queue_write (void *cls) | |||
966 | size_t usent = (size_t) sent; | 1304 | size_t usent = (size_t) sent; |
967 | 1305 | ||
968 | memmove (queue->cwrite_buf, | 1306 | memmove (queue->cwrite_buf, |
969 | &queue->cwrite_buf[sent], | 1307 | &queue->cwrite_buf[usent], |
970 | queue->cwrite_off - sent); | 1308 | queue->cwrite_off - usent); |
971 | reschedule_queue_timeout (queue); | 1309 | reschedule_queue_timeout (queue); |
972 | } | 1310 | } |
973 | /* can we encrypt more? (always encrypt full messages, needed | 1311 | /* can we encrypt more? (always encrypt full messages, needed |
@@ -1670,6 +2008,11 @@ get_queue_delete_it (void *cls, | |||
1670 | static void | 2008 | static void |
1671 | do_shutdown (void *cls) | 2009 | do_shutdown (void *cls) |
1672 | { | 2010 | { |
2011 | if (NULL != nat) | ||
2012 | { | ||
2013 | GNUNET_NAT_unregister (nat); | ||
2014 | nat = NULL; | ||
2015 | } | ||
1673 | if (NULL != listen_task) | 2016 | if (NULL != listen_task) |
1674 | { | 2017 | { |
1675 | GNUNET_SCHEDULER_cancel (listen_task); | 2018 | GNUNET_SCHEDULER_cancel (listen_task); |
@@ -1685,11 +2028,6 @@ do_shutdown (void *cls) | |||
1685 | &get_queue_delete_it, | 2028 | &get_queue_delete_it, |
1686 | NULL); | 2029 | NULL); |
1687 | GNUNET_CONTAINER_multipeermap_destroy (queue_map); | 2030 | GNUNET_CONTAINER_multipeermap_destroy (queue_map); |
1688 | if (NULL != ai) | ||
1689 | { | ||
1690 | GNUNET_TRANSPORT_communicator_address_remove (ai); | ||
1691 | ai = NULL; | ||
1692 | } | ||
1693 | if (NULL != ch) | 2031 | if (NULL != ch) |
1694 | { | 2032 | { |
1695 | GNUNET_TRANSPORT_communicator_disconnect (ch); | 2033 | GNUNET_TRANSPORT_communicator_disconnect (ch); |
@@ -1733,6 +2071,51 @@ enc_notify_cb (void *cls, | |||
1733 | 2071 | ||
1734 | 2072 | ||
1735 | /** | 2073 | /** |
2074 | * Signature of the callback passed to #GNUNET_NAT_register() for | ||
2075 | * a function to call whenever our set of 'valid' addresses changes. | ||
2076 | * | ||
2077 | * @param cls closure | ||
2078 | * @param add_remove #GNUNET_YES to add a new public IP address, | ||
2079 | * #GNUNET_NO to remove a previous (now invalid) one | ||
2080 | * @param ac address class the address belongs to | ||
2081 | * @param addr either the previous or the new public IP address | ||
2082 | * @param addrlen actual length of the @a addr | ||
2083 | */ | ||
2084 | static void | ||
2085 | nat_address_cb (void *cls, | ||
2086 | int add_remove, | ||
2087 | enum GNUNET_NAT_AddressClass ac, | ||
2088 | const struct sockaddr *addr, | ||
2089 | socklen_t addrlen) | ||
2090 | { | ||
2091 | char *my_addr; | ||
2092 | static struct GNUNET_TRANSPORT_AddressIdentifier *ai; // FIXME: store in *ctx of NAT! | ||
2093 | |||
2094 | if (GNUNET_YES == add_remove) | ||
2095 | { | ||
2096 | // FIXME: do better job at stringification of @a addr? | ||
2097 | GNUNET_asprintf (&my_addr, | ||
2098 | "%s-%s", | ||
2099 | COMMUNICATOR_ADDRESS_PREFIX, | ||
2100 | GNUNET_a2s (addr, | ||
2101 | addrlen)); | ||
2102 | // FIXME: translate 'ac' to 'nt'? | ||
2103 | ai = GNUNET_TRANSPORT_communicator_address_add (ch, | ||
2104 | my_addr, | ||
2105 | GNUNET_NT_LOOPBACK, // FIXME: wrong NT! | ||
2106 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
2107 | GNUNET_free (my_addr); | ||
2108 | } | ||
2109 | else | ||
2110 | { | ||
2111 | // FIXME: support removal! => improve NAT API! | ||
2112 | GNUNET_TRANSPORT_communicator_address_remove (ai); | ||
2113 | ai = NULL; | ||
2114 | } | ||
2115 | } | ||
2116 | |||
2117 | |||
2118 | /** | ||
1736 | * Setup communicator and launch network interactions. | 2119 | * Setup communicator and launch network interactions. |
1737 | * | 2120 | * |
1738 | * @param cls NULL (always) | 2121 | * @param cls NULL (always) |
@@ -1749,9 +2132,8 @@ run (void *cls, | |||
1749 | char *bindto; | 2132 | char *bindto; |
1750 | struct sockaddr *in; | 2133 | struct sockaddr *in; |
1751 | socklen_t in_len; | 2134 | socklen_t in_len; |
1752 | char *my_addr; | ||
1753 | (void) cls; | ||
1754 | 2135 | ||
2136 | (void) cls; | ||
1755 | cfg = c; | 2137 | cfg = c; |
1756 | if (GNUNET_OK != | 2138 | if (GNUNET_OK != |
1757 | GNUNET_CONFIGURATION_get_value_filename (cfg, | 2139 | GNUNET_CONFIGURATION_get_value_filename (cfg, |
@@ -1810,6 +2192,7 @@ run (void *cls, | |||
1810 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2192 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1811 | "Bound to `%s'\n", | 2193 | "Bound to `%s'\n", |
1812 | bindto); | 2194 | bindto); |
2195 | GNUNET_free (bindto); | ||
1813 | stats = GNUNET_STATISTICS_create ("C-TCP", | 2196 | stats = GNUNET_STATISTICS_create ("C-TCP", |
1814 | cfg); | 2197 | cfg); |
1815 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | 2198 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, |
@@ -1824,13 +2207,13 @@ run (void *cls, | |||
1824 | } | 2207 | } |
1825 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, | 2208 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, |
1826 | &my_identity.public_key); | 2209 | &my_identity.public_key); |
1827 | 2210 | /* start listening */ | |
1828 | listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 2211 | listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
1829 | listen_sock, | 2212 | listen_sock, |
1830 | &listen_cb, | 2213 | &listen_cb, |
1831 | NULL); | 2214 | NULL); |
1832 | queue_map = GNUNET_CONTAINER_multipeermap_create (10, | 2215 | queue_map = GNUNET_CONTAINER_multipeermap_create (10, |
1833 | GNUNET_NO); | 2216 | GNUNET_NO); |
1834 | ch = GNUNET_TRANSPORT_communicator_connect (cfg, | 2217 | ch = GNUNET_TRANSPORT_communicator_connect (cfg, |
1835 | COMMUNICATOR_CONFIG_SECTION, | 2218 | COMMUNICATOR_CONFIG_SECTION, |
1836 | COMMUNICATOR_ADDRESS_PREFIX, | 2219 | COMMUNICATOR_ADDRESS_PREFIX, |
@@ -1843,24 +2226,17 @@ run (void *cls, | |||
1843 | { | 2226 | { |
1844 | GNUNET_break (0); | 2227 | GNUNET_break (0); |
1845 | GNUNET_SCHEDULER_shutdown (); | 2228 | GNUNET_SCHEDULER_shutdown (); |
1846 | GNUNET_free (bindto); | ||
1847 | return; | 2229 | return; |
1848 | } | 2230 | } |
1849 | // FIXME: bindto is wrong here, we MUST get our external | 2231 | nat = GNUNET_NAT_register (cfg, |
1850 | // IP address and really look at 'in' here as we might | 2232 | COMMUNICATOR_CONFIG_SECTION, |
1851 | // be bound to loopback or some other specific IP address! | 2233 | IPPROTO_TCP, |
1852 | GNUNET_asprintf (&my_addr, | 2234 | 1 /* one address */, |
1853 | "%s-%s", | 2235 | (const struct sockaddr **) &in, |
1854 | COMMUNICATOR_ADDRESS_PREFIX, | 2236 | &in_len, |
1855 | bindto); | 2237 | &nat_address_cb, |
1856 | GNUNET_free (bindto); | 2238 | NULL /* FIXME: support reversal! */, |
1857 | // FIXME: based on our bindto, we might not be able to tell the | 2239 | NULL /* closure */); |
1858 | // network type yet! What to do here!? | ||
1859 | ai = GNUNET_TRANSPORT_communicator_address_add (ch, | ||
1860 | my_addr, | ||
1861 | GNUNET_NT_LOOPBACK, // FIXME: wrong NT! | ||
1862 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
1863 | GNUNET_free (my_addr); | ||
1864 | } | 2240 | } |
1865 | 2241 | ||
1866 | 2242 | ||