diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-14 22:23:44 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-14 22:23:44 +0000 |
commit | 269b1fc9b58fcba9dc5eb6e328ded1f07d8cb431 (patch) | |
tree | 3890f9ee137ca777c291702d5352f3fa1309b390 /src | |
parent | f181f6eaf8cdb1fdb47dc98cf171ad1be842b441 (diff) | |
download | gnunet-269b1fc9b58fcba9dc5eb6e328ded1f07d8cb431.tar.gz gnunet-269b1fc9b58fcba9dc5eb6e328ded1f07d8cb431.zip |
-finishing first draft of new VPN implementation to the point that it might run in theory
Diffstat (limited to 'src')
-rw-r--r-- | src/vpn/gnunet-service-vpn.c | 480 |
1 files changed, 327 insertions, 153 deletions
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c index edf1948e1..3e8178560 100644 --- a/src/vpn/gnunet-service-vpn.c +++ b/src/vpn/gnunet-service-vpn.c | |||
@@ -27,11 +27,15 @@ | |||
27 | * @author Christian Grothoff | 27 | * @author Christian Grothoff |
28 | * | 28 | * |
29 | * TODO: | 29 | * TODO: |
30 | * - create secondary mesh tunnels if needed / check overall tunnel creation/management code! | 30 | * Basics: |
31 | * => test! | 31 | * - test! |
32 | * - better message queue management (bounded state, drop oldest/RED?) | 32 | * - better message queue management (bounded state, drop oldest/RED?) |
33 | * - improve support for deciding which tunnels to keep and which ones to destroy | 33 | * - actually destroy "stale" tunnels once we have too many! |
34 | * | ||
35 | * Features: | ||
34 | * - add back ICMP support (especially needed for IPv6) | 36 | * - add back ICMP support (especially needed for IPv6) |
37 | * | ||
38 | * Code cleanup: | ||
35 | * - consider moving IP-header building / checksumming code into shared library | 39 | * - consider moving IP-header building / checksumming code into shared library |
36 | * with dns/exit/vpn (libgnunettun_tcpip?) | 40 | * with dns/exit/vpn (libgnunettun_tcpip?) |
37 | */ | 41 | */ |
@@ -46,17 +50,30 @@ | |||
46 | #include "vpn.h" | 50 | #include "vpn.h" |
47 | #include "exit.h" | 51 | #include "exit.h" |
48 | 52 | ||
53 | |||
54 | /** | ||
55 | * State we keep for each of our tunnels. | ||
56 | */ | ||
57 | struct TunnelState; | ||
58 | |||
59 | |||
49 | /** | 60 | /** |
50 | * Information we track for each IP address to determine which tunnel | 61 | * Information we track for each IP address to determine which tunnel |
51 | * to send the traffic over to the destination. | 62 | * to send the traffic over to the destination. |
52 | */ | 63 | */ |
53 | struct DestinationEntry | 64 | struct DestinationEntry |
54 | { | 65 | { |
66 | |||
55 | /** | 67 | /** |
56 | * Information about the tunnel to use, NULL if no tunnel | 68 | * Key under which this entry is in the 'destination_map' (only valid |
57 | * is available right now. | 69 | * if 'heap_node != NULL'. |
58 | */ | 70 | */ |
59 | struct GNUNET_MESH_Tunnel *tunnel; | 71 | GNUNET_HashCode key; |
72 | |||
73 | /** | ||
74 | * Pre-allocated tunnel for this destination, or NULL for none. | ||
75 | */ | ||
76 | struct TunnelState *ts; | ||
60 | 77 | ||
61 | /** | 78 | /** |
62 | * Entry for this entry in the destination_heap. | 79 | * Entry for this entry in the destination_heap. |
@@ -153,6 +170,12 @@ struct TunnelMessageQueueEntry | |||
153 | struct TunnelState | 170 | struct TunnelState |
154 | { | 171 | { |
155 | /** | 172 | /** |
173 | * Information about the tunnel to use, NULL if no tunnel | ||
174 | * is available right now. | ||
175 | */ | ||
176 | struct GNUNET_MESH_Tunnel *tunnel; | ||
177 | |||
178 | /** | ||
156 | * Active transmission handle, NULL for none. | 179 | * Active transmission handle, NULL for none. |
157 | */ | 180 | */ |
158 | struct GNUNET_MESH_TransmitHandle *th; | 181 | struct GNUNET_MESH_TransmitHandle *th; |
@@ -193,10 +216,10 @@ struct TunnelState | |||
193 | struct DestinationEntry destination; | 216 | struct DestinationEntry destination; |
194 | 217 | ||
195 | /** | 218 | /** |
196 | * GNUNET_NO if this is a tunnel to an Internet-exit, | 219 | * Destination entry that has a pointer to this tunnel state; |
197 | * GNUNET_YES if this tunnel is to a service. | 220 | * NULL if this tunnel state is in the tunnel map. |
198 | */ | 221 | */ |
199 | int is_service; | 222 | struct DestinationEntry *destination_container; |
200 | 223 | ||
201 | /** | 224 | /** |
202 | * Addess family used for this tunnel on the local TUN interface. | 225 | * Addess family used for this tunnel on the local TUN interface. |
@@ -204,6 +227,11 @@ struct TunnelState | |||
204 | int af; | 227 | int af; |
205 | 228 | ||
206 | /** | 229 | /** |
230 | * IPPROTO_TCP or IPPROTO_UDP once bound. | ||
231 | */ | ||
232 | uint8_t protocol; | ||
233 | |||
234 | /** | ||
207 | * IP address of the source on our end, initially uninitialized. | 235 | * IP address of the source on our end, initially uninitialized. |
208 | */ | 236 | */ |
209 | union | 237 | union |
@@ -279,7 +307,8 @@ static struct GNUNET_CONTAINER_Heap *destination_heap; | |||
279 | static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map; | 307 | static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map; |
280 | 308 | ||
281 | /** | 309 | /** |
282 | * Min-Heap sorted by activity time to expire old mappings. | 310 | * Min-Heap sorted by activity time to expire old mappings; values are |
311 | * of type 'struct TunnelState'. | ||
283 | */ | 312 | */ |
284 | static struct GNUNET_CONTAINER_Heap *tunnel_heap; | 313 | static struct GNUNET_CONTAINER_Heap *tunnel_heap; |
285 | 314 | ||
@@ -460,10 +489,18 @@ tunnel_peer_disconnect_handler (void *cls, | |||
460 | const struct | 489 | const struct |
461 | GNUNET_PeerIdentity * peer) | 490 | GNUNET_PeerIdentity * peer) |
462 | { | 491 | { |
463 | /* FIXME: should we do anything here? | 492 | struct TunnelState *ts = cls; |
464 | - stop transmitting to the tunnel (start queueing?) | 493 | |
465 | - possibly destroy the tunnel entirely (unless service tunnel?) | 494 | if (NULL != ts->th) |
466 | */ | 495 | { |
496 | GNUNET_MESH_notify_transmit_ready_cancel (ts->th); | ||
497 | ts->th = NULL; | ||
498 | } | ||
499 | if (ts->destination.is_service) | ||
500 | return; /* hope for reconnect eventually */ | ||
501 | /* as we are most likely going to change the exit node now, | ||
502 | we should just destroy the tunnel entirely... */ | ||
503 | GNUNET_MESH_tunnel_destroy (ts->tunnel); | ||
467 | } | 504 | } |
468 | 505 | ||
469 | 506 | ||
@@ -523,7 +560,7 @@ send_to_peer_notify_callback (void *cls, size_t size, void *buf) | |||
523 | ret = tnq->len; | 560 | ret = tnq->len; |
524 | GNUNET_free (tnq); | 561 | GNUNET_free (tnq); |
525 | if (NULL != (tnq = ts->head)) | 562 | if (NULL != (tnq = ts->head)) |
526 | ts->th = GNUNET_MESH_notify_transmit_ready (ts->destination.tunnel, | 563 | ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, |
527 | GNUNET_NO /* cork */, | 564 | GNUNET_NO /* cork */, |
528 | 42 /* priority */, | 565 | 42 /* priority */, |
529 | GNUNET_TIME_UNIT_FOREVER_REL, | 566 | GNUNET_TIME_UNIT_FOREVER_REL, |
@@ -536,8 +573,10 @@ send_to_peer_notify_callback (void *cls, size_t size, void *buf) | |||
536 | 573 | ||
537 | 574 | ||
538 | /** | 575 | /** |
539 | * Add the given message to the given tunnel and | 576 | * Add the given message to the given tunnel and trigger the |
540 | * trigger the transmission process. | 577 | * transmission process. |
578 | * | ||
579 | * FIXME: bound queue length! | ||
541 | * | 580 | * |
542 | * @param tnq message to queue | 581 | * @param tnq message to queue |
543 | * @param ts tunnel to queue the message for | 582 | * @param ts tunnel to queue the message for |
@@ -550,7 +589,7 @@ send_to_tunnel (struct TunnelMessageQueueEntry *tnq, | |||
550 | ts->tail, | 589 | ts->tail, |
551 | tnq); | 590 | tnq); |
552 | if (NULL == ts->th) | 591 | if (NULL == ts->th) |
553 | ts->th = GNUNET_MESH_notify_transmit_ready (ts->destination.tunnel, | 592 | ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, |
554 | GNUNET_NO /* cork */, | 593 | GNUNET_NO /* cork */, |
555 | 42 /* priority */, | 594 | 42 /* priority */, |
556 | GNUNET_TIME_UNIT_FOREVER_REL, | 595 | GNUNET_TIME_UNIT_FOREVER_REL, |
@@ -562,6 +601,65 @@ send_to_tunnel (struct TunnelMessageQueueEntry *tnq, | |||
562 | 601 | ||
563 | 602 | ||
564 | /** | 603 | /** |
604 | * Initialize the given destination entry's mesh tunnel. | ||
605 | * | ||
606 | * @param de destination entry for which we need to setup a tunnel | ||
607 | * @param client client to notify on successful tunnel setup, or NULL for none | ||
608 | * @param request_id request ID to send in client notification (unused if client is NULL) | ||
609 | * @return tunnel state of the tunnel that was created | ||
610 | */ | ||
611 | static struct TunnelState * | ||
612 | create_tunnel_to_destination (struct DestinationEntry *de, | ||
613 | struct GNUNET_SERVER_Client *client, | ||
614 | uint64_t request_id) | ||
615 | { | ||
616 | struct TunnelState *ts; | ||
617 | |||
618 | GNUNET_assert (NULL == de->ts); | ||
619 | ts = GNUNET_malloc (sizeof (struct TunnelState)); | ||
620 | if (NULL != client) | ||
621 | { | ||
622 | ts->request_id = request_id; | ||
623 | ts->client = client; | ||
624 | GNUNET_SERVER_client_keep (client); | ||
625 | } | ||
626 | ts->destination = *de; | ||
627 | ts->destination.heap_node = NULL; /* copy is NOT in destination heap */ | ||
628 | de->ts = ts; | ||
629 | ts->destination_container = de; /* we are referenced from de */ | ||
630 | ts->af = AF_UNSPEC; /* so far, unknown */ | ||
631 | ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle, | ||
632 | ts, | ||
633 | &tunnel_peer_connect_handler, | ||
634 | &tunnel_peer_disconnect_handler, | ||
635 | ts); | ||
636 | if (de->is_service) | ||
637 | { | ||
638 | GNUNET_MESH_peer_request_connect_add (ts->tunnel, | ||
639 | &de->details.service_destination.target); | ||
640 | } | ||
641 | else | ||
642 | { | ||
643 | switch (de->details.exit_destination.af) | ||
644 | { | ||
645 | case AF_INET: | ||
646 | GNUNET_MESH_peer_request_connect_by_type (ts->tunnel, | ||
647 | GNUNET_APPLICATION_TYPE_IPV4_GATEWAY); | ||
648 | break; | ||
649 | case AF_INET6: | ||
650 | GNUNET_MESH_peer_request_connect_by_type (ts->tunnel, | ||
651 | GNUNET_APPLICATION_TYPE_IPV6_GATEWAY); | ||
652 | break; | ||
653 | default: | ||
654 | GNUNET_assert (0); | ||
655 | break; | ||
656 | } | ||
657 | } | ||
658 | return ts; | ||
659 | } | ||
660 | |||
661 | |||
662 | /** | ||
565 | * Route a packet via mesh to the given destination. | 663 | * Route a packet via mesh to the given destination. |
566 | * | 664 | * |
567 | * @param destination description of the destination | 665 | * @param destination description of the destination |
@@ -590,7 +688,9 @@ route_packet (struct DestinationEntry *destination, | |||
590 | int is_new; | 688 | int is_new; |
591 | const struct udp_packet *udp; | 689 | const struct udp_packet *udp; |
592 | const struct tcp_packet *tcp; | 690 | const struct tcp_packet *tcp; |
593 | 691 | uint16_t spt; | |
692 | uint16_t dpt; | ||
693 | |||
594 | switch (protocol) | 694 | switch (protocol) |
595 | { | 695 | { |
596 | case IPPROTO_UDP: | 696 | case IPPROTO_UDP: |
@@ -602,12 +702,14 @@ route_packet (struct DestinationEntry *destination, | |||
602 | return; | 702 | return; |
603 | } | 703 | } |
604 | udp = payload; | 704 | udp = payload; |
705 | spt = ntohs (udp->spt); | ||
706 | dpt = ntohs (udp->dpt); | ||
605 | get_tunnel_key_from_ips (af, | 707 | get_tunnel_key_from_ips (af, |
606 | IPPROTO_UDP, | 708 | IPPROTO_UDP, |
607 | source_ip, | 709 | source_ip, |
608 | ntohs (udp->spt), | 710 | spt, |
609 | destination_ip, | 711 | destination_ip, |
610 | ntohs (udp->dpt), | 712 | dpt, |
611 | &key); | 713 | &key); |
612 | } | 714 | } |
613 | break; | 715 | break; |
@@ -620,12 +722,14 @@ route_packet (struct DestinationEntry *destination, | |||
620 | return; | 722 | return; |
621 | } | 723 | } |
622 | tcp = payload; | 724 | tcp = payload; |
725 | spt = ntohs (tcp->spt); | ||
726 | dpt = ntohs (tcp->dpt); | ||
623 | get_tunnel_key_from_ips (af, | 727 | get_tunnel_key_from_ips (af, |
624 | IPPROTO_TCP, | 728 | IPPROTO_TCP, |
625 | source_ip, | 729 | source_ip, |
626 | ntohs (tcp->spt), | 730 | spt, |
627 | destination_ip, | 731 | destination_ip, |
628 | ntohs (tcp->dpt), | 732 | dpt, |
629 | &key); | 733 | &key); |
630 | } | 734 | } |
631 | break; | 735 | break; |
@@ -660,29 +764,51 @@ route_packet (struct DestinationEntry *destination, | |||
660 | app_type = 0; | 764 | app_type = 0; |
661 | } | 765 | } |
662 | 766 | ||
663 | // FIXME: something is horrifically wrong here about | 767 | /* see if we have an existing tunnel for this destination */ |
664 | // how we lookup 'ts', match it and how we decide about | ||
665 | // creating new tunnels! | ||
666 | /* find tunnel */ | ||
667 | is_new = GNUNET_NO; | ||
668 | ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map, | 768 | ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map, |
669 | &key); | 769 | &key); |
670 | if (NULL == ts) | 770 | if (NULL == ts) |
671 | { | 771 | { |
672 | /* create new tunnel */ | 772 | /* need to either use the existing tunnel from the destination (if still |
773 | available) or create a fresh one */ | ||
673 | is_new = GNUNET_YES; | 774 | is_new = GNUNET_YES; |
674 | ts = GNUNET_malloc (sizeof (struct TunnelState)); | 775 | if (NULL == destination->ts) |
675 | ts->destination.tunnel = GNUNET_MESH_tunnel_create (mesh_handle, | 776 | ts = create_tunnel_to_destination (destination, NULL, 0); |
676 | ts, | ||
677 | &tunnel_peer_connect_handler, | ||
678 | &tunnel_peer_disconnect_handler, | ||
679 | ts); | ||
680 | if (destination->is_service) | ||
681 | GNUNET_MESH_peer_request_connect_add (ts->destination.tunnel, | ||
682 | &destination->details.service_destination.target); | ||
683 | else | 777 | else |
684 | GNUNET_MESH_peer_request_connect_by_type (ts->destination.tunnel, | 778 | ts = destination->ts; |
685 | app_type); | 779 | destination->ts = NULL; |
780 | ts->destination_container = NULL; /* no longer 'contained' */ | ||
781 | /* now bind existing "unbound" tunnel to our IP/port tuple */ | ||
782 | ts->protocol = protocol; | ||
783 | ts->af = af; | ||
784 | if (af == AF_INET) | ||
785 | { | ||
786 | ts->source_ip.v4 = * (const struct in_addr *) source_ip; | ||
787 | ts->destination_ip.v4 = * (const struct in_addr *) destination_ip; | ||
788 | } | ||
789 | else | ||
790 | { | ||
791 | ts->source_ip.v6 = * (const struct in6_addr *) source_ip; | ||
792 | ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip; | ||
793 | } | ||
794 | ts->source_port = spt; | ||
795 | ts->destination_port = dpt; | ||
796 | ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap, | ||
797 | ts, | ||
798 | GNUNET_TIME_absolute_get ().abs_value); | ||
799 | GNUNET_assert (GNUNET_YES == | ||
800 | GNUNET_CONTAINER_multihashmap_put (tunnel_map, | ||
801 | &key, | ||
802 | ts, | ||
803 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
804 | /* FIXME: expire OLD tunnels if we have too many! */ | ||
805 | } | ||
806 | else | ||
807 | { | ||
808 | is_new = GNUNET_NO; | ||
809 | GNUNET_CONTAINER_heap_update_cost (tunnel_heap, | ||
810 | ts->heap_node, | ||
811 | GNUNET_TIME_absolute_get ().abs_value); | ||
686 | } | 812 | } |
687 | 813 | ||
688 | /* send via tunnel */ | 814 | /* send via tunnel */ |
@@ -896,7 +1022,11 @@ message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, | |||
896 | &pkt6->destination_address, | 1022 | &pkt6->destination_address, |
897 | &key); | 1023 | &key); |
898 | de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key); | 1024 | de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key); |
899 | /* FIXME: do we need to guard against hash collision? */ | 1025 | /* FIXME: do we need to guard against hash collision? |
1026 | (if so, we need to also store the local destination IP in the | ||
1027 | destination entry and then compare here; however, the risk | ||
1028 | of collision seems minimal AND the impact is unlikely to be | ||
1029 | super-problematic as well... */ | ||
900 | if (NULL == de) | 1030 | if (NULL == de) |
901 | { | 1031 | { |
902 | char buf[INET6_ADDRSTRLEN]; | 1032 | char buf[INET6_ADDRSTRLEN]; |
@@ -933,7 +1063,11 @@ message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, | |||
933 | &pkt4->destination_address, | 1063 | &pkt4->destination_address, |
934 | &key); | 1064 | &key); |
935 | de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key); | 1065 | de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key); |
936 | /* FIXME: do we need to guard against hash collision? */ | 1066 | /* FIXME: do we need to guard against hash collision? |
1067 | (if so, we need to also store the local destination IP in the | ||
1068 | destination entry and then compare here; however, the risk | ||
1069 | of collision seems minimal AND the impact is unlikely to be | ||
1070 | super-problematic as well... */ | ||
937 | if (NULL == de) | 1071 | if (NULL == de) |
938 | { | 1072 | { |
939 | char buf[INET_ADDRSTRLEN]; | 1073 | char buf[INET_ADDRSTRLEN]; |
@@ -1004,6 +1138,11 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1004 | GNUNET_break_op (0); | 1138 | GNUNET_break_op (0); |
1005 | return GNUNET_SYSERR; | 1139 | return GNUNET_SYSERR; |
1006 | } | 1140 | } |
1141 | if (AF_UNSPEC == ts->af) | ||
1142 | { | ||
1143 | GNUNET_break_op (0); | ||
1144 | return GNUNET_SYSERR; | ||
1145 | } | ||
1007 | reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message; | 1146 | reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message; |
1008 | mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage); | 1147 | mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage); |
1009 | switch (ts->af) | 1148 | switch (ts->af) |
@@ -1125,14 +1264,9 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1125 | default: | 1264 | default: |
1126 | GNUNET_assert (0); | 1265 | GNUNET_assert (0); |
1127 | } | 1266 | } |
1128 | #if 0 | 1267 | GNUNET_CONTAINER_heap_update_cost (tunnel_heap, |
1129 | // FIXME: refresh entry to avoid expiration... | 1268 | ts->heap_node, |
1130 | struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); | ||
1131 | |||
1132 | GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, | ||
1133 | GNUNET_TIME_absolute_get ().abs_value); | 1269 | GNUNET_TIME_absolute_get ().abs_value); |
1134 | |||
1135 | #endif | ||
1136 | return GNUNET_OK; | 1270 | return GNUNET_OK; |
1137 | } | 1271 | } |
1138 | 1272 | ||
@@ -1286,15 +1420,9 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1286 | } | 1420 | } |
1287 | break; | 1421 | break; |
1288 | } | 1422 | } |
1289 | 1423 | GNUNET_CONTAINER_heap_update_cost (tunnel_heap, | |
1290 | #if 0 | 1424 | ts->heap_node, |
1291 | // FIXME: refresh entry to avoid expiration... | ||
1292 | struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); | ||
1293 | |||
1294 | GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, | ||
1295 | GNUNET_TIME_absolute_get ().abs_value); | 1425 | GNUNET_TIME_absolute_get ().abs_value); |
1296 | |||
1297 | #endif | ||
1298 | return GNUNET_OK; | 1426 | return GNUNET_OK; |
1299 | } | 1427 | } |
1300 | 1428 | ||
@@ -1436,7 +1564,6 @@ service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *cl | |||
1436 | void *addr; | 1564 | void *addr; |
1437 | struct DestinationEntry *de; | 1565 | struct DestinationEntry *de; |
1438 | GNUNET_HashCode key; | 1566 | GNUNET_HashCode key; |
1439 | struct TunnelState *ts; | ||
1440 | GNUNET_MESH_ApplicationType app_type; | 1567 | GNUNET_MESH_ApplicationType app_type; |
1441 | 1568 | ||
1442 | /* validate and parse request */ | 1569 | /* validate and parse request */ |
@@ -1540,6 +1667,7 @@ service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *cl | |||
1540 | get_destination_key_from_ip (result_af, | 1667 | get_destination_key_from_ip (result_af, |
1541 | addr, | 1668 | addr, |
1542 | &key); | 1669 | &key); |
1670 | de->key = key; | ||
1543 | GNUNET_assert (GNUNET_OK == | 1671 | GNUNET_assert (GNUNET_OK == |
1544 | GNUNET_CONTAINER_multihashmap_put (destination_map, | 1672 | GNUNET_CONTAINER_multihashmap_put (destination_map, |
1545 | &key, | 1673 | &key, |
@@ -1548,29 +1676,12 @@ service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *cl | |||
1548 | de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap, | 1676 | de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap, |
1549 | de, | 1677 | de, |
1550 | GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value); | 1678 | GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value); |
1679 | /* FIXME: expire OLD destinations if we have too many! */ | ||
1551 | /* setup tunnel to destination */ | 1680 | /* setup tunnel to destination */ |
1552 | ts = GNUNET_malloc (sizeof (struct TunnelState)); | 1681 | (void) create_tunnel_to_destination (de, |
1553 | if (GNUNET_NO != ntohl (msg->nac)) | 1682 | (GNUNET_NO == ntohl (msg->nac)) ? NULL : client, |
1554 | { | 1683 | msg->request_id); |
1555 | ts->request_id = msg->request_id; | 1684 | GNUNET_assert (NULL != de->ts); |
1556 | ts->client = client; | ||
1557 | GNUNET_SERVER_client_keep (client); | ||
1558 | } | ||
1559 | ts->destination = *de; | ||
1560 | ts->destination.heap_node = NULL; | ||
1561 | ts->is_service = GNUNET_NO; | ||
1562 | ts->af = result_af; | ||
1563 | if (result_af == AF_INET) | ||
1564 | ts->destination_ip.v4 = v4; | ||
1565 | else | ||
1566 | ts->destination_ip.v6 = v6; | ||
1567 | de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle, | ||
1568 | ts, | ||
1569 | &tunnel_peer_connect_handler, | ||
1570 | &tunnel_peer_disconnect_handler, | ||
1571 | ts); | ||
1572 | GNUNET_MESH_peer_request_connect_by_type (de->tunnel, | ||
1573 | app_type); | ||
1574 | /* we're done */ | 1685 | /* we're done */ |
1575 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1686 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1576 | } | 1687 | } |
@@ -1596,7 +1707,6 @@ service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Clien | |||
1596 | void *addr; | 1707 | void *addr; |
1597 | struct DestinationEntry *de; | 1708 | struct DestinationEntry *de; |
1598 | GNUNET_HashCode key; | 1709 | GNUNET_HashCode key; |
1599 | struct TunnelState *ts; | ||
1600 | 1710 | ||
1601 | /* parse request */ | 1711 | /* parse request */ |
1602 | msg = (const struct RedirectToServiceRequestMessage *) message; | 1712 | msg = (const struct RedirectToServiceRequestMessage *) message; |
@@ -1663,6 +1773,7 @@ service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Clien | |||
1663 | get_destination_key_from_ip (result_af, | 1773 | get_destination_key_from_ip (result_af, |
1664 | addr, | 1774 | addr, |
1665 | &key); | 1775 | &key); |
1776 | de->key = key; | ||
1666 | GNUNET_assert (GNUNET_OK == | 1777 | GNUNET_assert (GNUNET_OK == |
1667 | GNUNET_CONTAINER_multihashmap_put (destination_map, | 1778 | GNUNET_CONTAINER_multihashmap_put (destination_map, |
1668 | &key, | 1779 | &key, |
@@ -1671,30 +1782,10 @@ service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Clien | |||
1671 | de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap, | 1782 | de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap, |
1672 | de, | 1783 | de, |
1673 | GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value); | 1784 | GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value); |
1674 | 1785 | /* FIXME: expire OLD destinations if we have too many! */ | |
1675 | /* setup tunnel to destination */ | 1786 | (void) create_tunnel_to_destination (de, |
1676 | ts = GNUNET_malloc (sizeof (struct TunnelState)); | 1787 | (GNUNET_NO == ntohl (msg->nac)) ? NULL : client, |
1677 | if (GNUNET_NO != ntohl (msg->nac)) | 1788 | msg->request_id); |
1678 | { | ||
1679 | ts->request_id = msg->request_id; | ||
1680 | ts->client = client; | ||
1681 | GNUNET_SERVER_client_keep (client); | ||
1682 | } | ||
1683 | ts->destination = *de; | ||
1684 | ts->destination.heap_node = NULL; | ||
1685 | ts->is_service = GNUNET_YES; | ||
1686 | ts->af = result_af; | ||
1687 | if (result_af == AF_INET) | ||
1688 | ts->destination_ip.v4 = v4; | ||
1689 | else | ||
1690 | ts->destination_ip.v6 = v6; | ||
1691 | de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle, | ||
1692 | ts, | ||
1693 | &tunnel_peer_connect_handler, | ||
1694 | &tunnel_peer_disconnect_handler, | ||
1695 | ts); | ||
1696 | GNUNET_MESH_peer_request_connect_add (de->tunnel, | ||
1697 | &msg->target); | ||
1698 | /* we're done */ | 1789 | /* we're done */ |
1699 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1790 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1700 | } | 1791 | } |
@@ -1717,27 +1808,120 @@ inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel, | |||
1717 | const struct GNUNET_PeerIdentity *initiator, | 1808 | const struct GNUNET_PeerIdentity *initiator, |
1718 | const struct GNUNET_ATS_Information *atsi) | 1809 | const struct GNUNET_ATS_Information *atsi) |
1719 | { | 1810 | { |
1720 | /* Why should anyone open an inbound tunnel to vpn? */ | 1811 | /* How can and why should anyone open an inbound tunnel to vpn? */ |
1721 | GNUNET_break (0); | 1812 | GNUNET_break (0); |
1722 | return NULL; | 1813 | return NULL; |
1723 | } | 1814 | } |
1724 | 1815 | ||
1725 | 1816 | ||
1726 | /** | 1817 | /** |
1818 | * Free resources associated with a tunnel state. | ||
1819 | * | ||
1820 | * @param ts state to free | ||
1821 | */ | ||
1822 | static void | ||
1823 | free_tunnel_state (struct TunnelState *ts) | ||
1824 | { | ||
1825 | GNUNET_HashCode key; | ||
1826 | struct TunnelMessageQueueEntry *tnq; | ||
1827 | |||
1828 | while (NULL != (tnq = ts->head)) | ||
1829 | { | ||
1830 | GNUNET_CONTAINER_DLL_remove (ts->head, | ||
1831 | ts->tail, | ||
1832 | tnq); | ||
1833 | GNUNET_free (tnq); | ||
1834 | } | ||
1835 | if (NULL != ts->client) | ||
1836 | { | ||
1837 | GNUNET_SERVER_client_drop (ts->client); | ||
1838 | ts->client = NULL; | ||
1839 | } | ||
1840 | if (NULL != ts->th) | ||
1841 | { | ||
1842 | GNUNET_MESH_notify_transmit_ready_cancel (ts->th); | ||
1843 | ts->th = NULL; | ||
1844 | } | ||
1845 | GNUNET_assert (NULL == ts->destination.heap_node); | ||
1846 | if (NULL != ts->tunnel) | ||
1847 | { | ||
1848 | GNUNET_MESH_tunnel_destroy (ts->tunnel); | ||
1849 | ts->tunnel = NULL; | ||
1850 | } | ||
1851 | if (NULL != ts->heap_node) | ||
1852 | { | ||
1853 | GNUNET_CONTAINER_heap_remove_node (ts->heap_node); | ||
1854 | ts->heap_node = NULL; | ||
1855 | get_tunnel_key_from_ips (ts->af, | ||
1856 | ts->protocol, | ||
1857 | &ts->source_ip, | ||
1858 | ts->source_port, | ||
1859 | &ts->destination_ip, | ||
1860 | ts->destination_port, | ||
1861 | &key); | ||
1862 | GNUNET_assert (GNUNET_YES == | ||
1863 | GNUNET_CONTAINER_multihashmap_remove (tunnel_map, | ||
1864 | &key, | ||
1865 | ts)); | ||
1866 | } | ||
1867 | if (NULL != ts->destination_container) | ||
1868 | { | ||
1869 | GNUNET_assert (ts == ts->destination_container->ts); | ||
1870 | ts->destination_container->ts = NULL; | ||
1871 | ts->destination_container = NULL; | ||
1872 | } | ||
1873 | GNUNET_free (ts); | ||
1874 | } | ||
1875 | |||
1876 | |||
1877 | /** | ||
1878 | * Free resources occupied by a destination entry. | ||
1879 | * | ||
1880 | * @param de entry to free | ||
1881 | */ | ||
1882 | static void | ||
1883 | free_destination_entry (struct DestinationEntry *de) | ||
1884 | { | ||
1885 | if (NULL != de->ts) | ||
1886 | { | ||
1887 | free_tunnel_state (de->ts); | ||
1888 | GNUNET_assert (NULL == de->ts); | ||
1889 | } | ||
1890 | if (NULL != de->heap_node) | ||
1891 | { | ||
1892 | GNUNET_CONTAINER_heap_remove_node (de->heap_node); | ||
1893 | de->heap_node = NULL; | ||
1894 | GNUNET_assert (GNUNET_YES == | ||
1895 | GNUNET_CONTAINER_multihashmap_remove (destination_map, | ||
1896 | &de->key, | ||
1897 | de)); | ||
1898 | } | ||
1899 | GNUNET_free (de); | ||
1900 | } | ||
1901 | |||
1902 | |||
1903 | /** | ||
1727 | * Function called whenever an inbound tunnel is destroyed. Should clean up | 1904 | * Function called whenever an inbound tunnel is destroyed. Should clean up |
1728 | * any associated state. | 1905 | * any associated state. |
1729 | * | 1906 | * |
1730 | * @param cls closure (set from GNUNET_MESH_connect) | 1907 | * @param cls closure (set from GNUNET_MESH_connect) |
1731 | * @param tunnel connection to the other end (henceforth invalid) | 1908 | * @param tunnel connection to the other end (henceforth invalid) |
1732 | * @param tunnel_ctx place where local state associated | 1909 | * @param tunnel_ctx place where local state associated |
1733 | * with the tunnel is stored | 1910 | * with the tunnel is stored (our 'struct TunnelState') |
1734 | */ | 1911 | */ |
1735 | static void | 1912 | static void |
1736 | tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx) | 1913 | tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx) |
1737 | { | 1914 | { |
1738 | /* FIXME: is this function called for outbound tunnels that go down? | 1915 | struct TunnelState *ts = tunnel_ctx; |
1739 | Should we clean up something here? */ | 1916 | |
1740 | GNUNET_break (0); | 1917 | if (NULL == ts) |
1918 | { | ||
1919 | GNUNET_break (0); | ||
1920 | return; | ||
1921 | } | ||
1922 | GNUNET_assert (ts->tunnel == tunnel); | ||
1923 | ts->tunnel = NULL; | ||
1924 | free_tunnel_state (ts); | ||
1741 | } | 1925 | } |
1742 | 1926 | ||
1743 | 1927 | ||
@@ -1756,17 +1940,7 @@ cleanup_destination (void *cls, | |||
1756 | { | 1940 | { |
1757 | struct DestinationEntry *de = value; | 1941 | struct DestinationEntry *de = value; |
1758 | 1942 | ||
1759 | if (NULL != de->tunnel) | 1943 | free_destination_entry (de); |
1760 | { | ||
1761 | GNUNET_MESH_tunnel_destroy (de->tunnel); | ||
1762 | de->tunnel = NULL; | ||
1763 | } | ||
1764 | if (NULL != de->heap_node) | ||
1765 | { | ||
1766 | GNUNET_CONTAINER_heap_remove_node (de->heap_node); | ||
1767 | de->heap_node = NULL; | ||
1768 | } | ||
1769 | GNUNET_free (de); | ||
1770 | return GNUNET_OK; | 1944 | return GNUNET_OK; |
1771 | } | 1945 | } |
1772 | 1946 | ||
@@ -1785,37 +1959,8 @@ cleanup_tunnel (void *cls, | |||
1785 | void *value) | 1959 | void *value) |
1786 | { | 1960 | { |
1787 | struct TunnelState *ts = value; | 1961 | struct TunnelState *ts = value; |
1788 | struct TunnelMessageQueueEntry *tnq; | ||
1789 | 1962 | ||
1790 | while (NULL != (tnq = ts->head)) | 1963 | free_tunnel_state (ts); |
1791 | { | ||
1792 | GNUNET_CONTAINER_DLL_remove (ts->head, | ||
1793 | ts->tail, | ||
1794 | tnq); | ||
1795 | GNUNET_free (tnq); | ||
1796 | } | ||
1797 | if (NULL != ts->client) | ||
1798 | { | ||
1799 | GNUNET_SERVER_client_drop (ts->client); | ||
1800 | ts->client = NULL; | ||
1801 | } | ||
1802 | if (NULL != ts->th) | ||
1803 | { | ||
1804 | GNUNET_MESH_notify_transmit_ready_cancel (ts->th); | ||
1805 | ts->th = NULL; | ||
1806 | } | ||
1807 | if (NULL != ts->destination.tunnel) | ||
1808 | { | ||
1809 | GNUNET_MESH_tunnel_destroy (ts->destination.tunnel); | ||
1810 | ts->destination.tunnel = NULL; | ||
1811 | } | ||
1812 | if (NULL != ts->heap_node) | ||
1813 | { | ||
1814 | GNUNET_CONTAINER_heap_remove_node (ts->heap_node); | ||
1815 | ts->heap_node = NULL; | ||
1816 | } | ||
1817 | // FIXME... | ||
1818 | GNUNET_free (ts); | ||
1819 | return GNUNET_OK; | 1964 | return GNUNET_OK; |
1820 | } | 1965 | } |
1821 | 1966 | ||
@@ -1902,6 +2047,34 @@ cleanup_tunnel_client (void *cls, | |||
1902 | return GNUNET_OK; | 2047 | return GNUNET_OK; |
1903 | } | 2048 | } |
1904 | 2049 | ||
2050 | |||
2051 | /** | ||
2052 | * A client disconnected, clean up all references to it. | ||
2053 | * | ||
2054 | * @param cls the client that disconnected | ||
2055 | * @param key unused | ||
2056 | * @param value a 'struct DestinationEntry *' | ||
2057 | * @return GNUNET_OK (continue to iterate) | ||
2058 | */ | ||
2059 | static int | ||
2060 | cleanup_destination_client (void *cls, | ||
2061 | const GNUNET_HashCode *key, | ||
2062 | void *value) | ||
2063 | { | ||
2064 | struct GNUNET_SERVER_Client *client = cls; | ||
2065 | struct DestinationEntry *de = value; | ||
2066 | struct TunnelState *ts; | ||
2067 | |||
2068 | if (NULL == (ts = de->ts)) | ||
2069 | return GNUNET_OK; | ||
2070 | if (client == ts->client) | ||
2071 | { | ||
2072 | GNUNET_SERVER_client_drop (ts->client); | ||
2073 | ts->client = NULL; | ||
2074 | } | ||
2075 | return GNUNET_OK; | ||
2076 | } | ||
2077 | |||
1905 | 2078 | ||
1906 | /** | 2079 | /** |
1907 | * A client has disconnected from us. If we are currently building | 2080 | * A client has disconnected from us. If we are currently building |
@@ -1913,11 +2086,12 @@ cleanup_tunnel_client (void *cls, | |||
1913 | static void | 2086 | static void |
1914 | client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | 2087 | client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) |
1915 | { | 2088 | { |
1916 | // FIXME: check that all truly all 'struct TunnelState's | ||
1917 | // with clients are always in the tunnel map! | ||
1918 | GNUNET_CONTAINER_multihashmap_iterate (tunnel_map, | 2089 | GNUNET_CONTAINER_multihashmap_iterate (tunnel_map, |
1919 | &cleanup_tunnel_client, | 2090 | &cleanup_tunnel_client, |
1920 | client); | 2091 | client); |
2092 | GNUNET_CONTAINER_multihashmap_iterate (destination_map, | ||
2093 | &cleanup_destination_client, | ||
2094 | client); | ||
1921 | } | 2095 | } |
1922 | 2096 | ||
1923 | 2097 | ||