The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
|
Binary IO abstractions for retrying packets. More...
#include <freeradius-devel/bio/bio_priv.h>
#include <freeradius-devel/bio/null.h>
#include <freeradius-devel/bio/buf.h>
#include <freeradius-devel/util/rb.h>
#include <freeradius-devel/util/dlist.h>
#include <freeradius-devel/bio/retry.h>
Go to the source code of this file.
Data Structures | |
struct | fr_bio_retry_entry_s |
union | fr_bio_retry_entry_s.__unnamed10__ |
struct | fr_bio_retry_s |
Macros | |
#define | _BIO_RETRY_PRIVATE |
#define | fr_bio_retry_timer_clear(_x) |
Typedefs | |
typedef struct fr_bio_retry_list_s | fr_bio_retry_list_t |
typedef struct fr_bio_retry_s | fr_bio_retry_t |
Functions | |
static int8_t | _expiry_cmp (void const *one, void const *two) |
static int8_t | _next_retry_cmp (void const *one, void const *two) |
fr_bio_t * | fr_bio_retry_alloc (TALLOC_CTX *ctx, size_t max_saved, fr_bio_retry_sent_t sent, fr_bio_retry_response_t response, fr_bio_retry_rewrite_t rewrite, fr_bio_retry_release_t release, fr_bio_retry_config_t const *cfg, fr_bio_t *next) |
Allocate a fr_bio_retry_t. | |
static int | fr_bio_retry_destructor (fr_bio_retry_t *my) |
Cancel all outstanding packets. | |
int | fr_bio_retry_entry_cancel (fr_bio_t *bio, fr_bio_retry_entry_t *item) |
Cancel one item. | |
const fr_retry_t * | fr_bio_retry_entry_info (UNUSED fr_bio_t *bio, fr_bio_retry_entry_t *item) |
Allow the callbacks / application to know when things are being retried. | |
int | fr_bio_retry_entry_init (UNUSED fr_bio_t *bio, fr_bio_retry_entry_t *item, fr_retry_config_t const *cfg) |
Set a per-packet retry config. | |
static void | fr_bio_retry_expiry_timer (UNUSED fr_event_list_t *el, fr_time_t now, void *uctx) |
Run an expiry timer event. | |
static int | fr_bio_retry_expiry_timer_reset (fr_bio_retry_t *my) |
Reset the expiry timer after expiring one element. | |
fr_bio_retry_info_t const * | fr_bio_retry_info (fr_bio_t *bio) |
fr_bio_retry_entry_t * | fr_bio_retry_item_reserve (fr_bio_t *bio) |
Reserve an entry for later use with fr_bio_retry_rewrite() | |
size_t | fr_bio_retry_outstanding (fr_bio_t *bio) |
static ssize_t | fr_bio_retry_read (fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size) |
static void | fr_bio_retry_release (fr_bio_retry_t *my, fr_bio_retry_entry_t *item, fr_bio_retry_release_reason_t reason) |
Release an entry back to the free list. | |
ssize_t | fr_bio_retry_rewrite (fr_bio_t *bio, fr_bio_retry_entry_t *item, const void *buffer, size_t size) |
Resend a packet. | |
static ssize_t | fr_bio_retry_save_write (fr_bio_retry_t *my, fr_bio_retry_entry_t *item, ssize_t rcode) |
Save a partial packet when the write becomes blocked. | |
static void | fr_bio_retry_shutdown (fr_bio_t *bio) |
Orderly shutdown. | |
static void | fr_bio_retry_timer (UNUSED fr_event_list_t *el, fr_time_t now, void *uctx) |
Run a timer event. | |
static int | fr_bio_retry_timer_reset (fr_bio_retry_t *my) |
Reset the timer after changing the rb tree. | |
static ssize_t | fr_bio_retry_write (fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size) |
Write a request, and see if we have a reply. | |
static int | fr_bio_retry_write_blocked (fr_bio_t *bio) |
Writes are blocked. | |
static int | fr_bio_retry_write_delayed (fr_bio_retry_t *my, fr_time_t now) |
static ssize_t | fr_bio_retry_write_fatal (fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size) |
A previous timer write had a fatal error, so we forbid further writes. | |
static int | fr_bio_retry_write_item (fr_bio_retry_t *my, fr_bio_retry_entry_t *item, fr_time_t now) |
Write one item. | |
static ssize_t | fr_bio_retry_write_partial (fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size) |
There's a partial packet written. | |
static int | fr_bio_retry_write_resume (fr_bio_t *bio) |
Resume writes. | |
Binary IO abstractions for retrying packets.
The retry BIO provides a mechanism for the application to send one packet, and then delegate retransmissions to the retry bio.
This BIO will monitor writes, and run callbacks when a packet is sent, received, and released. The application should cache the request and response until the release callback has been run. The BIO will call the application on retries, or when the retransmissions have stopped.
The retry BIO also deals with partially written packets. The BIO takes responsibility for not writing partial packets, which means that requests can be rleeased even if the data has been partially written. The application can also cancel an ongoing retryt entrty at any time.
If something blocks IO, the application should call the blocked / resume functions for this BIO to inform it of IO changes. Otherwise, the only time this BIO blocks is when it runs out of retransmission slots.
There are provisions for application-layer watchdogs, where the application can reserve a retry entry. It can then call the fr_bio_retry_rewrite() function instead of fr_bio_write() to write the watchdog packet. Any retransmission timers for the application-layer watchdog must be handled by the application. The BIO will not retry reserved watchdog requests.
In general, the next BIO after this one should be the memory bio, so that this bio receives only complete packets.
Definition in file retry.c.
struct fr_bio_retry_entry_s |
Data Fields | ||
---|---|---|
union fr_bio_retry_entry_s.__unnamed10__ | __unnamed__ | |
uint8_t const * | buffer | cached copy of the packet to send |
bool | cancelled | was this item cancelled? |
fr_rb_node_t | expiry_node | for expiries |
fr_bio_retry_t * | my | so we can get to it from the event timer callback |
void * | packet_ctx | packet_ctx from the write() call |
bool | reserved | for application-layer watchdog |
fr_retry_t | retry | retry timers and counters |
fr_retry_t _CONST | retry | retry timers and counters |
fr_bio_retry_rewrite_t | rewrite | per-packet rewrite callback |
void * | rewrite_ctx | context specifically for rewriting this packet |
size_t | size | size of the cached packet |
void * | uctx | user-writable context |
union fr_bio_retry_entry_s.__unnamed10__ |
Data Fields | ||
---|---|---|
fr_rb_node_t | next_retry_node | for retries |
struct fr_bio_retry_s |
Data Fields | ||
---|---|---|
bool | all_used | blocked due to no free entries |
fr_bio_buf_t | buffer | to store partial packets |
ssize_t | error | |
fr_event_timer_t const * | ev | we only need one timer event: next time we do something |
fr_rb_tree_t | expiry_tree | when packets expire, so that we expire packets when the socket is blocked. |
FR_BIO_COMMON | ||
fr_bio_retry_info_t | info | |
fr_bio_retry_entry_t * | next_retry_item | for timers |
fr_rb_tree_t | next_retry_tree | when packets are retried next |
fr_bio_retry_entry_t * | partial | for partial writes |
fr_bio_retry_release_t | release | callback to release a request / response pair |
fr_bio_retry_response_t | response | callback to see if we got a valid response |
fr_retry_config_t | retry_config | |
fr_bio_retry_rewrite_t | rewrite | optional callback which can change a packet on retry |
fr_bio_retry_sent_t | sent | callback for when we successfully sent a packet |
#define fr_bio_retry_timer_clear | ( | _x | ) |
typedef struct fr_bio_retry_list_s fr_bio_retry_list_t |
typedef struct fr_bio_retry_s fr_bio_retry_t |
|
static |
|
static |
fr_bio_t * fr_bio_retry_alloc | ( | TALLOC_CTX * | ctx, |
size_t | max_saved, | ||
fr_bio_retry_sent_t | sent, | ||
fr_bio_retry_response_t | response, | ||
fr_bio_retry_rewrite_t | rewrite, | ||
fr_bio_retry_release_t | release, | ||
fr_bio_retry_config_t const * | cfg, | ||
fr_bio_t * | next | ||
) |
Allocate a fr_bio_retry_t.
Definition at line 1087 of file retry.c.
|
static |
int fr_bio_retry_entry_cancel | ( | fr_bio_t * | bio, |
fr_bio_retry_entry_t * | item | ||
) |
Cancel one item.
If "item" is NULL, the last entry in the timer tree is cancelled.
bio | the binary IO handler |
item | the retry context from fr_bio_retry_sent_t |
Definition at line 993 of file retry.c.
const fr_retry_t * fr_bio_retry_entry_info | ( | UNUSED fr_bio_t * | bio, |
fr_bio_retry_entry_t * | item | ||
) |
int fr_bio_retry_entry_init | ( | UNUSED fr_bio_t * | bio, |
fr_bio_retry_entry_t * | item, | ||
fr_retry_config_t const * | cfg | ||
) |
Set a per-packet retry config.
This function should be called from the fr_bio_retry_sent_t callback to set a unique retry timer for this packet. If no retry configuration is set, then the main one from the alloc() function is used.
Definition at line 1025 of file retry.c.
|
static |
|
static |
fr_bio_retry_info_t const * fr_bio_retry_info | ( | fr_bio_t * | bio | ) |
fr_bio_retry_entry_t * fr_bio_retry_item_reserve | ( | fr_bio_t * | bio | ) |
Reserve an entry for later use with fr_bio_retry_rewrite()
So that application-layer watchdogs can bypass the normal write / retry routines.
Definition at line 1184 of file retry.c.
|
static |
ssize_t fr_bio_retry_rewrite | ( | fr_bio_t * | bio, |
fr_bio_retry_entry_t * | item, | ||
const void * | buffer, | ||
size_t | size | ||
) |
Resend a packet.
This function should be called by the rewrite() callback, after (possibly) re-encoding the packet.
bio | the binary IO handler |
item | the retry context from fr_bio_retry_sent_t |
buffer | raw data for the packet. May be NULL, in which case the previous packet is retried |
size | size of the raw data |
Definition at line 554 of file retry.c.
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
There's a partial packet written.
Write all of that one first, before writing another packet.
The packet can either be cancelled, or IO blocked. In either case, we must write the full packet before going on to the next one, OR retrying another packet.
Definition at line 442 of file retry.c.