Skip to content

Commit d35d5bb

Browse files
kachayevztellman
authored andcommitted
Carefully release ByteBuf when processing WebSocketFrame (#430)
* Safer bytebuf copying procedure * Carefully release bytebuf when working with websocket frames * Additional comment for a closing frame * Simplify branching when checking WebSocketFrames
1 parent b1690c7 commit d35d5bb

File tree

2 files changed

+43
-32
lines changed

2 files changed

+43
-32
lines changed

src/aleph/http/server.clj

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -543,35 +543,45 @@
543543

544544
:channel-read
545545
([_ ctx msg]
546-
(try
547-
(let [ch (.channel ctx)]
548-
(if-not (instance? WebSocketFrame msg)
549-
(.fireChannelRead ctx msg)
550-
(let [^WebSocketFrame msg msg]
551-
(condp instance? msg
552-
553-
TextWebSocketFrame
554-
(netty/put! ch in (.text ^TextWebSocketFrame msg))
555-
556-
BinaryWebSocketFrame
557-
(let [body (.content ^BinaryWebSocketFrame msg)]
558-
(netty/put! ch in
559-
(if raw-stream?
560-
(netty/acquire body)
561-
(netty/buf->array body))))
562-
563-
PingWebSocketFrame
564-
(netty/write-and-flush ch (PongWebSocketFrame. (netty/acquire (.content msg))))
565-
566-
PongWebSocketFrame
567-
(http/resolve-pings! pending-pings true)
568-
569-
CloseWebSocketFrame
570-
(.close handshaker ch (netty/acquire msg))
571-
572-
(.fireChannelRead ctx msg)))))
573-
(finally
574-
(netty/release msg)))))]))))
546+
(let [ch (.channel ctx)]
547+
(cond
548+
(instance? TextWebSocketFrame msg)
549+
(let [text (.text ^TextWebSocketFrame msg)]
550+
;; working with text now, so we do not need
551+
;; ByteBuf inside TextWebSocketFrame
552+
;; note, that all *WebSocketFrame classes are
553+
;; subclasses of DefaultByteBufHolder, meaning
554+
;; there's no difference between releasing
555+
;; frame & frame's content
556+
(netty/release msg)
557+
(netty/put! ch in text))
558+
559+
(instance? BinaryWebSocketFrame msg)
560+
(let [body (.content ^BinaryWebSocketFrame msg)]
561+
(netty/put! ch in
562+
(if raw-stream?
563+
body
564+
;; copied data into byte array, deallocating ByteBuf
565+
(netty/release-buf->array body))))
566+
567+
(instance? PingWebSocketFrame msg)
568+
(let [body (.content ^PingWebSocketFrame msg)]
569+
;; reusing the same buffer
570+
;; will be deallocated by Netty
571+
(netty/write-and-flush ch (PongWebSocketFrame. body)))
572+
573+
(instance? PongWebSocketFrame msg)
574+
(http/resolve-pings! pending-pings true)
575+
576+
(instance? CloseWebSocketFrame msg)
577+
;; reusing the same buffer
578+
;; will be deallocated by Netty
579+
(.close handshaker ch msg)
580+
581+
:else
582+
;; no need to release buffer when passing to a next handler
583+
(.fireChannelRead ctx msg)))))]))))
584+
575585

576586
;; note, as we set `keep-alive?` to `false`, `send-message` will close the connection
577587
;; after writes are done, which is exactly what we expect to happen

src/aleph/netty.clj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,10 @@
119119
(.array dst)))
120120

121121
(defn release-buf->array [^ByteBuf buf]
122-
(let [ary (buf->array buf)]
123-
(release buf)
124-
ary))
122+
(try
123+
(buf->array buf)
124+
(finally
125+
(release buf))))
125126

126127
(defn bufs->array [bufs]
127128
(let [bufs' (mapcat #(.nioBuffers ^ByteBuf %) bufs)

0 commit comments

Comments
 (0)