]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
make write() work
authorAlan T. DeKok <aland@freeradius.org>
Mon, 10 Jul 2017 18:30:07 +0000 (14:30 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 10 Jul 2017 18:30:07 +0000 (14:30 -0400)
and add flush, for cases like TLS, where there's data to be
written to the socket even when there's no REQUEST

src/modules/rlm_radius/rlm_radius.c
src/modules/rlm_radius/rlm_radius.h

index 64b386eaa4179574b80d37f0ce51610be0b4f79f..86740e7a37b9c1374bf03c1e28119b912cf047a0 100644 (file)
@@ -228,12 +228,39 @@ static void mod_radius_conn_read(fr_event_list_t *el, int sock, UNUSED int flags
 static void mod_radius_conn_writable(UNUSED fr_event_list_t *el, UNUSED int sock, UNUSED int flags, void *uctx)
 {
        rlm_radius_connection_t *c = talloc_get_type_abort(uctx, rlm_radius_connection_t);
+       fr_dlist_t *entry, *next;
+       bool sent;
+
+       /*
+        *      Send all of the requests to the transport.
+        */
+       for (entry = FR_DLIST_FIRST(c->queued);
+            entry != NULL;
+            entry = next) {
+               rlm_radius_link_t *link;
+
+               link = fr_ptr_to_type(rlm_radius_link_t, entry, entry);
 
-       // if no requests, still call client_io->service, as it may have signaling data to write
+               next = FR_DLIST_NEXT(c->queued, entry);
+
+               rad_assert(link->waiting = false);
+
+               fr_dlist_remove(&link->entry);
+               fr_dlist_insert_head(&c->sent, &link->entry);
+               link->waiting = true;
+               sent = true;
 
-       // dequeue a REQUEST
-       // add it to the socket
-       // if EWOULDBLOCK, return.
+               // @todo - if this returns EWOULDBLOCK, stop
+               // @todo - if this returns "too many requests", stop.  But the caller should have checked...
+               (void) c->inst->client_io->write(link->request, link->request_io_ctx, c->client_io_ctx);
+       }
+
+       // @todo - maybe grab more packets from t->queued?
+
+       /*
+        *      We didn't send anything, go flush the socket.
+        */
+       if (!sent) (void) c->inst->client_io->flush(c->client_io_ctx);
 
        mod_radius_fd_idle(c);
 }
index b012ad15e96692c56a1491936c28c7c5c6d10da3..61651745896e4b52030191ce654ce9bbb4601274 100644 (file)
@@ -51,6 +51,10 @@ typedef int (*fr_radius_client_read_t)(REQUEST **p_request, rlm_rcode_t *p_rcode
  */
 typedef int (*fr_radius_client_write_t)(REQUEST *request, void *request_ctx, void *uctx);
 
+/** Flush a socket for writing
+ *
+ */
+typedef int (*fr_radius_client_flush_t)(void *uctx);
 
 
 /** Public structure describing an I/O path for an outgoing socket.
@@ -77,6 +81,7 @@ typedef struct fr_radius_client_io_t {
        fr_radius_client_write_t        write;                  //!< write a REQUEST to a socket
        fr_radius_client_write_t        remove;                 //!< remove a written request from a socket
        fr_radius_client_read_t         read;                   //!< read a REQUEST from a socket.
+       fr_radius_client_flush_t        flush;                  //!< flush data for an outgoing socket
 } fr_radius_client_io_t;
 
 #endif /* _RLM_RADIUS_H */