]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
on TCP EOF, flush all writes, and shut down the BIOs
authorAlan T. DeKok <aland@freeradius.org>
Thu, 7 Aug 2025 14:59:17 +0000 (10:59 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 7 Aug 2025 15:01:26 +0000 (11:01 -0400)
src/lib/bio/base.c
src/lib/bio/base.h
src/lib/bio/fd.c

index 0e00171cec9da79c86720dbd576411f3595f4355..f1dbf6378462d1f592c5f70be4ca454bb74cb654 100644 (file)
@@ -98,27 +98,24 @@ ssize_t fr_bio_shutdown_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNU
 int fr_bio_shutdown(fr_bio_t *bio)
 {
        int rcode;
-       fr_bio_t *this, *first;
+       fr_bio_t *head, *this;
        fr_bio_common_t *my;
 
        /*
         *      Find the first bio in the chain.
         */
-       for (this = bio; fr_bio_prev(this) != NULL; this = fr_bio_prev(this)) {
-               /* nothing */
-       }
-       first = this;
+       head = fr_bio_head(bio);
 
        /*
         *      We're in the process of shutting down, don't call ourselves recursively.
         */
-       my = (fr_bio_common_t *) this;
+       my = (fr_bio_common_t *) head;
        if (my->bio.read == fr_bio_shutdown_read) return 0;
 
        /*
         *      Walk back down the chain, calling the shutdown functions.
         */
-       for (/* nothing */; this != NULL; this = fr_bio_next(this)) {
+       for (this = head; this != NULL; this = fr_bio_next(this)) {
                my = (fr_bio_common_t *) this;
 
                if (my->priv_cb.shutdown) {
@@ -136,10 +133,10 @@ int fr_bio_shutdown(fr_bio_t *bio)
         *      Call the application shutdown routine to tell it that
         *      the BIO has been successfully shut down.
         */
-       my = (fr_bio_common_t *) first;
+       my = (fr_bio_common_t *) head;
 
        if (my->cb.shutdown) {
-               rcode = my->cb.shutdown(first);
+               rcode = my->cb.shutdown(head);
                if (rcode < 0) return rcode;
                my->cb.shutdown = NULL;
        }
index cf2b65b4f6723aa2cf8e4b8820be7583b2982779..c5a3134ea59bdaa4e61dafc9b20408c55bc63648 100644 (file)
@@ -137,6 +137,17 @@ static inline CC_HINT(nonnull) fr_bio_t *fr_bio_next(fr_bio_t *bio)
        return fr_dlist_entry_to_item(offsetof(fr_bio_t, entry), next);
 }
 
+static inline CC_HINT(nonnull) fr_bio_t *fr_bio_head(fr_bio_t *bio)
+{
+       fr_bio_t *this, *prev;
+
+       for (this = bio; (prev = fr_bio_prev(this)) != NULL; this = prev) {
+               /* nothing */
+       }
+
+       return this;
+}
+
 /** Read raw data from a bio
  *
  *  @param bio         the binary IO handler
index 44262a905f9aed5a513d90102eb0705a286e32eb..5dabcca8387414b8993bc3fcc08d0072042e30a2 100644 (file)
@@ -144,6 +144,18 @@ static ssize_t fr_bio_fd_read_stream(fr_bio_t *bio, UNUSED void *packet_ctx, voi
 retry:
        rcode = read(my->info.socket.fd, buffer, size);
        if (rcode == 0) {
+               fr_bio_t *head;
+
+               /*
+                *      Flush any pending writes, shut down the BIO, and then mark it as EOF.
+                */
+               head = fr_bio_head(bio);
+
+               (void) fr_bio_write(head, NULL, NULL, SIZE_MAX);
+
+               rcode = fr_bio_shutdown(head);
+               if (rcode < 0) return rcode;
+
                fr_bio_eof(bio);
                return 0;
        }