GNUnet  0.20.0
gnunet-service-peerinfo.c File Reference

maintains list of known peers More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_hello_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_statistics_service.h"
#include "peerinfo.h"
Include dependency graph for gnunet-service-peerinfo.c:

Go to the source code of this file.

Data Structures

struct  HostEntry
 In-memory cache of known hosts. More...
 
struct  ReadHostFileContext
 Result of reading a file. More...
 
struct  DirScanContext
 Closure for hosts_directory_scan_callback(). More...
 
struct  TransmitContext
 Closure for add_to_tc() More...
 

Macros

#define DATA_HOST_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
 How often do we scan the HOST_DIR for new entries? More...
 
#define DATA_HOST_CLEAN_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
 How often do we discard old entries in data/hosts/? More...
 

Functions

static struct InfoMessagemake_info_message (const struct HostEntry *he, int include_friend_only)
 Notify all clients in the notify list about the given host entry changing. More...
 
static int discard_expired (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
 Address iterator that causes expired entries to be discarded. More...
 
static int count_addresses (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
 Address iterator that counts the remaining addresses. More...
 
static char * get_host_filename (const struct GNUNET_PeerIdentity *id)
 Get the filename under which we would store the GNUNET_HELLO_Message for the given host and protocol. More...
 
static void notify_all (struct HostEntry *entry)
 Broadcast information about the given entry to all clients that care. More...
 
static void update_hello (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello)
 Bind a host address (hello) to a hostId. More...
 
static void read_host_file (const char *fn, int unlink_garbage, struct ReadHostFileContext *r)
 Try to read the HELLOs in the given filename and discard expired addresses. More...
 
static struct HostEntryadd_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
 Add a host to the list and notify clients about this event. More...
 
static void remove_garbage (const char *fullname)
 Remove a file that should not be there. More...
 
static int hosts_directory_scan_callback (void *cls, const char *fullname)
 Function that is called on each HELLO file in a particular directory. More...
 
static void cron_scan_directory_data_hosts (void *cls)
 Call this method periodically to scan data/hosts for new hosts. More...
 
static struct GNUNET_HELLO_Messageupdate_friend_hello (const struct GNUNET_HELLO_Message *hello, const struct GNUNET_HELLO_Message *friend_hello)
 Update the HELLO of a friend by merging the addresses. More...
 
static int add_to_tc (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Do transmit info about peer to given host. More...
 
static int discard_hosts_helper (void *cls, const char *fn)
 delete expired HELLO entries in directory More...
 
static void cron_clean_data_hosts (void *cls)
 Call this method periodically to scan peerinfo/ for ancient HELLOs to expire. More...
 
static int check_hello (void *cls, const struct GNUNET_HELLO_Message *hello)
 Check HELLO-message. More...
 
static void handle_hello (void *cls, const struct GNUNET_HELLO_Message *hello)
 Handle HELLO-message. More...
 
static void handle_get (void *cls, const struct ListPeerMessage *lpm)
 Handle GET-message. More...
 
static void handle_get_all (void *cls, const struct ListAllPeersMessage *lapm)
 Handle GET-ALL-message. More...
 
static void handle_notify (void *cls, const struct NotifyMessage *nm)
 Handle NOTIFY-message. More...
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
 Client connect callback. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
 Client disconnect callback. More...
 
static int free_host_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Release memory taken by a host entry. More...
 
static void shutdown_task (void *cls)
 Clean up our state. More...
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *service)
 Start up peerinfo service. More...
 
 GNUNET_SERVICE_MAIN ("peerinfo", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(hello, GNUNET_MESSAGE_TYPE_HELLO, struct GNUNET_HELLO_Message, NULL), GNUNET_MQ_hd_fixed_size(get, GNUNET_MESSAGE_TYPE_PEERINFO_GET, struct ListPeerMessage, NULL), GNUNET_MQ_hd_fixed_size(get_all, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL, struct ListAllPeersMessage, NULL), GNUNET_MQ_hd_fixed_size(notify, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY, struct NotifyMessage, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro. More...
 

Variables

static struct GNUNET_CONTAINER_MultiPeerMaphostmap
 The in-memory list of known hosts, mapping of host IDs to 'struct HostEntry*' values. More...
 
static struct GNUNET_NotificationContextnotify_list
 Clients to immediately notify about all changes. More...
 
static struct GNUNET_NotificationContextnotify_friend_only_list
 Clients to immediately notify about all changes, even for friend-only HELLOs. More...
 
static char * networkIdDirectory
 Directory where the hellos are stored in (peerinfo/) More...
 
static struct GNUNET_STATISTICS_Handlestats
 Handle for reporting statistics. More...
 
static struct GNUNET_SCHEDULER_Taskcron_clean
 Handle for task to run cron_clean_data_hosts() More...
 
static struct GNUNET_SCHEDULER_Taskcron_scan
 Handle for task to run cron_scan_directory_data_hosts() More...
 

Detailed Description

maintains list of known peers

Code to maintain the list of currently known hosts (in memory structure of data/hosts/).

Author
Christian Grothoff

Definition in file gnunet-service-peerinfo.c.

Macro Definition Documentation

◆ DATA_HOST_FREQ

#define DATA_HOST_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)

How often do we scan the HOST_DIR for new entries?

Definition at line 41 of file gnunet-service-peerinfo.c.

◆ DATA_HOST_CLEAN_FREQ

#define DATA_HOST_CLEAN_FREQ    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)

How often do we discard old entries in data/hosts/?

Definition at line 47 of file gnunet-service-peerinfo.c.

Function Documentation

◆ make_info_message()

static struct InfoMessage* make_info_message ( const struct HostEntry he,
int  include_friend_only 
)
static

Notify all clients in the notify list about the given host entry changing.

Parameters
heentry of the host for which we generate a notification
include_friend_onlycreate public of friend-only message
Returns
generated notification message

Definition at line 137 of file gnunet-service-peerinfo.c.

138 {
139  struct InfoMessage *im;
140  struct GNUNET_HELLO_Message *src;
141  size_t hs;
142 
144  src = he->friend_only_hello;
145  else
146  src = he->hello;
147  hs = (NULL == src) ? 0 : GNUNET_HELLO_size (src);
148  im = GNUNET_malloc (sizeof(struct InfoMessage) + hs);
149  im->header.size = htons (hs + sizeof(struct InfoMessage));
151  im->peer = he->identity;
152  GNUNET_memcpy (&im[1], src, hs);
153  return im;
154 }
static int include_friend_only
Option '-f'.
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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO
Information about one of the peers.
A HELLO message is used to exchange information about transports with other peers.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HELLO_Message * hello
Hello for the peer (can be NULL)
struct GNUNET_PeerIdentity identity
Identity of the peer.
struct GNUNET_HELLO_Message * friend_only_hello
Friend only hello for the peer (can be NULL)
Message used to inform the client about a particular peer; this message is optionally followed by a H...
Definition: peerinfo.h:102
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

References HostEntry::friend_only_hello, GNUNET_HELLO_size(), GNUNET_malloc, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_PEERINFO_INFO, GNUNET_YES, InfoMessage::header, HostEntry::hello, HostEntry::identity, include_friend_only, InfoMessage::peer, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by notify_all().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ discard_expired()

static int discard_expired ( void *  cls,
const struct GNUNET_HELLO_Address address,
struct GNUNET_TIME_Absolute  expiration 
)
static

Address iterator that causes expired entries to be discarded.

Parameters
clspointer to the current time
addressthe address
expirationexpiration time for the address
Returns
GNUNET_NO if expiration smaller than the current time

Definition at line 166 of file gnunet-service-peerinfo.c.

169 {
170  const struct GNUNET_TIME_Absolute *now = cls;
171 
172  if (now->abs_value_us > expiration.abs_value_us)
173  {
175  _ ("Removing expired address of transport `%s'\n"),
176  address->transport_name);
177  return GNUNET_NO;
178  }
179  return GNUNET_OK;
180 }
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
static char * address
GNS address for this phone.
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_NO
@ GNUNET_ERROR_TYPE_INFO
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.

References _, GNUNET_TIME_Absolute::abs_value_us, address, expiration, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, and GNUNET_OK.

Referenced by discard_hosts_helper(), and read_host_file().

Here is the caller graph for this function:

◆ count_addresses()

static int count_addresses ( void *  cls,
const struct GNUNET_HELLO_Address address,
struct GNUNET_TIME_Absolute  expiration 
)
static

Address iterator that counts the remaining addresses.

Parameters
clspointer to the counter
addressthe address
expirationexpiration time for the address
Returns
GNUNET_OK (always)

Definition at line 192 of file gnunet-service-peerinfo.c.

195 {
196  unsigned int *cnt = cls;
197 
198  (void) address;
199  (void) expiration;
200  (*cnt)++;
201  return GNUNET_OK;
202 }

References address, expiration, and GNUNET_OK.

Referenced by discard_hosts_helper(), distribute_bandwidth(), read_host_file(), and update_hello().

Here is the caller graph for this function:

◆ get_host_filename()

static char* get_host_filename ( const struct GNUNET_PeerIdentity id)
static

Get the filename under which we would store the GNUNET_HELLO_Message for the given host and protocol.

Parameters
idpeer for which we need the filename for the HELLO
Returns
filename of the form DIRECTORY/HOSTID

Definition at line 213 of file gnunet-service-peerinfo.c.

214 {
215  char *fn;
216 
217  if (NULL == networkIdDirectory)
218  return NULL;
219  GNUNET_asprintf (&fn,
220  "%s%s%s",
223  GNUNET_i2s_full (id));
224  return fn;
225 }
static char * networkIdDirectory
Directory where the hellos are stored in (peerinfo/)
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define DIR_SEPARATOR_STR
Definition: platform.h:166

References DIR_SEPARATOR_STR, GNUNET_asprintf(), GNUNET_i2s_full(), and networkIdDirectory.

Referenced by add_host_to_known_hosts(), and update_hello().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_all()

static void notify_all ( struct HostEntry entry)
static

Broadcast information about the given entry to all clients that care.

Parameters
entryentry to broadcast about

Definition at line 235 of file gnunet-service-peerinfo.c.

236 {
237  struct InfoMessage *msg_pub;
238  struct InfoMessage *msg_friend;
239 
241  "Notifying all clients about peer `%s'\n",
242  GNUNET_i2s (&entry->identity));
243  msg_pub = make_info_message (entry, GNUNET_NO);
245  &msg_pub->header,
246  GNUNET_NO);
247  GNUNET_free (msg_pub);
248  msg_friend = make_info_message (entry, GNUNET_YES);
250  &msg_friend->header,
251  GNUNET_NO);
252  GNUNET_free (msg_friend);
253 }
static struct InfoMessage * make_info_message(const struct HostEntry *he, int include_friend_only)
Notify all clients in the notify list about the given host entry changing.
static struct GNUNET_NotificationContext * notify_list
Clients to immediately notify about all changes.
static struct GNUNET_NotificationContext * notify_friend_only_list
Clients to immediately notify about all changes, even for friend-only HELLOs.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_notification_context_broadcast(struct GNUNET_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop)
Send a message to all subscribers of this context.
Definition: nc.c:190

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_notification_context_broadcast(), GNUNET_YES, InfoMessage::header, HostEntry::identity, make_info_message(), notify_friend_only_list, and notify_list.

