]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
catch more corner cases
authorAlan T. DeKok <aland@freeradius.org>
Wed, 6 Mar 2024 14:20:59 +0000 (09:20 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 6 Mar 2024 14:21:56 +0000 (09:21 -0500)
flush just goes to the next bio and flushes.

If the all retry timers are used, try to cancel the oldest one
and then use that.  This puts less work on the application to track
things.

src/lib/bio/retry.c

index 05d52b6b7b85d7ecca8edd720b7d85962183a9e4..ad116db35e6ff872eeedd3828afba57a58544b34 100644 (file)
@@ -92,12 +92,11 @@ static ssize_t fr_bio_retry_write(fr_bio_t *bio, void *packet_ctx, void const *b
 static int fr_bio_retry_reset_timer(fr_bio_retry_t *my)
 {
        fr_bio_retry_entry_t *first;
-       fr_rb_iter_inorder_t iter;
 
        /*
         *      Nothing to do, don't set any timers.
         */
-       first = fr_rb_iter_init_inorder(&iter, &my->rb);
+       first = fr_rb_first(&my->rb);
        if (!first) {
                fr_assert(!my->ev);
                my->first = NULL;
@@ -379,7 +378,9 @@ static void fr_bio_retry_timer(UNUSED fr_event_list_t *el, fr_time_t now, void *
        }
 }
 
-
+/** Write a request, and see if we have a reply.
+ *
+ */
 static ssize_t fr_bio_retry_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
 {
        ssize_t rcode;
@@ -389,19 +390,39 @@ static ssize_t fr_bio_retry_write(fr_bio_t *bio, void *packet_ctx, void const *b
 
        fr_assert(!my->partial);
 
-       /*
-        *      Catch the corner case where the max number of saved packets is exceeded.
-        */
-       if (fr_bio_retry_list_num_elements(&my->free) == 0) {
-               return fr_bio_error(BUFFER_FULL);
-       }
-
        /*
         *      There must be a next bio.
         */
        next = fr_bio_next(&my->bio);
        fr_assert(next != NULL);
        
+       /*
+        *      The caller is trying to flush partial data.  But we don't have any partial data, so just call
+        *      the next bio to flush it.
+        */
+       if (!buffer) {
+               return next->write(next, packet_ctx, NULL, size);
+       }
+
+       /*
+        *      Catch the corner case where the max number of saved packets is exceeded.
+        */
+       if (fr_bio_retry_list_num_elements(&my->free) == 0) {
+               item = fr_rb_last(&my->rb);
+               if (!item) return fr_bio_error(BUFFER_FULL);
+
+               if (!item->retry.replies) return fr_bio_error(BUFFER_FULL);
+
+               fr_assert(!item->cancelled);
+
+               if (fr_bio_retry_entry_cancel(bio, item) < 0) return fr_bio_error(BUFFER_FULL);
+
+               /*
+                *      We now have a free item, so we can use it.
+                */
+               fr_assert(fr_bio_retry_list_num_elements(&my->free) > 0);
+       }
+
        /*
         *      Write out the packet.  If there's an error, OR we wrote nothing, return.
         *