iPXE
peerdisc.c File Reference

Peer Content Caching and Retrieval (PeerDist) protocol peer discovery. More...

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/xfer.h>
#include <ipxe/iobuf.h>
#include <ipxe/open.h>
#include <ipxe/tcpip.h>
#include <ipxe/uuid.h>
#include <ipxe/base16.h>
#include <ipxe/netdevice.h>
#include <ipxe/timer.h>
#include <ipxe/fault.h>
#include <ipxe/settings.h>
#include <ipxe/pccrr.h>
#include <ipxe/pccrd.h>
#include <ipxe/peerdisc.h>

Go to the source code of this file.

Macros

#define PEERDISC_REPEAT_COUNT   2
 Number of repeated discovery attempts.
#define PEERDISC_REPEAT_TIMEOUT   ( 1 * TICKS_PER_SEC )
 Time between repeated discovery attempts.
#define PEERDISC_DEFAULT_TIMEOUT_SECS   2
 Default discovery timeout (in seconds).

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static LIST_HEAD (peerdisc_segments)
 List of discovery segments.
static struct peerdisc_segment * peerdisc_find (const char *id)
 Find PeerDist discovery segment.
static int peerdisc_discovered (struct peerdisc_segment *segment, struct peerdist_retrieval *retrieval, const char *location)
 Add discovered PeerDist peer.
