* write packets to the transport context. The data may or may not
* go out to the network right away.
*
- * If the writer returns LESS THAN buffer_len, that's a special case
- * saying "I took saved the data, but the socket wasn't ready, so you
- * need to call me again at a later point".
+ * If the write function does a partial write, it should return a
+ * value smaller than buffer_len to indicate this. The network
+ * functions will then pass that value to a subsequent write call, in
+ * the "written" argument.
+ *
+ * The reason for this odd API is that read/write should be writing
+ * *packets*, not raw streams of bytes. This API allows the "buffer"
+ * parameter to always contain a full packet.
*
* @param[in] instance the context for this function
* @param[in] packet_ctx Request specific data.
* @param[in] request_time when the original request was received
* @param[in] buffer the buffer where the raw packet will be written from
* @param[in] buffer_len the length of the buffer
+ * @param[in] written total number of bytes written in previous calls for this packet.
* @return
* - <0 on error
* - >=0 length of the data read or written.
*/
typedef ssize_t (*fr_io_data_write_t)(void *instance, void *packet_ctx, fr_time_t request_time,
- uint8_t *buffer, size_t buffer_len);
+ uint8_t *buffer, size_t buffer_len, size_t written);
/** Inject data into a socket.
*
}
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, size_t written)
{
fr_io_instance_t *inst;
fr_io_connection_t *connection;
*/
packet_len = inst->app_io->write(app_io_instance, track, request_time,
- buffer, buffer_len);
+ buffer, buffer_len, written);
if (packet_len > 0) {
rad_assert(buffer_len == (size_t) packet_len);
MEM(track->reply = talloc_memdup(track, buffer, buffer_len));
rad_assert(listen == cd->listen);
rcode = listen->app_io->write(listen->app_io_instance, cd->packet_ctx,
- cd->reply.request_time, cd->m.data, cd->m.data_size);
+ cd->reply.request_time,
+ cd->m.data, cd->m.data_size, 0);
if (rcode < 0) {
/*
* that NAKs are not written to the network.
*/
rcode = listen->app_io->write(listen->app_io_instance, cd->packet_ctx,
- cd->reply.request_time, cd->m.data, cd->m.data_size);
+ cd->reply.request_time,
+ cd->m.data, cd->m.data_size, 0);
if (rcode < 0) {
if (errno == EWOULDBLOCK) {
if (fr_event_fd_insert(nr, nr->el, s->fd,
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, UNUSED fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
{
proto_control_tcp_t *inst = talloc_get_type_abort(instance, proto_control_tcp_t);
fr_io_track_t *track = talloc_get_type_abort(packet_ctx, fr_io_track_t);
return inst->parent->work_io->decode(inst->parent->work_io_instance, request, data, data_len);
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, size_t written)
{
proto_detail_file_t const *inst = talloc_get_type_abort_const(instance, proto_detail_file_t);
- return inst->parent->work_io->write(inst->parent->work_io_instance, packet_ctx, request_time, buffer, buffer_len);
+ return inst->parent->work_io->write(inst->parent->work_io_instance, packet_ctx, request_time, buffer, buffer_len, written);
}
static void mod_vnode_extend(void *instance, UNUSED uint32_t fflags)
#endif
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
{
proto_detail_work_t *inst = talloc_get_type_abort(instance, proto_detail_work_t);
fr_detail_entry_t *track = packet_ctx;
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, UNUSED fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
{
proto_dhcpv4_udp_t *inst = talloc_get_type_abort(instance, proto_dhcpv4_udp_t);
fr_io_track_t *track = talloc_get_type_abort(packet_ctx, fr_io_track_t);
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, UNUSED fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
{
proto_radius_tcp_t *inst = talloc_get_type_abort(instance, proto_radius_tcp_t);
fr_io_track_t *track = talloc_get_type_abort(packet_ctx, fr_io_track_t);
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, UNUSED fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
{
proto_radius_udp_t *inst = talloc_get_type_abort(instance, proto_radius_udp_t);
fr_io_track_t *track = talloc_get_type_abort(packet_ctx, fr_io_track_t);
}
-static ssize_t mod_write(void *instance, void *packet_ctx,
- UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len)
+static ssize_t mod_write(void *instance, void *packet_ctx, UNUSED fr_time_t request_time,
+ uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
{
proto_vmps_udp_t *inst = talloc_get_type_abort(instance, proto_vmps_udp_t);
fr_io_track_t *track = talloc_get_type_abort(packet_ctx, fr_io_track_t);
static ssize_t test_write(void *ctx, UNUSED void *packet_ctx, UNUSED fr_time_t request_time,
- uint8_t *buffer, size_t buffer_len)
+ uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
{
ssize_t data_size;
fr_listen_test_t *io_ctx = talloc_get_type_abort(ctx, fr_listen_test_t);