more thoroughly convert the SSL machinery to use a connection-specific error function
svn: r4626
This commit is contained in:
parent
2ccf88b6db
commit
c18ca621a3
|
@ -142,7 +142,8 @@ otherwise.
|
||||||
[#:context context]
|
[#:context context]
|
||||||
[#:encrypt protocol-symbol]
|
[#:encrypt protocol-symbol]
|
||||||
[#:close-original? close?]
|
[#:close-original? close?]
|
||||||
[#:shutdown-on-close? shutdown?])
|
[#:shutdown-on-close? shutdown?]
|
||||||
|
[#:error/ssl error])
|
||||||
|
|
||||||
Returns two values --- an input port and an output port --- that
|
Returns two values --- an input port and an output port --- that
|
||||||
implement the SSL protocol over the given input and output port. (The
|
implement the SSL protocol over the given input and output port. (The
|
||||||
|
@ -174,6 +175,11 @@ default is #f. When shutdown is enabled, closing the output port can
|
||||||
fail if the given output port becomes unwritable (e.g., because the
|
fail if the given output port becomes unwritable (e.g., because the
|
||||||
other end of the given port has been closed by another process).
|
other end of the given port has been closed by another process).
|
||||||
|
|
||||||
|
The `error' argument is an error procedure to use for raising
|
||||||
|
communication errors. The default is `error', which raises `exn:fail';
|
||||||
|
in contrast, `ssl-accept' and `ssl-connect' use an error function that
|
||||||
|
raises `exn:fail:network'.
|
||||||
|
|
||||||
|
|
||||||
-- Context procedures --------------------------------------------
|
-- Context procedures --------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -263,7 +263,8 @@
|
||||||
flushing? must-write must-read
|
flushing? must-write must-read
|
||||||
refcount
|
refcount
|
||||||
close-original? shutdown-on-close?
|
close-original? shutdown-on-close?
|
||||||
finalizer-cancel))
|
finalizer-cancel
|
||||||
|
error))
|
||||||
|
|
||||||
(define (make-immobile-bytes n)
|
(define (make-immobile-bytes n)
|
||||||
(if 3m?
|
(if 3m?
|
||||||
|
@ -428,7 +429,7 @@
|
||||||
[else
|
[else
|
||||||
(let ([m (BIO_write r-bio buffer n)])
|
(let ([m (BIO_write r-bio buffer n)])
|
||||||
(unless (= m n)
|
(unless (= m n)
|
||||||
(error 'pump-input-once "couldn't write all bytes to BIO!"))
|
((mzssl-error mzssl) 'pump-input-once "couldn't write all bytes to BIO!"))
|
||||||
m)]))))
|
m)]))))
|
||||||
|
|
||||||
(define (pump-output-once mzssl need-progress? output-blocked-result)
|
(define (pump-output-once mzssl need-progress? output-blocked-result)
|
||||||
|
@ -443,7 +444,7 @@
|
||||||
(if (n . <= . 0)
|
(if (n . <= . 0)
|
||||||
(begin
|
(begin
|
||||||
(when need-progress?
|
(when need-progress?
|
||||||
(error 'pump-output-once "no output to pump!"))
|
((mzssl-error mzssl) 'pump-output-once "no output to pump!"))
|
||||||
#f)
|
#f)
|
||||||
(begin
|
(begin
|
||||||
(write-bytes buffer pipe-w 0 n)
|
(write-bytes buffer pipe-w 0 n)
|
||||||
|
@ -523,7 +524,8 @@
|
||||||
(wrap-evt (mzssl-o mzssl) (lambda (x) 0))))]
|
(wrap-evt (mzssl-o mzssl) (lambda (x) 0))))]
|
||||||
[else
|
[else
|
||||||
(set! must-read-len #f)
|
(set! must-read-len #f)
|
||||||
(error 'read-bytes "SSL read failed ~a"
|
((mzssl-error mzssl) 'read-bytes
|
||||||
|
"SSL read failed ~a"
|
||||||
(get-error-message (ERR_get_error)))]))))))]
|
(get-error-message (ERR_get_error)))]))))))]
|
||||||
[top-read
|
[top-read
|
||||||
(lambda (buffer)
|
(lambda (buffer)
|
||||||
|
@ -677,7 +679,8 @@
|
||||||
(wrap-evt (mzssl-o mzssl) (lambda (x) #f))))]
|
(wrap-evt (mzssl-o mzssl) (lambda (x) #f))))]
|
||||||
[else
|
[else
|
||||||
(set! must-write-len #f)
|
(set! must-write-len #f)
|
||||||
(error 'write-bytes "SSL write failed ~a"
|
((mzssl-error mzssl) 'write-bytes
|
||||||
|
"SSL write failed ~a"
|
||||||
(get-error-message (ERR_get_error)))])))))))]
|
(get-error-message (ERR_get_error)))])))))))]
|
||||||
[top-write
|
[top-write
|
||||||
(lambda (buffer s e non-block? enable-break?)
|
(lambda (buffer s e non-block? enable-break?)
|
||||||
|
@ -708,7 +711,7 @@
|
||||||
(unless (and (len . >= . must-write-len)
|
(unless (and (len . >= . must-write-len)
|
||||||
(bytes=? (subbytes xfer-buffer 0 must-write-len)
|
(bytes=? (subbytes xfer-buffer 0 must-write-len)
|
||||||
(subbytes buffer s (+ s must-write-len))))
|
(subbytes buffer s (+ s must-write-len))))
|
||||||
(error 'write-bytes
|
((mzssl-error mzssl) 'write-bytes
|
||||||
"SSL output request: ~e different from previous unsatisfied request: ~e"
|
"SSL output request: ~e different from previous unsatisfied request: ~e"
|
||||||
(subbytes buffer s e)
|
(subbytes buffer s e)
|
||||||
(subbytes xfer-buffer 0 must-write-len)))
|
(subbytes xfer-buffer 0 must-write-len)))
|
||||||
|
@ -762,7 +765,8 @@
|
||||||
;; out that we have and try again, up to 10 times.
|
;; out that we have and try again, up to 10 times.
|
||||||
(unless (cnt . >= . 10)
|
(unless (cnt . >= . 10)
|
||||||
(loop (add1 cnt)))
|
(loop (add1 cnt)))
|
||||||
(error 'read-bytes "SSL shutdown failed ~a"
|
((mzssl-error mzssl) 'read-bytes
|
||||||
|
"SSL shutdown failed ~a"
|
||||||
(get-error-message (ERR_get_error))))])))))))
|
(get-error-message (ERR_get_error))))])))))))
|
||||||
(set-mzssl-w-closed?! mzssl #t)
|
(set-mzssl-w-closed?! mzssl #t)
|
||||||
(mzssl-release mzssl)
|
(mzssl-release mzssl)
|
||||||
|
@ -794,10 +798,11 @@
|
||||||
[encrypt default-encrypt]
|
[encrypt default-encrypt]
|
||||||
[mode 'connect]
|
[mode 'connect]
|
||||||
[close-original? #f]
|
[close-original? #f]
|
||||||
[shutdown-on-close? #f])
|
[shutdown-on-close? #f]
|
||||||
(wrap-ports 'port->ssl-ports i o (or context encrypt) mode close-original? shutdown-on-close?))
|
[error/ssl error])
|
||||||
|
(wrap-ports 'port->ssl-ports i o (or context encrypt) mode close-original? shutdown-on-close? error/ssl))
|
||||||
|
|
||||||
(define (create-ssl who context-or-encrypt-method connect/accept)
|
(define (create-ssl who context-or-encrypt-method connect/accept error/ssl)
|
||||||
(atomically ; so we register the finalizer (and it's ok since everything is non-blocking)
|
(atomically ; so we register the finalizer (and it's ok since everything is non-blocking)
|
||||||
(let ([ctx (get-context who context-or-encrypt-method (eq? connect/accept 'connect))])
|
(let ([ctx (get-context who context-or-encrypt-method (eq? connect/accept 'connect))])
|
||||||
(check-valid ctx who "context creation")
|
(check-valid ctx who "context creation")
|
||||||
|
@ -852,14 +857,14 @@
|
||||||
;; Return SSL and the cancel boxL:
|
;; Return SSL and the cancel boxL:
|
||||||
(values ssl cancel r-bio w-bio connect?)))))))))
|
(values ssl cancel r-bio w-bio connect?)))))))))
|
||||||
|
|
||||||
(define (wrap-ports who i o context-or-encrypt-method connect/accept close? shutdown-on-close?)
|
(define/kw (wrap-ports who i o context-or-encrypt-method connect/accept close? shutdown-on-close? error/ssl)
|
||||||
(unless (input-port? i)
|
(unless (input-port? i)
|
||||||
(raise-type-error who "input port" i))
|
(raise-type-error who "input port" i))
|
||||||
(unless (output-port? o)
|
(unless (output-port? o)
|
||||||
(raise-type-error who "output port" o))
|
(raise-type-error who "output port" o))
|
||||||
;; Create the SSL connection:
|
;; Create the SSL connection:
|
||||||
(let-values ([(ssl cancel r-bio w-bio connect?)
|
(let-values ([(ssl cancel r-bio w-bio connect?)
|
||||||
(create-ssl who context-or-encrypt-method connect/accept)])
|
(create-ssl who context-or-encrypt-method connect/accept error/ssl)])
|
||||||
;; connect/accept:
|
;; connect/accept:
|
||||||
(let-values ([(buffer) (make-bytes BUFFER-SIZE)]
|
(let-values ([(buffer) (make-bytes BUFFER-SIZE)]
|
||||||
[(pipe-r pipe-w) (make-pipe)]
|
[(pipe-r pipe-w) (make-pipe)]
|
||||||
|
@ -869,7 +874,8 @@
|
||||||
#f #f
|
#f #f
|
||||||
#f #f #f 2
|
#f #f #f 2
|
||||||
close? shutdown-on-close?
|
close? shutdown-on-close?
|
||||||
cancel)])
|
cancel
|
||||||
|
error/ssl)])
|
||||||
(let loop ()
|
(let loop ()
|
||||||
(let ([status (if connect?
|
(let ([status (if connect?
|
||||||
(SSL_connect ssl)
|
(SSL_connect ssl)
|
||||||
|
@ -881,14 +887,14 @@
|
||||||
[(= err SSL_ERROR_WANT_READ)
|
[(= err SSL_ERROR_WANT_READ)
|
||||||
(let ([n (pump-input-once mzssl (if out-blocked? o #t))])
|
(let ([n (pump-input-once mzssl (if out-blocked? o #t))])
|
||||||
(when (eof-object? n)
|
(when (eof-object? n)
|
||||||
(error/network who "~a failed (input terminated prematurely)"
|
(error/ssl who "~a failed (input terminated prematurely)"
|
||||||
(if connect? "connect" "accept"))))
|
(if connect? "connect" "accept"))))
|
||||||
(loop)]
|
(loop)]
|
||||||
[(= err SSL_ERROR_WANT_WRITE)
|
[(= err SSL_ERROR_WANT_WRITE)
|
||||||
(pump-output-once mzssl #t #f)
|
(pump-output-once mzssl #t #f)
|
||||||
(loop)]
|
(loop)]
|
||||||
[else
|
[else
|
||||||
(error/network who "~a failed ~a"
|
(error/ssl who "~a failed ~a"
|
||||||
(if connect? "connect" "accept")
|
(if connect? "connect" "accept")
|
||||||
(get-error-message (ERR_get_error)))]))))))
|
(get-error-message (ERR_get_error)))]))))))
|
||||||
;; Connection complete; make ports
|
;; Connection complete; make ports
|
||||||
|
@ -956,7 +962,7 @@
|
||||||
(close-input-port i)
|
(close-input-port i)
|
||||||
(close-output-port o)
|
(close-output-port o)
|
||||||
(raise exn))])
|
(raise exn))])
|
||||||
(wrap-ports who i o (ssl-listener-mzctx ssl-listener) 'accept #t #f))))
|
(wrap-ports who i o (ssl-listener-mzctx ssl-listener) 'accept #t #f error/network))))
|
||||||
|
|
||||||
(define (ssl-accept ssl-listener)
|
(define (ssl-accept ssl-listener)
|
||||||
(do-ssl-accept 'ssl-accept tcp-accept ssl-listener))
|
(do-ssl-accept 'ssl-accept tcp-accept ssl-listener))
|
||||||
|
@ -974,7 +980,7 @@
|
||||||
(close-input-port i)
|
(close-input-port i)
|
||||||
(close-output-port o)
|
(close-output-port o)
|
||||||
(raise exn))])
|
(raise exn))])
|
||||||
(wrap-ports who i o client-context-or-protocol-symbol 'connect #t #f))))
|
(wrap-ports who i o client-context-or-protocol-symbol 'connect #t #f error/network))))
|
||||||
|
|
||||||
(define/kw (ssl-connect
|
(define/kw (ssl-connect
|
||||||
hostname port-k
|
hostname port-k
|
||||||
|
|
Loading…
Reference in New Issue
Block a user