void peerdisc_stat (struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
 Report peer discovery statistics.
static int peerdisc_socket_open (void)
 Open all PeerDist discovery sockets.
static void peerdisc_socket_tx (const char *uuid, const char *id)
 Attempt to transmit PeerDist discovery requests on all sockets.
static int peerdisc_socket_rx (struct peerdisc_socket *socket, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Handle received PeerDist discovery reply.
static void peerdisc_socket_close (int rc)
 Close all PeerDist discovery sockets.
static void peerdisc_free (struct refcnt *refcnt)
 Free PeerDist discovery segment.
static void peerdisc_expired (struct retry_timer *timer, int over __unused)
 Handle discovery timer expiry.
static struct peerdisc_segment * peerdisc_create (const char *id)
 Create PeerDist discovery segment.
static void peerdisc_destroy (struct peerdisc_segment *segment)
 Destroy PeerDist discovery segment.
int peerdisc_open (struct peerdisc_client *peerdisc, const void *id, size_t len)
 Open PeerDist discovery client.
void peerdisc_close (struct peerdisc_client *peerdisc)
 Close PeerDist discovery client.
const struct setting peerhost_setting __setting (SETTING_MISC, peerhost)
 PeerDist hosted cache server setting.
const struct setting peerpath_setting __setting (SETTING_MISC, peerpath)
 PeerDist local cache directory setting.
static int apply_peerdisc_settings (void)
 Apply PeerDist discovery settings.

Variables

unsigned int peerdisc_timeout_secs = PEERDISC_DEFAULT_TIMEOUT_SECS
 Recommended discovery timeout (in seconds).
static char * peerdisc_recent
 Most recently discovered peer (for any block).
static char * peerhost
 Hosted cache server.
static char * peerpath
 Local cache directory.
static struct interface_operation peerdisc_socket_operations []
 PeerDist discovery socket interface operations.
static struct interface_descriptor peerdisc_socket_desc
 PeerDist discovery socket interface descriptor.
struct peerdisc_socket peerdisc_socket_ipv4 __peerdisc_socket
 PeerDist discovery IPv4 socket.
struct settings_applicator peerdisc_applicator __settings_applicator
 PeerDist discovery settings applicator.

Detailed Description

Peer Content Caching and Retrieval (PeerDist) protocol peer discovery.

Definition in file peerdisc.c.

Macro Definition Documentation

◆ PEERDISC_REPEAT_COUNT

#define PEERDISC_REPEAT_COUNT   2

Number of repeated discovery attempts.

Definition at line 56 of file peerdisc.c.

Referenced by peerdisc_expired().

◆ PEERDISC_REPEAT_TIMEOUT

#define PEERDISC_REPEAT_TIMEOUT   ( 1 * TICKS_PER_SEC )

Time between repeated discovery attempts.

Definition at line 59 of file peerdisc.c.

Referenced by peerdisc_expired().

◆ PEERDISC_DEFAULT_TIMEOUT_SECS

#define PEERDISC_DEFAULT_TIMEOUT_SECS   2

Default discovery timeout (in seconds).

Definition at line 62 of file peerdisc.c.

Referenced by peerdisc_socket_rx().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ LIST_HEAD()

LIST_HEAD ( peerdisc_segments )
static

List of discovery segments.

◆ peerdisc_find()

struct peerdisc_segment * peerdisc_find ( const char * id)
static

Find PeerDist discovery segment.

Parameters
idSegment ID
Return values
segmentPeerDist discovery segment, or NULL if not found

Definition at line 373 of file peerdisc.c.

373 {
375
376 /* Look for a matching segment */
377 list_for_each_entry ( segment, &peerdisc_segments, list ) {
378 if ( strcmp ( id, segment->id ) == 0 )
379 return segment;
380 }
381
382 return NULL;
383}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
uint16_t segment
Code segment.
Definition librm.h:3
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
A PeerDist discovery segment.
Definition peerdisc.h:43
struct list_head list
List of segments.
Definition peerdisc.h:47

References peerdisc_segment::list, list_for_each_entry, NULL, segment, and strcmp().

Referenced by peerdisc_open(), and peerdisc_socket_rx().

◆ peerdisc_discovered()

int peerdisc_discovered ( struct peerdisc_segment * segment,
struct peerdist_retrieval * retrieval,
const char * location )
static

Add discovered PeerDist peer.

Parameters
segmentPeerDist discovery segment
retrievalPeerDist retrieval protocol
locationPeer location
Return values
rcReturn status code

Definition at line 393 of file peerdisc.c.

395 {
396 struct peerdisc_peer *peer;
397 struct peerdisc_client *peerdisc;
398 struct peerdisc_client *tmp;
399 char *recent;
400
401 /* Ignore duplicate peers */
402 list_for_each_entry ( peer, &segment->peers, list ) {
403 if ( strcmp ( peer->location, location ) == 0 ) {
404 DBGC2 ( segment, "PEERDISC %p duplicate %s\n",
405 segment, location );
406 return 0;
407 }
408 }
409 DBGC2 ( segment, "PEERDISC %p discovered %s\n", segment, location );
410
411 /* Allocate and initialise structure */
412 peer = zalloc ( sizeof ( *peer ) + strlen ( location ) + 1 /* NUL */ );
413 if ( ! peer )
414 return -ENOMEM;
415 peer->retrieval = retrieval;
416 strcpy ( peer->location, location );
417
418 /* Add to end of list of peers */
419 list_add_tail ( &peer->list, &segment->peers );
420
421 /* Record as most recently discovered peer, if applicable */
422 if ( ( location != peerdisc_recent ) &&
423 ( location != peerhost ) &&
424 ( location != peerpath ) ) {
425 recent = strdup ( location );
426 if ( recent ) {
428 peerdisc_recent = recent;
429 }
430 }
431
432 /* Notify all clients */
433 list_for_each_entry_safe ( peerdisc, tmp, &segment->clients, list )
434 peerdisc->op->discovered ( peerdisc );
435
436 return 0;
437}
#define DBGC2(...)
Definition compiler.h:547
#define ENOMEM
Not enough space.
Definition errno.h:578
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:1
static char * peerhost
Hosted cache server.
Definition peerdisc.c:82
static char * peerpath
Local cache directory.
Definition peerdisc.c:85
static char * peerdisc_recent
Most recently discovered peer (for any block).
Definition peerdisc.c:79
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
char * strdup(const char *src)
Duplicate string.
Definition string.c:425
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:378
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
void(* discovered)(struct peerdisc_client *peerdisc)
New peers have been discovered.
Definition peerdisc.h:97
A PeerDist discovery client.
Definition peerdisc.h:82
struct list_head list
List of clients.
Definition peerdisc.h:86
struct peerdisc_client_operations * op
Operations.
Definition peerdisc.h:88
A PeerDist discovery peer.
Definition peerdisc.h:72

References DBGC2, peerdisc_client_operations::discovered, ENOMEM, free, peerdisc_client::list, list_add_tail, list_for_each_entry, list_for_each_entry_safe, peerdisc_client::op, peer, peerdisc_recent, peerhost, peerpath, segment, strcmp(), strcpy(), strdup(), strlen(), tmp, and zalloc().

Referenced by peerdisc_create(), and peerdisc_socket_rx().

◆ peerdisc_stat()

void peerdisc_stat ( struct interface * intf,
struct peerdisc_peer * peer,
struct list_head * peers )

Report peer discovery statistics.

Parameters
intfInterface
peerSelected peer (or NULL)
peersList of available peers

Definition at line 106 of file peerdisc.c.

107 {
108 struct interface *dest;
109 peerdisc_stat_TYPE ( void * ) *op =
111 void *object = intf_object ( dest );
112
113 if ( op ) {
114 op ( object, peer, peers );
115 } else {
116 /* Default is to do nothing */
117 }
118
119 intf_put ( dest );
120}
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition interface.c:160
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition interface.c:150
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition interface.h:270
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
void peerdisc_stat(struct interface *intf, struct peerdisc_peer *peer, struct list_head *peers)
Report peer discovery statistics.
Definition peerdisc.c:106
#define peerdisc_stat_TYPE(object_type)
Definition peerdisc.h:117
An object interface.
Definition interface.h:125
struct interface * intf
Original interface.
Definition interface.h:159

References dest, interface::intf, intf_get_dest_op, intf_object(), intf_put(), op, peer, peerdisc_stat(), and peerdisc_stat_TYPE.

Referenced by peerblk_done(), and peerdisc_stat().

◆ peerdisc_socket_open()

int peerdisc_socket_open ( void )
static

Open all PeerDist discovery sockets.

Return values
rcReturn status code

Definition at line 134 of file peerdisc.c.

134 {
135 struct peerdisc_socket *socket;
136 int rc;
137
138 /* Open each socket */
140 if ( ( rc = xfer_open_socket ( &socket->xfer, SOCK_DGRAM,
141 &socket->address.sa,
142 NULL ) ) != 0 ) {
143 DBGC ( socket, "PEERDISC %s could not open socket: "
144 "%s\n", socket->name, strerror ( rc ) );
145 goto err;
146 }
147 }
148
149 return 0;
150
151 err:
153 intf_restart ( &socket->xfer, rc );
154 return rc;
155}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define SOCK_DGRAM
Definition socket.h:30
#define DBGC(...)
Definition compiler.h:530
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition open.c:152
#define PEERDISC_SOCKETS
PeerDist discovery socket table.
Definition peerdisc.h:37
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A PeerDist discovery socket.
Definition peerdisc.h:23
struct sockaddr sa
Definition peerdisc.h:30
const char * name
Name.
Definition peerdisc.h:25
struct interface xfer
Data transfer interface.
Definition peerdisc.h:27
union peerdisc_socket::@135052057250103003165261220231164357172243045304 address
Socket address.
#define for_each_table_entry_continue_reverse(pointer, table)
Iterate through all remaining entries within a linker table in reverse order.
Definition tables.h:470
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References peerdisc_socket::address, DBGC, for_each_table_entry, for_each_table_entry_continue_reverse, intf_restart(), peerdisc_socket::name, NULL, PEERDISC_SOCKETS, rc, peerdisc_socket::sa, SOCK_DGRAM, strerror(), peerdisc_socket::xfer, and xfer_open_socket().

Referenced by peerdisc_open().

◆ peerdisc_socket_tx()

void peerdisc_socket_tx ( const char * uuid,
const char * id )
static

Attempt to transmit PeerDist discovery requests on all sockets.

Parameters
uuidMessage UUID string
idSegment identifier string

Definition at line 163 of file peerdisc.c.

163 {
164 struct peerdisc_socket *socket;
165 struct net_device *netdev;
166 struct xfer_metadata meta;
167 union {
168 struct sockaddr sa;
169 struct sockaddr_tcpip st;
170 } address;
171 char *request;
172 size_t len;
173 int rc;
174
175 /* Construct discovery request */
177 if ( ! request )
178 goto err_request;
179 len = strlen ( request );
180
181 /* Initialise data transfer metadata */
182 memset ( &meta, 0, sizeof ( meta ) );
183 meta.dest = &address.sa;
184
185 /* Send message on each socket */
187
188 /* Initialise socket address */
189 memcpy ( &address.sa, &socket->address.sa,
190 sizeof ( address.sa ) );
191
192 /* Send message on each open network device */
194
195 /* Skip unopened network devices */
196 if ( ! netdev_is_open ( netdev ) )
197 continue;
198 address.st.st_scope_id = netdev->scope_id;
199
200 /* Discard request (for test purposes) if applicable */
201 if ( inject_fault ( PEERDISC_DISCARD_RATE ) )
202 continue;
203
204 /* Transmit request */
205 if ( ( rc = xfer_deliver_raw_meta ( &socket->xfer,
206 request, len,
207 &meta ) ) != 0 ) {
208 DBGC ( socket, "PEERDISC %s could not transmit "
209 "via %s: %s\n", socket->name,
210 netdev->name, strerror ( rc ) );
211 /* Contine to try other net devices/sockets */
212 continue;
213 }
214 }
215 }
216
217 free ( request );
218 err_request:
219 return;
220}
#define PEERDISC_DISCARD_RATE
Definition fault.h:22
ring len
Length.
Definition dwmac.h:226
uint8_t meta
Metadata flags.
Definition ena.h:3
uint64_t address
Base address.
Definition ena.h:13
static struct net_device * netdev
Definition gdbudp.c:53
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition netdevice.h:550
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:665
char * peerdist_discovery_request(const char *uuid, const char *id)
Construct discovery request.
Definition pccrd.c:107
A network device.
Definition netdevice.h:353
Data transfer metadata.
Definition xfer.h:23
struct sockaddr_tcpip st
Definition syslog.c:58
struct sockaddr sa
Definition syslog.c:57
A universally unique ID.
Definition uuid.h:16
int xfer_deliver_raw_meta(struct interface *intf, const void *data, size_t len, struct xfer_metadata *meta)
Deliver datagram as raw data.
Definition xfer.c:269

