+
+/**
+ * Request that the given peer isn't added to this tunnel in calls to
+ * connect_by_* calls, (due to misbehaviour, bad performance, ...).
+ *
+ * @param tunnel handle to existing tunnel.
+ * @param peer peer identity of the peer which should be blacklisted
+ * for the tunnel.
+ */
+void
+GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ struct GNUNET_MESH_PeerControl msg;
+
+ msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
+ msg.tunnel_id = htonl (tunnel->tid);
+ msg.peer = *peer;
+ send_packet (tunnel->mesh, &msg.header, tunnel);
+
+ return;
+}
+
+
+/**
+ * Request that the given peer isn't blacklisted anymore from this tunnel,
+ * and therefore can be added in future calls to connect_by_*.
+ * The peer must have been previously blacklisted for this tunnel.
+ *
+ * @param tunnel handle to existing tunnel.
+ * @param peer peer identity of the peer which shouldn't be blacklisted
+ * for the tunnel anymore.
+ */
+void
+GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ struct GNUNET_MESH_PeerControl msg;
+
+ msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
+ msg.tunnel_id = htonl (tunnel->tid);
+ msg.peer = *peer;
+ send_packet (tunnel->mesh, &msg.header, tunnel);
+
+ return;
+}
+
+
+/**
+ * Ask the mesh to call "notify" once it is ready to transmit the
+ * given number of bytes to the specified tunnel or target.
+ * Only one call can be active at any time, to issue another request,
+ * wait for the callback or cancel the current request.
+ *
+ * @param tunnel tunnel to use for transmission
+ * @param cork is corking allowed for this transmission?
+ * @param maxdelay how long can the message wait?
+ * @param target destination for the message
+ * NULL for multicast to all tunnel targets
+ * @param notify_size how many bytes of buffer space does notify want?
+ * @param notify function to call when buffer space is available;
+ * will be called with NULL on timeout or if the overall queue
+ * for this peer is larger than queue_size and this is currently
+ * the message with the lowest priority
+ * @param notify_cls closure for notify
+ * @return non-NULL if the notify callback was queued,
+ * NULL if we can not even queue the request (insufficient
+ * memory); if NULL is returned, "notify" will NOT be called.
+ */
+struct GNUNET_MESH_TransmitHandle *
+GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
+ struct GNUNET_TIME_Relative maxdelay,
+ const struct GNUNET_PeerIdentity *target,
+ size_t notify_size,
+ GNUNET_CONNECTION_TransmitReadyNotify notify,
+ void *notify_cls)
+{
+ struct GNUNET_MESH_TransmitHandle *th;
+ size_t overhead;
+
+ GNUNET_assert (NULL != tunnel);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "mesh notify transmit ready called\n");
+ if (NULL != target)
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " target %s\n", GNUNET_i2s (target));
+ else
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " target multicast\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size);
+ GNUNET_assert (NULL != notify);
+ GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
+ th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
+ th->tunnel = tunnel;
+ th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
+ th->target = GNUNET_PEER_intern (target);
+ if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
+ overhead = sizeof (struct GNUNET_MESH_ToOrigin);
+ else if (NULL == target)
+ overhead = sizeof (struct GNUNET_MESH_Multicast);
+ else
+ overhead = sizeof (struct GNUNET_MESH_Unicast);
+ tunnel->packet_size = th->size = notify_size + overhead;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size);
+ th->notify = notify;
+ th->notify_cls = notify_cls;
+ add_to_queue (tunnel->mesh, th);
+ if (NULL != tunnel->mesh->th)
+ return th;
+ if (GNUNET_NO == PID_OVERFLOW(tunnel->pid, tunnel->max_pid) &&
+ tunnel->max_pid <= tunnel->pid)
+ return th;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, " call notify tmt rdy\n");
+ tunnel->mesh->th =
+ GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_YES, &send_callback,
+ tunnel->mesh);
+ return th;
+}
+
+
+/**
+ * Cancel the specified transmission-ready notification.
+ *
+ * @param th handle that was returned by "notify_transmit_ready".
+ */
+void
+GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
+{
+ struct GNUNET_MESH_Handle *mesh;
+
+ th->tunnel->packet_size = 0;
+ mesh = th->tunnel->mesh;
+ if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (th->timeout_task);
+ GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
+ GNUNET_free (th);
+ if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
+ {
+ /* queue empty, no point in asking for transmission */
+ GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
+ mesh->th = NULL;
+ }
+}
+
+
+/**
+ * Transition API for tunnel ctx management
+ */
+void
+GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
+{
+ tunnel->ctx = data;
+}
+
+/**
+ * Transition API for tunnel ctx management
+ */
+void *
+GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
+{
+ return tunnel->ctx;