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
(define pkg-authors '(hnmdijkema))
(define version "0.1.6")
(define version "0.1.7")
(define license 'MIT)
(define collection "racket-upnp")
(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.
(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")))
+4 -4
View File
@@ -14,10 +14,10 @@ interface.
@section{Discovering devices}
@defproc[(upnp-default-ipv4-address) string?]{
Returns the local IPv4 address selected by the operating system for traffic to
the SSDP multicast destination @tt{239.255.255.250:1900}. No datagram is sent.
This is normally the interface through which UPnP devices on the local network
can be reached.
Returns a non-loopback local IPv4 address selected by the operating system for
normal outbound IPv4 traffic. No datagram is sent. The selected address is
normally also the interface through which SSDP multicast should be sent.
Loopback and wildcard addresses are rejected.
}