diff --git a/udp.rkt b/udp.rkt index b51f3bf..4841c68 100644 --- a/udp.rkt +++ b/udp.rkt @@ -38,8 +38,12 @@ (or (udp-handle? x) (udp-listener? x))) +;; USER-level protocol (struct udp-packet (source destination body) #:prefab) +;; KERNEL-level protocol +(struct udp-datagram (source-ip source-port destination-ip destination-port body) #:prefab) + (define any-remote (udp-remote-address ? ?)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -56,11 +60,18 @@ (send (port-allocation-request 'udp (lambda (port local-ips) (spawn-udp-relay port handle)))))) - (spawn-port-allocator 'udp - (list (project-subs (udp-packet (udp-remote-address (?!) (?!)) ? ?)) - (project-subs (udp-packet ? (udp-remote-address (?!) (?!)) ?)))) + (spawn-udp-port-allocator) (spawn-kernel-udp-driver))) +(define (spawn-udp-port-allocator) + (define udp-projector (project-pubs (udp-datagram (?!) (?!) ? ? ?))) + (spawn-port-allocator 'udp + (list udp-projector) + (lambda (g local-ips) + (for/set [(e (gestalt-project/keys g udp-projector)) + #:when (set-member? local-ips (car e))] + (cadr e))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Relaying @@ -75,18 +86,14 @@ (pub (udp-packet any-remote local-user-addr ?)) (sub (udp-packet local-user-addr any-remote ?))))] [(ip (in-set local-ips))] - (define hostname (ip-address->hostname ip)) - (define local-network-addr (udp-remote-address hostname local-port)) (gestalt-union g - (sub (udp-packet any-remote local-network-addr ?)) - (pub (udp-packet local-network-addr any-remote ?))))) + (sub (udp-datagram ? ? ip local-port ?)) + (pub (udp-datagram ip local-port ? ? ?))))) (spawn (lambda (e local-ips) - (log-info "RELAY ~v" e) (match e [(routing-update g) (define new-local-ips (gestalt->local-ip-addresses g)) - (log-info "Updating relay gestalt:\n~a" (gestalt->pretty-string (compute-gestalt new-local-ips))) (transition new-local-ips (list (when (gestalt-empty? (gestalt-filter g local-peer-gestalt)) (quit)) @@ -94,11 +101,18 @@ [(message (udp-packet (== local-user-addr) remote-addr bs) _ _) ;; Choose arbitrary local IP address for outbound packet! ;; TODO: what can be done? Must I examine the routing table? - (define local-network-addr - (udp-remote-address (ip-address->hostname (set-first local-ips)) local-port)) - (transition local-ips (send (udp-packet local-network-addr remote-addr bs)))] - [(message (udp-packet remote-addr (udp-remote-address _ _) bs) _ _) - (transition local-ips (send (udp-packet remote-addr local-user-addr bs)))] + (match-define (udp-remote-address remote-host remote-port) remote-addr) + (define remote-ip (ip-string->ip-address remote-host)) + (transition local-ips (send (udp-datagram (set-first local-ips) + local-port + remote-ip + remote-port + bs)))] + [(message (udp-datagram si sp _ _ bs) _ _) + (transition local-ips (send (udp-packet (udp-remote-address (ip-address->hostname si) + sp) + local-user-addr + bs)))] [_ #f])) (set) (compute-gestalt (set)))) @@ -115,8 +129,6 @@ (transition (gestalt->local-ip-addresses g) '())] [(message (ip-packet source-if src-ip dst-ip _ _ body) _ _) #:when (and source-if (set-member? local-ips dst-ip)) - (define src-host (ip-address->hostname src-ip)) - (define dst-host (ip-address->hostname dst-ip)) (bit-string-case body ([ (src-port :: integer bytes 2) (dst-port :: integer bytes 2) @@ -126,39 +138,38 @@ (bit-string-case data ([ (payload :: binary bytes (- length 8)) ;; min UDP header size is 8 bytes (:: binary) ] - (transition local-ips (send (udp-packet (udp-remote-address src-host src-port) - (udp-remote-address dst-host dst-port) - (bit-string->bytes payload))))) + (transition local-ips (send (udp-datagram src-ip + src-port + dst-ip + dst-port + (bit-string->bytes payload))))) (else #f))) (else #f))] - [(message (udp-packet (udp-remote-address sh sp) (udp-remote-address dh dp) bs) _ _) - (define src-ip (ip-string->ip-address sh)) - (define dst-ip (ip-string->ip-address dh)) - (and (set-member? local-ips src-ip) - (let* ((payload (bit-string (sp :: integer bytes 2) - (dp :: integer bytes 2) - ((+ 8 (bit-string-byte-count bs)) - :: integer bytes 2) - (0 :: integer bytes 2) ;; checksum location - (bs :: binary))) - (pseudo-header (bit-string (src-ip :: binary bytes 4) - (dst-ip :: binary bytes 4) - 0 - PROTOCOL-UDP - ((bit-string-byte-count payload) - :: integer bytes 2))) - (checksummed-payload (ip-checksum #:pseudo-header pseudo-header - 6 payload))) - (transition local-ips (send (ip-packet #f - src-ip - dst-ip - PROTOCOL-UDP - #"" - checksummed-payload)))))] + [(message (udp-datagram src-ip src-port dst-ip dst-port bs) _ _) + #:when (set-member? local-ips src-ip) + (let* ((payload (bit-string (src-port :: integer bytes 2) + (dst-port :: integer bytes 2) + ((+ 8 (bit-string-byte-count bs)) + :: integer bytes 2) + (0 :: integer bytes 2) ;; checksum location + (bs :: binary))) + (pseudo-header (bit-string (src-ip :: binary bytes 4) + (dst-ip :: binary bytes 4) + 0 + PROTOCOL-UDP + ((bit-string-byte-count payload) + :: integer bytes 2))) + (checksummed-payload (ip-checksum #:pseudo-header pseudo-header + 6 payload))) + (transition local-ips (send (ip-packet #f + src-ip + dst-ip + PROTOCOL-UDP + #"" + checksummed-payload))))] [_ #f])) (set) (gestalt-union (pub (ip-packet #f ? ? PROTOCOL-UDP ? ?)) (sub (ip-packet ? ? ? PROTOCOL-UDP ? ?)) - (sub (udp-packet any-remote any-remote ?)) - (pub (udp-packet any-remote any-remote ?)) + (sub (udp-datagram ? ? ? ? ?)) observe-local-ip-addresses-gestalt)))