chibi-scheme/lib/chibi/net/server.scm
Alex Shinn d7db3effa8 The guard-like macro in the core language is now called protect.
This is the recommended syntax for error-handling in Chibi-specific
programs, since it's not possible to get stack traces when using
R[67]RS guard.  guard is defined separately and according to the
standard in (scheme base).
2013-06-15 18:43:44 +09:00

67 lines
2.8 KiB
Scheme

;; Copyright (c) 2012 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt
(define default-max-requests 10000)
(define (run-net-server listener-or-addr handler . o)
(let* ((listener (cond
((fileno? listener-or-addr)
listener-or-addr)
((integer? listener-or-addr)
(make-listener-socket
(get-address-info "localhost" listener-or-addr)))
(else
(make-listener-socket listener-or-addr))))
(max-requests (if (pair? o) (car o) default-max-requests))
(debug? (and (pair? o) (pair? (cdr o)))))
(define (log-error msg . args)
(display msg (current-error-port))
(for-each
(lambda (x)
(write-char #\space (current-error-port))
(display x (current-error-port)))
args)
(newline (current-error-port)))
(define (log-debug msg . args)
(if debug? (apply log-error msg args)))
(define (run sock addr count)
(log-debug "net-server: accepting request:" count)
(let ((ports
(protect (exn
(else
(log-error "net-server: couldn't create port:" sock)
(close-file-descriptor sock)))
(cons (open-input-file-descriptor sock)
(open-output-file-descriptor sock)))))
(protect (exn
(else (log-error "net-server: error in request:" count)
(print-exception exn)
(print-stack-trace exn)
(close-input-port (car ports))
(close-output-port (cdr ports))
(close-file-descriptor sock)))
(handler (car ports) (cdr ports) sock addr)
(close-input-port (car ports))
(close-output-port (cdr ports))
(close-file-descriptor sock)))
(log-debug "net-server: finished: " count))
(let ((requests 0))
(let serve ((count 0))
(if (>= requests max-requests)
(thread-yield!)
(let* ((addr (get-address-info "127.0.0.1" "8000"))
(sock (accept listener
(address-info-address addr)
(address-info-address-length addr))))
(cond
((not sock)
(serve count))
(else
(thread-start!
(make-thread
(lambda ()
(set! requests (+ requests 1))
(run sock addr count)
(set! requests (- requests 1)))
(string-append "net-client-" (number->string count))))
(serve (+ 1 count))))))))))