27afad4
Branches > namespace-reorganization > 27afad4 > files / src / dev / grahp
Remove global state from instance.clj
Commit: 27afad45f04614a2c4a0c6cefff71382482c4bc7
Parent: 2eb109b
2 changed files:
src/net/bowmap/instance.clj view file
@@ -12,35 +12,25 @@ ; The logical server, holds a set of clients connected -; TODO Global state D:-(defonce instance (atom {::clients {}- ::message-out-channels {}}))--(defonce instance2 (atom {::conections {}}))--(defn send-message! [client msg]- ; TODO is put! okay?- (put! ((::message-out-channels @instance) (::client/id client)) msg))--(defn keep-alive! [client]+(defn keep-alive! [messages-out] (io-thread (loop [] (<!! (timeout 20000))- (send-message! client {::msg/id ::cl/keep-alive- :id (long (* (rand) Long/MAX_VALUE))})+ (put! messages-out {::msg/id ::cl/keep-alive+ :id (long (* (rand) Long/MAX_VALUE))}) (recur)))) (defn read-and-handle-packet "Reads/deserializes one packet into a message, and handles it. Because packet reading is dependent on the state of the client, and handling a packet can update the state of the client, Reading and handling must be synchronized!"- [pk client]+ [pk client messages-out] (when-some [msg (srv/packet->message pk (::state/connection-state client))] (let [{:keys [::client/client ::a/keep-alive? ::a/messages]} (a/apply-message msg client)] (when keep-alive?- (keep-alive! client))+ (keep-alive! messages-out)) (doseq [msg messages]- (send-message! client msg))+ (put! messages-out msg)) client))) (defn handle-packets-and-messages [client packets-in messages-out packets-out]@@ -51,7 +41,7 @@ client)) packets-in ([pk] (when pk- (read-and-handle-packet pk client)))))+ (read-and-handle-packet pk client messages-out))))) (defn connect! [client packets-in packets-out] (let [messages-out (chan 1024)]@@ -60,26 +50,22 @@ (loop [client client] (when-some [client (handle-packets-and-messages client packets-in messages-out packets-out)] ; Otherwise, stop?- (swap! instance update ::clients assoc (::client/id client) client) (recur client))))- (swap! instance update ::clients assoc (::client/id client) client)- (swap! instance update ::message-out-channels assoc (::client/id client) messages-out)- client))+ nil)) (defn client "Returns a new client value" []- ; TODO this state should be server-wide, I think.- ; ??? What is he on about ^- {::state/connection-state ::state/handshaking- ::client/id (random-uuid)})+ {::state/connection-state ::state/handshaking}) -(defn handle-client [packets-in packets-out]- (let [client (client)]- (connect! client packets-in packets-out)))--; TODO rename...+; TODO make reloadable, if port is already running, just swap it out? (defn start-server! [{:keys [port]}]- (server/start-server! {:port port- :handler #'handle-client})+ ; Start the client handling loop here+ (let [{::server/keys [server client-chan]} (server/start-server! {:port port})]+ (io-thread+ ; Loop over the instance?+ (loop []+ (when-some [{::server/keys [packets-in packets-out]} (<!! client-chan)]+ (connect! (client) packets-in packets-out)+ (recur))))) nil)src/net/bowmap/network/server.clj view file
@@ -1,24 +1,28 @@ (ns net.bowmap.network.server (:require [aleph.tcp :as tcp]- [clojure.core.async :refer [chan]]+ [clojure.core.async :refer [chan put!]] [manifold.stream :as s] [net.bowmap.network.packet.frame :as frame]) (:import [io.netty.bootstrap ServerBootstrap] [io.netty.channel ChannelOption])) -(defn- handle-client [handler stream info]+(defn- handle-client [client-chan stream info] (let [packets-in (chan 1 frame/packet-framer-xf) packets-out (chan)] (s/connect stream packets-in) (s/connect packets-out stream)- (handler packets-in packets-out)))+ (put! client-chan {::packets-in packets-in+ ::packets-out packets-out}))) +; Returns [:server :client-chan]? (defn start-server! "Starts a Minecraft server at the port, passing clients into the instance."- [& {:keys [port handler]}]- (tcp/start-server (fn [stream info]- (handle-client handler stream info))- {:port port- :bootstrap-transform #(ServerBootstrap/.childOption % ChannelOption/TCP_NODELAY true)}))+ [& {:keys [port]}]+ (let [client-chan (chan 64)]+ {::server (tcp/start-server (fn [stream info]+ (handle-client client-chan stream info))+ {:port port+ :bootstrap-transform #(ServerBootstrap/.childOption % ChannelOption/TCP_NODELAY true)})+ ::client-chan client-chan}))