GNUnet  0.11.x
peerinfo_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2001-2014 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_protocols.h"
29 #include "peerinfo.h"
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "peerinfo-api", __VA_ARGS__)
32 
33 
38 {
43 
48 
53 
58 
62  void *callback_cls;
63 
68 
72  int have_peer;
73 
78 };
79 
80 
85 {
90 
95 
100 
105 
110 };
111 
112 
118 static void
120 
121 
129 struct GNUNET_PEERINFO_Handle *
131 {
132  struct GNUNET_PEERINFO_Handle *h;
133 
134  h = GNUNET_new (struct GNUNET_PEERINFO_Handle);
135  h->cfg = cfg;
136  reconnect (h);
137  if (NULL == h->mq)
138  {
139  GNUNET_free (h);
140  return NULL;
141  }
142  return h;
143 }
144 
145 
155 void
157 {
159 
160  while (NULL != (ic = h->ic_head))
161  {
163  h->ic_tail,
164  ic);
165  GNUNET_free (ic);
166  }
167  if (NULL != h->mq)
168  {
169  GNUNET_MQ_destroy (h->mq);
170  h->mq = NULL;
171  }
172  if (NULL != h->r_task)
173  {
175  h->r_task = NULL;
176  }
177  GNUNET_free (h);
178 }
179 
180 
186 static void
187 reconnect_task (void *cls)
188 {
189  struct GNUNET_PEERINFO_Handle *h = cls;
190 
191  h->r_task = NULL;
192  reconnect (h);
193 }
194 
195 
201 static void
203 {
205 
206  GNUNET_MQ_destroy (h->mq);
207  h->mq = NULL;
208  if (NULL != ic)
209  {
211  h->ic_tail,
212  ic);
213  if (NULL != ic->callback)
214  ic->callback (ic->callback_cls,
215  NULL,
216  NULL,
217  _ ("Failed to receive response from `PEERINFO' service."));
218  GNUNET_free (ic);
219  }
221  h);
222 }
223 
224 
232 static void
233 mq_error_handler (void *cls,
234  enum GNUNET_MQ_Error error)
235 {
236  struct GNUNET_PEERINFO_Handle *h = cls;
237 
238  do_reconnect (h);
239 }
240 
241 
250 static int
251 check_info (void *cls,
252  const struct InfoMessage *im)
253 {
254  struct GNUNET_PEERINFO_Handle *h = cls;
256  uint16_t ms = ntohs (im->header.size) - sizeof(*im);
257 
258  if (0 != ntohl (im->reserved))
259  {
260  GNUNET_break (0);
261  return GNUNET_SYSERR;
262  }
263  if (NULL == ic)
264  {
265  /* didn't expect a response, bad */
266  GNUNET_break (0);
267  return GNUNET_SYSERR;
268  }
269  if ((GNUNET_YES == ic->have_peer) &&
270  (0 != GNUNET_memcmp (&ic->peer,
271  &im->peer)))
272  {
273  /* bogus message (from a different iteration call?); out of sequence! */
275  "Received HELLO for peer `%s', expected peer `%s'\n",
276  GNUNET_i2s (&im->peer),
277  GNUNET_i2s (&ic->peer));
278  GNUNET_break (0);
279  return GNUNET_SYSERR;
280  }
281  if (ms > sizeof(struct GNUNET_MessageHeader))
282  {
283  const struct GNUNET_HELLO_Message *hello;
284  struct GNUNET_PeerIdentity id;
285 
286  hello = (const struct GNUNET_HELLO_Message *) &im[1];
287  if (ms != GNUNET_HELLO_size (hello))
288  {
289  /* malformed message */
290  GNUNET_break (0);
291  return GNUNET_SYSERR;
292  }
293  if (GNUNET_OK !=
294  GNUNET_HELLO_get_id (hello,
295  &id))
296  {
297  /* malformed message */
298  GNUNET_break (0);
299  return GNUNET_SYSERR;
300  }
301  if (0 != GNUNET_memcmp (&im->peer,
302  &id))
303  {
304  /* malformed message */
305  GNUNET_break (0);
306  return GNUNET_SYSERR;
307  }
308  }
309  else if (0 != ms)
310  {
311  /* malformed message */
312  GNUNET_break (0);
313  return GNUNET_SYSERR;
314  }
315  return GNUNET_OK;
316 }
317 
318 
325 static void
326 handle_info (void *cls,
327  const struct InfoMessage *im)
328 {
329  struct GNUNET_PEERINFO_Handle *h = cls;
331  const struct GNUNET_HELLO_Message *hello = NULL;
332  uint16_t ms;
333 
334  ms = ntohs (im->header.size);
335  if (ms > sizeof(struct InfoMessage))
336  hello = (const struct GNUNET_HELLO_Message *) &im[1];
337  if (NULL != ic->callback)
338  ic->callback (ic->callback_cls,
339  &im->peer,
340  hello,
341  NULL);
342 }
343 
344 
350 static void
352 {
354  struct GNUNET_MQ_Envelope *env;
355  struct ListAllPeersMessage *lapm;
356  struct ListPeerMessage *lpm;
357 
358  if (NULL == ic)
359  {
360  GNUNET_break (0);
361  return;
362  }
363  if (NULL == h->mq)
364  {
365  GNUNET_break (0);
366  return;
367  }
368  if (GNUNET_NO == ic->have_peer)
369  {
371  "Requesting list of peers from PEERINFO service\n");
372  env = GNUNET_MQ_msg (lapm,
374  lapm->include_friend_only = htonl (ic->include_friend_only);
375  }
376  else
377  {
379  "Requesting information on peer `%s' from PEERINFO service\n",
380  GNUNET_i2s (&ic->peer));
381  env = GNUNET_MQ_msg (lpm,
383  lpm->include_friend_only = htonl (ic->include_friend_only);
384  lpm->peer = ic->peer;
385  }
386  GNUNET_MQ_send (h->mq,
387  env);
388 }
389 
390 
400 static void
402  const struct GNUNET_MessageHeader *msg)
403 {
404  struct GNUNET_PEERINFO_Handle *h = cls;
406 
407  if (NULL == ic)
408  {
409  /* didn't expect a response, reconnect */
410  GNUNET_break (0);
411  reconnect (h);
412  return;
413  }
415  "Received end of list of peers from PEERINFO service\n");
417  h->ic_tail,
418  ic);
419  if (NULL != h->ic_head)
420  send_ic_request (h);
421  if (NULL != ic->callback)
422  ic->callback (ic->callback_cls,
423  NULL,
424  NULL,
425  NULL);
426  GNUNET_free (ic);
427 }
428 
429 
435 static void
437 {
438  struct GNUNET_MQ_MessageHandler handlers[] = {
439  GNUNET_MQ_hd_var_size (info,
441  struct InfoMessage,
442  h),
443  GNUNET_MQ_hd_fixed_size (end_iteration,
445  struct GNUNET_MessageHeader,
446  h),
448  };
449 
450  if (NULL != h->r_task)
451  {
453  h->r_task = NULL;
454  }
455  if (NULL != h->mq)
456  {
457  GNUNET_MQ_destroy (h->mq);
458  h->mq = NULL;
459  }
460  h->mq = GNUNET_CLIENT_connect (h->cfg,
461  "peerinfo",
462  handlers,
464  h);
465  if (NULL != h->ic_head)
466  send_ic_request (h);
467 }
468 
469 
489  const struct GNUNET_PeerIdentity *peer,
491  void *callback_cls)
492 {
494 
496  ic->h = h;
498  ic->callback = callback;
500  if (NULL != peer)
501  {
502  ic->have_peer = GNUNET_YES;
503  ic->peer = *peer;
504  }
506  h->ic_tail,
507  ic);
508  if (h->ic_head == ic)
509  send_ic_request (h);
510  return ic;
511 }
512 
513 
519 void
521 {
522  struct GNUNET_PEERINFO_Handle *h = ic->h;
523 
524  ic->callback = NULL;
525  if (ic == h->ic_head)
526  return;
528  h->ic_tail,
529  ic);
530  GNUNET_free (ic);
531 }
532 
533 
552 struct GNUNET_MQ_Envelope *
554  const struct GNUNET_HELLO_Message *hello,
556  void *cont_cls)
557 {
558  struct GNUNET_MQ_Envelope *env;
559  struct GNUNET_PeerIdentity peer;
560 
561  if (NULL == h->mq)
562  return NULL;
564  GNUNET_HELLO_get_id (hello,
565  &peer));
567  "Adding peer `%s' to PEERINFO database\n",
568  GNUNET_i2s (&peer));
569  env = GNUNET_MQ_msg_copy ((const struct GNUNET_MessageHeader *) hello);
570  if (NULL != cont)
572  cont,
573  cont_cls);
574  GNUNET_MQ_send (h->mq,
575  env);
576  return env;
577 }
578 
579 
580 /* end of peerinfo_api.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:74
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET
Request update and listing of a peer.
struct GNUNET_MQ_Handle * mq
Connection to the service.
Definition: peerinfo_api.c:94
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:51
void(* GNUNET_PEERINFO_Processor)(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg)
Type of an iterator over the hosts.
int GNUNET_HELLO_get_id(const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer)
Get the peer identity from a HELLO message.
Definition: hello.c:671
struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_copy(const struct GNUNET_MessageHeader *hdr)
Create a new envelope by copying an existing message.
Definition: mq.c:653
Handle to the peerinfo service.
Definition: peerinfo_api.c:84
A HELLO message is used to exchange information about transports with other peers.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void reconnect(struct GNUNET_PEERINFO_Handle *h)
Close the existing connection to PEERINFO and reconnect.
Definition: peerinfo_api.c:436
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the peerinfo service.
Definition: peerinfo_api.c:130
struct GNUNET_PeerIdentity peer
Restrict to peers with this identity (optional field, check header.size!).
Definition: peerinfo.h:57
GNUNET_MQ_Error
Error codes for the queue.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void send_ic_request(struct GNUNET_PEERINFO_Handle *h)
Send the next IC request at the head of the queue.
Definition: peerinfo_api.c:351
Message used to inform the client about a particular peer; this message is optionally followed by a H...
Definition: peerinfo.h:102
struct GNUNET_PEERINFO_IteratorContext * ic_tail
Tail of iterator DLL.
Definition: peerinfo_api.c:104
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: peerinfo_api.c:89
struct GNUNET_PEERINFO_IteratorContext * ic_head
Head of iterator DLL.
Definition: peerinfo_api.c:99
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define LOG(kind,...)
Definition: peerinfo_api.c:31
Context for an iteration request.
Definition: peerinfo_api.c:37
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
static void do_reconnect(struct GNUNET_PEERINFO_Handle *h)
We encountered an error, reconnect to the PEERINFO service.
Definition: peerinfo_api.c:202
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_PeerIdentity peer
About which peer are we talking here?
Definition: peerinfo.h:117
struct GNUNET_PEERINFO_IteratorContext * GNUNET_PEERINFO_iterate(struct GNUNET_PEERINFO_Handle *h, int include_friend_only, const struct GNUNET_PeerIdentity *peer, GNUNET_PEERINFO_Processor callback, void *callback_cls)
Call a method for each known matching host.
Definition: peerinfo_api.c:487
void GNUNET_PEERINFO_iterate_cancel(struct GNUNET_PEERINFO_IteratorContext *ic)
Cancel an iteration over peer information.
Definition: peerinfo_api.c:520
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore...
Definition: mq.c:774
struct GNUNET_PEERINFO_IteratorContext * next
Kept in a DLL.
Definition: peerinfo_api.c:42
uint32_t reserved
Always zero.
Definition: peerinfo.h:112
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1280
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
We got a disconnect after asking regex to do the announcement.
Definition: peerinfo_api.c:233
void * callback_cls
Closure for callback.
Definition: peerinfo_api.c:62
static void handle_end_iteration(void *cls, const struct GNUNET_MessageHeader *msg)
Type of a function to call when we receive a message from the service.
Definition: peerinfo_api.c:401
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_PEERINFO_INFO.
Definition: peerinfo.h:107
struct GNUNET_MQ_Envelope * GNUNET_PEERINFO_add_peer(struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_HELLO_Message *hello, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Add a host to the persistent list.
Definition: peerinfo_api.c:553
static void reconnect_task(void *cls)
Task scheduled to re-try connecting to the peerinfo service.
Definition: peerinfo_api.c:187
Message handler for a specific message type.
struct GNUNET_SCHEDULER_Task * r_task
ID for a reconnect task.
Definition: peerinfo_api.c:109
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
common internal definitions for peerinfo service
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO
Information about one of the peers.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
Handle to a message queue.
Definition: mq.c:85
The identity of the host (wraps the signing key of the peer).
configuration data
Definition: configuration.c:85
GNUNET_PEERINFO_Processor callback
Function to call with the results.
Definition: peerinfo_api.c:57
static int check_info(void *cls, const struct InfoMessage *im)
Function called when we receive an info message.
Definition: peerinfo_api.c:251
static void handle_info(void *cls, const struct InfoMessage *im)
Handle info message.
Definition: peerinfo_api.c:326
Entry in list of pending tasks.
Definition: scheduler.c:134
Message requesting a listing of all peers, restricted to the specified peer identity.
Definition: peerinfo.h:64
int include_friend_only
Only include friends in reply?
Definition: peerinfo_api.c:77
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:652
Message requesting a listing of peers, restricted to the specified peer identity. ...
Definition: peerinfo.h:41
void GNUNET_PEERINFO_disconnect(struct GNUNET_PEERINFO_Handle *h)
Disconnect from the peerinfo service.
Definition: peerinfo_api.c:156
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL
Request update and listing of all peers.
Header for all communications.
struct GNUNET_PeerIdentity peer
Peer we are interested in (only valid if iteration was restricted to one peer).
Definition: peerinfo_api.c:67
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END
End of information about other peers.
struct GNUNET_PEERINFO_Handle * h
Handle to the PEERINFO service.
Definition: peerinfo_api.c:52
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
struct GNUNET_PEERINFO_IteratorContext * prev
Kept in a DLL.
Definition: peerinfo_api.c:47
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966