Referenced by add_host_to_known_hosts(), and update_hello().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_hello()

static void update_hello ( const struct GNUNET_PeerIdentity peer,
const struct GNUNET_HELLO_Message hello 
)
static

Bind a host address (hello) to a hostId.

Parameters
peerthe peer for which this is a hello
hellothe verified (!) hello message

Definition at line 683 of file gnunet-service-peerinfo.c.

685 {
686  char *fn;
687  struct HostEntry *host;
688  struct GNUNET_HELLO_Message *mrg;
689  struct GNUNET_HELLO_Message **dest;
691  unsigned int cnt;
692  unsigned int size;
693  int friend_hello_type;
694  int store_hello;
695  int store_friend_hello;
696  unsigned int pos;
697  char *buffer;
698 
700  GNUNET_assert (NULL != host);
701 
702  friend_hello_type = GNUNET_HELLO_is_friend_only (hello);
704  "Updating %s HELLO for `%s'\n",
705  (GNUNET_YES == friend_hello_type) ? "friend-only" : "public",
706  GNUNET_i2s (peer));
707 
708  dest = NULL;
709  if (GNUNET_YES == friend_hello_type)
710  {
711  dest = &host->friend_only_hello;
712  }
713  else
714  {
715  dest = &host->hello;
716  }
717 
718  if (NULL == (*dest))
719  {
720  (*dest) = GNUNET_malloc (GNUNET_HELLO_size (hello));
721  GNUNET_memcpy ((*dest), hello, GNUNET_HELLO_size (hello));
722  }
723  else
724  {
725  mrg = GNUNET_HELLO_merge ((*dest), hello);
727  if (delta.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
728  {
729  /* no differences, just ignore the update */
731  "No change in %s HELLO for `%s'\n",
732  (GNUNET_YES == friend_hello_type) ? "friend-only" : "public",
733  GNUNET_i2s (peer));
734  GNUNET_free (mrg);
735  return;
736  }
737  GNUNET_free ((*dest));
738  (*dest) = mrg;
739  }
740 
741  if ((NULL != (host->hello)) && (GNUNET_NO == friend_hello_type))
742  {
743  /* Update friend only hello */
744  mrg = update_friend_hello (host->hello, host->friend_only_hello);
745  if (NULL != host->friend_only_hello)
747  host->friend_only_hello = mrg;
748  }
749 
750  if (NULL != host->hello)
752  if (NULL != host->friend_only_hello)
753  GNUNET_assert (
755 
756  fn = get_host_filename (peer);
757  if ((NULL != fn) && (GNUNET_OK == GNUNET_DISK_directory_create_for_file (fn)))
758  {
759  store_hello = GNUNET_NO;
760  size = 0;
761  cnt = 0;
762  if (NULL != host->hello)
764  GNUNET_NO,
766  &cnt);
767  if (cnt > 0)
768  {
769  store_hello = GNUNET_YES;
770  size += GNUNET_HELLO_size (host->hello);
771  }
772  cnt = 0;
773  if (NULL != host->friend_only_hello)
775  GNUNET_NO,
777  &cnt);
778  store_friend_hello = GNUNET_NO;
779  if (0 < cnt)
780  {
781  store_friend_hello = GNUNET_YES;
783  }
784 
785  if ((GNUNET_NO == store_hello) && (GNUNET_NO == store_friend_hello))
786  {
787  /* no valid addresses, don't put HELLO on disk; in fact,
788  if one exists on disk, remove it */
789  (void) unlink (fn);
790  }
791  else
792  {
793  buffer = GNUNET_malloc (size);
794  pos = 0;
795 
796  if (GNUNET_YES == store_hello)
797  {
798  GNUNET_memcpy (buffer, host->hello, GNUNET_HELLO_size (host->hello));
799  pos += GNUNET_HELLO_size (host->hello);
800  }
801  if (GNUNET_YES == store_friend_hello)
802  {
803  GNUNET_memcpy (&buffer[pos],
804  host->friend_only_hello,
806  pos += GNUNET_HELLO_size (host->friend_only_hello);
807  }
808  GNUNET_assert (pos == size);
809 
810  if (GNUNET_SYSERR ==
812  buffer,
813  size,
819  else
821  "Stored %s %s HELLO in %s with total size %u\n",
822  (GNUNET_YES == store_friend_hello) ? "friend-only" : "",
823  (GNUNET_YES == store_hello) ? "public" : "",
824  fn,
825  size);
826  GNUNET_free (buffer);
827  }
828  }
829  GNUNET_free (fn);
830  notify_all (host);
831 }
static void notify_all(struct HostEntry *entry)
Broadcast information about the given entry to all clients that care.
static struct GNUNET_HELLO_Message * update_friend_hello(const struct GNUNET_HELLO_Message *hello, const struct GNUNET_HELLO_Message *friend_hello)
Update the HELLO of a friend by merging the addresses.
static char * get_host_filename(const struct GNUNET_PeerIdentity *id)
Get the filename under which we would store the GNUNET_HELLO_Message for the given host and protocol.
static int count_addresses(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Address iterator that counts the remaining addresses.
static struct GNUNET_CONTAINER_MultiPeerMap * hostmap
The in-memory list of known hosts, mapping of host IDs to 'struct HostEntry*' values.
enum GNUNET_GenericReturnValue GNUNET_DISK_fn_write(const char *fn, const void *buf, size_t buf_size, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file atomically.
Definition: disk.c:725
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_PERM_OTHER_READ
Everybody can read.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
struct GNUNET_HELLO_Message * GNUNET_HELLO_merge(const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2)
Construct a HELLO message by merging the addresses in two existing HELLOs (which must be for the same...
Definition: hello.c:515
int GNUNET_HELLO_is_friend_only(const struct GNUNET_HELLO_Message *h)
Return HELLO type.
Definition: hello.c:89
struct GNUNET_TIME_Absolute GNUNET_HELLO_equals(const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2, struct GNUNET_TIME_Absolute now)
Test if two HELLO messages contain the same addresses.
Definition: hello.c:812
struct GNUNET_HELLO_Message * GNUNET_HELLO_iterate_addresses(const struct GNUNET_HELLO_Message *msg, int return_modified, GNUNET_HELLO_AddressIterator it, void *it_cls)
Iterate over all of the addresses in the HELLO.
Definition: hello.c:254
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition: peer.c:68
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
In-memory cache of known hosts.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.

References count_addresses(), delta, warningfilter::dest, HostEntry::friend_only_hello, get_host_filename(), GNUNET_assert, GNUNET_CONTAINER_multipeermap_get(), GNUNET_DISK_directory_create_for_file(), GNUNET_DISK_fn_write(), GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_OTHER_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_equals(), GNUNET_HELLO_is_friend_only(), GNUNET_HELLO_iterate_addresses(), GNUNET_HELLO_merge(), GNUNET_HELLO_size(), GNUNET_i2s(), GNUNET_log, GNUNET_log_strerror_file, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_YES, HostEntry::hello, hostmap, notify_all(), peer, size, and update_friend_hello().

Referenced by add_host_to_known_hosts(), handle_hello(), and hosts_directory_scan_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_host_file()

static void read_host_file ( const char *  fn,
int  unlink_garbage,
struct ReadHostFileContext r 
)
static

Try to read the HELLOs in the given filename and discard expired addresses.

Removes the file if one the HELLO is malformed. If all addresses are expired, the HELLO is also removed (but the HELLO with the public key is still returned if it was found and valid). The file can contain multiple HELLO messages.

Parameters
fnname of the file
unlink_garbageif GNUNET_YES, try to remove useless files
rReadHostFileContext to store the resutl

Definition at line 279 of file gnunet-service-peerinfo.c.

282 {
283  char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
284  ssize_t size_total;
285  struct GNUNET_TIME_Absolute now;
286  unsigned int left;
287  const struct GNUNET_HELLO_Message *hello;
288  struct GNUNET_HELLO_Message *hello_clean;
289  size_t read_pos;
290  uint16_t size_hello;
291 
292  r->friend_only_hello = NULL;
293  r->hello = NULL;
294 
295  if (GNUNET_YES != GNUNET_DISK_file_test (fn))
296  return;
297  size_total = GNUNET_DISK_fn_read (fn, buffer, sizeof(buffer));
299  "Read %d bytes from `%s'\n",
300  (int) size_total,
301  fn);
302  if ((size_total < 0) ||
303  (((size_t) size_total) < sizeof(struct GNUNET_MessageHeader)))
304  {
306  _ ("Failed to parse HELLO in file `%s': %s\n"),
307  fn,
308  "File has invalid size");
309  if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)) &&
310  (ENOENT != errno))
312  return;
313  }
314 
315  read_pos = 0;
316  while (read_pos < (size_t) size_total)
317  {
318  hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos];
319  size_hello = GNUNET_HELLO_size (hello);
320  if ((0 == size_hello) || (((size_t) size_total) - read_pos < size_hello))
321  {
323  _ ("Failed to parse HELLO in file `%s'\n"),
324  fn);
325  if (0 == read_pos)
326  {
327  if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)) &&
328  (ENOENT != errno))
330  }
331  else
332  {
333  if ((GNUNET_YES == unlink_garbage) && (0 != truncate (fn, read_pos)) &&
334  (ENOENT != errno))
336  }
337  return;
338  }
339 
340  now = GNUNET_TIME_absolute_get ();
341  hello_clean = GNUNET_HELLO_iterate_addresses (hello,
342  GNUNET_YES,
344  &now);
345  if (NULL == hello_clean)
346  {
348  _ ("Failed to parse HELLO in file `%s'\n"),
349  fn);
350  if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)) &&
351  (ENOENT != errno))
353  return;
354  }
355  left = 0;
356  (void) GNUNET_HELLO_iterate_addresses (hello_clean,
357  GNUNET_NO,
359  &left);
360 
361  if (0 == left)
362  {
363  GNUNET_free (hello_clean);
364  break;
365  }
366 
367  if (GNUNET_NO == GNUNET_HELLO_is_friend_only (hello_clean))
368  {
369  if (NULL == r->hello)
370  r->hello = hello_clean;
371  else
372  {
373  GNUNET_break (0);
374  GNUNET_free (r->hello);
375  r->hello = hello_clean;
376  }
377  }
378  else
379  {
380  if (NULL == r->friend_only_hello)
381  r->friend_only_hello = hello_clean;
382  else
383  {
384  GNUNET_break (0);
386  r->friend_only_hello = hello_clean;
387  }
388  }
389  read_pos += size_hello;
390  }
391 
392  if (0 == left)
393  {
394  /* no addresses left, remove from disk */
395  if ((GNUNET_YES == unlink_garbage) && (0 != unlink (fn)))
397  }
399  "Found `%s' and `%s' HELLO message in file\n",
400  (NULL != r->hello) ? "public" : "NON-public",
401  (NULL != r->friend_only_hello) ? "friend only"
402  : "NO friend only");
403 }
static int discard_expired(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Address iterator that causes expired entries to be discarded.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:482
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:664
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#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
Header for all communications.
struct GNUNET_HELLO_Message * friend_only_hello
Friend only hello for the peer (can be NULL)
struct GNUNET_HELLO_Message * hello
Hello for the peer (can be NULL)

References _, count_addresses(), discard_expired(), ReadHostFileContext::friend_only_hello, GNUNET_ALIGN, GNUNET_break, GNUNET_DISK_file_test(), GNUNET_DISK_fn_read(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_is_friend_only(), GNUNET_HELLO_iterate_addresses(), GNUNET_HELLO_size(), GNUNET_log, GNUNET_log_strerror_file, GNUNET_MAX_MESSAGE_SIZE, GNUNET_NO, GNUNET_TIME_absolute_get(), GNUNET_YES, and ReadHostFileContext::hello.

Referenced by add_host_to_known_hosts(), and hosts_directory_scan_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_host_to_known_hosts()

static struct HostEntry* add_host_to_known_hosts ( const struct GNUNET_PeerIdentity identity)
static

Add a host to the list and notify clients about this event.

Parameters
identitythe identity of the host
Returns
the HostEntry

Definition at line 413 of file gnunet-service-peerinfo.c.

414 {
415  struct HostEntry *entry;
416  struct ReadHostFileContext r;
417  char *fn;
418 
420  if (NULL == entry)
421  {
423  "Adding new peer `%s'\n",
424  GNUNET_i2s (identity));
426  gettext_noop ("# peers known"),
427  1,
428  GNUNET_NO);
429  entry = GNUNET_new (struct HostEntry);
430  entry->identity = *identity;
433  hostmap,
434  &entry->identity,
435  entry,
437  notify_all (entry);
439  if (NULL != fn)
440  {
441  read_host_file (fn, GNUNET_YES, &r);
442  if (NULL != r.hello)
443  update_hello (identity, r.hello);
444  if (NULL != r.friend_only_hello)
445  update_hello (identity, r.friend_only_hello);
446  GNUNET_free (r.hello);
447  GNUNET_free (r.friend_only_hello);
448  GNUNET_free (fn);
449  }
450  }
451  return entry;
452 }
#define gettext_noop(String)
Definition: gettext.h:70
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
static struct GNUNET_STATISTICS_Handle * stats
Handle for reporting statistics.
static void read_host_file(const char *fn, int unlink_garbage, struct ReadHostFileContext *r)
Try to read the HELLOs in the given filename and discard expired addresses.
static void update_hello(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello)
Bind a host address (hello) to a hostId.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
Result of reading a file.

