diff options
author | Bart Polot <bart@net.in.tum.de> | 2011-10-07 13:05:48 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2011-10-07 13:05:48 +0000 |
commit | 2dd4ee49cb5718ebc55e28ae93d21f2aeb5ad7da (patch) | |
tree | bd374275d92b865586032281c11971cc80dc200f /src/mesh | |
parent | d5417c5b080c8fb66b9117adf815dd1953bc012a (diff) | |
download | gnunet-2dd4ee49cb5718ebc55e28ae93d21f2aeb5ad7da.tar.gz gnunet-2dd4ee49cb5718ebc55e28ae93d21f2aeb5ad7da.zip |
Refactored connection to peers, cancelation of transmissions
Diffstat (limited to 'src/mesh')
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 536 |
1 files changed, 324 insertions, 212 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index a35ef9a66..612cade81 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -320,6 +320,11 @@ struct MeshPathInfo | |||
320 | * Path itself | 320 | * Path itself |
321 | */ | 321 | */ |
322 | struct MeshPeerPath *path; | 322 | struct MeshPeerPath *path; |
323 | |||
324 | /** | ||
325 | * Position in peer's transmit queue | ||
326 | */ | ||
327 | unsigned int pos; | ||
323 | }; | 328 | }; |
324 | 329 | ||
325 | 330 | ||
@@ -621,12 +626,167 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
621 | /******************************************************************************/ | 626 | /******************************************************************************/ |
622 | 627 | ||
623 | /** | 628 | /** |
629 | * Check if client has registered with the service and has not disconnected | ||
630 | * | ||
631 | * @param client the client to check | ||
632 | * | ||
633 | * @return non-NULL if client exists in the global DLL | ||
634 | */ | ||
635 | static struct MeshClient * | ||
636 | client_get (struct GNUNET_SERVER_Client *client) | ||
637 | { | ||
638 | struct MeshClient *c; | ||
639 | |||
640 | c = clients; | ||
641 | while (NULL != c) | ||
642 | { | ||
643 | if (c->handle == client) | ||
644 | return c; | ||
645 | c = c->next; | ||
646 | } | ||
647 | return NULL; | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Checks if a given client has subscribed to certain message type | ||
653 | * | ||
654 | * @param message_type Type of message to check | ||
655 | * @param c Client to check | ||
656 | * | ||
657 | * @return GNUNET_YES or GNUNET_NO, depending on subscription status | ||
658 | * | ||
659 | * TODO inline? | ||
660 | */ | ||
661 | static int | ||
662 | client_is_subscribed (uint16_t message_type, struct MeshClient *c) | ||
663 | { | ||
664 | GNUNET_HashCode hc; | ||
665 | |||
666 | GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc); | ||
667 | return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc); | ||
668 | } | ||
669 | |||
670 | |||
671 | /** | ||
672 | * Send the message to all clients that have subscribed to its type | ||
673 | * | ||
674 | * @param msg Pointer to the message itself | ||
675 | * @return number of clients this message was sent to | ||
676 | */ | ||
677 | static unsigned int | ||
678 | send_subscribed_clients (struct GNUNET_MessageHeader *msg) | ||
679 | { | ||
680 | struct MeshClient *c; | ||
681 | unsigned int count; | ||
682 | uint16_t type; | ||
683 | |||
684 | type = ntohs (msg->type); | ||
685 | for (count = 0, c = clients; c != NULL; c = c->next) | ||
686 | { | ||
687 | if (client_is_subscribed (type, c)) | ||
688 | { | ||
689 | count++; | ||
690 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, msg, | ||
691 | GNUNET_YES); | ||
692 | } | ||
693 | } | ||
694 | return count; | ||
695 | } | ||
696 | |||
697 | |||
698 | /** | ||
699 | * Notify the client that owns the tunnel that a peer has connected to it | ||
700 | * | ||
701 | * @param t Tunnel whose owner to notify | ||
702 | * @param id Short id of the peer that has connected | ||
703 | */ | ||
704 | static void | ||
705 | send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id) | ||
706 | { | ||
707 | struct GNUNET_MESH_PeerControl pc; | ||
708 | |||
709 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); | ||
710 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); | ||
711 | pc.tunnel_id = htonl (t->local_tid); | ||
712 | GNUNET_PEER_resolve (id, &pc.peer); | ||
713 | GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, | ||
714 | &pc.header, GNUNET_NO); | ||
715 | } | ||
716 | |||
717 | |||
718 | /** | ||
719 | * Cancel a core transmission that was already requested and free all resources | ||
720 | * associated to the request. | ||
721 | * | ||
722 | * @param peer PeeInfo of the peer whose transmission is cancelled. | ||
723 | * @param i Position of the transmission to be cancelled. | ||
724 | */ | ||
725 | static void | ||
726 | peer_info_cancel_transmission(struct MeshPeerInfo *peer, unsigned int i) | ||
727 | { | ||
728 | if (peer->core_transmit[i]) | ||
729 | { | ||
730 | struct MeshDataDescriptor *dd; | ||
731 | struct MeshPathInfo *path_info; | ||
732 | GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit[i]); | ||
733 | /* TODO: notify that tranmission has failed */ | ||
734 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
735 | "MESH: Cancelled data transmission at %u\n", | ||
736 | i); | ||
737 | switch (peer->types[i]) | ||
738 | { | ||
739 | case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: | ||
740 | case GNUNET_MESSAGE_TYPE_MESH_UNICAST: | ||
741 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: | ||
742 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type payload\n"); | ||
743 | dd = peer->infos[i]; | ||
744 | if (0 == --(*dd->copies)) | ||
745 | { | ||
746 | GNUNET_free (dd->copies); | ||
747 | GNUNET_free (dd->data); | ||
748 | } | ||
749 | break; | ||
750 | case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: | ||
751 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type create path\n"); | ||
752 | path_info = peer->infos[i]; | ||
753 | path_destroy(path_info->path); | ||
754 | break; | ||
755 | } | ||
756 | GNUNET_free (peer->infos[i]); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | |||
761 | /** | ||
762 | * | ||
763 | */ | ||
764 | static unsigned int | ||
765 | peer_info_transmit_position (struct MeshPeerInfo *peer) | ||
766 | { | ||
767 | unsigned int i; | ||
768 | |||
769 | for (i = 0; peer->core_transmit[i]; i++) | ||
770 | { | ||
771 | if (i == (CORE_QUEUE_SIZE - 1)) | ||
772 | { | ||
773 | /* All positions are taken! Overwriting! */ | ||
774 | GNUNET_break (0); | ||
775 | peer_info_cancel_transmission(peer, 0); | ||
776 | return 0; | ||
777 | } | ||
778 | } | ||
779 | return i; | ||
780 | } | ||
781 | |||
782 | |||
783 | /** | ||
624 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one | 784 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one |
625 | * and insert it in the appropiate structures if the peer is not known yet. | 785 | * and insert it in the appropiate structures if the peer is not known yet. |
626 | * | 786 | * |
627 | * @param peer Identity of the peer | 787 | * @param peer Full identity of the peer. |
628 | * | 788 | * |
629 | * @return Existing or newly created peer info | 789 | * @return Existing or newly created peer info. |
630 | */ | 790 | */ |
631 | static struct MeshPeerInfo * | 791 | static struct MeshPeerInfo * |
632 | peer_info_get (const struct GNUNET_PeerIdentity *peer) | 792 | peer_info_get (const struct GNUNET_PeerIdentity *peer) |
@@ -647,6 +807,113 @@ peer_info_get (const struct GNUNET_PeerIdentity *peer) | |||
647 | } | 807 | } |
648 | 808 | ||
649 | 809 | ||
810 | /** | ||
811 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one | ||
812 | * and insert it in the appropiate structures if the peer is not known yet. | ||
813 | * | ||
814 | * @param peer Short identity of the peer. | ||
815 | * | ||
816 | * @return Existing or newly created peer info. | ||
817 | */ | ||
818 | static struct MeshPeerInfo * | ||
819 | peer_info_get_short (const GNUNET_PEER_Id peer) | ||
820 | { | ||
821 | struct GNUNET_PeerIdentity id; | ||
822 | |||
823 | GNUNET_PEER_resolve(peer, &id); | ||
824 | return peer_info_get(&id); | ||
825 | } | ||
826 | |||
827 | |||
828 | /** | ||
829 | * Function called to notify a client about the socket | ||
830 | * being ready to queue more data. "buf" will be | ||
831 | * NULL and "size" zero if the socket was closed for | ||
832 | * writing in the meantime. | ||
833 | * | ||
834 | * @param cls closure | ||
835 | * @param size number of bytes available in buf | ||
836 | * @param buf where the callee should write the message | ||
837 | * @return number of bytes written to buf | ||
838 | */ | ||
839 | static size_t | ||
840 | send_core_create_path (void *cls, size_t size, void *buf); | ||
841 | |||
842 | |||
843 | /** | ||
844 | * Try to establish a new connection to this peer. | ||
845 | * Use the best path for the given tunnel. | ||
846 | * If the peer doesn't have any path to it yet, try to get one. | ||
847 | * If the peer already has some path, send a CREATE PATH towards it. | ||
848 | * | ||
849 | * @param peer PeerInfo of the peer. | ||
850 | * @param t Tunnel for which to create the path, if possible. | ||
851 | */ | ||
852 | static void | ||
853 | peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t) | ||
854 | { | ||
855 | struct MeshPeerPath *p; | ||
856 | struct MeshPathInfo *path_info; | ||
857 | struct MeshPeerInfo *neighbor; | ||
858 | |||
859 | if (NULL != peer->path_head) | ||
860 | { | ||
861 | p = tree_get_path_to_peer(t->tree, peer->id); | ||
862 | if (p->length > 1) | ||
863 | { | ||
864 | struct GNUNET_PeerIdentity *id; | ||
865 | |||
866 | path_info = GNUNET_malloc (sizeof (struct MeshPathInfo)); | ||
867 | path_info->path = p; | ||
868 | path_info->peer = peer; | ||
869 | path_info->t = t; | ||
870 | id = path_get_first_hop(t->tree, peer->id); | ||
871 | neighbor = peer_info_get(id); | ||
872 | path_info->pos = peer_info_transmit_position(neighbor); | ||
873 | neighbor->types[path_info->pos] = GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE; | ||
874 | neighbor->infos[path_info->pos] = path_info; | ||
875 | neighbor->core_transmit[path_info->pos] = | ||
876 | GNUNET_CORE_notify_transmit_ready ( | ||
877 | core_handle, /* handle */ | ||
878 | 0, /* cork */ | ||
879 | 0, /* priority */ | ||
880 | GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */ | ||
881 | id, /* target */ | ||
882 | sizeof (struct GNUNET_MESH_ManipulatePath) | ||
883 | + (p->length * sizeof (struct GNUNET_PeerIdentity)), /*size */ | ||
884 | &send_core_create_path, /* callback */ | ||
885 | path_info); /* cls */ | ||
886 | } | ||
887 | else | ||
888 | { | ||
889 | send_client_peer_connected(t, myid); | ||
890 | } | ||
891 | } | ||
892 | else if (NULL == peer->dhtget) | ||
893 | { | ||
894 | struct GNUNET_PeerIdentity id; | ||
895 | |||
896 | GNUNET_PEER_resolve(peer->id, &id); | ||
897 | path_info = GNUNET_malloc(sizeof(struct MeshPathInfo)); | ||
898 | path_info->peer = peer; | ||
899 | path_info->t = t; | ||
900 | peer->dhtget = | ||
901 | GNUNET_DHT_get_start(dht_handle, /* handle */ | ||
902 | GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */ | ||
903 | GNUNET_BLOCK_TYPE_TEST, /* type */ | ||
904 | &id.hashPubKey, /* key to search */ | ||
905 | 4, /* replication level */ | ||
906 | GNUNET_DHT_RO_RECORD_ROUTE | | ||
907 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
908 | NULL, /* xquery */ | ||
909 | 0, /* xquery bits */ | ||
910 | &dht_get_id_handler, | ||
911 | path_info); | ||
912 | } | ||
913 | /* Otherwise, there is no path but the DHT get is already started. */ | ||
914 | } | ||
915 | |||
916 | |||
650 | #if LATER | 917 | #if LATER |
651 | /** | 918 | /** |
652 | * Destroy the peer_info and free any allocated resources linked to it | 919 | * Destroy the peer_info and free any allocated resources linked to it |
@@ -749,8 +1016,7 @@ path_remove_from_peer (struct MeshPeerInfo *peer, | |||
749 | * Trivial immiediate fix: try to reconnect to the disconnected node. All | 1016 | * Trivial immiediate fix: try to reconnect to the disconnected node. All |
750 | * its children will be reachable trough him. | 1017 | * its children will be reachable trough him. |
751 | */ | 1018 | */ |
752 | GNUNET_PEER_resolve(d, &id); | 1019 | peer_d = peer_info_get_short(d); |
753 | peer_d = peer_info_get(&id); | ||
754 | best = UINT_MAX; | 1020 | best = UINT_MAX; |
755 | aux = NULL; | 1021 | aux = NULL; |
756 | for (p = peer_d->path_head; NULL != p; p = p->next) | 1022 | for (p = peer_d->path_head; NULL != p; p = p->next) |
@@ -817,6 +1083,11 @@ path_add_to_peer (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path) | |||
817 | } | 1083 | } |
818 | 1084 | ||
819 | l = path_get_length (path); | 1085 | l = path_get_length (path); |
1086 | if (0 == l) | ||
1087 | { | ||
1088 | GNUNET_free (path); | ||
1089 | return; | ||
1090 | } | ||
820 | 1091 | ||
821 | for (aux = peer_info->path_head; aux != NULL; aux = aux->next) | 1092 | for (aux = peer_info->path_head; aux != NULL; aux = aux->next) |
822 | { | 1093 | { |
@@ -963,49 +1234,6 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
963 | 1234 | ||
964 | 1235 | ||
965 | /** | 1236 | /** |
966 | * Check if client has registered with the service and has not disconnected | ||
967 | * | ||
968 | * @param client the client to check | ||
969 | * | ||
970 | * @return non-NULL if client exists in the global DLL | ||
971 | */ | ||
972 | static struct MeshClient * | ||
973 | client_get (struct GNUNET_SERVER_Client *client) | ||
974 | { | ||
975 | struct MeshClient *c; | ||
976 | |||
977 | c = clients; | ||
978 | while (NULL != c) | ||
979 | { | ||
980 | if (c->handle == client) | ||
981 | return c; | ||
982 | c = c->next; | ||
983 | } | ||
984 | return NULL; | ||
985 | } | ||
986 | |||
987 | |||
988 | /** | ||
989 | * Checks if a given client has subscribed to certain message type | ||
990 | * | ||
991 | * @param message_type Type of message to check | ||
992 | * @param c Client to check | ||
993 | * | ||
994 | * @return GNUNET_YES or GNUNET_NO, depending on subscription status | ||
995 | * | ||
996 | * TODO inline? | ||
997 | */ | ||
998 | static int | ||
999 | client_is_subscribed (uint16_t message_type, struct MeshClient *c) | ||
1000 | { | ||
1001 | GNUNET_HashCode hc; | ||
1002 | |||
1003 | GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc); | ||
1004 | return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc); | ||
1005 | } | ||
1006 | |||
1007 | |||
1008 | /** | ||
1009 | * Search for a tunnel among the tunnels for a client | 1237 | * Search for a tunnel among the tunnels for a client |
1010 | * | 1238 | * |
1011 | * @param c the client whose tunnels to search in | 1239 | * @param c the client whose tunnels to search in |
@@ -1069,24 +1297,27 @@ tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) | |||
1069 | void | 1297 | void |
1070 | notify_peer_disconnected (const struct MeshTunnelTreeNode *n) | 1298 | notify_peer_disconnected (const struct MeshTunnelTreeNode *n) |
1071 | { | 1299 | { |
1072 | struct GNUNET_MESH_PeerControl msg; | 1300 | struct MeshPeerInfo *peer; |
1073 | |||
1074 | if (NULL == n->t->client || NULL == nc) | ||
1075 | return; | ||
1076 | 1301 | ||
1077 | msg.header.size = htons (sizeof (msg)); | 1302 | if (NULL != n->t->client && NULL != nc) |
1078 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); | 1303 | { |
1079 | msg.tunnel_id = htonl (n->t->local_tid); | 1304 | struct GNUNET_MESH_PeerControl msg; |
1080 | GNUNET_PEER_resolve (n->peer, &msg.peer); | 1305 | msg.header.size = htons (sizeof (msg)); |
1081 | GNUNET_SERVER_notification_context_unicast (nc, n->t->client->handle, | 1306 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); |
1082 | &msg.header, GNUNET_NO); | 1307 | msg.tunnel_id = htonl (n->t->local_tid); |
1308 | GNUNET_PEER_resolve (n->peer, &msg.peer); | ||
1309 | GNUNET_SERVER_notification_context_unicast (nc, n->t->client->handle, | ||
1310 | &msg.header, GNUNET_NO); | ||
1311 | } | ||
1312 | peer = peer_info_get_short(n->peer); | ||
1313 | peer_info_connect(peer, n->t); | ||
1083 | } | 1314 | } |
1084 | 1315 | ||
1085 | 1316 | ||
1086 | /** | 1317 | /** |
1087 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all | 1318 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all |
1088 | * needed rescources. | 1319 | * needed rescources. |
1089 | * If peer already exists, do nothing. | 1320 | * If peer already exists, reevaluate shortest path and change if different. |
1090 | * | 1321 | * |
1091 | * @param t Tunnel we want to add a new peer to | 1322 | * @param t Tunnel we want to add a new peer to |
1092 | * @param peer PeerInfo of the peer being added | 1323 | * @param peer PeerInfo of the peer being added |
@@ -1095,40 +1326,48 @@ notify_peer_disconnected (const struct MeshTunnelTreeNode *n) | |||
1095 | static void | 1326 | static void |
1096 | tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) | 1327 | tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) |
1097 | { | 1328 | { |
1098 | struct MeshPeerPath *p; | 1329 | struct GNUNET_PeerIdentity id; |
1099 | struct MeshPeerPath *best_p; | 1330 | struct MeshPeerPath *best_p; |
1331 | struct MeshPeerPath *p; | ||
1100 | unsigned int best_cost; | 1332 | unsigned int best_cost; |
1101 | unsigned int cost; | 1333 | unsigned int cost; |
1102 | 1334 | ||
1103 | if (NULL != tree_find_peer(t->tree->root, peer->id)) | 1335 | GNUNET_PEER_resolve(peer->id, &id); |
1104 | { | 1336 | if (GNUNET_NO == |
1105 | /* Already have it, nothing to do. */ | 1337 | GNUNET_CONTAINER_multihashmap_contains(t->peers, &id.hashPubKey)) |
1106 | return; | ||
1107 | } | ||
1108 | |||
1109 | t->peers_total++; | ||
1110 | GNUNET_array_append (peer->tunnels, peer->ntunnels, t); | ||
1111 | if (NULL == (p = peer->path_head)) | ||
1112 | { | 1338 | { |
1113 | GNUNET_break (0); | 1339 | t->peers_total++; |
1114 | return; | 1340 | GNUNET_array_append (peer->tunnels, peer->ntunnels, t); |
1341 | GNUNET_CONTAINER_multihashmap_put( | ||
1342 | t->peers, | ||
1343 | &id.hashPubKey, | ||
1344 | peer, | ||
1345 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1115 | } | 1346 | } |
1116 | 1347 | ||
1117 | best_p = p; | 1348 | if (NULL != (p = peer->path_head)) |
1118 | best_cost = UINT_MAX; | ||
1119 | while (NULL != p) | ||
1120 | { | 1349 | { |
1121 | if ((cost = path_get_cost (t->tree, p)) < best_cost) | 1350 | best_p = p; |
1351 | best_cost = UINT_MAX; | ||
1352 | while (NULL != p) | ||
1122 | { | 1353 | { |
1123 | best_cost = cost; | 1354 | if ((cost = path_get_cost (t->tree, p)) < best_cost) |
1124 | best_p = p; | 1355 | { |
1356 | best_cost = cost; | ||
1357 | best_p = p; | ||
1358 | } | ||
1359 | p = p->next; | ||
1125 | } | 1360 | } |
1126 | p = p->next; | 1361 | tree_add_path (t->tree, best_p, ¬ify_peer_disconnected); |
1362 | if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task) | ||
1363 | t->path_refresh_task = | ||
1364 | GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); | ||
1365 | } | ||
1366 | else | ||
1367 | { | ||
1368 | /* Start a DHT get if necessary */ | ||
1369 | peer_info_connect(peer, t); | ||
1127 | } | 1370 | } |
1128 | tree_add_path (t->tree, best_p, ¬ify_peer_disconnected); | ||
1129 | if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task) | ||
1130 | t->path_refresh_task = | ||
1131 | GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); | ||
1132 | } | 1371 | } |
1133 | 1372 | ||
1134 | 1373 | ||
@@ -1240,7 +1479,6 @@ tunnel_destroy_iterator (void *cls, const GNUNET_HashCode * key, void *value) | |||
1240 | /**************** MESH NETWORK HANDLER HELPERS ***********************/ | 1479 | /**************** MESH NETWORK HANDLER HELPERS ***********************/ |
1241 | /******************************************************************************/ | 1480 | /******************************************************************************/ |
1242 | 1481 | ||
1243 | |||
1244 | /** | 1482 | /** |
1245 | * Function called to notify a client about the socket | 1483 | * Function called to notify a client about the socket |
1246 | * being ready to queue more data. "buf" will be | 1484 | * being ready to queue more data. "buf" will be |
@@ -1519,54 +1757,6 @@ send_p2p_tunnel_destroy (void *cls, size_t size, void *buf) | |||
1519 | #endif | 1757 | #endif |
1520 | 1758 | ||
1521 | 1759 | ||
1522 | /** | ||
1523 | * Send the message to all clients that have subscribed to its type | ||
1524 | * | ||
1525 | * @param msg Pointer to the message itself | ||
1526 | * @return number of clients this message was sent to | ||
1527 | */ | ||
1528 | static unsigned int | ||
1529 | send_subscribed_clients (struct GNUNET_MessageHeader *msg) | ||
1530 | { | ||
1531 | struct MeshClient *c; | ||
1532 | unsigned int count; | ||
1533 | uint16_t type; | ||
1534 | |||
1535 | type = ntohs (msg->type); | ||
1536 | for (count = 0, c = clients; c != NULL; c = c->next) | ||
1537 | { | ||
1538 | if (client_is_subscribed (type, c)) | ||
1539 | { | ||
1540 | count++; | ||
1541 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, msg, | ||
1542 | GNUNET_YES); | ||
1543 | } | ||
1544 | } | ||
1545 | return count; | ||
1546 | } | ||
1547 | |||
1548 | |||
1549 | |||
1550 | /** | ||
1551 | * Notify the client that owns the tunnel that a peer has connected to it | ||
1552 | * | ||
1553 | * @param t Tunnel whose owner to notify | ||
1554 | * @param id Short id of the peer that has connected | ||
1555 | */ | ||
1556 | static void | ||
1557 | send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id) | ||
1558 | { | ||
1559 | struct GNUNET_MESH_PeerControl pc; | ||
1560 | |||
1561 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); | ||
1562 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); | ||
1563 | pc.tunnel_id = htonl (t->local_tid); | ||
1564 | GNUNET_PEER_resolve (id, &pc.peer); | ||
1565 | GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, | ||
1566 | &pc.header, GNUNET_NO); | ||
1567 | } | ||
1568 | |||
1569 | |||
1570 | /******************************************************************************/ | 1760 | /******************************************************************************/ |
1571 | /******************** MESH NETWORK HANDLERS **************************/ | 1761 | /******************** MESH NETWORK HANDLERS **************************/ |
1572 | /******************************************************************************/ | 1762 | /******************************************************************************/ |
@@ -2185,9 +2375,7 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
2185 | enum GNUNET_BLOCK_Type type, size_t size, const void *data) | 2375 | enum GNUNET_BLOCK_Type type, size_t size, const void *data) |
2186 | { | 2376 | { |
2187 | struct MeshPathInfo *path_info = cls; | 2377 | struct MeshPathInfo *path_info = cls; |
2188 | struct MeshPathInfo *path_info_aux; | ||
2189 | struct MeshPeerPath *p; | 2378 | struct MeshPeerPath *p; |
2190 | struct MeshPeerPath *aux; | ||
2191 | struct GNUNET_PeerIdentity pi; | 2379 | struct GNUNET_PeerIdentity pi; |
2192 | int i; | 2380 | int i; |
2193 | 2381 | ||
@@ -2197,63 +2385,14 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
2197 | GNUNET_h2s_full(&pi.hashPubKey)); | 2385 | GNUNET_h2s_full(&pi.hashPubKey)); |
2198 | GNUNET_DHT_get_stop(path_info->peer->dhtget); | 2386 | GNUNET_DHT_get_stop(path_info->peer->dhtget); |
2199 | path_info->peer->dhtget = NULL; | 2387 | path_info->peer->dhtget = NULL; |
2200 | if (NULL == get_path || NULL == put_path) | ||
2201 | { | ||
2202 | if (NULL == path_info->peer->path_head) | ||
2203 | { | ||
2204 | // Find ourselves some alternate initial path to the destination: retry | ||
2205 | GNUNET_PEER_resolve(path_info->peer->id, &pi); | ||
2206 | path_info->peer->dhtget = | ||
2207 | GNUNET_DHT_get_start(dht_handle, /* handle */ | ||
2208 | GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */ | ||
2209 | GNUNET_BLOCK_TYPE_TEST, /* type */ | ||
2210 | &pi.hashPubKey, /*key to search */ | ||
2211 | 4, /* replication level */ | ||
2212 | GNUNET_DHT_RO_RECORD_ROUTE | | ||
2213 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
2214 | NULL, /* xquery */ | ||
2215 | 0, /* xquery bits */ | ||
2216 | &dht_get_id_handler, | ||
2217 | (void *) path_info); | ||
2218 | return; | ||
2219 | } | ||
2220 | } | ||
2221 | 2388 | ||
2222 | p = path_build_from_dht (get_path, get_path_length, put_path, put_path_length); | 2389 | p = path_build_from_dht (get_path, get_path_length, |
2390 | put_path, put_path_length); | ||
2223 | path_add_to_peer (path_info->peer, p); | 2391 | path_add_to_peer (path_info->peer, p); |
2224 | for (i = 0; i < path_info->peer->ntunnels; i++) | 2392 | for (i = 0; i < path_info->peer->ntunnels; i++) |
2225 | { | 2393 | { |
2226 | tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer); | 2394 | tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer); |
2227 | aux = tree_get_path_to_peer(path_info->peer->tunnels[i]->tree, | 2395 | peer_info_connect(path_info->peer, path_info->t); |
2228 | path_info->peer->id); | ||
2229 | if (aux->length > 1) | ||
2230 | { | ||
2231 | struct GNUNET_PeerIdentity id; | ||
2232 | |||
2233 | path_info_aux = GNUNET_malloc (sizeof (struct MeshPathInfo)); | ||
2234 | path_info_aux->path = aux; | ||
2235 | path_info_aux->peer = path_info->peer; | ||
2236 | path_info_aux->t = path_info->t; | ||
2237 | GNUNET_PEER_resolve (p->peers[1], &id); | ||
2238 | GNUNET_CORE_notify_transmit_ready (core_handle, /* handle */ | ||
2239 | 0, /* cork */ | ||
2240 | 0, /* priority */ | ||
2241 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
2242 | /* timeout */ | ||
2243 | &id, /* target */ | ||
2244 | sizeof (struct GNUNET_MESH_ManipulatePath) | ||
2245 | + | ||
2246 | (aux->length * | ||
2247 | sizeof (struct GNUNET_PeerIdentity)), | ||
2248 | /*size */ | ||
2249 | &send_core_create_path, | ||
2250 | /* callback */ | ||
2251 | path_info_aux); /* cls */ | ||
2252 | } | ||
2253 | else | ||
2254 | { | ||
2255 | send_client_peer_connected(path_info->t, myid); | ||
2256 | } | ||
2257 | } | 2396 | } |
2258 | GNUNET_free (path_info); | 2397 | GNUNET_free (path_info); |
2259 | 2398 | ||
@@ -3214,34 +3353,7 @@ core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) | |||
3214 | } | 3353 | } |
3215 | for (i = 0; i < CORE_QUEUE_SIZE; i++) | 3354 | for (i = 0; i < CORE_QUEUE_SIZE; i++) |
3216 | { | 3355 | { |
3217 | if (pi->core_transmit[i]) | 3356 | peer_info_cancel_transmission(pi, i); |
3218 | { | ||
3219 | struct MeshDataDescriptor *dd; | ||
3220 | struct MeshPathInfo *path_info; | ||
3221 | GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit[i]); | ||
3222 | /* TODO: notify that tranmission has failed */ | ||
3223 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: data at %u\n", i); | ||
3224 | switch (pi->types[i]) | ||
3225 | { | ||
3226 | case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: | ||
3227 | case GNUNET_MESSAGE_TYPE_MESH_UNICAST: | ||
3228 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: | ||
3229 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type payload\n"); | ||
3230 | dd = pi->infos[i]; | ||
3231 | if (0 == --(*dd->copies)) | ||
3232 | { | ||
3233 | GNUNET_free (dd->copies); | ||
3234 | GNUNET_free (dd->data); | ||
3235 | } | ||
3236 | break; | ||
3237 | case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: | ||
3238 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type create path\n"); | ||
3239 | path_info = pi->infos[i]; | ||
3240 | path_destroy(path_info->path); | ||
3241 | break; | ||
3242 | } | ||
3243 | GNUNET_free (pi->infos[i]); | ||
3244 | } | ||
3245 | } | 3357 | } |
3246 | path_remove_from_peer (pi, pi->id, myid); | 3358 | path_remove_from_peer (pi, pi->id, myid); |
3247 | if (myid == pi->id) | 3359 | if (myid == pi->id) |