#lang racket/base (require racket/contract "timer.rkt") (define-struct connection (id timer i-port o-port custodian close?) #:mutable) (provide/contract [struct connection ([id integer?] [timer timer?] [i-port input-port?] [o-port output-port?] [custodian custodian?] [close? boolean?])] [start-connection-manager (-> void)] [new-connection (number? input-port? output-port? custodian? boolean? . -> . connection?)] [kill-connection! (connection? . -> . void)] [adjust-connection-timeout! (connection? number? . -> . void)]) ;; start-connection-manager: custodian -> void ;; calls the timer manager (define (start-connection-manager) (start-timer-manager)) ;; new-connection: number i-port o-port custodian -> connection ;; ask the connection manager for a new connection (define i (box 0)) (define (new-connection time-to-live i-port o-port cust close?) (define conn (make-connection (begin0 (unbox i) (set-box! i (add1 (unbox i)))) #f i-port o-port cust close?)) (define conn-wb (make-weak-box conn)) (set-connection-timer! conn (start-timer time-to-live (lambda () (cond [(weak-box-value conn-wb) => kill-connection-w/o-timer!])))) conn) ;; kill-connection!: connection -> void ;; kill this connection (define (kill-connection! conn) #;(printf "K: ~a\n" (connection-id conn)) (with-handlers ([exn:fail? void]) (cancel-timer! (connection-timer conn))) (kill-connection-w/o-timer! conn)) (define (kill-connection-w/o-timer! conn) (with-handlers ([exn:fail:network? void]) (close-output-port (connection-o-port conn))) (with-handlers ([exn:fail:network? void]) (close-input-port (connection-i-port conn))) (custodian-shutdown-all (connection-custodian conn))) ;; adjust-connection-timeout!: connection number -> void ;; change the expiration time for this connection (define (adjust-connection-timeout! conn time) (increment-timer! (connection-timer conn) time))