References address, peerdisc_socket::address, DBGC, for_each_netdev, for_each_table_entry, free, len, memcpy(), memset(), meta, peerdisc_socket::name, netdev, netdev_is_open(), PEERDISC_DISCARD_RATE, PEERDISC_SOCKETS, peerdist_discovery_request(), rc, request, peerdisc_socket::sa, sa, st, strerror(), strlen(), peerdisc_socket::xfer, and xfer_deliver_raw_meta().

Referenced by peerdisc_expired().

◆ peerdisc_socket_rx()

int peerdisc_socket_rx ( struct peerdisc_socket * socket,
struct io_buffer * iobuf,
struct xfer_metadata *meta __unused )
static

Handle received PeerDist discovery reply.

Parameters
socketPeerDist discovery socket
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 230 of file peerdisc.c.

232 {
233 struct peerdist_discovery_reply reply;
235 char *id;
236 char *location;
237 int rc;
238
239 /* Discard reply (for test purposes) if applicable */
240 if ( ( rc = inject_fault ( PEERDISC_DISCARD_RATE ) ) != 0 )
241 goto err;
242
243 /* Parse reply */
244 if ( ( rc = peerdist_discovery_reply ( iobuf->data, iob_len ( iobuf ),
245 &reply ) ) != 0 ) {
246 DBGC ( socket, "PEERDISC %s could not parse reply: %s\n",
247 socket->name, strerror ( rc ) );
248 DBGC_HDA ( socket, 0, iobuf->data, iob_len ( iobuf ) );
249 goto err;
250 }
251
252 /* Any kind of discovery reply indicates that there are active
253 * peers on a local network, so restore the recommended
254 * discovery timeout to its default value for future requests.
255 */
257 DBGC ( socket, "PEERDISC %s restoring timeout to %d seconds\n",
259 }
261
262 /* Iterate over segment IDs */
263 for ( id = reply.ids ; *id ; id += ( strlen ( id ) + 1 /* NUL */ ) ) {
264
265 /* Find corresponding segment */
266 segment = peerdisc_find ( id );
267 if ( ! segment ) {
268 DBGC ( socket, "PEERDISC %s ignoring reply for %s\n",
269 socket->name, id );
270 continue;
271 }
272
273 /* Report all discovered peer locations */
274 for ( location = reply.locations ; *location ;
275 location += ( strlen ( location ) + 1 /* NUL */ ) ) {
276
277 /* Report discovered peer location */
278 if ( ( rc = peerdisc_discovered ( segment,
280 location ) ) != 0 ) {
281 goto err;
282 }
283 }
284 }
285
286 err:
287 free_iob ( iobuf );
288 return rc;
289}
uint8_t id
Request identifier.
Definition ena.h:1
#define DBGC_HDA(...)
Definition compiler.h:531
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
struct peerdist_retrieval peerdist_post
PeerDist retrieval protocol using HTTP POST.
Definition pccrr.c:143
static struct peerdisc_segment * peerdisc_find(const char *id)
Find PeerDist discovery segment.
Definition peerdisc.c:373
unsigned int peerdisc_timeout_secs
Recommended discovery timeout (in seconds).
Definition peerdisc.c:76
static int peerdisc_discovered(struct peerdisc_segment *segment, struct peerdist_retrieval *retrieval, const char *location)
Add discovered PeerDist peer.
Definition peerdisc.c:393
#define PEERDISC_DEFAULT_TIMEOUT_SECS
Default discovery timeout (in seconds).
Definition peerdisc.c:62
void * data
Start of data.
Definition iobuf.h:113
A PeerDist discovery reply.
Definition pccrd.h:32

