|
|
|
@ -34,7 +34,7 @@
|
|
|
|
|
(define current-websocket (make-parameter #f))
|
|
|
|
|
(define ping-interval (make-parameter 15))
|
|
|
|
|
(define close-timeout (make-parameter 5))
|
|
|
|
|
(define connection-timeout (make-parameter 58))
|
|
|
|
|
(define connection-timeout (make-parameter 58)) ; a little grace period from 60s
|
|
|
|
|
(define accept-connection (make-parameter (lambda (origin) #t)))
|
|
|
|
|
(define drop-incoming-pings (make-parameter #t))
|
|
|
|
|
(define propagate-common-errors (make-parameter #f))
|
|
|
|
@ -104,7 +104,7 @@
|
|
|
|
|
fragment?
|
|
|
|
|
(payload fragment-payload)
|
|
|
|
|
(length fragment-length)
|
|
|
|
|
(masked fragment-masked?)
|
|
|
|
|
(masked fragment-masked? set-fragment-masked!)
|
|
|
|
|
(masking-key fragment-masking-key)
|
|
|
|
|
(fin fragment-last?)
|
|
|
|
|
(optype fragment-optype))
|
|
|
|
@ -180,12 +180,13 @@
|
|
|
|
|
(write-string data len outbound-port)
|
|
|
|
|
#t))
|
|
|
|
|
|
|
|
|
|
(define (send-message optype #!optional (data "") (ws (current-websocket)))
|
|
|
|
|
(define (send-message data #!optional (optype 'text) (ws (current-websocket)))
|
|
|
|
|
;; TODO break up large data into multiple frames?
|
|
|
|
|
(optype->opcode optype) ; triggers error if invalid
|
|
|
|
|
(dynamic-wind
|
|
|
|
|
(lambda () (mutex-lock! (websocket-send-mutex ws)))
|
|
|
|
|
(lambda () (send-frame ws optype data #t))
|
|
|
|
|
(lambda () (mutex-unlock! (websocket-send-mutex ws)))))
|
|
|
|
|
(lambda () (mutex-unlock! (websocket-send-mutex ws))))
|
|
|
|
|
|
|
|
|
|
(define (websocket-unmask-frame-payload payload len frame-masking-key)
|
|
|
|
|
(define tmaskkey (make-u8vector 4 #f #t #t))
|
|
|
|
@ -224,10 +225,12 @@
|
|
|
|
|
|
|
|
|
|
(define (unmask fragment)
|
|
|
|
|
(if (fragment-masked? fragment)
|
|
|
|
|
(websocket-unmask-frame-payload
|
|
|
|
|
(let ((r (websocket-unmask-frame-payload
|
|
|
|
|
(fragment-payload fragment)
|
|
|
|
|
(fragment-length fragment)
|
|
|
|
|
(fragment-masking-key fragment))
|
|
|
|
|
(fragment-masking-key fragment))))
|
|
|
|
|
(set-fragment-masked! fragment #f)
|
|
|
|
|
r)
|
|
|
|
|
(fragment-payload fragment)))
|
|
|
|
|
|
|
|
|
|
(define (read-frame-payload inbound-port frame-payload-length)
|
|
|
|
@ -326,16 +329,12 @@
|
|
|
|
|
(read-frame-payload inbound-port frame-payload-length)
|
|
|
|
|
frame-payload-length frame-masked
|
|
|
|
|
frame-masking-key frame-fin frame-optype))
|
|
|
|
|
((eq? frame-optype 'connection-close)
|
|
|
|
|
((eq? frame-optype 'connection-close) ; TODO, same as above?
|
|
|
|
|
(make-fragment
|
|
|
|
|
(read-frame-payload inbound-port frame-payload-length)
|
|
|
|
|
frame-payload-length frame-masked frame-masking-key
|
|
|
|
|
frame-fin frame-optype))
|
|
|
|
|
(else
|
|
|
|
|
(thread-signal! (websocket-user-thread ws)
|
|
|
|
|
(make-websocket-exception
|
|
|
|
|
(make-property-condition 'unhandled-opcode
|
|
|
|
|
'optype frame-optype)))
|
|
|
|
|
(signal (make-websocket-exception
|
|
|
|
|
(make-property-condition 'unhandled-opcode
|
|
|
|
|
'optype frame-optype)))))))))))
|
|
|
|
@ -456,7 +455,7 @@ static const uint8_t utf8d[] = {
|
|
|
|
|
; immediate response
|
|
|
|
|
((and (eq? optype 'ping) last-frame (<= len 125))
|
|
|
|
|
(unless (drop-incoming-pings)
|
|
|
|
|
(send-message 'pong (unmask fragment)))
|
|
|
|
|
(send-message (unmask fragment) 'pong))
|
|
|
|
|
(loop fragments first type total-size))
|
|
|
|
|
|
|
|
|
|
; protocol violation checks
|
|
|
|
@ -501,6 +500,7 @@ static const uint8_t utf8d[] = {
|
|
|
|
|
(values #!eof optype)
|
|
|
|
|
(process-fragments fragments optype)))))
|
|
|
|
|
|
|
|
|
|
; TODO does #!optional and #!key work together?
|
|
|
|
|
(define (close-websocket #!optional (ws (current-websocket))
|
|
|
|
|
#!key (close-reason 'normal) (data (make-u8vector 0)))
|
|
|
|
|
(define invalid-close-reason #f)
|
|
|
|
@ -542,8 +542,7 @@ static const uint8_t utf8d[] = {
|
|
|
|
|
;; (make-websocket-exception
|
|
|
|
|
;; (make-property-condition 'close-timeout)))
|
|
|
|
|
)
|
|
|
|
|
(thread-join! close-thread))
|
|
|
|
|
(log-to (error-log) "closed")))
|
|
|
|
|
(thread-join! close-thread))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (sha1-sum in-bv)
|
|
|
|
@ -586,7 +585,7 @@ static const uint8_t utf8d[] = {
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let loop ()
|
|
|
|
|
(thread-sleep! (ping-interval))
|
|
|
|
|
(send-message 'ping "" ws)
|
|
|
|
|
(send-message "" 'ping ws)
|
|
|
|
|
(loop))))))
|
|
|
|
|
|
|
|
|
|
; make sure the request meets the spec for websockets
|
|
|
|
@ -682,7 +681,9 @@ static const uint8_t utf8d[] = {
|
|
|
|
|
(close-input-port (request-port (current-request))))
|
|
|
|
|
(unless (port-closed? (response-port (current-response)))
|
|
|
|
|
(close-output-port (response-port (current-response))))
|
|
|
|
|
(signal (make-websocket-exception (make-property-condition 'unexpected-error)))))))
|
|
|
|
|
(abort exn)
|
|
|
|
|
;(signal (make-websocket-exception (make-property-condition 'unexpected-error)))
|
|
|
|
|
))))
|
|
|
|
|
|
|
|
|
|
(define (with-concurrent-websocket proc)
|
|
|
|
|
(let ((parent-thread (current-thread)))
|
|
|
|
|