References ReadHostFileContext::friend_only_hello, get_host_filename(), gettext_noop, GNUNET_assert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_YES, ReadHostFileContext::hello, hostmap, identity, HostEntry::identity, notify_all(), read_host_file(), stats, and update_hello().

Referenced by handle_hello(), and hosts_directory_scan_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_garbage()

static void remove_garbage ( const char *  fullname)
static

Remove a file that should not be there.

LOG success or failure.

Parameters
fullnamename of the file to remove

Definition at line 462 of file gnunet-service-peerinfo.c.

463 {
464  if (0 == unlink (fullname))
465  GNUNET_log (
467  _ (
468  "File `%s' in directory `%s' does not match naming convention. Removed.\n"),
469  fullname,
471  else
473  "unlink",
474  fullname);
475 }
@ GNUNET_ERROR_TYPE_BULK

References _, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror_file, and networkIdDirectory.

Referenced by hosts_directory_scan_callback().

Here is the caller graph for this function:

◆ hosts_directory_scan_callback()

static int hosts_directory_scan_callback ( void *  cls,
const char *  fullname 
)
static

Function that is called on each HELLO file in a particular directory.

Try to parse the file and add the HELLO to our list.

Parameters
clspointer to 'unsigned int' to increment for each file, or NULL if the file is from a read-only, read-once resource directory
fullnamename of the file to parse
Returns
GNUNET_OK (continue iteration)