References __unused, io_buffer::data, DBGC, DBGC_HDA, free_iob(), id, peerdist_discovery_reply::ids, iob_len(), peerdist_discovery_reply::locations, meta, peerdisc_socket::name, PEERDISC_DEFAULT_TIMEOUT_SECS, PEERDISC_DISCARD_RATE, peerdisc_discovered(), peerdisc_find(), peerdisc_timeout_secs, peerdist_post, rc, segment, strerror(), and strlen().

◆ peerdisc_socket_close()

void peerdisc_socket_close ( int rc)
static

Close all PeerDist discovery sockets.

Parameters
rcReason for close

Definition at line 296 of file peerdisc.c.

296 {
297 struct peerdisc_socket *socket;
298
299 /* Close all sockets */
301 intf_restart ( &socket->xfer, rc );
302}

References for_each_table_entry, intf_restart(), PEERDISC_SOCKETS, rc, and peerdisc_socket::xfer.

Referenced by peerdisc_close().

◆ peerdisc_free()

void peerdisc_free ( struct refcnt * refcnt)
static

Free PeerDist discovery segment.

Parameters
refcntReference count

Definition at line 351 of file peerdisc.c.

351 {
352 struct peerdisc_segment *segment =
354 struct peerdisc_peer *peer;
355 struct peerdisc_peer *tmp;
356
357 /* Free all discovered peers */
359 list_del ( &peer->list );
360 free ( peer );
361 }
362
363 /* Free segment */
364 free ( segment );
365}
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
struct list_head list
List of peers.
Definition peerdisc.h:74
A reference counter.
Definition refcnt.h:27

