- if ( (pr->prev != NULL) ||
- (pr->next != NULL) ||
- (pr == h->ready_peer_head) )
- {
- /* the request that was 'approved' by core was
- canceled before it could be transmitted; remove
- us from the 'ready' list */
- GNUNET_CONTAINER_DLL_remove (h->ready_peer_head,
- h->ready_peer_tail,
- pr);
- }
- request_next_transmission (pr);
- }
-}
-
-
-/* ****************** GNUNET_CORE_peer_request_connect ******************** */
-
-/**
- * Handle for a request to the core to connect to
- * a particular peer. Can be used to cancel the request
- * (before the 'cont'inuation is called).
- */
-struct GNUNET_CORE_PeerRequestHandle
-{
-
- /**
- * Link to control message.
- */
- struct ControlMessage *cm;
-
- /**
- * Core handle used.
- */
- struct GNUNET_CORE_Handle *h;
-
- /**
- * Continuation to run when done.
- */
- GNUNET_SCHEDULER_Task cont;
-
- /**
- * Closure for 'cont'.
- */
- void *cont_cls;
-
-};
-
-
-/**
- * Continuation called when the control message was transmitted.
- * Calls the original continuation and frees the remaining
- * resources.
- *
- * @param cls the 'struct GNUNET_CORE_PeerRequestHandle'
- * @param tc scheduler context
- */
-static void
-peer_request_connect_cont (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct GNUNET_CORE_PeerRequestHandle *ret = cls;
-
- if (ret->cont != NULL)
- {
- if (tc == NULL)
- GNUNET_SCHEDULER_add_now (ret->cont,
- ret->cont_cls);
- else
- ret->cont (ret->cont_cls, tc);
- }
- GNUNET_free (ret);
-}
-
-
-/**
- * Request that the core should try to connect to a particular peer.
- * Once the request has been transmitted to the core, the continuation
- * function will be called. Note that this does NOT mean that a
- * connection was successfully established -- it only means that the
- * core will now try. Successful establishment of the connection
- * will be signalled to the 'connects' callback argument of
- * 'GNUNET_CORE_connect' only. If the core service does not respond
- * to our connection attempt within the given time frame, 'cont' will
- * be called with the TIMEOUT reason code.
- *
- * @param h core handle
- * @param timeout how long to try to talk to core
- * @param peer who should we connect to
- * @param cont function to call once the request has been completed (or timed out)
- * @param cont_cls closure for cont
- * @return NULL on error (cont will not be called), otherwise handle for cancellation
- */
-struct GNUNET_CORE_PeerRequestHandle *
-GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h,
- struct GNUNET_TIME_Relative timeout,
- const struct GNUNET_PeerIdentity * peer,
- GNUNET_SCHEDULER_Task cont,
- void *cont_cls)
-{
- struct GNUNET_CORE_PeerRequestHandle *ret;
- struct ControlMessage *cm;
- struct ConnectMessage *msg;
-
- cm = GNUNET_malloc (sizeof (struct ControlMessage) +
- sizeof (struct ConnectMessage));
- msg = (struct ConnectMessage*) &cm[1];
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT);
- msg->header.size = htons (sizeof (struct ConnectMessage));
- msg->reserved = htonl (0);
- msg->timeout = GNUNET_TIME_relative_hton (timeout);
- msg->peer = *peer;
- GNUNET_CONTAINER_DLL_insert (h->control_pending_head,
- h->control_pending_tail,
- cm);
- ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle));
- ret->h = h;
- ret->cm = cm;
- ret->cont = cont;
- ret->cont_cls = cont_cls;
- cm->cont = &peer_request_connect_cont;
- cm->cont_cls = ret;
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Queueing REQUEST_CONNECT request\n");
-#endif
- if (h->control_pending_head == cm)
- trigger_next_request (h, GNUNET_NO);
- return ret;
-}
-
-
-/**
- * Cancel a pending request to connect to a particular peer. Must not
- * be called after the 'cont' function was invoked.
- *
- * @param req request handle that was returned for the original request
- */
-void
-GNUNET_CORE_peer_request_connect_cancel (struct GNUNET_CORE_PeerRequestHandle *req)
-{
- struct GNUNET_CORE_Handle *h = req->h;
- struct ControlMessage *cm = req->cm;
-
- GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
- h->control_pending_tail,
- cm);
- GNUNET_free (cm);
- GNUNET_free (req);
-}
-
-
-/* ****************** GNUNET_CORE_peer_change_preference ******************** */
-
-
-struct GNUNET_CORE_InformationRequestContext
-{
-
- /**
- * Our connection to the service.
- */
- struct GNUNET_CORE_Handle *h;
-
- /**
- * Function to call with the information.
- */
- GNUNET_CORE_PeerConfigurationInfoCallback info;
-
- /**
- * Closure for info.
- */
- void *info_cls;
-
- /**
- * Link to control message, NULL if CM was sent.
- */
- struct ControlMessage *cm;
-
- /**
- * Link to peer record.
- */
- struct PeerRecord *pr;
-};
-
-
-/**
- * CM was sent, remove link so we don't double-free.
- *
- * @param cls the 'struct GNUNET_CORE_InformationRequestContext'
- * @param tc scheduler context
- */
-static void
-change_preference_send_continuation (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct GNUNET_CORE_InformationRequestContext *irc = cls;
-
- irc->cm = NULL;
-}
-
-
-/**
- * Obtain statistics and/or change preferences for the given peer.
- *
- * @param h core handle
- * @param peer identifies the peer
- * @param timeout after how long should we give up (and call "info" with NULL
- * for "peer" to signal an error)?
- * @param bw_out set to the current bandwidth limit (sending) for this peer,
- * caller should set "bw_out" to "-1" to avoid changing
- * the current value; otherwise "bw_out" will be lowered to
- * the specified value; passing a pointer to "0" can be used to force
- * us to disconnect from the peer; "bw_out" might not increase
- * as specified since the upper bound is generally
- * determined by the other peer!
- * @param amount reserve N bytes for receiving, negative
- * amounts can be used to undo a (recent) reservation;
- * @param preference increase incoming traffic share preference by this amount;
- * in the absence of "amount" reservations, we use this
- * preference value to assign proportional bandwidth shares
- * to all connected peers
- * @param info function to call with the resulting configuration information
- * @param info_cls closure for info
- * @return NULL on error
- */
-struct GNUNET_CORE_InformationRequestContext *
-GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h,
- const struct GNUNET_PeerIdentity *peer,
- struct GNUNET_TIME_Relative timeout,
- struct GNUNET_BANDWIDTH_Value32NBO bw_out,
- int32_t amount,
- uint64_t preference,
- GNUNET_CORE_PeerConfigurationInfoCallback info,
- void *info_cls)
-{
- struct GNUNET_CORE_InformationRequestContext *irc;
- struct PeerRecord *pr;
- struct RequestInfoMessage *rim;
- struct ControlMessage *cm;
-
- pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
- &peer->hashPubKey);
- if (NULL == pr)
- {
- /* attempt to change preference on peer that is not connected */
- GNUNET_break (0);
- return NULL;
- }
- if (pr->pcic != NULL)
- {
- /* second change before first one is done */
- GNUNET_break (0);
- return NULL;
- }
- irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext));
- irc->h = h;
- irc->pr = pr;
- irc->info = info;
- irc->info_cls = info_cls;
- cm = GNUNET_malloc (sizeof (struct ControlMessage) +
- sizeof (struct RequestInfoMessage));
- cm->cont = &change_preference_send_continuation;
- cm->cont_cls = irc;
- irc->cm = cm;
- rim = (struct RequestInfoMessage*) &cm[1];
- rim->header.size = htons (sizeof (struct RequestInfoMessage));
- rim->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO);
- rim->rim_id = htonl (pr->rim_id = h->rim_id_gen++);
- rim->limit_outbound = bw_out;
- rim->reserve_inbound = htonl (amount);
- rim->preference_change = GNUNET_htonll(preference);
- rim->peer = *peer;
-#if DEBUG_CORE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Queueing CHANGE PREFERENCE request\n");
-#endif
- GNUNET_CONTAINER_DLL_insert (h->control_pending_head,
- h->control_pending_tail,
- cm);
- pr->pcic = info;
- pr->pcic_cls = info_cls;
- if (h->control_pending_head == cm)
- trigger_next_request (h, GNUNET_NO);
- return irc;
-}
-
-
-/**
- * Cancel request for getting information about a peer.
- * Note that an eventual change in preference, trust or bandwidth
- * assignment MAY have already been committed at the time,
- * so cancelling a request is NOT sure to undo the original
- * request. The original request may or may not still commit.
- * The only thing cancellation ensures is that the callback
- * from the original request will no longer be called.
- *
- * @param irc context returned by the original GNUNET_CORE_peer_get_info call
- */
-void
-GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequestContext *irc)
-{
- struct GNUNET_CORE_Handle *h = irc->h;
- struct PeerRecord *pr = irc->pr;
-
- if (irc->cm != NULL)
- {
- GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
- h->control_pending_tail,
- irc->cm);
- GNUNET_free (irc->cm);