PR1411 Jays observations re thread-server

This commit is contained in:
Tim Brown 2016-08-15 10:27:07 +01:00
parent 29997da340
commit 9da549ea87
4 changed files with 86 additions and 84 deletions

View File

@ -1,22 +1,28 @@
#lang racket/base #lang racket/base
; An echo server -- ripped off the racket homepage (provide server current-listen-port current-conn-timeout)
(provide server current-listen-port)
(require racket/port "generic-server.rkt") (require racket/port "generic-server.rkt")
(define (server) (define (server)
;; Although this is ≡ (serve copy-port), Im explicit about i and o
;; to illustrate the calling convention for serve
(serve (lambda (i o) (copy-port i o)))) (serve (lambda (i o) (copy-port i o))))
(module+ (module+
main main
(define-values (server-thread shutdown-server) (server)) (define-values (server-thread shutdown-server) (server))
(thread-wait server-thread)) (dynamic-wind
void
(λ () (thread-wait server-thread))
shutdown-server))
(module+ (module+
test test
(require rackunit racket/tcp) (require rackunit racket/tcp)
(define-values (server-thread shutdown-server) (server)) (define-values (server-thread shutdown-server) (server))
(dynamic-wind
void
(λ ()
(define-values (cl:from cl:to) (define-values (cl:from cl:to)
(tcp-connect "localhost" (current-listen-port))) (tcp-connect "localhost" (current-listen-port)))
(file-stream-buffer-mode cl:to 'none) (file-stream-buffer-mode cl:to 'none)
@ -25,6 +31,5 @@
(flush-output cl:to) (flush-output cl:to)
(close-output-port cl:to) (close-output-port cl:to)
(check-equal? (read-string 1024 cl:from) "Monkeys!") (check-equal? (read-string 1024 cl:from) "Monkeys!")
(tcp-abandon-port cl:from) (tcp-abandon-port cl:from))
(sleep 5) shutdown-server))
(shutdown-server))

View File

@ -1,38 +1,35 @@
#lang racket/base #lang racket/base
;; with thanks to "More: Systems Programming with Racket" (provide serve
(provide serve current-listen-port) current-listen-port
current-conn-timeout)
(require racket/tcp) (require mzlib/thread
racket/tcp)
(define current-listen-port (make-parameter 12345)) (define current-listen-port (make-parameter 12345))
(define (accept-and-handle listener handler) (define current-conn-timeout (make-parameter #f))
(define cust (make-custodian))
(define handler-thread
(parameterize ([current-custodian cust])
(define-values (in out) (tcp-accept listener))
(file-stream-buffer-mode in 'none)
(file-stream-buffer-mode out 'none)
(thread (lambda ()
(handler in out)
(close-output-port out)
(close-input-port in)))))
(thread (lambda ()
(thread-wait handler-thread)
(custodian-shutdown-all cust))))
(define (serve handler) (define (serve conn-proc)
(define serving-sem (make-semaphore)) ;; use of semaphore `s` allows us to wait until the server is listening before continuing
(define main-cust (make-custodian)) ;; -- needed for test suites that “just want to get on with it”
(define server-thread (define s (make-semaphore 0))
(parameterize ([current-custodian main-cust]) (define t (thread
(define listener (tcp-listen (current-listen-port) 5 #t)) (λ ()
(semaphore-post serving-sem) ; listening... so caller is ready to continue (run-server (current-listen-port)
(define (loop) conn-proc
(accept-and-handle listener handler) (current-conn-timeout)
(loop)) void ; handler
(thread loop))) (λ (port-no
(values server-thread (lambda () (custodian-shutdown-all main-cust)))) (max-allow-wait 4)
(reuse? #f)
(hostname #f))
(dynamic-wind
void
(λ () (tcp-listen port-no max-allow-wait reuse? hostname))
(λ () (semaphore-post s))))))))
(semaphore-wait s)
(values t (λ () (kill-thread t))))
;; tested via the echo-server (in this directory) ;; tested via the echo-server (in this directory)
;; (module+ test) ;; (module+ test)

View File

@ -1,16 +1,15 @@
#lang racket/base #lang racket/base
; It may look like an HTTPS server, but it very isnt ; It may look like an HTTPS server, but it very isnt
(provide server current-listen-port) (provide server
current-listen-port
current-conn-timeout)
(require racket/match (require racket/match
racket/port
openssl openssl
syntax/modresolve syntax/modresolve
"generic-server.rkt") "generic-server.rkt")
(define (server) (define (conn-proc i o)
(serve
(lambda (i o)
(define ssl-srvr-ctx (ssl-make-server-context 'secure)) (define ssl-srvr-ctx (ssl-make-server-context 'secure))
(define test.pem-path (build-path (define test.pem-path (build-path
(let-values (([base name mbd?] (let-values (([base name mbd?]
@ -23,8 +22,7 @@
#:mode 'accept #:mode 'accept
#:context ssl-srvr-ctx #:context ssl-srvr-ctx
#:close-original? #t #:close-original? #t
#:shutdown-on-close? #t #:shutdown-on-close? #t))
))
(define request-lines (define request-lines
(for/list ((l (in-lines s:i 'return-linefeed)) #:break (string=? l "")) l)) (for/list ((l (in-lines s:i 'return-linefeed)) #:break (string=? l "")) l))
(define-syntax-rule (out/flush fmt args ...) (define-syntax-rule (out/flush fmt args ...)
@ -39,11 +37,13 @@
[(cons (regexp #px"^(\\S+)\\s+(\\S+)(\\s+HTTP/\\S+)?$" [(cons (regexp #px"^(\\S+)\\s+(\\S+)(\\s+HTTP/\\S+)?$"
(list request method request-uri http-version)) _) (list request method request-uri http-version)) _)
(out/flush "HTTP/1.1 405 Method Not Allowed\r\n\r\n")] (out/flush "HTTP/1.1 405 Method Not Allowed\r\n\r\n")]
[_ (out/flush "HTTP/1.1 400 Bad Request\r\n\r\n")])))) [_ (out/flush "HTTP/1.1 400 Bad Request\r\n\r\n")]))
(define (server) (serve conn-proc))
(module+ (module+
main main
(define-values (server-thread shutdown-server) (server)) (define-values (server-thread shutdown-server) (server))
(thread-wait server-thread)) (dynamic-wind void (λ () (thread-wait server-thread)) shutdown-server))
(module+ test) (module+ test)

View File

@ -3,9 +3,9 @@
;; oozes security leaks and I wouldnt be surprised if it leaked fids too. ;; oozes security leaks and I wouldnt be surprised if it leaked fids too.
(require racket/port racket/match racket/tcp "generic-server.rkt") (require racket/port racket/match racket/tcp "generic-server.rkt")
(provide server current-listen-port) (provide server
current-listen-port
(define serving-sem (make-semaphore)) current-conn-timeout)
(define (http-tunnel-serve in out) (define (http-tunnel-serve in out)
(let/ec (let/ec