References container_of, free, peerdisc_peer::list, list_del, list_for_each_entry_safe, peer, segment, and tmp.

Referenced by peerdisc_create().

◆ peerdisc_expired()

void peerdisc_expired ( struct retry_timer * timer,
int over __unused )
static

Handle discovery timer expiry.

Parameters
timerDiscovery timer
overFailure indicator

Definition at line 445 of file peerdisc.c.

445 {
446 struct peerdisc_segment *segment =
448
449 /* Attempt to transmit discovery requests */
450 peerdisc_socket_tx ( segment->uuid, segment->id );
451
452 /* Schedule next transmission, if applicable */
453 if ( timer->count < PEERDISC_REPEAT_COUNT )
455}
static void peerdisc_socket_tx(const char *uuid, const char *id)
Attempt to transmit PeerDist discovery requests on all sockets.
Definition peerdisc.c:163
#define PEERDISC_REPEAT_COUNT
Number of repeated discovery attempts.
Definition peerdisc.c:56
#define PEERDISC_REPEAT_TIMEOUT
Time between repeated discovery attempts.
Definition peerdisc.c:59
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
A timer.
Definition timer.h:29

References __unused, container_of, PEERDISC_REPEAT_COUNT, PEERDISC_REPEAT_TIMEOUT, peerdisc_socket_tx(), segment, and start_timer_fixed().

Referenced by peerdisc_create().

◆ peerdisc_create()

struct peerdisc_segment * peerdisc_create ( const char * id)
static

Create PeerDist discovery segment.

Parameters
idSegment ID
Return values
segmentPeerDist discovery segment, or NULL on error

Definition at line 463 of file peerdisc.c.