Definition at line 508 of file gnunet-service-peerinfo.c.

509 {
510  struct DirScanContext *dsc = cls;
512  struct ReadHostFileContext r;
513  const char *filename;
514  struct GNUNET_PeerIdentity id_public;
515  struct GNUNET_PeerIdentity id_friend;
516  struct GNUNET_PeerIdentity id;
517 
518  if (GNUNET_YES != GNUNET_DISK_file_test (fullname))
519  return GNUNET_OK; /* ignore non-files */
520 
521  filename = strrchr (fullname, DIR_SEPARATOR);
522  if ((NULL == filename) || (1 > strlen (filename)))
523  filename = fullname;
524  else
525  filename++;
526 
527  read_host_file (fullname, dsc->remove_files, &r);
528  if ((NULL == r.hello) && (NULL == r.friend_only_hello))
529  return GNUNET_OK;
530  if (NULL != r.friend_only_hello)
531  {
532  if (GNUNET_OK != GNUNET_HELLO_get_id (r.friend_only_hello, &id_friend))
533  {
534  if (GNUNET_YES == dsc->remove_files)
535  remove_garbage (fullname);
536  return GNUNET_OK;
537  }
538  id = id_friend;
539  }
540  if (NULL != r.hello)
541  {
542  if (GNUNET_OK != GNUNET_HELLO_get_id (r.hello, &id_public))
543  {
544  if (GNUNET_YES == dsc->remove_files)
545  remove_garbage (fullname);
546  return GNUNET_OK;
547  }
548  id = id_public;
549  }
550 
551  if ((NULL != r.hello) && (NULL != r.friend_only_hello) &&
552  (0 != GNUNET_memcmp (&id_friend, &id_public)))
553  {
554  /* HELLOs are not for the same peer */
555  GNUNET_break (0);
556  if (GNUNET_YES == dsc->remove_files)
557  remove_garbage (fullname);
558  return GNUNET_OK;
559  }
560  if (GNUNET_OK ==
562  strlen (filename),
563  &identity.public_key))
564  {
565  if (0 != GNUNET_memcmp (&id, &identity))
566  {
567  /* HELLOs are not for the same peer */
568  GNUNET_break (0);
569  if (GNUNET_YES == dsc->remove_files)
570  remove_garbage (fullname);
571  return GNUNET_OK;
572  }
573  }
574 
575  /* ok, found something valid, remember HELLO */
577  if (NULL != r.hello)
578  {
580  "Updating peer `%s' public HELLO \n",
581  GNUNET_i2s (&id));
582  update_hello (&id, r.hello);
583  GNUNET_free (r.hello);
584  }
585  if (NULL != r.friend_only_hello)
586  {
588  "Updating peer `%s' friend only HELLO \n",
589  GNUNET_i2s (&id));
590  update_hello (&id, r.friend_only_hello);
591  GNUNET_free (r.friend_only_hello);
592  }
593  dsc->matched++;
594  return GNUNET_OK;
595 }
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
static char * filename
static void remove_garbage(const char *fullname)
Remove a file that should not be there.
static struct HostEntry * add_host_to_known_hosts(const struct GNUNET_PeerIdentity *identity)
Add a host to the list and notify clients about this event.
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
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:358
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define DIR_SEPARATOR
Definition: platform.h:165
Closure for hosts_directory_scan_callback().
int remove_files
GNUNET_YES if we should remove files that are broken, GNUNET_NO if the directory we are iterating ove...
unsigned int matched
Counter for the number of (valid) entries found, incremented by one for each match.
The identity of the host (wraps the signing key of the peer).

