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
+1 -1
View File
@@ -1,7 +1,7 @@
#lang info #lang info
(define pkg-authors '(hnmdijkema)) (define pkg-authors '(hnmdijkema))
(define version "0.1.6") (define version "0.1.7")
(define license 'MIT) (define license 'MIT)
(define collection "racket-upnp") (define collection "racket-upnp")
(define pkg-desc "racket-upnp - UpnP and DLNA for racket") (define pkg-desc "racket-upnp - UpnP and DLNA for racket")
+55 -14
View File
@@ -2,32 +2,73 @@
;; Network helpers used by UPnP and SSDP. ;; Network helpers used by UPnP and SSDP.
(require racket/udp (require racket/list
racket/string
racket/udp
simple-log) simple-log)
(provide upnp-default-ipv4-address) (provide upnp-default-ipv4-address)
(sl-def-log upnp-network) (sl-def-log upnp-network)
(define ssdp-multicast-address "239.255.255.250") ;; These destinations are only used to make the operating system select its
(define ssdp-multicast-port 1900) ;; 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 (define (loopback-ipv4-address? address)
;; to the SSDP multicast destination. No datagram is transmitted. (string-prefix? address "127."))
(define (upnp-default-ipv4-address)
(let ([socket (udp-open-socket ssdp-multicast-address (define (usable-ipv4-address? address)
ssdp-multicast-port)]) (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 (dynamic-wind
void void
(lambda () (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) (define-values (local-address local-port remote-address remote-port)
(udp-addresses socket #t)) (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) local-address)
(lambda () (lambda ()
(udp-close socket))))) (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")))
+4 -4
View File
@@ -14,10 +14,10 @@ interface.
@section{Discovering devices} @section{Discovering devices}
@defproc[(upnp-default-ipv4-address) string?]{ @defproc[(upnp-default-ipv4-address) string?]{
Returns the local IPv4 address selected by the operating system for traffic to Returns a non-loopback local IPv4 address selected by the operating system for
the SSDP multicast destination @tt{239.255.255.250:1900}. No datagram is sent. normal outbound IPv4 traffic. No datagram is sent. The selected address is
This is normally the interface through which UPnP devices on the local network normally also the interface through which SSDP multicast should be sent.
can be reached. Loopback and wildcard addresses are rejected.
} }