463 {
465 union {
466 union uuid uuid;
467 uint32_t dword[ sizeof ( union uuid ) / sizeof ( uint32_t ) ];
468 } random_uuid;
469 size_t uuid_len;
470 size_t id_len;
471 const char *uuid;
472 char *uuid_copy;
473 char *id_copy;
474 unsigned int i;
475 int rc;
476
477 /* Generate a random message UUID. This does not require high
478 * quality randomness.
479 */
480 for ( i = 0 ; i < ( sizeof ( random_uuid.dword ) /
481 sizeof ( random_uuid.dword[0] ) ) ; i++ )
482 random_uuid.dword[i] = random();
483 uuid = uuid_ntoa ( &random_uuid.uuid );
484
485 /* Calculate string lengths */
486 id_len = ( strlen ( id ) + 1 /* NUL */ );
487 uuid_len = ( strlen ( uuid ) + 1 /* NUL */ );
488
489 /* Allocate and initialise structure */
490 segment = zalloc ( sizeof ( *segment ) + id_len + uuid_len );
491 if ( ! segment )
492 goto err_alloc;
493 id_copy = ( ( ( void * ) segment ) + sizeof ( *segment ) );
494 memcpy ( id_copy, id, id_len );
495 uuid_copy = ( ( ( void * ) id_copy ) + id_len );
496 memcpy ( uuid_copy, uuid, uuid_len );
497 ref_init ( &segment->refcnt, peerdisc_free );
498 segment->id = id_copy;
499 segment->uuid = uuid_copy;
500 INIT_LIST_HEAD ( &segment->peers );
501 INIT_LIST_HEAD ( &segment->clients );
502 timer_init ( &segment->timer, peerdisc_expired, &segment->refcnt );
503
504 /* Add local cache directory, if any */
505 if ( peerpath )
507
508 /* Add hosted cache server or initiate discovery */
509 if ( peerhost ) {
510
511 /* Add hosted cache server to list of peers */
513 peerhost ) ) != 0 ) {
514 goto err_peerhost;
515 }
516
517 } else {
518
519 /* Add most recently discovered peer to list of peers
520 *
521 * This is a performance optimisation: we assume that
522 * the most recently discovered peer for any block has
523 * a high probability of also having a copy of the
524 * next block that we attempt to discover.
525 */
526 if ( peerdisc_recent ) {
529 }
530
531 /* Start discovery timer */
532 start_timer_nodelay ( &segment->timer );
533 DBGC2 ( segment, "PEERDISC %p discovering %s\n",
534 segment, segment->id );
535 }
536
537 /* Add to list of segments, transfer reference to list, and return */
538 list_add_tail ( &segment->list, &peerdisc_segments );
539 return segment;
540
541 err_peerhost:
542 ref_put ( &segment->refcnt );
543 err_alloc:
544 return NULL;
545}
unsigned int uint32_t
Definition stdint.h:12
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
struct peerdist_retrieval peerdist_get
PeerDist retrieval protocol using HTTP GET or local file.
Definition pccrr.c:190
static void peerdisc_expired(struct retry_timer *timer, int over __unused)
Handle discovery timer expiry.
Definition peerdisc.c:445
static void peerdisc_free(struct refcnt *refcnt)
Free PeerDist discovery segment.
Definition peerdisc.c:351
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
unsigned long int dword
Definition smc9000.h:40
const char * uuid
Message UUID string.
Definition peerdisc.h:55
const char * uuid_ntoa(const union uuid *uuid)
Convert UUID to printable string.
Definition uuid.c:46

References DBGC2, INIT_LIST_HEAD, list_add_tail, memcpy(), NULL, peerdisc_discovered(), peerdisc_expired(), peerdisc_free(), peerdisc_recent, peerdist_get, peerdist_post, peerhost, peerpath, random(), rc, ref_init, ref_put, segment, start_timer_nodelay(), strlen(), uuid_ntoa(), and zalloc().

Referenced by peerdisc_open().

◆ peerdisc_destroy()

void peerdisc_destroy ( struct peerdisc_segment * segment)
static

Destroy PeerDist discovery segment.

Parameters
segmentPeerDist discovery segment

Definition at line 552 of file peerdisc.c.

552 {
553
554 /* Sanity check */
555 assert ( list_empty ( &segment->clients ) );
556
557 /* Stop timer */
558 stop_timer ( &segment->timer );
559
560 /* Remove from list of segments and drop list's reference */
561 list_del ( &segment->list );
562 ref_put ( &segment->refcnt );
563}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118

References assert, list_del, list_empty, ref_put, segment, and stop_timer().

Referenced by peerdisc_close().

◆ peerdisc_open()

int peerdisc_open ( struct peerdisc_client * peerdisc,
const void * id,
size_t len )

Open PeerDist discovery client.

Parameters
peerdiscPeerDist discovery client
idSegment ID
lenLength of segment ID
Return values
rcReturn status code

Definition at line 580 of file peerdisc.c.

