aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-14 22:23:44 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-14 22:23:44 +0000
commit269b1fc9b58fcba9dc5eb6e328ded1f07d8cb431 (patch)
tree3890f9ee137ca777c291702d5352f3fa1309b390 /src
parentf181f6eaf8cdb1fdb47dc98cf171ad1be842b441 (diff)
downloadgnunet-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.c480
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 */
57struct 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 */
53struct DestinationEntry 64struct 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
153struct TunnelState 170struct 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;
279static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map; 307static 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 */
284static struct GNUNET_CONTAINER_Heap *tunnel_heap; 313static 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 */
611static struct TunnelState *
612create_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 */
1822static void
1823free_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 */
1882static void
1883free_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 */
1735static void 1912static void
1736tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx) 1913tunnel_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 */
2059static int
2060cleanup_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,
1913static void 2086static void
1914client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) 2087client_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