References add_host_to_known_hosts(), DIR_SEPARATOR, filename, ReadHostFileContext::friend_only_hello, GNUNET_break, GNUNET_CRYPTO_eddsa_public_key_from_string(), GNUNET_DISK_file_test(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_HELLO_get_id(), GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_OK, GNUNET_YES, ReadHostFileContext::hello, id, identity, DirScanContext::matched, read_host_file(), DirScanContext::remove_files, remove_garbage(), and update_hello().

Referenced by cron_scan_directory_data_hosts(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cron_scan_directory_data_hosts()

static void cron_scan_directory_data_hosts ( void *  cls)
static

Call this method periodically to scan data/hosts for new hosts.

Parameters
clsunused

Definition at line 604 of file gnunet-service-peerinfo.c.

605 {
606  static unsigned int retries;
607  struct DirScanContext dsc;
608 
609  (void) cls;
610  cron_scan = NULL;
612  {
613  cron_scan =
616  &
618  NULL);
619  return;
620  }
621  dsc.matched = 0;
622  dsc.remove_files = GNUNET_YES;
624  _ ("Scanning directory `%s'\n"),
628  &dsc);
629  if ((0 == dsc.matched) && (0 == (++retries & 31)))
631  _ ("Still no peers found in `%s'!\n"),
633  cron_scan =
637  NULL);
638 }
static struct GNUNET_SCHEDULER_Task * cron_scan
Handle for task to run cron_scan_directory_data_hosts()
static int hosts_directory_scan_callback(void *cls, const char *fullname)
Function that is called on each HELLO file in a particular directory.
static void cron_scan_directory_data_hosts(void *cls)
Call this method periodically to scan data/hosts for new hosts.
#define DATA_HOST_FREQ
How often do we scan the HOST_DIR for new entries?
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:496
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:814
@ GNUNET_SCHEDULER_PRIORITY_IDLE
Run when otherwise idle.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1202