581 {
583 char id_string[ base16_encoded_len ( len ) + 1 /* NUL */ ];
584 char *id_chr;
585 int rc;
586
587 /* Construct ID string */
588 base16_encode ( id, len, id_string, sizeof ( id_string ) );
589 for ( id_chr = id_string ; *id_chr ; id_chr++ )
590 *id_chr = toupper ( *id_chr );
591
592 /* Sanity check */
593 assert ( peerdisc->segment == NULL );
594
595 /* Open socket if this is the first segment */
596 if ( list_empty ( &peerdisc_segments ) &&
597 ( ( rc = peerdisc_socket_open() ) != 0 ) )
598 return rc;
599
600 /* Find or create segment */
601 if ( ! ( ( segment = peerdisc_find ( id_string ) ) ||
602 ( segment = peerdisc_create ( id_string ) ) ) )
603 return -ENOMEM;
604
605 /* Add to list of clients */
606 ref_get ( &segment->refcnt );
607 peerdisc->segment = segment;
608 list_add_tail ( &peerdisc->list, &segment->clients );
609
610 return 0;
611}
static size_t base16_encoded_len(size_t raw_len)
Calculate length of base16-encoded data.
Definition base16.h:25
static int toupper(int character)
Convert character to upper case.
Definition ctype.h:121
uint8_t id_string[24]
ID string.
Definition eltorito.h:12
static struct peerdisc_segment * peerdisc_create(const char *id)
Create PeerDist discovery segment.
Definition peerdisc.c:463
static int peerdisc_socket_open(void)
Open all PeerDist discovery sockets.
Definition peerdisc.c:134
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
struct peerdisc_segment * segment
Discovery segment.
Definition peerdisc.h:84

References assert, base16_encoded_len(), ENOMEM, id_string, len, peerdisc_client::list, list_add_tail, list_empty, NULL, peerdisc_create(), peerdisc_find(), peerdisc_socket_open(), rc, ref_get, peerdisc_client::segment, segment, and toupper().

Referenced by peerblk_open().

◆ peerdisc_close()

void peerdisc_close ( struct peerdisc_client * peerdisc)

Close PeerDist discovery client.

Parameters
peerdiscPeerDist discovery client

Definition at line 618 of file peerdisc.c.

618 {
619 struct peerdisc_segment *segment = peerdisc->segment;
620
621 /* Ignore if discovery is already closed */
622 if ( ! segment )
623 return;
624
625 /* If no peers were discovered, reduce the recommended
626 * discovery timeout to minimise delays on future requests.
627 */
628 if ( list_empty ( &segment->peers ) && peerdisc_timeout_secs ) {
630 DBGC ( segment, "PEERDISC %p reducing timeout to %d "
631 "seconds\n", peerdisc, peerdisc_timeout_secs );
632 }
633
634 /* Remove from list of clients */
635 peerdisc->segment = NULL;
636 list_del ( &peerdisc->list );
637 ref_put ( &segment->refcnt );
638
639 /* If this was the last clients, destroy the segment */
640 if ( list_empty ( &segment->clients ) )
642
643 /* If there are no more segments, close the socket */
644 if ( list_empty ( &peerdisc_segments ) )
646}
static void peerdisc_destroy(struct peerdisc_segment *segment)
Destroy PeerDist discovery segment.
Definition peerdisc.c:552
static void peerdisc_socket_close(int rc)
Close all PeerDist discovery sockets.
Definition peerdisc.c:296

References DBGC, peerdisc_client::list, list_del, list_empty, NULL, peerdisc_destroy(), peerdisc_socket_close(), peerdisc_timeout_secs, ref_put, peerdisc_client::segment, and segment.

Referenced by peerblk_close().

◆ __setting() [1/2]

const struct setting peerhost_setting __setting ( SETTING_MISC ,
peerhost  )

PeerDist hosted cache server setting.

References __setting, peerhost, and SETTING_MISC.

◆ __setting() [2/2]

const struct setting peerpath_setting __setting ( SETTING_MISC ,
peerpath  )

PeerDist local cache directory setting.

References __setting, peerpath, and SETTING_MISC.

◆ apply_peerdisc_settings()

int apply_peerdisc_settings ( void )
static

Apply PeerDist discovery settings.

Return values
rcReturn status code

Definition at line 674 of file peerdisc.c.

