diff options
author | Bart Polot <bart@net.in.tum.de> | 2011-06-24 08:04:56 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2011-06-24 08:04:56 +0000 |
commit | 8153b07b74e4fc34992dee4360173389656bb366 (patch) | |
tree | d631ae5946b893a5276d73fc51847a2d1a306252 | |
parent | b734352920d1731a739800549b0281421fe7b98c (diff) | |
download | gnunet-8153b07b74e4fc34992dee4360173389656bb366.tar.gz gnunet-8153b07b74e4fc34992dee4360173389656bb366.zip |
WiP (mesh data handling and connection ACKs)
-rw-r--r-- | src/include/gnunet_protocols.h | 2 | ||||
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 225 | ||||
-rw-r--r-- | src/mesh/mesh.h | 2 |
3 files changed, 209 insertions, 20 deletions
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 598d566bf..000b71f3b 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -835,7 +835,7 @@ extern "C" | |||
835 | /** | 835 | /** |
836 | * We need flow control | 836 | * We need flow control |
837 | */ | 837 | */ |
838 | #define GNUNET_MESSAGE_TYPE_MESH_SPEED_NOTIFY 263 | 838 | #define GNUNET_MESSAGE_TYPE_MESH_SPEED_NOTIFY 270 |
839 | 839 | ||
840 | /** | 840 | /** |
841 | * Connect to the mesh service, specifying subscriptions | 841 | * Connect to the mesh service, specifying subscriptions |
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 6cf01b6d4..afa9aec03 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -468,6 +468,29 @@ add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path) | |||
468 | 468 | ||
469 | 469 | ||
470 | /** | 470 | /** |
471 | * Add the path to the peer and update the path used to reach it in case this | ||
472 | * is the shortest. The path is given in reverse, the destination peer is | ||
473 | * path[0]. The function modifies the path, inverting it to use the origin as | ||
474 | * destination. | ||
475 | * @param peer_info Destination peer to add the path to. | ||
476 | * @param path New path to add. First peer must be the peer in arg 1. | ||
477 | */ | ||
478 | static void | ||
479 | add_path_to_origin(struct MeshPeerInfo *peer_info, struct MeshPath *path) | ||
480 | { | ||
481 | GNUNET_PEER_Id aux; | ||
482 | unsigned int i; | ||
483 | |||
484 | for (i = 0; i < path->length/2; i++) { | ||
485 | aux = path->peers[i]; | ||
486 | path->peers[i] = path->peers[path->length - i - 1]; | ||
487 | path->peers[path->length - i - 1] = aux; | ||
488 | } | ||
489 | add_path_to_peer(peer_info, path); | ||
490 | } | ||
491 | |||
492 | |||
493 | /** | ||
471 | * Check if client has registered with the service and has not disconnected | 494 | * Check if client has registered with the service and has not disconnected |
472 | * @param client the client to check | 495 | * @param client the client to check |
473 | * @return non-NULL if client exists in the global DLL | 496 | * @return non-NULL if client exists in the global DLL |
@@ -672,13 +695,116 @@ send_core_create_path_for_peer (void *cls, size_t size, void *buf) | |||
672 | GNUNET_PEER_resolve(p->peers[i], peer_ptr++); | 695 | GNUNET_PEER_resolve(p->peers[i], peer_ptr++); |
673 | } | 696 | } |
674 | 697 | ||
675 | peer_info->state = MESH_PEER_WAITING; // TODO maybe already ready? | 698 | peer_info->state = MESH_PEER_WAITING; |
676 | 699 | ||
677 | return size_needed; | 700 | return size_needed; |
678 | } | 701 | } |
679 | 702 | ||
703 | /** | ||
704 | * FIXME / COMMENT | ||
705 | * There are several options to send a "data to origin" or similar packet. | ||
706 | * The core callback function needs to know at least: ID of tunnel and the | ||
707 | * data itself, so one parameter (cls) is not enough. | ||
708 | * 1. Build the message inside the original funtction, call core_ntfy_trnsmt_rdy | ||
709 | * passing the created message as cls | ||
710 | * - # memcpy: 2 (function X: to message struct, callback: from cls to buf) | ||
711 | * - Very messy, original function becomes huge and ugly | ||
712 | * (see "handle_mesh_path_create" for example) | ||
713 | * 2. Create a helper function to build the packet, then call | ||
714 | * core_ntfy_trnsmt_rdy with message as cls. | ||
715 | * - # memcpy: 2 (in helper function data->msg and in callback cls->buf) | ||
716 | * 3- Define new container, pass container with pointers | ||
717 | * - # memcpy = 1 (in callback, cls->buf) | ||
718 | * - Noise: extra containers defined per type of message | ||
719 | */ | ||
720 | struct info_for_data_to_origin | ||
721 | { | ||
722 | struct MESH_TunnelID *origin; | ||
723 | void *data; | ||
724 | size_t size; | ||
725 | }; | ||
726 | |||
727 | /** | ||
728 | * Function called to notify a client about the socket | ||
729 | * being ready to queue more data. "buf" will be | ||
730 | * NULL and "size" zero if the socket was closed for | ||
731 | * writing in the meantime. | ||
732 | * | ||
733 | * @param cls closure (data itself) | ||
734 | * @param size number of bytes available in buf | ||
735 | * @param buf where the callee should write the message | ||
736 | * @return number of bytes written to buf | ||
737 | */ | ||
738 | static size_t | ||
739 | send_core_data_to_origin (void *cls, size_t size, void *buf) | ||
740 | { | ||
741 | struct info_for_data_to_origin *info = cls; | ||
742 | struct GNUNET_MESH_DataMessageToOrigin *msg = buf; | ||
743 | size_t total_size; | ||
744 | |||
745 | GNUNET_assert(NULL != info); | ||
746 | total_size = sizeof(struct GNUNET_MESH_DataMessageToOrigin) + info->size; | ||
747 | GNUNET_assert(total_size < (uint16_t) -1); /* FIXME */ | ||
748 | |||
749 | if (total_size > size) { | ||
750 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | ||
751 | "not enough buffer to send data to origin\n"); | ||
752 | return 0; | ||
753 | } | ||
754 | msg->header.size = htons(total_size); | ||
755 | msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN); | ||
756 | GNUNET_PEER_resolve(info->origin->oid, &msg->oid); | ||
757 | msg->tid = htonl(info->origin->tid); | ||
758 | if (0 != info->size && NULL != info->data) { | ||
759 | memcpy(&msg[1], info->data, info->size); | ||
760 | } | ||
761 | GNUNET_free(info); | ||
762 | return total_size; | ||
763 | } | ||
764 | |||
765 | |||
680 | #if LATER | 766 | #if LATER |
681 | /** | 767 | /** |
768 | * Function called to notify a client about the socket | ||
769 | * being ready to queue more data. "buf" will be | ||
770 | * NULL and "size" zero if the socket was closed for | ||
771 | * writing in the meantime. | ||
772 | * | ||
773 | * @param cls closure (data itself) | ||
774 | * @param size number of bytes available in buf | ||
775 | * @param buf where the callee should write the message | ||
776 | * @return number of bytes written to buf | ||
777 | */ | ||
778 | static size_t | ||
779 | send_core_data_to_peer (void *cls, size_t size, void *buf) | ||
780 | { | ||
781 | struct info_for_data_to_origin *info = cls; | ||
782 | struct GNUNET_MESH_DataMessageToOrigin *msg = buf; | ||
783 | size_t total_size; | ||
784 | |||
785 | GNUNET_assert(NULL != info); | ||
786 | total_size = sizeof(struct GNUNET_MESH_DataMessageToOrigin) + info->size; | ||
787 | /* FIXME better constant? short >= 16 bits, not == 16 bits... */ | ||
788 | GNUNET_assert(total_size < USHRT_MAX); | ||
789 | |||
790 | if (total_size > size) { | ||
791 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | ||
792 | "not enough buffer to send data to origin\n"); | ||
793 | return 0; | ||
794 | } | ||
795 | msg->header.size = htons(total_size); | ||
796 | msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN); | ||
797 | GNUNET_PEER_resolve(info->origin->oid, &msg->oid); | ||
798 | msg->tid = htonl(info->origin->tid); | ||
799 | if (0 != info->size && NULL != info->data) { | ||
800 | memcpy(&msg[1], info->data, info->size); | ||
801 | } | ||
802 | GNUNET_free(info); | ||
803 | return total_size; | ||
804 | } | ||
805 | |||
806 | |||
807 | /** | ||
682 | * Send another peer a notification to destroy a tunnel | 808 | * Send another peer a notification to destroy a tunnel |
683 | * @param cls The tunnel to destroy | 809 | * @param cls The tunnel to destroy |
684 | * @param size Size in the buffer | 810 | * @param size Size in the buffer |
@@ -734,9 +860,11 @@ handle_mesh_path_create (void *cls, | |||
734 | MESH_TunnelNumber tid; | 860 | MESH_TunnelNumber tid; |
735 | struct GNUNET_MESH_ManipulatePath *msg; | 861 | struct GNUNET_MESH_ManipulatePath *msg; |
736 | struct GNUNET_PeerIdentity *pi; | 862 | struct GNUNET_PeerIdentity *pi; |
863 | struct GNUNET_PeerIdentity id; | ||
737 | GNUNET_HashCode hash; | 864 | GNUNET_HashCode hash; |
738 | struct MeshPath *path; | 865 | struct MeshPath *path; |
739 | struct MeshPeerInfo *peer_info; | 866 | struct MeshPeerInfo *dest_peer_info; |
867 | struct MeshPeerInfo *orig_peer_info; | ||
740 | struct MeshTunnel *t; | 868 | struct MeshTunnel *t; |
741 | 869 | ||
742 | 870 | ||
@@ -786,17 +914,28 @@ handle_mesh_path_create (void *cls, | |||
786 | } | 914 | } |
787 | 915 | ||
788 | } | 916 | } |
789 | peer_info = GNUNET_CONTAINER_multihashmap_get(peers, | 917 | dest_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, |
790 | &pi[size - 1].hashPubKey); | 918 | &pi[size - 1].hashPubKey); |
791 | if (NULL == peer_info) { | 919 | if (NULL == dest_peer_info) { |
792 | peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo)); | 920 | dest_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo)); |
793 | peer_info->id = GNUNET_PEER_intern(&pi[size - 1]); | 921 | dest_peer_info->id = GNUNET_PEER_intern(&pi[size - 1]); |
794 | peer_info->state = MESH_PEER_WAITING; | 922 | dest_peer_info->state = MESH_PEER_WAITING; |
795 | GNUNET_CONTAINER_multihashmap_put(peers, | 923 | GNUNET_CONTAINER_multihashmap_put(peers, |
796 | &pi[size - 1].hashPubKey, | 924 | &pi[size - 1].hashPubKey, |
797 | peer_info, | 925 | dest_peer_info, |
798 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | 926 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); |
799 | } | 927 | } |
928 | orig_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, &pi->hashPubKey); | ||
929 | if (NULL == orig_peer_info) { | ||
930 | orig_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo)); | ||
931 | orig_peer_info->id = GNUNET_PEER_intern(pi); | ||
932 | orig_peer_info->state = MESH_PEER_WAITING; | ||
933 | GNUNET_CONTAINER_multihashmap_put(peers, | ||
934 | &pi->hashPubKey, | ||
935 | orig_peer_info, | ||
936 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
937 | } | ||
938 | |||
800 | 939 | ||
801 | path = GNUNET_malloc(sizeof(struct MeshPath)); | 940 | path = GNUNET_malloc(sizeof(struct MeshPath)); |
802 | path->length = size; | 941 | path->length = size; |
@@ -810,15 +949,42 @@ handle_mesh_path_create (void *cls, | |||
810 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | 949 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, |
811 | "create path: self not found in path through self\n"); | 950 | "create path: self not found in path through self\n"); |
812 | destroy_path(path); | 951 | destroy_path(path); |
813 | /* FIXME destroy tunnel? leave for timeout? */ | 952 | /* FIXME error. destroy tunnel? leave for timeout? */ |
814 | return 0; | 953 | return 0; |
815 | } | 954 | } |
816 | if (own_pos == size - 1) { /* it is for us! */ | 955 | if (own_pos == size - 1) { /* it is for us! */ |
817 | destroy_path(path); /* not needed anymore */ | 956 | add_path_to_origin(orig_peer_info, path); /* inverts path! */ |
818 | /* TODO: send ack? new meesage type? */ | 957 | GNUNET_PEER_resolve(get_first_hop(path), &id); /* path is inverted :) */ |
958 | /* FIXME / COMMENT | ||
959 | * is it allowed/desired to declare variables this way? | ||
960 | * (style, best bractices, etc) | ||
961 | * This variable is short lived and completely irrelevant for the rest | ||
962 | * of the function | ||
963 | */ | ||
964 | struct info_for_data_to_origin *info = | ||
965 | GNUNET_malloc(sizeof(struct info_for_data_to_origin)); | ||
966 | info->origin = &t->id; | ||
967 | info->data = NULL; | ||
968 | info->size = 0; | ||
969 | GNUNET_CORE_notify_transmit_ready(core_handle, | ||
970 | 0, | ||
971 | 0, | ||
972 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
973 | &id, | ||
974 | sizeof(struct GNUNET_MessageHeader), | ||
975 | &send_core_data_to_origin, | ||
976 | info); | ||
819 | } else { | 977 | } else { |
820 | add_path_to_peer(peer_info, path); | 978 | add_path_to_peer(dest_peer_info, path); |
821 | /* TODO: Retransmit to next link in chain, if any (core_notify + callback) */ | 979 | GNUNET_PEER_resolve(get_first_hop(path), &id); |
980 | GNUNET_CORE_notify_transmit_ready(core_handle, | ||
981 | 0, | ||
982 | 0, | ||
983 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
984 | &id, | ||
985 | sizeof(struct GNUNET_MessageHeader), | ||
986 | &send_core_create_path_for_peer, | ||
987 | dest_peer_info); | ||
822 | } | 988 | } |
823 | return GNUNET_OK; | 989 | return GNUNET_OK; |
824 | } | 990 | } |
@@ -1540,7 +1706,9 @@ handle_local_network_traffic (void *cls, | |||
1540 | { | 1706 | { |
1541 | struct MeshClient *c; | 1707 | struct MeshClient *c; |
1542 | struct MeshTunnel *t; | 1708 | struct MeshTunnel *t; |
1709 | struct MeshPeerInfo *pi; | ||
1543 | struct GNUNET_MESH_Data *data_msg; | 1710 | struct GNUNET_MESH_Data *data_msg; |
1711 | struct GNUNET_PeerIdentity next_hop; | ||
1544 | MESH_TunnelNumber tid; | 1712 | MESH_TunnelNumber tid; |
1545 | 1713 | ||
1546 | /* Sanity check for client registration */ | 1714 | /* Sanity check for client registration */ |
@@ -1568,16 +1736,37 @@ handle_local_network_traffic (void *cls, | |||
1568 | return; | 1736 | return; |
1569 | } | 1737 | } |
1570 | 1738 | ||
1571 | /* Does client own tunnel? */ | 1739 | /* Is it a local tunnel? Then, does client own the tunnel? */ |
1572 | if (t->client->handle != client) { | 1740 | if (t->client->handle != NULL && t->client->handle != client) { |
1573 | GNUNET_break(0); | 1741 | GNUNET_break(0); |
1574 | GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); | 1742 | GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); |
1575 | return; | 1743 | return; |
1576 | } | 1744 | } |
1577 | 1745 | ||
1578 | /* TODO */ | 1746 | pi = GNUNET_CONTAINER_multihashmap_get(t->peers, |
1579 | 1747 | &data_msg->peer_id.hashPubKey); | |
1580 | GNUNET_SERVER_receive_done(client, GNUNET_OK); | 1748 | /* Is the selected peer in the tunnel? */ |
1749 | if (NULL == pi) { | ||
1750 | /* TODO | ||
1751 | * Are we SO nice that we automatically try to add him to the tunnel? | ||
1752 | */ | ||
1753 | GNUNET_break(0); | ||
1754 | GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); | ||
1755 | return; | ||
1756 | } | ||
1757 | GNUNET_PEER_resolve(get_first_hop(pi->path), &next_hop); | ||
1758 | GNUNET_CORE_notify_transmit_ready(core_handle, | ||
1759 | 0, | ||
1760 | 0, | ||
1761 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1762 | &next_hop, | ||
1763 | /* FIXME re-check types */ | ||
1764 | message->size - sizeof(struct GNUNET_MESH_Data) | ||
1765 | + sizeof(struct GNUNET_MESH_DataMessageFromOrigin), | ||
1766 | &send_core_data_to_origin, /* FIXME re-check */ | ||
1767 | NULL); | ||
1768 | |||
1769 | GNUNET_SERVER_receive_done(client, GNUNET_OK); /* FIXME not yet */ | ||
1581 | return; | 1770 | return; |
1582 | } | 1771 | } |
1583 | 1772 | ||
diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h index bbfad3225..38f0486fb 100644 --- a/src/mesh/mesh.h +++ b/src/mesh/mesh.h | |||
@@ -206,7 +206,7 @@ struct GNUNET_MESH_Data { | |||
206 | struct GNUNET_MessageHeader header; | 206 | struct GNUNET_MessageHeader header; |
207 | 207 | ||
208 | /** | 208 | /** |
209 | * ID of a tunnel controlled by this client. | 209 | * ID of a tunnel in which this client participates. |
210 | */ | 210 | */ |
211 | MESH_TunnelNumber tunnel_id GNUNET_PACKED; | 211 | MESH_TunnelNumber tunnel_id GNUNET_PACKED; |
212 | 212 | ||