References _, cron_scan, DATA_HOST_FREQ, GNUNET_DISK_directory_create(), GNUNET_DISK_directory_scan(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_SCHEDULER_add_delayed_with_priority(), GNUNET_SCHEDULER_PRIORITY_IDLE, GNUNET_SYSERR, GNUNET_YES, hosts_directory_scan_callback(), DirScanContext::matched, networkIdDirectory, and DirScanContext::remove_files.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_friend_hello()

static struct GNUNET_HELLO_Message* update_friend_hello ( const struct GNUNET_HELLO_Message hello,
const struct GNUNET_HELLO_Message friend_hello 
)
static

Update the HELLO of a friend by merging the addresses.

Parameters
hellooriginal hello
friend_hellohello with additional addresses
Returns
merged HELLO

Definition at line 649 of file gnunet-service-peerinfo.c.

651 {
652  struct GNUNET_HELLO_Message *res;
653  struct GNUNET_HELLO_Message *tmp;
654  struct GNUNET_PeerIdentity pid;
655 
656  if (NULL != friend_hello)
657  {
658  res = GNUNET_HELLO_merge (hello, friend_hello);
660  return res;
661  }
662 
663  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
664  {
665  GNUNET_break (0);
666  return NULL;
667  }
668  tmp = GNUNET_HELLO_create (&pid.public_key, NULL, NULL, GNUNET_YES);
669  res = GNUNET_HELLO_merge (hello, tmp);
670  GNUNET_free (tmp);
672  return res;
673 }
static int res
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
struct GNUNET_HELLO_Message * GNUNET_HELLO_create(const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, GNUNET_HELLO_GenerateAddressListCallback addrgen, void *addrgen_cls, int friend_only)
Construct a HELLO message given the public key, expiration time and an iterator that spews the transp...
Definition: hello.c:204
struct GNUNET_CRYPTO_EddsaPublicKey public_key

References GNUNET_assert, GNUNET_break, GNUNET_free, GNUNET_HELLO_create(), GNUNET_HELLO_get_id(), GNUNET_HELLO_is_friend_only(), GNUNET_HELLO_merge(), GNUNET_OK, GNUNET_YES, pid, GNUNET_PeerIdentity::public_key, and res.

Referenced by update_hello().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_to_tc()

static int add_to_tc ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Do transmit info about peer to given host.

Parameters
clsNULL to hit all hosts, otherwise specifies a particular target
keyhostID
valueinformation to transmit
Returns
GNUNET_YES (continue to iterate)

Definition at line 860 of file gnunet-service-peerinfo.c.

861 {
862  struct TransmitContext *tc = cls;
863  struct HostEntry *pos = value;
864  struct InfoMessage *im;
865  uint16_t hs;
866  struct GNUNET_MQ_Envelope *env;
867 
868  hs = 0;
869 
870  if ((NULL != pos->hello) && (GNUNET_NO == tc->friend_only))
871  {
872  /* Copy public HELLO */
873  hs = GNUNET_HELLO_size (pos->hello);
874  GNUNET_assert (hs < GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InfoMessage));
876  GNUNET_memcpy (&im[1], pos->hello, hs);
878  "Sending public HELLO with size %u for peer `%s'\n",
879  hs,
880  GNUNET_i2s (key));
881  }
882  else if ((NULL != pos->friend_only_hello) && (GNUNET_YES == tc->friend_only))
883  {
884  /* Copy friend only HELLO */
886  GNUNET_assert (hs < GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InfoMessage));
888  GNUNET_memcpy (&im[1], pos->friend_only_hello, hs);
890  "Sending friend-only HELLO with size %u for peer `%s'\n",
891  hs,
892  GNUNET_i2s (key));
893  }
894  else
895  {
898  "Adding no HELLO for peer `%s'\n",
899  GNUNET_i2s (key));
900  }
901  im->peer = pos->identity;
903  return GNUNET_YES;
904 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct GNUNET_HashCode key
The key used in the DHT.
static char * value
Value of the record to add/remove.
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_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2443
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
Closure for add_to_tc()

References env, HostEntry::friend_only_hello, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELLO_size(), GNUNET_i2s(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_PEERINFO_INFO, GNUNET_MQ_msg, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_SERVICE_client_get_mq(), GNUNET_YES, HostEntry::hello, HostEntry::identity, key, InfoMessage::peer, tc, and value.

Referenced by handle_get(), handle_get_all(), and handle_notify().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ discard_hosts_helper()

static int discard_hosts_helper ( void *  cls,
const char *  fn 
)
static

delete expired HELLO entries in directory

Parameters
clspointer to current time (struct GNUNET_TIME_Absolute *)
fnfilename to test to see if the HELLO expired
Returns
GNUNET_OK (continue iteration)

Definition at line 915 of file gnunet-service-peerinfo.c.

916 {
917  struct GNUNET_TIME_Absolute *now = cls;
918  char buffer[GNUNET_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
919  const struct GNUNET_HELLO_Message *hello;
920  struct GNUNET_HELLO_Message *new_hello;
921  int read_size;
922  unsigned int cur_hello_size;
923  unsigned int new_hello_size;
924  int read_pos;
925  int write_pos;
926  unsigned int cnt;
927  char *writebuffer;
928  uint64_t fsize;
929 
931  {
934  "fstat",
935  fn);
936  return GNUNET_OK;
937  }
938  read_size = GNUNET_DISK_fn_read (fn, buffer, sizeof(buffer));
939 
940  if ((read_size < (int) sizeof(struct GNUNET_MessageHeader)) ||
941  (fsize > GNUNET_MAX_MESSAGE_SIZE))
942  {
943  if (0 != unlink (fn))
946  "unlink",
947  fn);
948  return GNUNET_OK;
949  }
950 
951  writebuffer = GNUNET_malloc (read_size);
952  read_pos = 0;
953  write_pos = 0;
954  while (read_pos < read_size)
955  {
956  /* Check each HELLO */
957  hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos];
958  cur_hello_size = GNUNET_HELLO_size (hello);
959  if (0 == cur_hello_size)
960  {
961  /* Invalid data, discard */
962  if (0 != unlink (fn))
965  "unlink",
966  fn);
967  GNUNET_free (writebuffer);
968  return GNUNET_OK;
969  }
970  new_hello =
972  cnt = 0;
973  if (NULL != new_hello)
974  (void) GNUNET_HELLO_iterate_addresses (hello,
975  GNUNET_NO,
977  &cnt);
978  if ((NULL != new_hello) && (0 < cnt))
979  {
980  /* Store new HELLO to write it when done */
981  new_hello_size = GNUNET_HELLO_size (new_hello);
982  GNUNET_memcpy (&writebuffer[write_pos], new_hello, new_hello_size);
983  write_pos += new_hello_size;
984  }
985  read_pos += cur_hello_size;
986  GNUNET_free (new_hello);
987  }
988 
989  if (0 < write_pos)
990  {
991  (void) GNUNET_DISK_directory_remove (fn);
994  writebuffer,
995  write_pos,
1000  }
1001  else if (0 != unlink (fn))
1004  "unlink",
1005  fn);
1006 
1007  GNUNET_free (writebuffer);
1008  return GNUNET_OK;
1009 }
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:221
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1087

References count_addresses(), discard_expired(), GNUNET_ALIGN, GNUNET_assert, GNUNET_DISK_directory_remove(), GNUNET_DISK_file_size(), GNUNET_DISK_fn_read(), GNUNET_DISK_fn_write(), GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_OTHER_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_iterate_addresses(), GNUNET_HELLO_size(), GNUNET_log_strerror_file, GNUNET_malloc, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, and GNUNET_YES.

Referenced by cron_clean_data_hosts().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cron_clean_data_hosts()

static void cron_clean_data_hosts ( void *  cls)
static

Call this method periodically to scan peerinfo/ for ancient HELLOs to expire.

Parameters
clsunused

Definition at line 1019 of file gnunet-service-peerinfo.c.

1020 {
1021  struct GNUNET_TIME_Absolute now;
1022 
1023  (void) cls;
1024  cron_clean = NULL;
1025  now = GNUNET_TIME_absolute_get ();
1027  _ ("Cleaning up directory `%s'\n"),
1032  NULL);
1033 }
static void cron_clean_data_hosts(void *cls)
Call this method periodically to scan peerinfo/ for ancient HELLOs to expire.
#define DATA_HOST_CLEAN_FREQ
How often do we discard old entries in data/hosts/?
static int discard_hosts_helper(void *cls, const char *fn)
delete expired HELLO entries in directory
static struct GNUNET_SCHEDULER_Task * cron_clean
Handle for task to run cron_clean_data_hosts()
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1272