674 {
675 char *host;
676 char *path;
677
678 /* Set hosted cache server, if any */
679 fetch_string_setting_copy ( NULL, &peerhost_setting, &host );
680 if ( host && ! ( peerhost && ( strcmp ( host, peerhost ) == 0 ) ) ) {
681 DBGC ( &peerdisc_segments, "PEERDISC using hosted cache %s\n",
682 host );
683 }
684 free ( peerhost );
685 peerhost = host;
686
687 /* Set local cache directory, if any */
688 fetch_string_setting_copy ( NULL, &peerpath_setting, &path );
689 if ( path && ! ( peerpath && ( strcmp ( path, peerpath ) == 0 ) ) ) {
690 DBGC ( &peerdisc_segments, "PEERDISC using local cache %s\n",
691 path );
692 }
693 free ( peerpath );
694 peerpath = path;
695
696 return 0;
697}
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition settings.c:874

References DBGC, fetch_string_setting_copy(), free, NULL, peerhost, peerpath, and strcmp().

Variable Documentation

◆ peerdisc_timeout_secs

unsigned int peerdisc_timeout_secs = PEERDISC_DEFAULT_TIMEOUT_SECS

Recommended discovery timeout (in seconds).

We reduce the recommended discovery timeout whenever a segment fails to discover any peers, and restore the default value whenever a valid discovery reply is received. We continue to send discovery requests even if the recommended timeout is reduced to zero.

This strategy is intended to minimise discovery delays when no peers are available on the network, while allowing downloads to quickly switch back to using PeerDist acceleration if new peers become available.

Definition at line 76 of file peerdisc.c.

Referenced by peerblk_open(), peerdisc_close(), and peerdisc_socket_rx().

◆ peerdisc_recent

char* peerdisc_recent
static

Most recently discovered peer (for any block).

Definition at line 79 of file peerdisc.c.

Referenced by peerdisc_create(), and peerdisc_discovered().

◆ peerhost

char* peerhost
static

Hosted cache server.

Definition at line 82 of file peerdisc.c.

Referenced by __setting(), apply_peerdisc_settings(), peerdisc_create(), and peerdisc_discovered().

◆ peerpath

char* peerpath
static

Local cache directory.

Definition at line 85 of file peerdisc.c.

Referenced by __setting(), apply_peerdisc_settings(), peerdisc_create(), and peerdisc_discovered().

◆ peerdisc_socket_operations

struct interface_operation peerdisc_socket_operations[]
static
Initial value:
= {
}
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
static int peerdisc_socket_rx(struct peerdisc_socket *socket, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Handle received PeerDist discovery reply.
Definition peerdisc.c:230
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195

PeerDist discovery socket interface operations.

Definition at line 305 of file peerdisc.c.

305 {
307};

◆ peerdisc_socket_desc

struct interface_descriptor peerdisc_socket_desc
static
Initial value:
=
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static struct interface_operation peerdisc_socket_operations[]
PeerDist discovery socket interface operations.
Definition peerdisc.c:305

PeerDist discovery socket interface descriptor.

Definition at line 310 of file peerdisc.c.

◆ __peerdisc_socket

struct peerdisc_socket peerdisc_socket_ipv6 __peerdisc_socket
Initial value:
= {
.name = "IPv4",
.address = {
.sin = {
.sin_family = AF_INET,
.sin_port = htons ( PEERDIST_DISCOVERY_PORT ),
.sin_addr.s_addr = PEERDIST_DISCOVERY_IPV4,
},
},
}
#define AF_INET
IPv4 Internet addresses.
Definition socket.h:64
#define htons(value)
Definition byteswap.h:136
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition interface.h:218
#define PEERDIST_DISCOVERY_PORT
PeerDist discovery port.
Definition pccrd.h:16
#define PEERDIST_DISCOVERY_IPV4
PeerDist discovery IPv4 address (239.255.255.250).
Definition pccrd.h:19
static struct interface_descriptor peerdisc_socket_desc
PeerDist discovery socket interface descriptor.
Definition peerdisc.c:310

PeerDist discovery IPv4 socket.

PeerDist discovery IPv6 socket.

Definition at line 314 of file peerdisc.c.

314 {
315 .name = "IPv4",
316 .address = {
317 .sin = {
318 .sin_family = AF_INET,
319 .sin_port = htons ( PEERDIST_DISCOVERY_PORT ),
320 .sin_addr.s_addr = PEERDIST_DISCOVERY_IPV4,
321 },
322 },
324};

◆ __settings_applicator

struct settings_applicator peerdisc_applicator __settings_applicator
Initial value:
= {
}
static int apply_peerdisc_settings(void)
Apply PeerDist discovery settings.
Definition peerdisc.c:674

PeerDist discovery settings applicator.

Definition at line 700 of file peerdisc.c.

700 {
702};