stuff
[oweals/gnunet.git] / src / core / core_api_peer_get_info.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
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 2, or (at your
8      option) any later version.
9
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.
14
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.
19 */
20
21 /**
22  * @file core/core_api_peer_get_info.c
23  * @brief implementation of the peer_change_preference functions 
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_core_service.h"
28 #include "core.h"
29
30
31 struct GNUNET_CORE_InformationRequestContext 
32 {
33   
34   /**
35    * Our connection to the service.
36    */
37   struct GNUNET_CLIENT_Connection *client;
38
39   /**
40    * Function to call with the information.
41    */
42   GNUNET_CORE_PeerConfigurationInfoCallback info;
43
44   /**
45    * Closure for info.
46    */
47   void *info_cls;
48
49 };
50
51
52 /**
53  * Receive reply from core service with information about a peer.
54  *
55  * @param cls our 'struct  GNUNET_CORE_InformationRequestContext *'
56  * @param msg NULL on error (i.e. timeout)
57  */
58 static void
59 receive_info (void *cls,
60               const struct GNUNET_MessageHeader *msg)
61 {
62   struct GNUNET_CORE_InformationRequestContext *irc = cls;
63   const struct ConfigurationInfoMessage *cim;
64   static struct GNUNET_BANDWIDTH_Value32NBO zbw; /* zero bandwidth */
65
66   if (msg == NULL)
67     {
68       if (irc->info != NULL)
69         irc->info (irc->info_cls, 
70                    NULL, zbw, zbw, 0, 0);     
71       GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
72       GNUNET_free (irc);
73       return;
74     }
75   if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO) ||
76        (ntohs (msg->size) != sizeof (struct ConfigurationInfoMessage)) )
77     {
78       GNUNET_break (0);
79       if (irc->info != NULL)
80         irc->info (irc->info_cls, 
81                    NULL, zbw, zbw, 0, 0);     
82       GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
83       GNUNET_free (irc);
84       return;
85     }
86   cim = (const struct ConfigurationInfoMessage*) msg;
87   if (irc->info != NULL)
88     irc->info (irc->info_cls,
89                &cim->peer,
90                cim->bw_in,
91                cim->bw_out,
92                ntohl (cim->reserved_amount),
93                GNUNET_ntohll (cim->preference));  
94   GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
95   GNUNET_free (irc);
96 }
97
98
99 /**
100  * Obtain statistics and/or change preferences for the given peer.
101  *
102  * @param sched scheduler to use
103  * @param cfg configuration to use
104  * @param peer identifies the peer
105  * @param timeout after how long should we give up (and call "info" with NULL
106  *                for "peer" to signal an error)?
107  * @param bw_out set to the current bandwidth limit (sending) for this peer,
108  *                caller should set "bw_out" to "-1" to avoid changing
109  *                the current value; otherwise "bw_out" will be lowered to
110  *                the specified value; passing a pointer to "0" can be used to force
111  *                us to disconnect from the peer; "bw_out" might not increase
112  *                as specified since the upper bound is generally
113  *                determined by the other peer!
114  * @param amount reserve N bytes for receiving, negative
115  *                amounts can be used to undo a (recent) reservation;
116  * @param preference increase incoming traffic share preference by this amount;
117  *                in the absence of "amount" reservations, we use this
118  *                preference value to assign proportional bandwidth shares
119  *                to all connected peers
120  * @param info function to call with the resulting configuration information
121  * @param info_cls closure for info
122  * @return NULL on error
123  */
124 struct GNUNET_CORE_InformationRequestContext *
125 GNUNET_CORE_peer_change_preference (struct GNUNET_SCHEDULER_Handle *sched,
126                                     const struct GNUNET_CONFIGURATION_Handle *cfg,
127                                     const struct GNUNET_PeerIdentity *peer,
128                                     struct GNUNET_TIME_Relative timeout,
129                                     struct GNUNET_BANDWIDTH_Value32NBO bw_out,
130                                     int32_t amount,
131                                     uint64_t preference,
132                                     GNUNET_CORE_PeerConfigurationInfoCallback info,
133                                     void *info_cls)
134 {
135   struct GNUNET_CORE_InformationRequestContext *irc;
136   struct RequestInfoMessage rim;
137   struct GNUNET_CLIENT_Connection *client;
138   int retry;
139
140   client = GNUNET_CLIENT_connect (sched, "core", cfg);
141   if (client == NULL)
142     return NULL;
143   irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext));
144   irc->client = client;
145   irc->info = info;
146   irc->info_cls = info_cls;
147   rim.header.size = htons (sizeof (struct RequestInfoMessage));
148   rim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO);
149   rim.reserved = htonl (0);
150   rim.limit_outbound = bw_out;
151   rim.reserve_inbound = htonl (amount);
152   rim.preference_change = GNUNET_htonll(preference);
153   rim.peer = *peer;
154   retry = ( (amount == 0) && (preference == 0) ) ? GNUNET_YES : GNUNET_NO;
155   GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client,
156                                                                        &rim.header,
157                                                                        timeout,
158                                                                        retry,
159                                                                        &receive_info,
160                                                                        irc));  
161   return irc;
162 }
163
164
165 /**
166  * Cancel request for getting information about a peer.
167  *
168  * @param irc context returned by the original GNUNET_CORE_peer_get_info call
169  */
170 void
171 GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequestContext *irc)
172 {
173   GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
174   GNUNET_free (irc);
175 }
176
177 /* end of core_api_peer_get_info.c */