connections.clj

Bowmap · bowmap.git · Tickets

Branches > main > 8372250 > 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.codec :as codec]
   [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 (codec/decode-frame client x))]
       [client' {::client/clientbound-packets packets}])

     ::client/clientbound-packet
     [client {::connection/clientbound-frames [(codec/encode-packet client x)]}])))

(defn handle-connection! [{::connection/keys! [serverbound-frames clientbound-frames]}]
  (let [clientbound-packets (chan 1024)]
    (io-thread
      (loop [client-state (client-step nil)]
        (let [[x ch] (alts!! [serverbound-frames clientbound-packets])
              in (condp = ch
                   serverbound-frames ::connection/serverbound-frame
                   clientbound-packets ::client/clientbound-packet)]
          (when (some? x)
            (let [[client' {frames ::connection/clientbound-frames
                            packets ::client/clientbound-packets}]
                  (client-step client-state in x)]
              (doseq [frame frames]
                (put! clientbound-frames frame))
              (doseq [packet packets]
                (put! clientbound-packets 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))))