References _, cron_clean, DATA_HOST_CLEAN_FREQ, discard_hosts_helper(), GNUNET_DISK_directory_scan(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_absolute_get(), and networkIdDirectory.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_hello()

static int check_hello ( void *  cls,
const struct GNUNET_HELLO_Message hello 
)
static

Check HELLO-message.

Parameters
clsidentification of the client
hellothe actual message
Returns
GNUNET_OK if hello is well-formed

Definition at line 1044 of file gnunet-service-peerinfo.c.

1045 {
1046  struct GNUNET_PeerIdentity pid;
1047 
1048  (void) cls;
1049  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
1050  {
1051  GNUNET_break (0);
1052  return GNUNET_SYSERR;
1053  }
1054  return GNUNET_OK;
1055 }

References GNUNET_break, GNUNET_HELLO_get_id(), GNUNET_OK, GNUNET_SYSERR, and pid.

Here is the call graph for this function:

◆ handle_hello()

static void handle_hello ( void *  cls,
const struct GNUNET_HELLO_Message hello 
)
static

Handle HELLO-message.

Parameters
clsidentification of the client
hellothe actual message

Definition at line 1065 of file gnunet-service-peerinfo.c.

1066 {
1067  struct GNUNET_SERVICE_Client *client = cls;
1068  struct GNUNET_PeerIdentity pid;
1069 
1072  "HELLO message received for peer `%s'\n",
1073  GNUNET_i2s (&pid));
1075  update_hello (&pid, hello);
1077 }
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2249
Handle to a client that is connected to a service.
Definition: service.c:252

References add_host_to_known_hosts(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELLO_get_id(), GNUNET_i2s(), GNUNET_log, GNUNET_OK, GNUNET_SERVICE_client_continue(), pid, and update_hello().

Here is the call graph for this function:

◆ handle_get()

static void handle_get ( void *  cls,
const struct ListPeerMessage lpm 
)
static

Handle GET-message.

Parameters
clsidentification of the client
lpmthe actual message

Definition at line 1087 of file gnunet-service-peerinfo.c.

1088 {
1089  struct GNUNET_SERVICE_Client *client = cls;
1090  struct TransmitContext tcx;
1091  struct GNUNET_MessageHeader *msg;
1092  struct GNUNET_MQ_Envelope *env;
1093 
1095  "GET message received for peer `%s'\n",
1096  GNUNET_i2s (&lpm->peer));
1097  tcx.friend_only = ntohl (lpm->include_friend_only);
1098  tcx.client = client;
1100  &lpm->peer,
1101  &add_to_tc,
1102  &tcx);
1106 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static int add_to_tc(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Do transmit info about peer to given host.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
#define GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END
End of information about other peers.
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

References add_to_tc(), TransmitContext::client, env, TransmitContext::friend_only, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), hostmap, ListPeerMessage::include_friend_only, msg, and ListPeerMessage::peer.

Here is the call graph for this function:

◆ handle_get_all()

static void handle_get_all ( void *  cls,
const struct ListAllPeersMessage lapm 
)
static

Handle GET-ALL-message.

Parameters
clsidentification of the client
lapmthe actual message

Definition at line 1116 of file gnunet-service-peerinfo.c.

1117 {
1118  struct GNUNET_SERVICE_Client *client = cls;
1119  struct TransmitContext tcx;
1120  struct GNUNET_MQ_Envelope *env;
1121  struct GNUNET_MessageHeader *msg;
1122 
1123  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GET_ALL message received\n");
1124  tcx.friend_only = ntohl (lapm->include_friend_only);
1125  tcx.client = client;
1130 }
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:73

References add_to_tc(), TransmitContext::client, env, TransmitContext::friend_only, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), hostmap, ListAllPeersMessage::include_friend_only, and msg.

Here is the call graph for this function:

◆ handle_notify()

static void handle_notify ( void *  cls,
const struct NotifyMessage nm 
)
static

Handle NOTIFY-message.

Parameters
clsidentification of the client
nmthe actual message

Definition at line 1140 of file gnunet-service-peerinfo.c.

1141 {
1142  struct GNUNET_SERVICE_Client *client = cls;
1143  struct GNUNET_MQ_Handle *mq;
1144  struct TransmitContext tcx;
1145  struct GNUNET_MQ_Envelope *env;
1146  struct GNUNET_MessageHeader *msg;
1147 
1148  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "NOTIFY message received\n");
1149  mq = GNUNET_SERVICE_client_get_mq (client);
1151  if (ntohl (nm->include_friend_only))
1153  else
1155  tcx.friend_only = ntohl (nm->include_friend_only);
1156  tcx.client = client;
1161 }
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:161
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2413
Handle to a message queue.
Definition: mq.c:87
uint32_t include_friend_only
Include friend only HELLOs and peers in callbacks.
Definition: peerinfo.h:90

References add_to_tc(), TransmitContext::client, env, TransmitContext::friend_only, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_notification_context_add(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), GNUNET_SERVICE_client_mark_monitor(), hostmap, NotifyMessage::include_friend_only, mq, msg, notify_friend_only_list, and notify_list.

Here is the call graph for this function:

◆ client_connect_cb()

static void* client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
struct GNUNET_MQ_Handle mq 
)
static

Client connect callback.

Parameters
clsunused
clientserver client
mqfor client
Returns
client

Definition at line 1173 of file gnunet-service-peerinfo.c.

1176 {
1177  (void) cls;
1178  (void) mq;
1179  return client;
1180 }

References mq.

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  app_ctx 
)
static

Client disconnect callback.

Parameters
clsunused
clientserver client
app_ctxshould be client

Definition at line 1191 of file gnunet-service-peerinfo.c.

1194 {
1195  (void) cls;
1196  GNUNET_assert (app_ctx == client);
1197 }

References GNUNET_assert.

◆ free_host_entry()

static int free_host_entry ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Release memory taken by a host entry.

Parameters
clsNULL
keykey of the host entry
valuethe struct HostEntry to free
Returns
GNUNET_YES (continue to iterate)

Definition at line 1209 of file gnunet-service-peerinfo.c.

1210 {
1211  struct HostEntry *he = value;
1212 
1213  (void) cls;
1214  (void) key;
1215  GNUNET_free (he->hello);
1217  GNUNET_free (he);
1218  return GNUNET_YES;
1219 }

References HostEntry::friend_only_hello, GNUNET_free, GNUNET_YES, HostEntry::hello, key, and value.

Referenced by shutdown_task().

Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Clean up our state.

Called during shutdown.

Parameters
clsunused

Definition at line 1228 of file gnunet-service-peerinfo.c.

