Subject: bug#65399: [PATCH] web: Fix non-IPv4 default socket.

From: Leo Nikkilä <[email-masked]>
Date: Sun, 20 Aug 2023 12:15:37 +0300

PF_INET sockets were being created by default with #:family AF_INET6 or
AF_UNIX, resulting in

    In procedure bind: Address family not supported by protocol

* module/web/server/http.scm (make-default-socket): Use #:family.
* doc/ref/web.texi (Web Server): Fix quoting in documentation, bind to
suitable address.
* test-suite/tests/web-server.test: Test it.
---
 doc/ref/web.texi                 |  4 ++-
 module/web/server/http.scm       |  2 +-
 test-suite/tests/web-server.test | 59 +++++++++++++++++++-------------
 3 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/doc/ref/web.texi b/doc/ref/web.texi
index 607c855b6..d76529456 100644
--- a/doc/ref/web.texi
+++ b/doc/ref/web.texi
@@ -1827,7 +1827,9 @@ implementation's open function.
 ;; On a different port
 (run-server handler 'http '(#:port 8081))
 ;; IPv6
-(run-server handler 'http '(#:family AF_INET6 #:port 8081))
+(run-server handler 'http `(#:family ,AF_INET6
+                            #:addr ,IN6ADDR_LOOPBACK
+                            #:port 8081))
 ;; Custom socket
 (run-server handler 'http `(#:socket ,(sudo-make-me-a-socket)))
 @end example
diff --git a/module/web/server/http.scm b/module/web/server/http.scm
index 05bf46bf0..447282f4c 100644
--- a/module/web/server/http.scm
+++ b/module/web/server/http.scm
@@ -39,7 +39,7 @@

 (define (make-default-socket family addr port)
-  (let ((sock (socket PF_INET SOCK_STREAM 0)))
+  (let ((sock (socket family SOCK_STREAM 0)))
     (setsockopt sock SOL_SOCKET SO_REUSEADDR 1)
     (bind sock family addr port)
     sock))
diff --git a/test-suite/tests/web-server.test b/test-suite/tests/web-server.test
index d84c47d18..38e23e791 100644
--- a/test-suite/tests/web-server.test
+++ b/test-suite/tests/web-server.test
@@ -56,14 +56,42 @@
                              '((content-type . (application/octet-stream))))
              (string->utf8 "forbidden")))))
 
-(define %port-number 8885)
+(define %port-number4 8885)
+(define %port-number6 8886)
 (define %server-base-uri "http://localhost:8885")
 
 (when (provided? 'threads)
-  ;; Run a local publishing server in a separate thread.
+  ;; Run local publishing servers (IPv4, IPv6) in separate threads.
   (call-with-new-thread
    (lambda ()
-     (run-server handle-request 'http `(#:port ,%port-number)))))
+     (run-server handle-request 'http `(#:port ,%port-number4))))
+  (call-with-new-thread
+   (lambda ()
+     (run-server handle-request 'http `(#:family ,AF_INET6
+                                        #:addr ,IN6ADDR_LOOPBACK
+                                        #:port ,%port-number6)))))
+
+(define (connect-to-server family addr port-number)
+  (let ((socket (socket family SOCK_STREAM 0)))
+    (let loop ((n 1))
+      (define success?
+        (catch 'system-error
+          (lambda ()
+            (format (current-error-port)
+                    "connecting to the server, attempt #~a~%" n)
+            (connect socket family addr port-number)
+            (close-port socket)
+            #t)
+          (lambda args
+            (if (and (= ECONNREFUSED (system-error-errno args))
+                     (<= n 15))
+                #f
+                (apply throw args)))))
+
+      (or success?
+          (begin
+            (sleep 1)
+            (loop (+ n 1)))))))
 
 (define-syntax-rule (expect method path code args ...)
   (if (provided? 'threads)
@@ -79,26 +107,11 @@
 (pass-if "server is listening"
   ;; First, wait until the server is listening, up to a few seconds.
   (if (provided? 'threads)
-      (let ((socket (socket AF_INET SOCK_STREAM 0)))
-        (let loop ((n 1))
-          (define success?
-            (catch 'system-error
-              (lambda ()
-                (format (current-error-port)
-                        "connecting to the server, attempt #~a~%" n)
-                (connect socket AF_INET INADDR_LOOPBACK %port-number)
-                (close-port socket)
-                #t)
-              (lambda args
-                (if (and (= ECONNREFUSED (system-error-errno args))
-                         (<= n 15))
-                    #f
-                    (apply throw args)))))
-
-          (or success?
-              (begin
-                (sleep 1)
-                (loop (+ n 1))))))
+      (begin
+        (format (current-error-port) "connecting using IPv4...~%")
+        (connect-to-server AF_INET INADDR_LOOPBACK %port-number4)
+        (format (current-error-port) "connecting using IPv6...~%")
+        (connect-to-server AF_INET6 IN6ADDR_LOOPBACK %port-number6))
       (throw 'unresolved)))
 
 (pass-if-equal "GET /"

base-commit: c7632b8f974abc3bb654e116d62e4165c39490af
-- 
2.41.0