* it again later.
*
* @param my the packet-based bio
- * @param[out] request_ctx_p the larger context for the original request packet
+ * @param[out] pctx_p the larger context for the original request packet
* @param[out] packet_p Where the allocated #fr_packet_t will be stored
* @param[out] out_ctx for the output pairs
* @param[out] out decoded output pairs
* - <0 on error. This is fr_bio_error(FOO)
* - 0 for success
*/
-static inline CC_HINT(nonnull) int fr_bio_packet_read(fr_bio_packet_t *my, void **request_ctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out)
+static inline CC_HINT(nonnull) int fr_bio_packet_read(fr_bio_packet_t *my, void **pctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out)
{
- return my->read(my, request_ctx_p, packet_p, out_ctx, out);
+ return my->read(my, pctx_p, packet_p, out_ctx, out);
}
/** Write a packet to a packet BIO
* it again later.
*
* @param my the packet-based bio
- * @param request_ctx the larger context for the packet
+ * @param pctx the larger context for the packet
* @param packet the output packet descriptor. Contains raw protocol data (IDs, counts, etc.)
* @param list of pairs to write
* @return
* - <0 on error. This is fr_bio_error(FOO)
* - 0 for success
*/
-static inline CC_HINT(nonnull) int fr_bio_packet_write(fr_bio_packet_t *my, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
+static inline CC_HINT(nonnull) int fr_bio_packet_write(fr_bio_packet_t *my, void *pctx, fr_packet_t *packet, fr_pair_list_t *list)
{
int rcode;
*/
if (my->write_blocked) return fr_bio_error(IO_WOULD_BLOCK);
- rcode = my->write(my, request_ctx, packet, list);
+ rcode = my->write(my, pctx, packet, list);
if (rcode == 0) return 0;
my->write_blocked = (rcode == fr_bio_error(IO_WOULD_BLOCK));
client_udp.c \
client_tcp.c \
id.c \
- bio.c
+ bio.c \
+ server.c \
+ server_udp.c
TGT_PREREQS += libfreeradius-bio$(L)
endif
return my;
}
-int fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
+int fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, void *pctx, fr_packet_t *packet, fr_pair_list_t *list)
{
ssize_t slen;
uint8_t *end;
id_ctx = fr_radius_code_id_pop(my->codes, packet);
if (!id_ctx) goto all_ids_used;
}
- id_ctx->request_ctx = request_ctx;
+ id_ctx->request_ctx = pctx;
fr_assert(id_ctx->packet == packet);
/*
packet->data_len = end - my->buffer;
fr_nbo_from_uint16(my->buffer + 2, packet->data_len);
- packet->data = talloc_array(packet, uint8_t, packet->data_len);
- if (!packet->data) goto fail;
-
slen = fr_radius_sign(my->buffer, NULL,
(uint8_t const *) my->cfg.verify.secret, my->cfg.verify.secret_len);
if (slen < 0) goto fail;
+ /*
+ * The other BIOs will take care of calling fr_radius_client_bio_write_blocked() when the write
+ * is blocked.
+ *
+ * The "next" BIO is a memory one, which can store the entire packet. So write() never returns a
+ * partial packet.
+ */
slen = fr_bio_write(my->common.bio, &packet->socket, my->buffer, packet->data_len);
if (slen < 0) {
+ fr_assert((slen != fr_bio_error(IO_WOULD_BLOCK)) || my->common.write_blocked);
+
fr_radius_code_id_push(my->codes, packet);
return slen;
}
+ fr_assert((size_t) slen == packet->data_len);
+
/*
- * Only after successful write do we copy the data back to the packet structure.
+ * We only allocate packet data after writing it to the socket. If the write fails, we avoid a
+ * memory alloc / free.
*/
- memcpy(packet->data, my->buffer, packet->data_len);
- memcpy(packet->vector, packet->data + 4, RADIUS_AUTH_VECTOR_LENGTH);
+ packet->data = talloc_array(packet, uint8_t, packet->data_len);
+ if (!packet->data) goto fail;
/*
- * We are using an outgoing memory bio, which takes care of writing partial packets. As a
- * result, our call to the bio will always return that a full packet was written.
+ * Only after successful write do we copy the data back to the packet structure.
*/
- fr_assert((size_t) slen == packet->data_len);
+ memcpy(packet->data, my->buffer, packet->data_len);
+ memcpy(packet->vector, packet->data + 4, RADIUS_AUTH_VECTOR_LENGTH);
return 0;
}
return 0;
}
-int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, void **request_ctx_p, fr_packet_t **packet_p,
+int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, void **pctx_p, fr_packet_t **packet_p,
UNUSED TALLOC_CTX *out_ctx, fr_pair_list_t *out)
{
ssize_t slen;
return -1;
}
- *request_ctx_p = original->uctx;
+ *pctx_p = original->uctx;
*packet_p = reply;
return 1;
/** Allocate an ID, and write one packet.
*
*/
-static int fr_radius_client_tcp_bio_write(fr_bio_packet_t *bio, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
+static int fr_radius_client_tcp_bio_write(fr_bio_packet_t *bio, void *pctx, fr_packet_t *packet, fr_pair_list_t *list)
{
fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
*/
fr_assert(!packet->data);
- return fr_radius_client_fd_bio_write(my, request_ctx, packet, list);
+ return fr_radius_client_fd_bio_write(my, pctx, packet, list);
}
/** Allocate a RADIUS bio for writing client packets
/** Allocate an ID, and write one packet.
*
*/
-static int fr_radius_client_udp_bio_write(fr_bio_packet_t *bio, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
+static int fr_radius_client_udp_bio_write(fr_bio_packet_t *bio, void *pctx, fr_packet_t *packet, fr_pair_list_t *list)
{
ssize_t slen;
fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
- if (!packet->data) return fr_radius_client_fd_bio_write(my, request_ctx, packet, list);
+ if (!packet->data) return fr_radius_client_fd_bio_write(my, pctx, packet, list);
slen = fr_bio_write(my->common.bio, &packet->socket, packet->data, packet->data_len);
if (slen <= 0) return -1;