f2af1d9
Branches > main > f2af1d9 > files / src / net / bowmap
Add functions to read and write frames with streams
Commit: f2af1d98f50cc3785f129daa1454b56f72842fa9
Parent: 08c3a6c
3 changed files:
deps.edn view file
@@ -2,4 +2,5 @@ {:run {:exec-fn net.bowmap.core/-main :extra-deps {nrepl/nrepl {:mvn/version "1.7.0"}}}} :deps- {org.clojure/clojure {:mvn/version "1.13.0-alpha6"}}}+ {org.clojure/clojure {:mvn/version "1.13.0-alpha6"}+ io.netty/netty-buffer {:mvn/version "4.1.111.Final"}}}src/net/bowmap/network/frame/types.clj view file
@@ -0,0 +1,3 @@+(ns net.bowmap.network.frame.types)++(def max-varint-size 5)src/net/bowmap/network/socket.clj view file
@@ -0,0 +1,71 @@+(ns net.bowmap.network.socket+ "Functions for reading frames to and from java.net.Sockets."+ (:require+ [net.bowmap.network.frame.types :refer [max-varint-size]])+ (:import+ [io.netty.buffer ByteBuf Unpooled]+ [java.io+ EOFException+ IOException+ InputStream+ OutputStream]+ [java.net Socket]))++(defn read-byte!!+ "Blocks and reads an unsigned byte (int) from an InputStream.+ Throws if EOF is reached."+ [input-stream]+ (let [x (InputStream/.read input-stream)]+ (if (= x -1)+ (throw (EOFException. "EOF while reading from InputStream"))+ x)))++(defn read-varint!!+ "Blocks and reads a varint from an InputStream.+ Throws if EOF is reached, or if the encoded varint is invalid."+ [input-stream]+ (loop [num-read 0+ result 0]+ (if (>= num-read max-varint-size)+ (throw (IOException. "VarInt too long"))+ (let [b (read-byte!! input-stream)+ result' (bit-or result (bit-shift-left (bit-and b 0x7F) (* 7 num-read)))]+ (if (zero? (bit-and b 0x80))+ result'+ (recur (inc num-read) result'))))))++(defn read-frame!!+ "Blocks and reads a frame from an InputStream.+ Throws if EOF is reached, or if the encoded frame is invalid."+ [input-stream]+ (let [len (read-varint!! input-stream)+ arr (byte-array len)]+ (loop [offset 0]+ (when (< offset len)+ (let [r (InputStream/.read input-stream arr offset (- len offset))]+ (if (= r -1)+ (throw (EOFException. "EOF while reading frame"))+ (recur (+ offset r))))))+ (Unpooled/wrappedBuffer arr)))++(defn write-frame!!+ "Blocks and writes a frame to an OutputStream.+ Throws if the frame cannot be written."+ [frame output-stream]+ (let [len (ByteBuf/.readableBytes frame)+ arr (byte-array len)]+ (ByteBuf/.readBytes frame arr)+ (OutputStream/.write output-stream arr)+ (OutputStream/.flush output-stream)))++(defn receive-frame!!+ "Blocks and reads a frame from socket's InputStream.+ Throws if EOF is reached, or if the encoded frame is invalid."+ [socket]+ (read-frame!! (Socket/.getInputStream socket)))++(defn send-frame!!+ "Blocks and writes a frame to socket's OutputStream.+ Throws if the frame cannot be written."+ [frame socket]+ (write-frame!! frame (Socket/.getOutputStream socket)))