connection.clj
Branches > main > 32cb01c > files / src / net / bowmap / server / network / connection.clj
(ns net.bowmap.server.network.connection
"A connection to the Minecraft server."
(:require
[clojure.spec.alpha :as s]
[clojure.stacktrace :refer [print-stack-trace]]
[clojure.tools.logging :as log]
[net.bowmap.server.network.streams :as streams])
(:import
[java.io IOException]
[java.net Socket]))
(defprotocol Connection
(send-frame! [conn frame]
"Sends 'frame' to the connection asynchronously. Returns nil immediately.")
(receive-frame!! [conn]
"Blocks until a frame can be read from 'conn'.
Returns nil when a frame cannot be read."))
(s/def ::connection #(satisfies? Connection %))
(defn- log-unexpected-exception [ex]
(when-not (instance? IOException ex)
(log/warn
(with-out-str
(print-stack-trace ex)))))
(defn connection
"Creates a connection from a given java.net.Socket."
[socket]
(let [input-stream (Socket/.getInputStream socket)
output-stream (Socket/.getOutputStream socket)]
(Socket/.setTcpNoDelay socket true)
(reify Connection
(send-frame! [_ frame]
(Thread/startVirtualThread
#(try (streams/write-frame!! frame output-stream)
(catch Exception e
(Socket/.close socket)
(log-unexpected-exception e))))
nil)
(receive-frame!! [_]
(try (streams/read-frame!! input-stream)
(catch Exception e
(Socket/.close socket)
(log-unexpected-exception e)
nil))))))