]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Use something like wait_for_activity() from demos/quic-server-non-block.c
authorJean-Frederic Clere <jfclere@gmail.com>
Fri, 25 Oct 2024 14:23:35 +0000 (16:23 +0200)
committerNeil Horman <nhorman@openssl.org>
Mon, 17 Feb 2025 16:27:33 +0000 (11:27 -0500)
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25859)

demos/http3/ossl-nghttp3-demo-server.c

index c511fb88bf76e485877117684de6b3d8192daa77..ad419bc90d4532ac3689e359ecc614411632f004 100644 (file)
@@ -607,33 +607,81 @@ err:
     return -1;
 }
 
-static int waitsocket(int fd, int sec)
+/* Copied from demos/guide/quic-server-non-block.c */
+/**
+ * @brief Waits for activity on the SSL socket, either for reading or writing.
+ *
+ * This function monitors the underlying file descriptor of the given SSL
+ * connection to determine when it is ready for reading or writing, or both.
+ * It uses the select function to wait until the socket is either readable
+ * or writable, depending on what the SSL connection requires.
+ *
+ * @param ssl A pointer to the SSL object representing the connection.
+ *
+ * @note This function blocks until there is activity on the socket. In a real
+ * application, you might want to perform other tasks while waiting, such as
+ * updating a GUI or handling other connections.
+ *
+ * @note This function uses select for simplicity and portability. Depending
+ * on your application's requirements, you might consider using other
+ * mechanisms like poll or epoll for handling multiple file descriptors.
+ */
+static int wait_for_activity(SSL *ssl)
 {
-    fd_set read_fds;
-    int fdmax = fd;
-    int ret;
-
-    FD_ZERO(&read_fds);
-    FD_SET(fd, &read_fds);
-    if (sec) {
-        struct timeval tv;
-
-        tv.tv_sec = sec;
-        tv.tv_usec = 0;
-        printf("waitsocket for %d\n", sec);
-        ret = select(fdmax + 1, &read_fds, NULL, NULL, &tv);
-    } else {
-        printf("waitsocket for ever\n");
-        ret = select(fdmax + 1, &read_fds, NULL, NULL, NULL);
-    }
-    if (ret == -1) {
-        fprintf(stderr, "waitsocket failed\n");
-        return -2;
-    } else if (ret) {
-        printf("waitsocket %d\n", FD_ISSET(fd, &read_fds));
-        return 0;
+    int sock, isinfinite;
+    fd_set read_fd, write_fd;
+    struct timeval tv;
+    struct timeval *tvp = NULL;
+
+    /* Get hold of the underlying file descriptor for the socket */
+    if ((sock = SSL_get_fd(ssl)) == -1) {
+        fprintf(stderr, "Unable to get file descriptor");
+        return -1;
     }
-    return -1; /* Timeout */
+
+    /* Initialize the fd_set structure */
+    FD_ZERO(&read_fd);
+    FD_ZERO(&write_fd);
+
+    /*
+     * Determine if we would like to write to the socket, read from it, or both.
+     */
+    if (SSL_net_write_desired(ssl))
+        FD_SET(sock, &write_fd);
+    if (SSL_net_read_desired(ssl))
+        FD_SET(sock, &read_fd);
+
+    /* Add the socket file descriptor to the fd_set */
+    FD_SET(sock, &read_fd);
+
+    /*
+     * Find out when OpenSSL would next like to be called, regardless of
+     * whether the state of the underlying socket has changed or not.
+     */
+    if (SSL_get_event_timeout(ssl, &tv, &isinfinite) && !isinfinite)
+        tvp = &tv;
+
+    /*
+     * Wait until the socket is writeable or readable. We use select here
+     * for the sake of simplicity and portability, but you could equally use
+     * poll/epoll or similar functions
+     *
+     * NOTE: For the purposes of this demonstration code this effectively
+     * makes this demo block until it has something more useful to do. In a
+     * real application you probably want to go and do other work here (e.g.
+     * update a GUI, or service other connections).
+     *
+     * Let's say for example that you want to update the progress counter on
+     * a GUI every 100ms. One way to do that would be to use the timeout in
+     * the last parameter to "select" below. If the tvp value is greater
+     * than 100ms then use 100ms instead. Then, when select returns, you
+     * check if it did so because of activity on the file descriptors or
+     * because of the timeout. If the 100ms GUI timeout has expired but the
+     * tvp timeout has not then go and update the GUI and then restart the
+     * "select" (with updated timeouts).
+     */
+
+    return (select(sock + 1, &read_fd, &write_fd, NULL, tvp));
 }
 
 /* Main loop for server to accept QUIC connections. */
@@ -680,10 +728,10 @@ static int run_quic_server(SSL_CTX *ctx, int fd)
         if (!hassomething) {
             fprintf(stderr, "waiting on socket\n");
             fflush(stderr);
-            ret = waitsocket(fd, 0);
-            if (ret == -2) {
+            ret = wait_for_activity(listener);
+            if (ret == -1) {
                 SSL_free(conn);
-                printf("waitsocket tells -2\n");
+                printf("wait_for_activity tells -1\n");
                 fflush(stdout);
                 goto err;
             }
@@ -743,12 +791,7 @@ restart:
         numtimeout = 0;
         while (!h3ssl.end_headers_received) {
             if (!hassomething) {
-                /*
-                 * XXX: 25 is TOO BIG.
-                 * Probably something wrong when waiting for the close on
-                 * the previous request/response
-                 */
-                if (waitsocket(fd, 1)) {
+                if (wait_for_activity(h3ssl.ssl_ids[0].s) == 0) {
                     printf("waiting for end_headers_received timeout %d\n", numtimeout);
                     numtimeout++;
                     if (numtimeout == 25)
@@ -860,7 +903,7 @@ wait_close:
         for (;;) {
             int hasnothing;
 
-            if (waitsocket(fd, 60)) {
+            if (wait_for_activity(h3ssl.ssl_ids[0].s) == 0) {
                 printf("hasnothing timeout\n");
                 /* XXX probably not always OK */
                 break;