summaryrefslogtreecommitdiff
path: root/web/socket/server.scm
diff options
context:
space:
mode:
Diffstat (limited to 'web/socket/server.scm')
-rw-r--r--web/socket/server.scm42
1 files changed, 6 insertions, 36 deletions
diff --git a/web/socket/server.scm b/web/socket/server.scm
index 2d1694d..3394d3b 100644
--- a/web/socket/server.scm
+++ b/web/socket/server.scm
@@ -1,6 +1,7 @@
;;; guile-websocket --- WebSocket client/server
;;; Copyright © 2015 David Thompson <davet@gnu.org>
;;; Copyright © 2021 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+;;; Copyright © 2023 Andrew Whatson <whatson@tailcall.au>
;;;
;;; This file is part of guile-websocket.
;;;
@@ -87,48 +88,17 @@ called for each complete message that is received."
(when response
(write-frame response client-socket))))
- (define (read-frame-maybe)
- (and (not (port-eof? client-socket))
- (read-frame client-socket)))
-
;; Perform the HTTP handshake and upgrade to WebSocket protocol.
(let* ((request (read-handshake-request client-socket))
(client-key (assoc-ref (request-headers request) 'sec-websocket-key))
(response (make-handshake-response client-key)))
(write-response response client-socket)
- (let loop ((fragments '())
- (type #f))
- (let ((frame (read-frame-maybe)))
- (cond
- ;; EOF - port is closed.
- ((not frame)
- (close-port client-socket))
- ;; Per section 5.4, control frames may appear interspersed
- ;; along with a fragmented message.
- ((close-frame? frame)
- ;; Per section 5.5.1, echo the close frame back to the
- ;; client before closing the socket. The client may no
- ;; longer be listening.
- (false-if-exception
- (write-frame (make-close-frame (frame-data frame)) client-socket))
- (close-port client-socket))
- ((ping-frame? frame)
- ;; Per section 5.5.3, a pong frame must include the exact
- ;; same data as the ping frame.
- (write-frame (make-pong-frame (frame-data frame)) client-socket)
- (loop fragments type))
- ((pong-frame? frame) ; silently ignore pongs
- (loop fragments type))
- ((first-fragment-frame? frame) ; begin accumulating fragments
- (loop (list frame) (frame-type frame)))
- ((final-fragment-frame? frame) ; concatenate all fragments
- (handle-data-frame type (frame-concatenate (reverse fragments)))
- (loop '() #f))
- ((fragment-frame? frame) ; add a fragment
- (loop (cons frame fragments) type))
- ((data-frame? frame) ; unfragmented data frame
+ (force-output client-socket)
+ (let loop ()
+ (let ((frame (read-data-frame client-socket #:echo-close? #t)))
+ (when frame
(handle-data-frame (frame-type frame) (frame-data frame))
- (loop '() #f)))))))
+ (loop))))))
(define* (run-server handler #:optional (server-socket (make-server-socket)))
"Run WebSocket server on SERVER-SOCKET. HANDLER, a procedure that