aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo/peerinfo_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/peerinfo/peerinfo_api.c')
-rw-r--r--src/peerinfo/peerinfo_api.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c
new file mode 100644
index 000000000..ba5ade199
--- /dev/null
+++ b/src/peerinfo/peerinfo_api.c
@@ -0,0 +1,302 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2004, 2005, 2007, 2009 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 peerinfo/peerinfo_api.c
23 * @brief API to access peerinfo service
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_client_lib.h"
28#include "gnunet_peerinfo_service.h"
29#include "gnunet_protocols.h"
30#include "gnunet_time_lib.h"
31#include "peerinfo.h"
32
33#define ADD_PEER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
34
35
36struct CAFContext
37{
38 struct GNUNET_CLIENT_Connection *client;
39 struct GNUNET_MessageHeader *msg;
40};
41
42
43static size_t
44copy_and_free (void *cls, size_t size, void *buf)
45{
46 struct CAFContext *cc = cls;
47 struct GNUNET_MessageHeader *msg = cc->msg;
48 uint16_t msize;
49
50 if (buf == NULL)
51 {
52 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
53 _
54 ("Failed to transmit message of type %u to `%s' service.\n"),
55 ntohs (msg->type), "peerinfo");
56 GNUNET_free (msg);
57 GNUNET_CLIENT_disconnect (cc->client);
58 GNUNET_free (cc);
59 return 0;
60 }
61 msize = ntohs (msg->size);
62 GNUNET_assert (size >= msize);
63 memcpy (buf, msg, msize);
64 GNUNET_free (msg);
65 GNUNET_CLIENT_disconnect (cc->client);
66 GNUNET_free (cc);
67 return msize;
68}
69
70
71
72/**
73 * Add a host to the persistent list.
74 *
75 * @param cfg configuration to use
76 * @param sched scheduler to use
77 * @param peer identity of the peer
78 * @param hello the verified (!) HELLO message
79 * @param expiration when the HELLO will expire
80 */
81void
82GNUNET_PEERINFO_add_peer (struct GNUNET_CONFIGURATION_Handle *cfg,
83 struct GNUNET_SCHEDULER_Handle *sched,
84 const struct GNUNET_PeerIdentity *peer,
85 const struct GNUNET_HELLO_Message *hello)
86{
87 struct GNUNET_CLIENT_Connection *client;
88 struct PeerAddMessage *pam;
89 uint16_t hs;
90 struct CAFContext *cc;
91
92 client = GNUNET_CLIENT_connect (sched, "peerinfo", cfg);
93 if (client == NULL)
94 {
95 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
96 _("Could not connect to `%s' service.\n"), "peerinfo");
97 return;
98 }
99 hs = GNUNET_HELLO_size (hello);
100 pam = GNUNET_malloc (sizeof (struct PeerAddMessage) + hs);
101 pam->header.size = htons (hs + sizeof (struct PeerAddMessage));
102 pam->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_ADD);
103 memcpy (&pam->peer, peer, sizeof (struct GNUNET_PeerIdentity));
104 memcpy (&pam[1], hello, hs);
105 cc = GNUNET_malloc (sizeof (struct CAFContext));
106 cc->client = client;
107 cc->msg = &pam->header;
108 GNUNET_CLIENT_notify_transmit_ready (client,
109 ntohs (pam->header.size),
110 ADD_PEER_TIMEOUT, &copy_and_free, cc);
111}
112
113
114/**
115 * Context for the info handler.
116 */
117struct InfoContext
118{
119
120 /**
121 * Our connection to the PEERINFO service.
122 */
123 struct GNUNET_CLIENT_Connection *client;
124
125 /**
126 * Function to call with information.
127 */
128 GNUNET_PEERINFO_Processor callback;
129
130 /**
131 * Closure for callback.
132 */
133 void *callback_cls;
134
135 /**
136 * When should we time out?
137 */
138 struct GNUNET_TIME_Absolute timeout;
139
140};
141
142
143/**
144 * Type of a function to call when we receive a message
145 * from the service.
146 *
147 * @param cls closure
148 * @param msg message received, NULL on timeout or fatal error
149 */
150static void
151info_handler (void *cls, const struct GNUNET_MessageHeader *msg)
152{
153 struct InfoContext *ic = cls;
154 const struct InfoMessage *im;
155 const struct GNUNET_HELLO_Message *hello;
156 uint16_t ms;
157
158 if (msg == NULL)
159 {
160 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
161 _("Failed to receive response from `%s' service.\n"),
162 "peerinfo");
163 ic->callback (ic->callback_cls, NULL, NULL, 1);
164 GNUNET_CLIENT_disconnect (ic->client);
165 GNUNET_free (ic);
166 return;
167 }
168 if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END)
169 {
170 ic->callback (ic->callback_cls, NULL, NULL, 0);
171 GNUNET_CLIENT_disconnect (ic->client);
172 GNUNET_free (ic);
173 return;
174 }
175 ms = ntohs (msg->size);
176 if ((ms < sizeof (struct InfoMessage)) ||
177 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO))
178 {
179 GNUNET_break (0);
180 ic->callback (ic->callback_cls, NULL, NULL, 2);
181 GNUNET_CLIENT_disconnect (ic->client);
182 GNUNET_free (ic);
183 return;
184 }
185 im = (const struct InfoMessage *) msg;
186 hello = NULL;
187 if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader))
188 {
189 hello = (const struct GNUNET_HELLO_Message *) &im[1];
190 if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello))
191 {
192 GNUNET_break (0);
193 ic->callback (ic->callback_cls, NULL, NULL, 2);
194 GNUNET_CLIENT_disconnect (ic->client);
195 GNUNET_free (ic);
196 return;
197 }
198 }
199 ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust));
200 GNUNET_CLIENT_receive (ic->client,
201 &info_handler,
202 ic,
203 GNUNET_TIME_absolute_get_remaining (ic->timeout));
204}
205
206
207static size_t
208copy_then_receive (void *cls, size_t size, void *buf)
209{
210 struct InfoContext *ic = cls;
211 const struct GNUNET_MessageHeader *msg =
212 (const struct GNUNET_MessageHeader *) &ic[1];
213 uint16_t msize;
214
215 if (buf == NULL)
216 {
217 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
218 _
219 ("Failed to transmit message of type %u to `%s' service.\n"),
220 ntohs (msg->type), "peerinfo");
221 ic->callback (ic->callback_cls, NULL, NULL, 1);
222 GNUNET_CLIENT_disconnect (ic->client);
223 GNUNET_free (ic);
224 return 0;
225 }
226 msize = ntohs (msg->size);
227 GNUNET_assert (size >= msize);
228 memcpy (buf, msg, msize);
229 GNUNET_CLIENT_receive (ic->client,
230 &info_handler,
231 ic,
232 GNUNET_TIME_absolute_get_remaining (ic->timeout));
233 return msize;
234}
235
236
237/**
238 * Call a method for each known matching host and change
239 * its trust value. The method will be invoked once for
240 * each host and then finally once with a NULL pointer.
241 * Note that the last call can be triggered by timeout or
242 * by simply being done; however, the trust argument will
243 * be set to zero if we are done and to 1 if we timed out.
244 *
245 * @param cfg configuration to use
246 * @param sched scheduler to use
247 * @param peer restrict iteration to this peer only (can be NULL)
248 * @param trust_delta how much to change the trust in all matching peers
249 * @param timeout how long to wait until timing out
250 * @param callback the method to call for each peer
251 * @param callback_cls closure for callback
252 */
253void
254GNUNET_PEERINFO_for_all (struct GNUNET_CONFIGURATION_Handle *cfg,
255 struct GNUNET_SCHEDULER_Handle *sched,
256 const struct GNUNET_PeerIdentity *peer,
257 int trust_delta,
258 struct GNUNET_TIME_Relative timeout,
259 GNUNET_PEERINFO_Processor callback,
260 void *callback_cls)
261{
262 struct GNUNET_CLIENT_Connection *client;
263 struct ListAllPeersMessage *lapm;
264 struct ListPeerMessage *lpm;
265 size_t hs;
266 struct InfoContext *ihc;
267
268 client = GNUNET_CLIENT_connect (sched, "peerinfo", cfg);
269 if (client == NULL)
270 {
271 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
272 _("Could not connect to `%s' service.\n"), "peerinfo");
273 callback (callback_cls, NULL, NULL, 2);
274 return;
275 }
276 ihc = GNUNET_malloc (sizeof (struct InfoContext) +
277 sizeof (struct ListPeerMessage));
278 ihc->client = client;
279 ihc->callback = callback;
280 ihc->callback_cls = callback_cls;
281 ihc->timeout = GNUNET_TIME_relative_to_absolute (timeout);
282 hs = 0;
283 if (peer == NULL)
284 {
285 lapm = (struct ListAllPeersMessage *) &ihc[1];
286 lapm->header.size = htons (hs = sizeof (struct ListAllPeersMessage));
287 lapm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
288 lapm->trust_change = htonl (trust_delta);
289 }
290 else
291 {
292 lpm = (struct ListPeerMessage *) &ihc[1];
293 lpm->header.size = htons (hs = sizeof (struct ListPeerMessage));
294 lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
295 lpm->trust_change = htonl (trust_delta);
296 memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
297 }
298 GNUNET_CLIENT_notify_transmit_ready (client,
299 hs, timeout, &copy_then_receive, ihc);
300}
301
302/* end of peerinfo_api.c */