+
+ size_needed = sizeof(struct GNUNET_MESH_PeerControl);
+ peer_info = (struct MeshPeerInfo *) cls;
+ msg = (struct GNUNET_MESH_PeerControl *) buf;
+ msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
+ msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
+// msg->tunnel_id = htonl(peer_info->t->tid);
+ GNUNET_PEER_resolve(peer_info->id, &id);
+ memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
+
+ return size_needed;
+}
+#endif
+
+
+/**
+ * Send keepalive packets for a peer
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct MeshPeerInfo *peer_info = cls;
+ struct GNUNET_PeerIdentity id;
+
+ if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
+ GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
+ GNUNET_CORE_notify_transmit_ready(core_handle,
+ 0,
+ 0,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &id,
+ sizeof(struct GNUNET_MESH_ManipulatePath)
+ + (peer_info->path->length
+ * sizeof (struct GNUNET_PeerIdentity)),
+ &send_core_create_path_for_peer,
+ peer_info);
+
+ return;
+}
+
+
+/**
+ * Function to process paths received for a new peer addition. The recorded
+ * paths form the initial tunnel, which can be optimized later.
+ * Called on each result obtained for the DHT search.
+ *
+ * @param cls closure
+ * @param exp when will this value expire
+ * @param key key of the result
+ * @param get_path NULL-terminated array of pointers
+ * to the peers on reverse GET path (or NULL if not recorded)
+ * @param put_path NULL-terminated array of pointers
+ * to the peers on the PUT path (or NULL if not recorded)
+ * @param type type of the result
+ * @param size number of bytes in data
+ * @param data pointer to the result data
+ */
+static void
+dht_get_response_handler(void *cls,
+ struct GNUNET_TIME_Absolute exp,
+ const GNUNET_HashCode * key,
+ const struct GNUNET_PeerIdentity * const *get_path,
+ const struct GNUNET_PeerIdentity * const *put_path,
+ enum GNUNET_BLOCK_Type type,
+ size_t size,
+ const void *data)
+{
+ struct MeshPeerInfo *peer_info = cls;
+ struct MeshPath *p;
+ struct GNUNET_PeerIdentity pi;
+ int i;
+
+ if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
+ // Find ourselves some alternate initial path to the destination: retry
+ GNUNET_DHT_get_stop(peer_info->dhtget);
+ GNUNET_PEER_resolve(peer_info->id, &pi);
+ peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_BLOCK_TYPE_ANY,
+ &pi.hashPubKey,
+ 4, /* replication level */
+ GNUNET_DHT_RO_RECORD_ROUTE,
+ NULL, /* bloom filter */
+ 0, /* mutator */
+ NULL, /* xquery */
+ 0, /* xquery bits */
+ dht_get_response_handler,
+ (void *)peer_info);
+ }
+
+ p = GNUNET_malloc(sizeof(struct MeshPath));
+ for (i = 0; get_path[i] != NULL; i++);
+ for (i--; i >= 0; i--) {
+ p->peers = GNUNET_realloc(p->peers,
+ sizeof(GNUNET_PEER_Id) * (p->length + 1));
+ p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
+ p->length++;
+ }
+ for (i = 0; put_path[i] != NULL; i++);
+ for (i--; i >= 0; i--) {
+ p->peers = GNUNET_realloc(p->peers,
+ sizeof(GNUNET_PEER_Id) * (p->length + 1));
+ p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
+ p->length++;
+ }
+ add_path_to_peer(peer_info, p);
+ GNUNET_CORE_notify_transmit_ready(core_handle,
+ 0,
+ 0,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ get_path[1],
+ sizeof(struct GNUNET_MESH_ManipulatePath)
+ + (p->length
+ * sizeof (struct GNUNET_PeerIdentity)),
+ &send_core_create_path_for_peer,
+ peer_info);
+ GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
+ return;