ac6158f
Branches > client-handling-rewrite > ac6158f > files / src / net / bowmap / server.clj
Handle clients with core.async
Commit: ac6158f732589044faaf533be11d28751352dc39
Parent: a408573
3 changed files:
src/net/bowmap/core.clj view file
@@ -1,100 +1,51 @@ (ns net.bowmap.core (:require- [manifold.deferred :as d]- [manifold.stream :as s]+ [clojure.core.async :refer [<!! >!! alt!! chan io-thread put! timeout]] [net.bowmap.client.state :as state] [net.bowmap.packet :as pk] [net.bowmap.packet-handling :as handle] [net.bowmap.packet.client :as cp]- [net.bowmap.packet.read :as read] [net.bowmap.packet.server :as sp]- [net.bowmap.server :as server])- (:import- [io.netty.buffer ByteBuf Unpooled]))--(defn packet-framer-xf- "Transducer that frames bytes from incoming byte arrays and outputs ByteBufs of- framed serialized serverbound packets."- [rf]- (let [buf (Unpooled/buffer)]- (fn- ([] (rf))- ([res] (rf res))- ([res input]- (ByteBuf/.writeBytes buf input)- (loop [res res]- (if (read/can-read-packet? buf)- (let [len (read/read-varint! buf)- res' (rf res (ByteBuf/.copy (ByteBuf/.readRetainedSlice buf len)))]- (ByteBuf/.discardReadBytes buf)- (recur res'))- res))))))+ [net.bowmap.server :as server])) (defn handle-packet "Handles one ByteBuf of a framed serialized serverbound packet, and returns a map of :client and :packets." [client packet-buf] (let [pk (sp/decode-packet packet-buf (::state/state client))]- (when (= (::pk/id pk) ::sp/finish-config)- ; Because the return map is arbitrary, this can definitely be idk literally anywhere else lmao- ; These 3 functions definitely need to change although I don't know what that looks like.- (s/connect (s/periodically 5000 0 (fn []- {::pk/id ::cp/keep-alive- :id (long (* (rand) Long/MAX_VALUE))}))- (::packet-stream client)- {:downstream? false})) (handle/response client pk))) -(defn handle-message- "Handles either a serverbound or clientbound packet, returning the new client- state, and sending either the clientbound packets it was given, or the- packets that handling the serverbound packet it was given returned.- Should only be used synchronously as serialization depends on client state!"- [client msg]- (let [{:keys [stream val]} msg]- (case stream- :serverbound-packets- (let [{:keys [client response]} (handle-packet client val)]- (reduce (fn [client pk]- (handle-message client {:stream :clientbound-packets :val pk}))- client response))+(defn handle-something-or-other [client in packets-out out]+ (alt!!+ in ([buf]+ (when buf+ (let [response (handle-packet client buf)]+ (when (:keepalive response)+ (io-thread+ (loop []+ (<!! (timeout 5000))+ (when (>!! packets-out {::pk/id ::cp/keep-alive+ :id (long (* (rand) Long/MAX_VALUE))})+ (recur)))))+ (doseq [pk (:response response)]+ (put! packets-out pk))+ (:client response))))+ packets-out ([pk]+ (assert (>!! out (cp/encode-packet pk (::state/state client))))+ client))) - :clientbound-packets- (let [pk (cp/encode-packet val (::state/state client))]- @(s/put! (::stream client) pk)- client))))--(defn feed- "Sends all messages from the source to the sink with a transducer."- [source xform sink]- (let [stream (s/stream 1 xform)]- (s/connect source stream)- (s/connect stream sink {:upstream? false})))--(defn alt-onto- "Takes a map of keywords to streams and returns a stream with vals {:stream keyword :val val-from-stream}."- [chans]- (let [out-stream (s/stream)]- (doseq [[kw s] chans]- (feed ssrc/net/bowmap/packet_handling.clj view file
@@ -55,6 +55,7 @@ (defmethod handle-packet ::sp/finish-config [pk client] {:client (assoc client ::state/state ::state/play)+ :keepalive true :response [{::pk/id ::cp/login :entity-id 0 ;; TODO magic zero :p :hardcore? falsesrc/net/bowmap/server.clj view file
@@ -1,13 +1,43 @@ (ns net.bowmap.server (:require- [aleph.tcp :as tcp])+ [aleph.tcp :as tcp]+ [clojure.core.async :refer [chan io-thread]]+ [manifold.stream :as s]+ [net.bowmap.packet.read :as read]) (:import [io.netty.bootstrap ServerBootstrap]+ [io.netty.buffer ByteBuf Unpooled] [io.netty.channel ChannelOption])) -(defn start-server!- "Starts a TCP server at port 'port', calling 'handler' with each client, with TCP_NODELAY enabled."+(defn packet-framer-xf+ "Transducer that frames bytes from incoming byte arrays and outputs ByteBufs of+ framed serialized serverbound packets."+ [rf]+ (let [buf (Unpooled/buffer)]+ (fn+ ([] (rf))+ ([res] (rf res))+ ([res input]+ (ByteBuf/.writeBytes buf input)+ (loop [res res]+ (if (read/can-read-packet? buf)+ (let [len (read/read-varint! buf)+ res' (rf res (ByteBuf/.copy (ByteBuf/.readRetainedSlice buf len)))]+ (ByteBuf/.discardReadBytes buf)+ (recur res'))+ res))))))++(defn- handle-client [handler stream info]+ (let [in (chan 1 packet-framer-xf)+ out (chan)]+ (s/connect stream in)+ (s/connect out stream)+ (io-thread (handler in out))))++; Could return a channel of clients?+(defn start-server2! [& {:keys [handler port]}]- (tcp/start-server handler+ (tcp/start-server (fn [stream info]+ (handle-client handler stream info)) {:port port :bootstrap-transform #(ServerBootstrap/.childOption % ChannelOption/TCP_NODELAY true)}))