network detection better.

This commit is contained in:
2026-08-03 16:48:29 +02:00
parent 1f9208560f
commit 91c6755bb1
3 changed files with 60 additions and 19 deletions
+55 -14
View File
@@ -2,32 +2,73 @@
;; Network helpers used by UPnP and SSDP.
(require racket/udp
(require racket/list
racket/string
racket/udp
simple-log)
(provide upnp-default-ipv4-address)
(sl-def-log upnp-network)
(define ssdp-multicast-address "239.255.255.250")
(define ssdp-multicast-port 1900)
;; These destinations are only used to make the operating system select its
;; normal outbound IPv4 route. UDP connect does not transmit a datagram.
(define route-probes
'(("1.1.1.1" 53)
("8.8.8.8" 53)))
;; Return the local IPv4 address selected by the operating system for traffic
;; to the SSDP multicast destination. No datagram is transmitted.
(define (upnp-default-ipv4-address)
(let ([socket (udp-open-socket ssdp-multicast-address
ssdp-multicast-port)])
(define (loopback-ipv4-address? address)
(string-prefix? address "127."))
(define (usable-ipv4-address? address)
(and (string? address)
(not (string=? address "0.0.0.0"))
(not (loopback-ipv4-address? address))))
(define (local-address-for destination port)
(let ([socket (udp-open-socket destination port)])
(dynamic-wind
void
(lambda ()
(udp-connect! socket ssdp-multicast-address ssdp-multicast-port)
(udp-connect! socket destination port)
(define-values (local-address local-port remote-address remote-port)
(udp-addresses socket #t))
(dbg-upnp-network
"Selected UPnP IPv4 address ~a for SSDP destination ~a:~a"
local-address
ssdp-multicast-address
ssdp-multicast-port)
local-address)
(lambda ()
(udp-close socket)))))
;; Return the local non-loopback IPv4 address selected by the operating system
;; for normal outbound traffic. This is also the interface normally suitable
;; for SSDP multicast. No datagram is transmitted.
(define (upnp-default-ipv4-address)
(or
(for/or ([probe (in-list route-probes)])
(define destination (first probe))
(define port (second probe))
(with-handlers
([exn:fail?
(lambda (exception)
(dbg-upnp-network
"Could not determine local IPv4 address using route to ~a:~a: ~a"
destination
port
(exn-message exception))
#f)])
(define address (local-address-for destination port))
(cond
[(usable-ipv4-address? address)
(dbg-upnp-network
"Selected UPnP IPv4 address ~a using route to ~a:~a"
address
destination
port)
address]
[else
(dbg-upnp-network
"Rejected unusable local IPv4 address ~a selected for route to ~a:~a"
address
destination
port)
#f])))
(error 'upnp-default-ipv4-address
"could not determine a non-loopback IPv4 address")))