Skip to content

Instantly share code, notes, and snippets.

@jarppe
Created June 16, 2024 12:17
Show Gist options
  • Save jarppe/3dfa15c00a63db797fbce811f260e59a to your computer and use it in GitHub Desktop.
Save jarppe/3dfa15c00a63db797fbce811f260e59a to your computer and use it in GitHub Desktop.
Converting Channel to Java InputStream and OutputStream using proxies
(ns proxy-byte-channels-example
(:import (java.io InputStream
OutputStream)
(java.nio ByteBuffer)
(java.net UnixDomainSocketAddress
StandardProtocolFamily)
(java.nio.channels ByteChannel
SocketChannel)
(java.nio.charset StandardCharsets)))
(defn ch->in ^InputStream [^ByteChannel ch]
(let [buffer (doto (ByteBuffer/allocate 1024)
(.flip))
ensure-data (fn []
(if (.hasRemaining buffer)
true
(do (.clear buffer)
(if (= (.read ch buffer) -1)
false
(do (.flip buffer)
true)))))]
(proxy [InputStream] []
(read
([]
(if (ensure-data)
(-> (.get buffer) (bit-and 0xff))
-1))
([b]
(if (ensure-data)
(.get buffer b)
-1))
([b off len]
(if (ensure-data)
(.get buffer b off len)
-1))))))
(defn ch->out ^OutputStream [^ByteChannel ch]
(proxy [OutputStream] []
(write
([v]
(if (bytes? v)
(.write ch (ByteBuffer/wrap v))
(let [buffer (ByteBuffer/allocate 1)]
(.put buffer (-> (Integer. v) (.byteValue)))
(.flip buffer)
(.write ch buffer))))
([v off len]
(.write ch (ByteBuffer/wrap v off len))))))
(defn open-docker-channel []
(doto (SocketChannel/open StandardProtocolFamily/UNIX)
(.connect (UnixDomainSocketAddress/of "/var/run/docker.sock"))
(.finishConnect)))
(defn get-docker-version []
(with-open [ch (open-docker-channel)]
(doto (ch->out ch)
(.write (-> (str "GET /version HTTP/1.0\r\n"
"Host: docker.com\r\n"
"\r\n")
(.getBytes StandardCharsets/UTF_8)))
(.flush))
(let [in (ch->in ch)]
(loop [c (.read in)]
(when-not (= c -1)
(when-not (= c (int \return))
(print (char c)))
(recur (.read in)))))))
(comment
(get-docker-version)
;=>
; HTTP/1.0 200 OK
; Api-Version: 1.45
; Content-Type: application/json
; Date: Sun, 16 Jun 2024 11:53:10 GMT
; Docker-Experimental: false
; Ostype: linux
; Server: Docker/26.1.1 (linux)
;
; {"Platform":{"Name":"Docker Desktop 4.30.0 (149282)"},"Components":[{"Name"...
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment