connection.clj
Branches > main > bce5890 > files / src / net / bowmap / server / network / connection.clj
(ns net.bowmap.server.network.connection
"A connection to the Minecraft server."
(:require
[clojure.core.async :refer [<!! >!! chan close! io-thread]]
[clojure.spec.alpha :as s]
[net.bowmap.server.network.streams :as streams])
(:import
[java.io IOException]
[java.net Socket]))
(s/def ::connection (s/keys :opt [::clientbound-frame-chan ::serverbound-frame-chan]))
(defn connection
"Returns a connection from a given java.net.Socket.
Connection has keys [::clientbound-frame-chan ::serverbound-frame-chan],
which are channels of clientbound and serverbound frames respectively.
The lifecycles of the client socket and both frame channels are coupled."
[socket]
(let [clientbound-frames (chan 128)
serverbound-frames (chan 128)
input-stream (Socket/.getInputStream socket)
output-stream (Socket/.getOutputStream socket)]
(Socket/.setTcpNoDelay socket true)
(io-thread
(try
(loop []
(when (>!! serverbound-frames (streams/read-frame!! input-stream))
(recur)))
(catch IOException _)
(finally
(close! serverbound-frames)
(close! clientbound-frames)
(Socket/.close socket))))
(io-thread
(try
(loop []
(when-some [frame (<!! clientbound-frames)]
(streams/write-frame!! frame output-stream)
(recur)))
(catch IOException _)
(finally
(close! clientbound-frames)
(close! serverbound-frames)
(Socket/.close socket))))
{::clientbound-frame-chan clientbound-frames
::serverbound-frame-chan serverbound-frames}))