1229 {
1230  (void) cls;
1232  notify_list = NULL;
1234  notify_friend_only_list = NULL;
1235 
1238  if (NULL != stats)
1239  {
1241  stats = NULL;
1242  }
1243  if (NULL != cron_clean)
1244  {
1246  cron_clean = NULL;
1247  }
1248  if (NULL != cron_scan)
1249  {
1251  cron_scan = NULL;
1252  }
1253  if (NULL != networkIdDirectory)
1254  {
1256  networkIdDirectory = NULL;
1257  }
1258 }
static int free_host_entry(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Release memory taken by a host entry.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:138
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).

References cron_clean, cron_scan, free_host_entry(), GNUNET_CONTAINER_multipeermap_destroy(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_free, GNUNET_NO, GNUNET_notification_context_destroy(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_destroy(), hostmap, networkIdDirectory, notify_friend_only_list, notify_list, and stats.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle cfg,
struct GNUNET_SERVICE_Handle service 
)
static

Start up peerinfo service.

Parameters
clsclosure
cfgconfiguration to use
servicethe initialized service

Definition at line 1269 of file gnunet-service-peerinfo.c.

1272 {
1273  char *peerdir;
1274  char *ip;
1275  struct DirScanContext dsc;
1276  int noio;
1277  int use_included;
1278 
1279  (void) cls;
1280  (void) service;
1282  stats = GNUNET_STATISTICS_create ("peerinfo", cfg);
1285  noio = GNUNET_CONFIGURATION_get_value_yesno (cfg, "peerinfo", "NO_IO");
1286  use_included = GNUNET_CONFIGURATION_get_value_yesno (cfg,
1287  "peerinfo",
1288  "USE_INCLUDED_HELLOS");
1289  if (GNUNET_SYSERR == use_included)
1290  use_included = GNUNET_NO;
1292  if (GNUNET_YES != noio)
1293  {
1294  GNUNET_assert (
1295  GNUNET_OK ==
1297  "peerinfo",
1298  "HOSTS",
1299  &networkIdDirectory));
1301  {
1303  return;
1304  }
1305 
1306  cron_scan =
1309  NULL);
1310 
1311  cron_clean =
1314  NULL);
1315  if (GNUNET_YES == use_included)
1316  {
1318  GNUNET_asprintf (&peerdir, "%shellos", ip);
1319  GNUNET_free (ip);
1320 
1322  _ ("Importing HELLOs from `%s'\n"),
1323  peerdir);
1324  dsc.matched = 0;
1325  dsc.remove_files = GNUNET_NO;
1326 
1327  GNUNET_DISK_directory_scan (peerdir,
1329  &dsc);
1330  GNUNET_free (peerdir);
1331  }
1332  else
1333  {
1335  _ ("Skipping import of included HELLOs\n"));
1336  }
1337  }
1338 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static void shutdown_task(void *cls)
Clean up our state.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:122
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
@ GNUNET_OS_IPK_DATADIR
Return the directory where data is installed (share/gnunet/)
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1226
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1334
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.

References _, cfg, cron_clean, cron_clean_data_hosts(), cron_scan, cron_scan_directory_data_hosts(), GNUNET_asprintf(), GNUNET_assert, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_multipeermap_create(), GNUNET_DISK_directory_create(), GNUNET_DISK_directory_scan(), GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_notification_context_create(), GNUNET_OK, GNUNET_OS_installation_get_path(), GNUNET_OS_IPK_DATADIR, GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_add_with_priority(), GNUNET_SCHEDULER_PRIORITY_IDLE, GNUNET_SCHEDULER_shutdown(), GNUNET_STATISTICS_create(), GNUNET_SYSERR, GNUNET_YES, hostmap, hosts_directory_scan_callback(), DirScanContext::matched, networkIdDirectory, notify_friend_only_list, notify_list, DirScanContext::remove_files, service, shutdown_task(), and stats.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( "peerinfo"  ,
GNUNET_SERVICE_OPTION_NONE  ,
run,
client_connect_cb,
client_disconnect_cb,
NULL  ,
GNUNET_MQ_hd_var_size(hello, GNUNET_MESSAGE_TYPE_HELLO, struct GNUNET_HELLO_Message, NULL)  ,
GNUNET_MQ_hd_fixed_size(get, GNUNET_MESSAGE_TYPE_PEERINFO_GET, struct ListPeerMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(get_all, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL, struct ListAllPeersMessage, NULL)  ,
GNUNET_MQ_hd_fixed_size(notify, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY, struct NotifyMessage, NULL)  ,
GNUNET_MQ_handler_end()   
)

Define "main" method using service macro.

Variable Documentation

◆ hostmap

struct GNUNET_CONTAINER_MultiPeerMap* hostmap
static

The in-memory list of known hosts, mapping of host IDs to 'struct HostEntry*' values.

Definition at line 94 of file gnunet-service-peerinfo.c.

Referenced by add_host_to_known_hosts(), handle_get(), handle_get_all(), handle_notify(), run(), shutdown_task(), and update_hello().

◆ notify_list

struct GNUNET_NotificationContext* notify_list
static

Clients to immediately notify about all changes.

Definition at line 99 of file gnunet-service-peerinfo.c.

Referenced by handle_notify(), notify_all(), run(), and shutdown_task().

◆ notify_friend_only_list

struct GNUNET_NotificationContext* notify_friend_only_list
static

Clients to immediately notify about all changes, even for friend-only HELLOs.

Definition at line 105 of file gnunet-service-peerinfo.c.

Referenced by handle_notify(), notify_all(), run(), and shutdown_task().

◆ networkIdDirectory

char* networkIdDirectory
static

Directory where the hellos are stored in (peerinfo/)

Definition at line 110 of file gnunet-service-peerinfo.c.

Referenced by cron_clean_data_hosts(), cron_scan_directory_data_hosts(), get_host_filename(), remove_garbage(), run(), and shutdown_task().

◆ stats

struct GNUNET_STATISTICS_Handle* stats
static

Handle for reporting statistics.

Definition at line 115 of file gnunet-service-peerinfo.c.

Referenced by add_host_to_known_hosts(), run(), and shutdown_task().

◆ cron_clean

struct GNUNET_SCHEDULER_Task* cron_clean
static

Handle for task to run cron_clean_data_hosts()

Definition at line 120 of file gnunet-service-peerinfo.c.

Referenced by cron_clean_data_hosts(), run(), and shutdown_task().

◆ cron_scan

struct GNUNET_SCHEDULER_Task* cron_scan
static

Handle for task to run cron_scan_directory_data_hosts()

Definition at line 125 of file gnunet-service-peerinfo.c.

Referenced by cron_scan_directory_data_hosts(), run(), and shutdown_task().