#lang imperative-syndicate (provide (struct-out server-connection) (struct-out server-inbound) (struct-out server-outbound) (struct-out server-envelope)) (require "wire-protocol.rkt") (require imperative-syndicate/term) (require racket/set) ;; Internal connection protocol (assertion-struct server-connection (connection-id scope)) (assertion-struct server-inbound (connection-id body)) (assertion-struct server-outbound (connection-id body)) ;; Internal isolation (assertion-struct server-envelope (scope body)) (spawn #:name 'server-connection-factory (during/spawn (server-connection $id $scope) (define endpoints (set)) (on (message (server-inbound id (Assert $ep $a))) (when (not (set-member? endpoints ep)) (set! endpoints (set-add endpoints ep)) (react (on-stop (set! endpoints (set-remove endpoints ep))) (field [assertion a]) (define (recompute-endpoint) (define a (assertion)) (if (observe? a) (let* ((pattern (observe-specification a)) (spec (server-envelope scope pattern))) (values (observe spec) (term->skeleton-interest spec (capture-facet-context (lambda (op . captured-values) (schedule-script! (current-actor) (lambda () (define ctor (match op ['+ Add] ['- Del] ['! Msg])) (send! (server-outbound id (ctor ep captured-values)))))))))) (values (server-envelope scope a) #f))) (add-endpoint! (current-facet) "server" #t recompute-endpoint) (on (message (server-inbound id (Assert ep $new-a))) (assertion new-a)) (stop-when (message (server-inbound id (Clear ep))))))) (on (message (server-inbound id (Message $body))) (send! (server-envelope scope body))) (on (message (server-inbound id (Ping))) (send! (server-outbound id (Pong))))))