@@ -34,8 +34,13 @@ public final class WebSocket {
3434 private var waitingForPong : Bool
3535 private var waitingForClose : Bool
3636 private var scheduledTimeoutTask : Scheduled < Void > ?
37-
38- init ( channel: Channel , type: PeerType ) {
37+ private var outboundMaxFrameSize : WebSocketMaxFrameSize
38+
39+ init (
40+ channel: Channel ,
41+ type: PeerType ,
42+ outboundMaxFrameSize: WebSocketMaxFrameSize = . default
43+ ) {
3944 self . channel = channel
4045 self . type = type
4146 self . onTextCallback = { _, _ in }
@@ -45,6 +50,7 @@ public final class WebSocket {
4550 self . waitingForPong = false
4651 self . waitingForClose = false
4752 self . scheduledTimeoutTask = nil
53+ self . outboundMaxFrameSize = outboundMaxFrameSize
4854 }
4955
5056 public func onText( _ callback: @escaping ( WebSocket , String ) -> ( ) ) {
@@ -88,12 +94,78 @@ public final class WebSocket {
8894 let string = String ( text)
8995 var buffer = channel. allocator. buffer ( capacity: text. count)
9096 buffer. writeString ( string)
91- self . send ( raw: buffer. readableBytesView, opcode: . text, fin: true , promise: promise)
9297
98+ self . send ( buffer: buffer, opcode: . text, promise: promise)
9399 }
94100
95101 public func send( _ binary: [ UInt8 ] , promise: EventLoopPromise < Void > ? = nil ) {
96- self . send ( raw: binary, opcode: . binary, fin: true , promise: promise)
102+ var buffer = channel. allocator. buffer ( capacity: binary. count)
103+ buffer. writeBytes ( binary)
104+ self . send ( buffer: buffer, opcode: . binary, promise: promise)
105+ }
106+
107+ public func send(
108+ buffer: NIO . ByteBuffer ,
109+ opcode: WebSocketOpcode ,
110+ promise: EventLoopPromise < Void > ? = nil
111+ ) {
112+
113+ guard buffer. readableBytes > self . outboundMaxFrameSize. value else {
114+ let frame = WebSocketFrame (
115+ fin: true ,
116+ opcode: opcode,
117+ maskKey: self . makeMaskKey ( ) ,
118+ data: buffer
119+ )
120+ self . channel. writeAndFlush ( frame, promise: promise)
121+ return
122+ }
123+
124+ var buffer = buffer
125+
126+ // We need to ensure we write all of these items in order on the event loop without other writes interrupting the frames.
127+ self . channel. eventLoop. execute {
128+ // Send the first frame with the opcode
129+ let frameBuffer = buffer. readSlice ( length: self . outboundMaxFrameSize. value) !
130+ let frame = WebSocketFrame (
131+ fin: false ,
132+ opcode: opcode,
133+ maskKey: self . makeMaskKey ( ) ,
134+ data: frameBuffer
135+ )
136+
137+ self . channel. write ( frame, promise: nil )
138+
139+
140+ while let frameBuffer = buffer. readSlice ( length: self . outboundMaxFrameSize. value) {
141+
142+ let isFinalFrame = buffer. readableBytes == 0
143+
144+ let frame = WebSocketFrame (
145+ fin: isFinalFrame,
146+ opcode: . continuation,
147+ maskKey: self . makeMaskKey ( ) ,
148+ data: frameBuffer
149+ )
150+
151+ if isFinalFrame {
152+ self . channel. writeAndFlush ( frame, promise: promise)
153+ return
154+ } else {
155+ // write operations that happen when already on the event loop go directly through without any `delay`.
156+ self . channel. write ( frame, promise: nil )
157+ }
158+ }
159+ // we will end up here if the number bytes is not a multiple of the `outboundMaxFrameSize`
160+ let finalFrame = WebSocketFrame (
161+ fin: true ,
162+ opcode: . continuation,
163+ maskKey: self . makeMaskKey ( ) ,
164+ data: buffer
165+ )
166+
167+ self . channel. writeAndFlush ( finalFrame, promise: promise)
168+ }
97169 }
98170
99171 public func sendPing( promise: EventLoopPromise < Void > ? = nil ) {
@@ -115,6 +187,7 @@ public final class WebSocket {
115187 {
116188 var buffer = channel. allocator. buffer ( capacity: data. count)
117189 buffer. writeBytes ( data)
190+
118191 let frame = WebSocketFrame (
119192 fin: fin,
120193 opcode: opcode,
@@ -213,16 +286,16 @@ public final class WebSocket {
213286 self . close ( code: . protocolError, promise: nil )
214287 }
215288 case . text, . binary, . pong:
216- // create a new frame sequence or use existing
217- var frameSequence : WebSocketFrameSequence
218- if let existing = self . frameSequence {
219- frameSequence = existing
289+ if self . frameSequence != nil {
290+ // we should not have an existing sequence
291+ self . close ( code: . protocolError, promise: nil )
220292 } else {
221- frameSequence = WebSocketFrameSequence ( type: frame. opcode)
293+ // Create a new frame sequence
294+ var frameSequence = WebSocketFrameSequence ( type: frame. opcode)
295+ // Append this frame and update the sequence
296+ frameSequence. append ( frame)
297+ self . frameSequence = frameSequence
222298 }
223- // append this frame and update the sequence
224- frameSequence. append ( frame)
225- self . frameSequence = frameSequence
226299 case . continuation:
227300 // we must have an existing sequence
228301 if var frameSequence = self . frameSequence {
0 commit comments