connections.clj
Branches > main > 30cd6b9 > files / src / net / bowmap / server / runtime / connections.clj
(ns net.bowmap.server.runtime.connections
(:require
[clojure.core.async :refer [<!! alts!! chan io-thread put!]]
[net.bowmap.server.network.connection :as connection]
[net.bowmap.server.protocol.client :as client]
[net.bowmap.server.protocol.packet-serialization :as serialize]
[net.bowmap.server.protocol.phase :as phase]
[net.bowmap.server.runtime.packets :as packets]))
(defn client-step
([_] {::phase/phase ::phase/handshaking})
([client in x]
(case in
::connection/serverbound-frame
(let [[client' packets] (packets/apply-packet client (serialize/decode-frame client x))]
[client' {::client/clientbound-packet-chan packets}])
::client/clientbound-packet
[client {::connection/clientbound-frame-chan [(serialize/encode-packet client x)]}])))
(defn handle-connection! [{::connection/keys! [serverbound-frame-chan clientbound-frame-chan]}]
(let [clientbound-packet-chan (chan 1024)]
(io-thread
(loop [client-state (client-step nil)]
(let [[x ch] (alts!! [serverbound-frame-chan clientbound-packet-chan])
in (condp = ch
serverbound-frame-chan ::connection/serverbound-frame
clientbound-packet-chan ::client/clientbound-packet)]
(when (some? x)
(let [[client' {frames ::connection/clientbound-frame-chan
packets ::client/clientbound-packet-chan}]
(client-step client-state in x)]
(doseq [frame frames]
(put! clientbound-frame-chan frame))
(doseq [packet packets]
(put! clientbound-packet-chan packet))
(recur client'))))))))
(defn handle-connections!
"Handles connections from a channel of connections.
Blocks until the channel closes."
[connection-chan]
(loop []
(when-some [connection (<!! connection-chan)]
(handle-connection! connection)
(recur))))