+ GNUNET_CONTAINER_DLL_insert (sets_head,
+ sets_tail,
+ set);
+ GNUNET_SERVER_receive_done (client,
+ GNUNET_OK);
+}
+
+
+/**
+ * Timeout happens iff:
+ * - we suggested an operation to our listener,
+ * but did not receive a response in time
+ * - we got the channel from a peer but no #GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST
+ *
+ * @param cls channel context
+ * @param tc context information (why was this task triggered now)
+ */
+static void
+incoming_timeout_cb (void *cls)
+{
+ struct Operation *incoming = cls;
+
+ incoming->timeout_task = NULL;
+ GNUNET_assert (GNUNET_YES == incoming->is_incoming);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Remote peer's incoming request timed out\n");
+ incoming_destroy (incoming);
+}
+
+
+/**
+ * Terminates an incoming operation in case we have not yet received an
+ * operation request. Called by the channel destruction handler.
+ *
+ * @param op the channel context
+ */
+static void
+handle_incoming_disconnect (struct Operation *op)
+{
+ GNUNET_assert (GNUNET_YES == op->is_incoming);
+ /* channel is already dead, incoming_destroy must not
+ * destroy it ... */
+ op->channel = NULL;
+ incoming_destroy (op);
+ op->vt = NULL;
+}
+
+
+/**
+ * Method called whenever another peer has added us to a channel the
+ * other peer initiated. Only called (once) upon reception of data
+ * from a channel we listen on.
+ *
+ * The channel context represents the operation itself and gets added
+ * to a DLL, from where it gets looked up when our local listener
+ * client responds to a proposed/suggested operation or connects and
+ * associates with this operation.
+ *
+ * @param cls closure
+ * @param channel new handle to the channel
+ * @param initiator peer that started the channel
+ * @param port Port this channel is for.
+ * @param options Unused.
+ * @return initial channel context for the channel
+ * returns NULL on error
+ */
+static void *
+channel_new_cb (void *cls,
+ struct GNUNET_CADET_Channel *channel,
+ const struct GNUNET_PeerIdentity *initiator,
+ const struct GNUNET_HashCode *port,
+ enum GNUNET_CADET_ChannelOption options)
+{
+ static const struct SetVT incoming_vt = {
+ .msg_handler = &handle_incoming_msg,
+ .peer_disconnect = &handle_incoming_disconnect
+ };
+ struct Listener *listener = cls;
+ struct Operation *incoming;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "New incoming channel\n");
+ incoming = GNUNET_new (struct Operation);
+ incoming->listener = listener;
+ incoming->is_incoming = GNUNET_YES;
+ incoming->peer = *initiator;
+ incoming->channel = channel;
+ incoming->mq = GNUNET_CADET_mq_create (incoming->channel);
+ incoming->vt = &incoming_vt;
+ incoming->timeout_task
+ = GNUNET_SCHEDULER_add_delayed (INCOMING_CHANNEL_TIMEOUT,
+ &incoming_timeout_cb,
+ incoming);
+ GNUNET_CONTAINER_DLL_insert_tail (incoming_head,
+ incoming_tail,
+ incoming);
+ // incoming_suggest (incoming,
+ // listener);
+ return incoming;