@@ -34,8 +34,13 @@ public final class WebSocket {
34
34
private var waitingForPong : Bool
35
35
private var waitingForClose : Bool
36
36
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
+ ) {
39
44
self . channel = channel
40
45
self . type = type
41
46
self . onTextCallback = { _, _ in }
@@ -45,6 +50,7 @@ public final class WebSocket {
45
50
self . waitingForPong = false
46
51
self . waitingForClose = false
47
52
self . scheduledTimeoutTask = nil
53
+ self . outboundMaxFrameSize = outboundMaxFrameSize
48
54
}
49
55
50
56
public func onText( _ callback: @escaping ( WebSocket , String ) -> ( ) ) {
@@ -88,12 +94,78 @@ public final class WebSocket {
88
94
let string = String ( text)
89
95
var buffer = channel. allocator. buffer ( capacity: text. count)
90
96
buffer. writeString ( string)
91
- self . send ( raw: buffer. readableBytesView, opcode: . text, fin: true , promise: promise)
92
97
98
+ self . send ( buffer: buffer, opcode: . text, promise: promise)
93
99
}
94
100
95
101
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
+ }
97
169
}
98
170
99
171
public func sendPing( promise: EventLoopPromise < Void > ? = nil ) {
@@ -115,6 +187,7 @@ public final class WebSocket {
115
187
{
116
188
var buffer = channel. allocator. buffer ( capacity: data. count)
117
189
buffer. writeBytes ( data)
190
+
118
191
let frame = WebSocketFrame (
119
192
fin: fin,
120
193
opcode: opcode,
@@ -213,16 +286,16 @@ public final class WebSocket {
213
286
self . close ( code: . protocolError, promise: nil )
214
287
}
215
288
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 )
220
292
} 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
222
298
}
223
- // append this frame and update the sequence
224
- frameSequence. append ( frame)
225
- self . frameSequence = frameSequence
226
299
case . continuation:
227
300
// we must have an existing sequence
228
301
if var frameSequence = self . frameSequence {
0 commit comments