diff --git a/lib/chibi/net.scm b/lib/chibi/net.scm index f42e3e5c..af4d0b13 100644 --- a/lib/chibi/net.scm +++ b/lib/chibi/net.scm @@ -65,7 +65,8 @@ ;;> Convenience wrapper to call socket, bind and listen to return ;;> a socket suitable for accepting connections on the given ;;> @var{addrinfo}. @var{max-conn} is the maximum number of pending -;;> connections, and defaults to 128. +;;> connections, and defaults to 128. Automatically specifies +;;> @scheme{socket-opt/reuseaddr}. (define (make-listener-socket addrinfo . o) (let* ((max-connections (if (pair? o) (car o) 128)) @@ -75,6 +76,8 @@ (cond ((negative? sock) (error "couldn't create socket for: " addrinfo)) + ((not (set-socket-option! sock level/socket socket-opt/reuseaddr 1)) + (error "couldn't set the socket to be reusable" addrinfo)) ((negative? (bind sock (address-info-address addrinfo) (address-info-address-length addrinfo))) @@ -85,3 +88,12 @@ (error "couldn't listen on socket for: " addrinfo)) (else sock)))) + +;;> Returns the socket option of the given @var{name} for @var{socket}. +;;> @var{socket} should be a file descriptor, level the constant +;;> @scheme{level/socket}, and name one of the constants beginning with +;;> "socket-opt/". + +(define (get-socket-option socket level name) + (let ((res (getsockopt socket level name))) + (and (pair? res) (car res)))) diff --git a/lib/chibi/net.sld b/lib/chibi/net.sld index 8953f664..9fdf975e 100644 --- a/lib/chibi/net.sld +++ b/lib/chibi/net.sld @@ -7,7 +7,12 @@ address-info-address address-info-address-length address-info-next address-family/unix address-family/inet socket-type/stream socket-type/datagram socket-type/raw - ip-proto/tcp ip-proto/udp) + ip-proto/tcp ip-proto/udp + get-socket-option set-socket-option! level/socket + socket-opt/debug socket-opt/broadcast socket-opt/reuseaddr + socket-opt/keepalive socket-opt/oobinline socket-opt/sndbuf + socket-opt/rcvbuf socket-opt/dontroute socket-opt/rcvlowat + socket-opt/sndlowat) (import (scheme) (chibi filesystem)) (include-shared "net") (include "net.scm")) diff --git a/lib/chibi/net.stub b/lib/chibi/net.stub index 971e534f..ecdc96ac 100644 --- a/lib/chibi/net.stub +++ b/lib/chibi/net.stub @@ -60,3 +60,30 @@ ;;/ (c-include "accept.c") + +(define-c errno getsockopt + (int int int (result int) (result (value (sizeof int) socklen_t)))) + +;;> Set an option for the given socket. For example, to make the +;;> address reusable: +;;> @scheme{(set-socket-option! sock level/socket socket-opt/reuseaddr 1)} + +(define-c errno (set-socket-option! "setsockopt") + (int int int (pointer int) (value (sizeof int) socklen_t))) + +(define-c-const int (level/socket "SOL_SOCKET")) + +(define-c-const int (socket-opt/debug "SO_DEBUG")) +(define-c-const int (socket-opt/broadcast "SO_BROADCAST")) +(define-c-const int (socket-opt/reuseaddr "SO_REUSEADDR")) +(define-c-const int (socket-opt/keepalive "SO_KEEPALIVE")) +(define-c-const int (socket-opt/oobinline "SO_OOBINLINE")) +(define-c-const int (socket-opt/sndbuf "SO_SNDBUF")) +(define-c-const int (socket-opt/rcvbuf "SO_RCVBUF")) +(define-c-const int (socket-opt/dontroute "SO_DONTROUTE")) +(define-c-const int (socket-opt/rcvlowat "SO_RCVLOWAT")) +(define-c-const int (socket-opt/sndlowat "SO_SNDLOWAT")) + +;;> The constants for the @scheme{get-socket-option} and +;;> @scheme{set-socket-option!}. +;;/