@@ -35,6 +35,7 @@ local http_patts = require "lpeg_patterns.http"
35
35
local rand = require " openssl.rand"
36
36
local digest = require " openssl.digest"
37
37
local bit = require " http.bit"
38
+ local onerror = require " http.connection_common" .onerror
38
39
local new_headers = require " http.headers" .new
39
40
local http_request = require " http.request"
40
41
@@ -177,13 +178,18 @@ local function build_close(code, message, mask)
177
178
end
178
179
179
180
local function read_frame (sock , deadline )
180
- local frame do
181
- local first_2 , err , errno = sock :xread (2 , " b" , deadline and (deadline - monotime ()))
181
+ local frame , first_2 do
182
+ local err , errno
183
+ first_2 , err , errno = sock :xread (2 , " b" , deadline and (deadline - monotime ()))
182
184
if not first_2 then
183
185
return nil , err , errno
184
186
elseif # first_2 ~= 2 then
185
187
sock :seterror (" r" , ce .EILSEQ )
186
- return nil , ce .strerror (ce .EILSEQ ), ce .EILSEQ
188
+ local ok , errno2 = sock :unget (first_2 )
189
+ if not ok then
190
+ return nil , onerror (sock , " unget" , errno2 )
191
+ end
192
+ return nil , onerror (sock , " read_frame" , ce .EILSEQ )
187
193
end
188
194
local byte1 , byte2 = first_2 :byte (1 , 2 )
189
195
frame = {
@@ -200,50 +206,80 @@ local function read_frame(sock, deadline)
200
206
}
201
207
end
202
208
203
- if frame .length == 126 then
204
- local length , err , errno = sock :xread (2 , " b" , deadline and (deadline - monotime ()))
205
- if not length or # length ~= 2 then
206
- if err == nil then
209
+ local fill_length = frame .length
210
+ if fill_length == 126 then
211
+ fill_length = 2
212
+ elseif fill_length == 127 then
213
+ fill_length = 8
214
+ end
215
+ if frame .MASK then
216
+ fill_length = fill_length + 4
217
+ end
218
+ do
219
+ local ok , err , errno = sock :fill (fill_length , 0 )
220
+ if not ok then
221
+ local unget_ok1 , unget_errno1 = sock :unget (first_2 )
222
+ if not unget_ok1 then
223
+ return nil , onerror (sock , " unget" , unget_errno1 )
224
+ end
225
+ if errno == ce .ETIMEDOUT then
226
+ local timeout = deadline and deadline - monotime ()
227
+ if cqueues .poll (sock , timeout ) ~= timeout then
228
+ -- retry
229
+ return read_frame (sock , deadline )
230
+ end
231
+ elseif err == nil then
207
232
sock :seterror (" r" , ce .EILSEQ )
208
- return nil , ce . strerror ( ce . EILSEQ ), ce .EILSEQ
233
+ return nil , onerror ( sock , " read_frame " , ce .EILSEQ )
209
234
end
210
235
return nil , err , errno
211
236
end
212
- frame .length = sunpack (" >I2" , length )
237
+ end
238
+
239
+ -- if `fill` succeeded these shouldn't be able to fail
240
+ local extra_fill_unget
241
+ if frame .length == 126 then
242
+ extra_fill_unget = assert (sock :xread (2 , " b" , 0 ))
243
+ frame .length = sunpack (" >I2" , extra_fill_unget )
244
+ fill_length = fill_length - 2
213
245
elseif frame .length == 127 then
214
- local length , err , errno = sock :xread (8 , " b" , deadline and (deadline - monotime ()))
215
- if not length or # length ~= 8 then
216
- if err == nil then
246
+ extra_fill_unget = assert (sock :xread (8 , " b" , 0 ))
247
+ frame .length = sunpack (" >I8" , extra_fill_unget )
248
+ fill_length = fill_length - 8 + frame .length
249
+ end
250
+
251
+ if extra_fill_unget then
252
+ local ok , err , errno = sock :fill (fill_length , 0 )
253
+ if not ok then
254
+ local unget_ok1 , unget_errno1 = sock :unget (extra_fill_unget )
255
+ if not unget_ok1 then
256
+ return nil , onerror (sock , " unget" , unget_errno1 )
257
+ end
258
+ local unget_ok2 , unget_errno2 = sock :unget (first_2 )
259
+ if not unget_ok2 then
260
+ return nil , onerror (sock , " unget" , unget_errno2 )
261
+ end
262
+ if errno == ce .ETIMEDOUT then
263
+ local timeout = deadline and deadline - monotime ()
264
+ if cqueues .poll (sock , timeout ) ~= timeout then
265
+ -- retry
266
+ return read_frame (sock , deadline )
267
+ end
268
+ elseif err == nil then
217
269
sock :seterror (" r" , ce .EILSEQ )
218
- return nil , ce . strerror ( ce . EILSEQ ), ce .EILSEQ
270
+ return nil , onerror ( sock , " read_frame " , ce .EILSEQ )
219
271
end
220
272
return nil , err , errno
221
273
end
222
- frame .length = sunpack (" >I8" , length )
223
274
end
224
275
225
276
if frame .MASK then
226
- local key , err , errno = sock :xread (4 , " b" , deadline and (deadline - monotime ()))
227
- if not key or # key ~= 4 then
228
- if err == nil then
229
- sock :seterror (" r" , ce .EILSEQ )
230
- return nil , ce .strerror (ce .EILSEQ ), ce .EILSEQ
231
- end
232
- return nil , err , errno
233
- end
277
+ local key = assert (sock :xread (4 , " b" , 0 ))
234
278
frame .key = { key :byte (1 , 4 ) }
235
279
end
236
280
237
281
do
238
- local data , err , errno = sock :xread (frame .length , " b" , deadline and (deadline - monotime ()))
239
- if data == nil or # data ~= frame .length then
240
- if err == nil then
241
- sock :seterror (" r" , ce .EILSEQ )
242
- return nil , ce .strerror (ce .EILSEQ ), ce .EILSEQ
243
- end
244
- return nil , err , errno
245
- end
246
-
282
+ local data = assert (sock :xread (frame .length , " b" , 0 ))
247
283
if frame .MASK then
248
284
frame .data = apply_mask (data , frame .key )
249
285
else
267
303
268
304
function websocket_methods :send_frame (frame , timeout )
269
305
if self .readyState < 1 then
270
- return nil , ce . strerror ( ce . ENOTCONN ), ce .ENOTCONN
306
+ return nil , onerror ( self . socket , " send_frame " , ce .ENOTCONN )
271
307
elseif self .readyState > 2 then
272
- return nil , ce . strerror ( ce . EPIPE ), ce .EPIPE
308
+ return nil , onerror ( self . socket , " send_frame " , ce .EPIPE )
273
309
end
274
310
local ok , err , errno = self .socket :xwrite (build_frame (frame ), " bn" , timeout )
275
311
if not ok then
349
385
350
386
function websocket_methods :receive (timeout )
351
387
if self .readyState < 1 then
352
- return nil , ce . strerror ( ce . ENOTCONN ), ce .ENOTCONN
388
+ return nil , onerror ( self . socket , " receive " , ce .ENOTCONN )
353
389
elseif self .readyState > 2 then
354
- return nil , ce . strerror ( ce . EPIPE ), ce .EPIPE
390
+ return nil , onerror ( self . socket , " receive " , ce .EPIPE )
355
391
end
356
392
local deadline = timeout and (monotime ()+ timeout )
357
393
while true do
@@ -638,6 +674,7 @@ local function handle_websocket_response(self, headers, stream)
638
674
-- Success!
639
675
assert (self .socket == nil , " websocket:connect called twice" )
640
676
self .socket = assert (stream .connection :take_socket ())
677
+ self .socket :onerror (onerror )
641
678
self .request = nil
642
679
self .headers = headers
643
680
self .readyState = 1
@@ -776,6 +813,7 @@ function websocket_methods:accept(options, timeout)
776
813
end
777
814
778
815
self .socket = assert (self .stream .connection :take_socket ())
816
+ self .socket :onerror (onerror )
779
817
self .stream = nil
780
818
self .readyState = 1
781
819
self .protocol = chosen_protocol
0 commit comments