2 This file is part of GNUnet.
3 (C) 2010,2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file ats/ats_api_peer_change_preference.c
22 * @brief automatic transport selection API, preference management
23 * @author Christian Grothoff
24 * @author Matthias Wachs
28 * - extend API to get performance data
29 * - implement simplistic strategy based on say 'lowest latency' or strict ordering
30 * - extend API to get peer preferences, implement proportional bandwidth assignment
31 * - re-implement API against a real ATS service (!)
34 #include "gnunet_ats_service.h"
37 struct GNUNET_ATS_InformationRequestContext
41 * Our connection to the service.
43 struct GNUNET_ATS_SchedulingHandle *h;
49 GNUNET_ATS_PeerConfigurationInfoCallback info;
53 struct GNUNET_PeerIdentity peer;
55 GNUNET_SCHEDULER_TaskIdentifier task;
61 exec_pcp (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
63 struct GNUNET_ATS_InformationRequestContext *irc = cls;
66 struct GNUNET_TIME_Relative rdelay;
67 struct AllocationRecord *ar;
69 rdelay = GNUNET_TIME_UNIT_ZERO;
70 want_reserv = irc->amount;
71 ar = GNUNET_CONTAINER_multihashmap_get (irc->h->peers, &irc->peer.hashPubKey);
74 /* attempt to change preference on peer that is not connected */
75 /* FIXME: this can happen if the 'service' didn't yet tell us about
76 * a new connection, fake it! */
77 irc->info (irc->info_cls, &irc->peer, want_reserv, rdelay);
83 got_reserv = want_reserv;
85 else if (want_reserv > 0)
88 GNUNET_BANDWIDTH_tracker_get_delay (&ar->available_recv_window,
90 if (rdelay.rel_value == 0)
91 got_reserv = want_reserv;
93 got_reserv = 0; /* all or nothing */
97 GNUNET_BANDWIDTH_tracker_consume (&ar->available_recv_window, got_reserv);
99 irc->info (irc->info_cls, &irc->peer, got_reserv, rdelay);
105 * Obtain statistics and/or change preferences for the given peer.
107 * @param h core handle
108 * @param peer identifies the peer
109 * @param amount reserve N bytes for receiving, negative
110 * amounts can be used to undo a (recent) reservation;
111 * @param preference increase incoming traffic share preference by this amount;
112 * in the absence of "amount" reservations, we use this
113 * preference value to assign proportional bandwidth shares
114 * to all connected peers
115 * @param info function to call with the resulting configuration information
116 * @param info_cls closure for info
117 * @return NULL on error
119 struct GNUNET_ATS_InformationRequestContext *
120 GNUNET_ATS_peer_change_preference (struct GNUNET_ATS_SchedulingHandle *h,
121 const struct GNUNET_PeerIdentity *peer,
122 int32_t amount, uint64_t preference,
123 GNUNET_ATS_PeerConfigurationInfoCallback
124 info, void *info_cls)
126 struct GNUNET_ATS_InformationRequestContext *irc;
128 irc = GNUNET_malloc (sizeof (struct GNUNET_ATS_InformationRequestContext));
131 irc->amount = amount;
132 irc->preference = preference;
134 irc->info_cls = info_cls;
135 irc->task = GNUNET_SCHEDULER_add_now (&exec_pcp, irc);
141 * Cancel request for getting information about a peer.
142 * Note that an eventual change in preference, trust or bandwidth
143 * assignment MAY have already been committed at the time,
144 * so cancelling a request is NOT sure to undo the original
145 * request. The original request may or may not still commit.
146 * The only thing cancellation ensures is that the callback
147 * from the original request will no longer be called.
149 * @param irc context returned by the original GNUNET_ATS_peer_get_info call
152 GNUNET_ATS_peer_change_preference_cancel (struct
153 GNUNET_ATS_InformationRequestContext
156 GNUNET_SCHEDULER_cancel (irc->task);
162 /* old CORE API implementation follows for future reference */
163 struct GNUNET_ATS_InformationRequestContext
167 * Our connection to the service.
169 struct GNUNET_ATS_SchedulingHandle *h;
172 * Link to control message, NULL if CM was sent.
174 struct ControlMessage *cm;
177 * Link to peer record.
179 struct PeerRecord *pr;
184 * CM was sent, remove link so we don't double-free.
186 * @param cls the 'struct GNUNET_ATS_InformationRequestContext'
187 * @param success were we successful?
190 change_preference_send_continuation (void *cls, int success)
192 struct GNUNET_ATS_InformationRequestContext *irc = cls;
199 * Obtain statistics and/or change preferences for the given peer.
201 * @param h core handle
202 * @param peer identifies the peer
203 * @param amount reserve N bytes for receiving, negative
204 * amounts can be used to undo a (recent) reservation;
205 * @param preference increase incoming traffic share preference by this amount;
206 * in the absence of "amount" reservations, we use this
207 * preference value to assign proportional bandwidth shares
208 * to all connected peers
209 * @param info function to call with the resulting configuration information
210 * @param info_cls closure for info
211 * @return NULL on error
213 struct GNUNET_ATS_InformationRequestContext *
214 GNUNET_ATS_peer_change_preference (struct GNUNET_ATS_SchedulingHandle *h,
215 const struct GNUNET_PeerIdentity *peer,
216 int32_t amount, uint64_t preference,
217 GNUNET_ATS_PeerConfigurationInfoCallback
218 info, void *info_cls)
220 struct GNUNET_ATS_InformationRequestContext *irc;
221 struct PeerRecord *pr;
222 struct RequestInfoMessage *rim;
223 struct ControlMessage *cm;
225 pr = GNUNET_CONTAINER_multihashmap_get (h->peers, &peer->hashPubKey);
228 /* attempt to change preference on peer that is not connected */
232 if (pr->pcic != NULL)
234 /* second change before first one is done */
238 irc = GNUNET_malloc (sizeof (struct GNUNET_ATS_InformationRequestContext));
241 cm = GNUNET_malloc (sizeof (struct ControlMessage) +
242 sizeof (struct RequestInfoMessage));
243 cm->cont = &change_preference_send_continuation;
246 rim = (struct RequestInfoMessage *) &cm[1];
247 rim->header.size = htons (sizeof (struct RequestInfoMessage));
248 rim->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_REQUEST_INFO);
249 rim->rim_id = htonl (pr->rim_id = h->rim_id_gen++);
250 rim->reserved = htonl (0);
251 rim->reserve_inbound = htonl (amount);
252 rim->preference_change = GNUNET_htonll (preference);
254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255 "Queueing CHANGE PREFERENCE request for peer `%s' with RIM %u\n",
256 GNUNET_i2s (peer), (unsigned int) pr->rim_id);
257 GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
258 h->control_pending_tail, cm);
260 pr->pcic_cls = info_cls;
261 pr->pcic_ptr = irc; /* for free'ing irc */
262 if (NULL != h->client)
263 trigger_next_request (h, GNUNET_NO);
269 * Cancel request for getting information about a peer.
270 * Note that an eventual change in preference, trust or bandwidth
271 * assignment MAY have already been committed at the time,
272 * so cancelling a request is NOT sure to undo the original
273 * request. The original request may or may not still commit.
274 * The only thing cancellation ensures is that the callback
275 * from the original request will no longer be called.
277 * @param irc context returned by the original GNUNET_ATS_peer_get_info call
280 GNUNET_ATS_peer_change_preference_cancel (struct
281 GNUNET_ATS_InformationRequestContext
284 struct GNUNET_ATS_SchedulingHandle *h = irc->h;
285 struct PeerRecord *pr = irc->pr;
287 GNUNET_assert (pr->pcic_ptr == irc);
290 GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
291 h->control_pending_tail, irc->cm);
292 GNUNET_free (irc->cm);
301 /* end of ats_api_peer_change_preference.c */