CS3700-project2/router

133 lines
3.3 KiB
Racket
Executable File

#!/usr/bin/env racket
#lang racket
; vim:syntax=racket
(require json
"iputil.rkt"
"unix-socket.rkt"
"msg.rkt")
;; info : Peer
;; sock-in : Input-Port
;; sock-out : Output-Port
(struct peer-conn
[info sock-in sock-out]
#:transparent)
;; alist : [Listof [Cons IP Route]]
(struct router
[(alist #:mutable)]
#:transparent)
;; -> Router
(define (make-router)
(router '()))
;; Router Route IP -> Void
(define (router-add! rs r src)
(set-router-alist! rs
(cons (cons src r)
(router-alist rs))))
;; Router IP -> (U IP #f)
(define (router-find-best rs src)
#f)
;; Str [Listof Peer-Conn] -> Void
;; --
;; Runs router logic, given a list of peer connections.
(define (run-router/conns ans peer-conns)
(define mail
(make-channel))
(define peer-threads
(for/list ([pc (in-list peer-conns)])
(match-define (peer-conn peer sock-in sock-out) pc)
(thread (λ ()
(define buf (make-bytes 65536))
(let loop ()
(define len (read-bytes-avail! buf sock-in))
(printf "got ~a bytes from ~a...\n" len peer)
(define msg (bytes->msg (subbytes buf 0 len)))
(channel-put mail (list peer msg))
(loop))))))
(define (ip->peer-conn ip)
(findf (λ (p)
(equal? ip (peer-ip (peer-conn-info p))))
peer-conns))
(define router
(make-router))
(define (loop)
(match-define (list src-peer msg) (channel-get mail))
(printf "====\nfrom ~a:\n~s\n" src-peer msg)
(match msg
[(msg:update src dst r)
(router-add! router r src)]
[(msg:data src dst data)
(define-values [dst-peer resp-msg]
(match (router-find-best router dst)
[#f
(values peer
(msg:no-route src
dst))]
[dst-peer-ip
(values (ip->peer-conn dst-peer-ip)
msg)]))
(printf "----\nwant to send back ~a to ~a\n"
dst-peer
resp-msg)]
[_
(printf "----\nignored\n")])
(loop))
(printf "waiting for messages...\n")
(loop))
;; Str [Listof Peer] ->
;; Router main
(define (run-router asn peers)
(displayln asn)
(map displayln peers)
(displayln "------------")
(with-handlers ([exn:break? (λ (e) (printf "time to die.\n"))])
(run-router/conns
asn
(for/list ([peer (in-list peers)])
(define-values [sock-in sock-out]
(unix-socket-connect (ip->string (peer-ip peer))
'SOCK-SEQPACKET))
(peer-conn peer
sock-in
sock-out)))))
(module+ main
(command-line
#:program "router"
#:args
(asn . peers)
(with-output-to-file "log.txt"
#:exists 'replace
(λ ()
;; Run the router
(run-router asn (map string->peer peers))))))
(module+ test
(define-values [in1 out1] (make-pipe))
(define-values [in2 out2] (make-pipe))
(define p1 (peer-conn (string->peer "1.2.3.4-cust") in1 out1))
(define p2 (peer-conn (string->peer "1.2.3.5-peer") in2 out2))
; (define abort-router
(run-router/conns "123"
(list p1 p2))
(void
(write-string "{\"a\": 1, \"b\": [1,2,3]}" out1)))