GNUnet  0.20.0
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 
122 struct GNUNET_PEERINFO_Handle *
124 {
125  struct GNUNET_PEERINFO_Handle *h;
126 
128  h->cfg = cfg;
129  reconnect (h);
130  if (NULL == h->mq)
131  {
132  GNUNET_free (h);
133  return NULL;
134  }
135  return h;
136 }
137 
138 
148 void
150 {
152 
153  while (NULL != (ic = h->ic_head))
154  {
155  GNUNET_CONTAINER_DLL_remove (h->ic_head,
156  h->ic_tail,
157  ic);
158  GNUNET_free (ic);
159  }
160  if (NULL != h->mq)
161  {
163  h->mq = NULL;
164  }
165  if (NULL != h->r_task)
166  {
167  GNUNET_SCHEDULER_cancel (h->r_task);
168  h->r_task = NULL;
169  }
170  GNUNET_free (h);
171 }
172 
173 
179 static void
180 reconnect_task (void *cls)
181 {
182  struct GNUNET_PEERINFO_Handle *h = cls;
183 
184  h->r_task = NULL;
185  reconnect (h);
186 }
187 
188 
194 static void
196 {
197  struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
198 
200  h->mq = NULL;
201  if (NULL != ic)
202  {
203  GNUNET_CONTAINER_DLL_remove (h->ic_head,
204  h->ic_tail,
205  ic);
206  if (NULL != ic->callback)
207  ic->callback (ic->callback_cls,
208  NULL,
209  NULL,
210  _ ("Failed to receive response from `PEERINFO' service."));
211  GNUNET_free (ic);
212  }
214  h);
215 }
216 
217 
225 static void
226 mq_error_handler (void *cls,
227  enum GNUNET_MQ_Error error)
228 {
229  struct GNUNET_PEERINFO_Handle *h = cls;
230 
231  do_reconnect (h);
232 }
233 
234 
243 static int
244 check_info (void *cls,
245  const struct InfoMessage *im)
246 {
247  struct GNUNET_PEERINFO_Handle *h = cls;
248  struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
249  uint16_t ms = ntohs (im->header.size) - sizeof(*im);
250 
251  if (0 != ntohl (im->reserved))
252  {
253  GNUNET_break (0);
254  return GNUNET_SYSERR;
255  }
256  if (NULL == ic)
257  {
258  /* didn't expect a response, bad */
259  GNUNET_break (0);
260  return GNUNET_SYSERR;
261  }
262  if ((GNUNET_YES == ic->have_peer) &&
263  (0 != GNUNET_memcmp (&ic->peer,
264  &im->peer)))
265  {
266  /* bogus message (from a different iteration call?); out of sequence! */
268  "Received HELLO for peer `%s', expected peer `%s'\n",
269  GNUNET_i2s (&im->peer),
270  GNUNET_i2s (&ic->peer));
271  GNUNET_break (0);
272  return GNUNET_SYSERR;
273  }
274  if (ms > sizeof(struct GNUNET_MessageHeader))
275  {
276  const struct GNUNET_HELLO_Message *hello;
277  struct GNUNET_PeerIdentity id;
278 
279  hello = (const struct GNUNET_HELLO_Message *) &im[1];
280  if (ms != GNUNET_HELLO_size (hello))
281  {
282  /* malformed message */
283  GNUNET_break (0);
284  return GNUNET_SYSERR;
285  }
286  if (GNUNET_OK !=
287  GNUNET_HELLO_get_id (hello,
288  &id))
289  {
290  /* malformed message */
291  GNUNET_break (0);
292  return GNUNET_SYSERR;
293  }
294  if (0 != GNUNET_memcmp (&im->peer,
295  &id))
296  {
297  /* malformed message */
298  GNUNET_break (0);
299  return GNUNET_SYSERR;
300  }
301  }
302  else if (0 != ms)
303  {
304  /* malformed message */
305  GNUNET_break (0);
306  return GNUNET_SYSERR;
307  }
308  return GNUNET_OK;
309 }
310 
311 
318 static void
319 handle_info (void *cls,
320  const struct InfoMessage *im)
321 {
322  struct GNUNET_PEERINFO_Handle *h = cls;
323  struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
324  const struct GNUNET_HELLO_Message *hello = NULL;
325  uint16_t ms;
326 
327  ms = ntohs (im->header.size);
328  if (ms > sizeof(struct InfoMessage))
329  hello = (const struct GNUNET_HELLO_Message *) &im[1];
330  if (NULL != ic->callback)
331  ic->callback (ic->callback_cls,
332  &im->peer,
333  hello,
334  NULL);
335 }
336 
337 
343 static void
345 {
346  struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
347  struct GNUNET_MQ_Envelope *env;
348  struct ListAllPeersMessage *lapm;
349  struct ListPeerMessage *lpm;
350 
351  if (NULL == ic)
352  {
353  GNUNET_break (0);
354  return;
355  }
356  if (NULL == h->mq)
357  {
358  GNUNET_break (0);
359  return;
360  }
361  if (GNUNET_NO == ic->have_peer)
362  {
364  "Requesting list of peers from PEERINFO service\n");
365  env = GNUNET_MQ_msg (lapm,
367  lapm->include_friend_only = htonl (ic->include_friend_only);
368  }
369  else
370  {
372  "Requesting information on peer `%s' from PEERINFO service\n",
373  GNUNET_i2s (&ic->peer));
374  env = GNUNET_MQ_msg (lpm,
376  lpm->include_friend_only = htonl (ic->include_friend_only);
377  lpm->peer = ic->peer;
378  }
379  GNUNET_MQ_send (h->mq,
380  env);
381 }
382 
383 
393 static void
395  const struct GNUNET_MessageHeader *msg)
396 {
397  struct GNUNET_PEERINFO_Handle *h = cls;
398  struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head;
399 
400  if (NULL == ic)
401  {
402  /* didn't expect a response, reconnect */
403  GNUNET_break (0);
404  reconnect (h);
405  return;
406  }
408  "Received end of list of peers from PEERINFO service\n");
409  GNUNET_CONTAINER_DLL_remove (h->ic_head,
410  h->ic_tail,
411  ic);
412  if (NULL != h->ic_head)
413  send_ic_request (h);
414  if (NULL != ic->callback)
415  ic->callback (ic->callback_cls,
416  NULL,
417  NULL,
418  NULL);
419  GNUNET_free (ic);
420 }
421 
422 
428 static void
430 {
434  struct InfoMessage,
435  h),
436  GNUNET_MQ_hd_fixed_size (end_iteration,
438  struct GNUNET_MessageHeader,
439  h),
441  };
442 
443  if (NULL != h->r_task)
444  {
445  GNUNET_SCHEDULER_cancel (h->r_task);
446  h->r_task = NULL;
447  }
448  if (NULL != h->mq)
449  {
451  h->mq = NULL;
452  }
454  "peerinfo",
455  handlers,
457  h);
458  if (NULL != h->ic_head)
459  send_ic_request (h);
460 }
461 
462 
466  const struct GNUNET_PeerIdentity *peer,
468  void *callback_cls)
469 {
471 
473  ic->h = h;
475  ic->callback = callback;
477  if (NULL != peer)
478  {
479  ic->have_peer = GNUNET_YES;
480  ic->peer = *peer;
481  }
483  h->ic_tail,
484  ic);
485  if (h->ic_head == ic)
486  send_ic_request (h);
487  return ic;
488 }
489 
490 
496 void
498 {
499  struct GNUNET_PEERINFO_Handle *h = ic->h;
500 
501  ic->callback = NULL;
502  if (ic == h->ic_head)
503  return;
504  GNUNET_CONTAINER_DLL_remove (h->ic_head,
505  h->ic_tail,
506  ic);
507  GNUNET_free (ic);
508 }
509 
510 
529 struct GNUNET_MQ_Envelope *
531  const struct GNUNET_HELLO_Message *hello,
533  void *cont_cls)
534 {
535  struct GNUNET_MQ_Envelope *env;
536  struct GNUNET_PeerIdentity peer;
537 
538  if (NULL == h->mq)
539  return NULL;
541  GNUNET_HELLO_get_id (hello,
542  &peer));
544  "Adding peer `%s' to PEERINFO database\n",
545  GNUNET_i2s (&peer));
546  env = GNUNET_MQ_msg_copy ((const struct GNUNET_MessageHeader *) hello);
547  if (NULL != cont)
549  cont,
550  cont_cls);
551  GNUNET_MQ_send (h->mq,
552  env);
553  return env;
554 }
555 
556 
557 /* end of peerinfo_api.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
static int include_friend_only
Option '-f'.
#define info
Constants for network protocols.
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
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
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:649
uint16_t GNUNET_HELLO_size(const struct GNUNET_HELLO_Message *hello)
Return the size of the given HELLO message.
Definition: hello.c:630
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_MQ_Error
Error codes for the queue.
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:304
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
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:638
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:533
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
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.
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:530
struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the peerinfo service.
Definition: peerinfo_api.c:123
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:464
void GNUNET_PEERINFO_iterate_cancel(struct GNUNET_PEERINFO_IteratorContext *ic)
Cancel an iteration over peer information.
Definition: peerinfo_api.c:497
void GNUNET_PEERINFO_disconnect(struct GNUNET_PEERINFO_Handle *h)
Disconnect from the peerinfo service.
Definition: peerinfo_api.c:149
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END
End of information about other peers.
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET
Request update and listing of a peer.
#define GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL
Request update and listing of all peers.
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO
Information about one of the peers.
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:1299
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
common internal definitions for peerinfo service
static void handle_info(void *cls, const struct InfoMessage *im)
Handle info message.
Definition: peerinfo_api.c:319
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:344
static void reconnect(struct GNUNET_PEERINFO_Handle *h)
Close the existing connection to PEERINFO and reconnect.
Definition: peerinfo_api.c:429
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:226
static int check_info(void *cls, const struct InfoMessage *im)
Function called when we receive an info message.
Definition: peerinfo_api.c:244
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:394
static void do_reconnect(struct GNUNET_PEERINFO_Handle *h)
We encountered an error, reconnect to the PEERINFO service.
Definition: peerinfo_api.c:195
#define LOG(kind,...)
Definition: peerinfo_api.c:31
static void reconnect_task(void *cls)
Task scheduled to re-try connecting to the peerinfo service.
Definition: peerinfo_api.c:180
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
struct GNUNET_MQ_Handle * mq
Our connection to the ARM service.
Definition: arm_api.c:107
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration that we are using.
Definition: arm_api.c:112
A HELLO message is used to exchange information about transports with other peers.
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Handle to the peerinfo service.
Definition: peerinfo_api.c:85
struct GNUNET_MQ_Handle * mq
Connection to the service.
Definition: peerinfo_api.c:94
struct GNUNET_PEERINFO_IteratorContext * ic_tail
Tail of iterator DLL.
Definition: peerinfo_api.c:104
struct GNUNET_SCHEDULER_Task * r_task
ID for a reconnect task.
Definition: peerinfo_api.c:109
struct GNUNET_PEERINFO_IteratorContext * ic_head
Head of iterator DLL.
Definition: peerinfo_api.c:99
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: peerinfo_api.c:89
Context for an iteration request.
Definition: peerinfo_api.c:38
struct GNUNET_PEERINFO_IteratorContext * next
Kept in a DLL.
Definition: peerinfo_api.c:42
struct GNUNET_PEERINFO_IteratorContext * prev
Kept in a DLL.
Definition: peerinfo_api.c:47
void * callback_cls
Closure for callback.
Definition: peerinfo_api.c:62
struct GNUNET_PeerIdentity peer
Peer we are interested in (only valid if iteration was restricted to one peer).
Definition: peerinfo_api.c:67
GNUNET_PEERINFO_Processor callback
Function to call with the results.
Definition: peerinfo_api.c:57
int include_friend_only
Only include friends in reply?
Definition: peerinfo_api.c:77
struct GNUNET_PEERINFO_Handle * h
Handle to the PEERINFO service.
Definition: peerinfo_api.c:52
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:136
Message used to inform the client about a particular peer; this message is optionally followed by a H...
Definition: peerinfo.h:102
uint32_t reserved
Always zero.
Definition: peerinfo.h:111
struct GNUNET_PeerIdentity peer
About which peer are we talking here?
Definition: peerinfo.h:116
struct GNUNET_MessageHeader header
Type will be GNUNET_MESSAGE_TYPE_PEERINFO_INFO.
Definition: peerinfo.h:106
Message requesting a listing of all peers, restricted to the specified peer identity.
Definition: peerinfo.h:64
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:73
Message requesting a listing of peers, restricted to the specified peer identity.
Definition: peerinfo.h:41
struct GNUNET_PeerIdentity peer
Restrict to peers with this identity (optional field, check header.size!).
Definition: peerinfo.h:56
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:50
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.