Software /
code /
prosody
Annotate
util/dbuffer.lua @ 13652:a08065207ef0
net.server_epoll: Call :shutdown() on TLS sockets when supported
Comment from Matthew:
This fixes a potential issue where the Prosody process gets blocked on sockets
waiting for them to close. Unlike non-TLS sockets, closing a TLS socket sends
layer 7 data, and this can cause problems for sockets which are in the process
of being cleaned up.
This depends on LuaSec changes which are not yet upstream.
From Martijn's original email:
So first my analysis of luasec. in ssl.c the socket is put into blocking
mode right before calling SSL_shutdown() inside meth_destroy(). My best
guess to why this is is because meth_destroy is linked to the __close
and __gc methods, which can't exactly be called multiple times and
luasec does want to make sure that a tls session is shutdown as clean
as possible.
I can't say I disagree with this reasoning and don't want to change this
behaviour. My solution to this without changing the current behaviour is
to introduce a shutdown() method. I am aware that this overlaps in a
conflicting way with tcp's shutdown method, but it stays close to the
OpenSSL name. This method calls SSL_shutdown() in the current
(non)blocking mode of the underlying socket and returns a boolean
whether or not the shutdown is completed (matching SSL_shutdown()'s 0
or 1 return values), and returns the familiar ssl_ioerror() strings on
error with a false for completion. This error can then be used to
determine if we have wantread/wantwrite to finalize things. Once
meth_shutdown() has been called once a shutdown flag will be set, which
indicates to meth_destroy() that the SSL_shutdown() has been handled
by the application and it shouldn't be needed to set the socket to
blocking mode. I've left the SSL_shutdown() call in the
LSEC_STATE_CONNECTED to prevent TOCTOU if the application reaches a
timeout for the shutdown code, which might allow SSL_shutdown() to
clean up anyway at the last possible moment.
Another thing I've changed to luasec is the call to socket_setblocking()
right before calling close(2) in socket_destroy() in usocket.c.
According to the latest POSIX[0]:
Note that the requirement for close() on a socket to block for up to
the current linger interval is not conditional on the O_NONBLOCK
setting.
Which I read to mean that removing O_NONBLOCK on the socket before close
doesn't impact the behaviour and only causes noise in system call
tracers. I didn't touch the windows bits of this, since I don't do
windows.
For the prosody side of things I've made the TLS shutdown bits resemble
interface:onwritable(), and put it under a combined guard of self._tls
and self.conn.shutdown. The self._tls bit is there to prevent getting
stuck on this condition, and self.conn.shutdown is there to prevent the
code being called by instances where the patched luasec isn't deployed.
The destroy() method can be called from various places and is read by
me as the "we give up" error path. To accommodate for these unexpected
entrypoints I've added a single call to self.conn:shutdown() to prevent
the socket being put into blocking mode. I have no expectations that
there is any other use here. Same as previous, the self.conn.shutdown
check is there to make sure it's not called on unpatched luasec
deployments and self._tls is there to make sure we don't call shutdown()
on tcp sockets.
I wouldn't recommend logging of the conn:shutdown() error inside
close(), since a lot of clients simply close the connection before
SSL_shutdown() is done.
author | Martijn van Duren <martijn@openbsd.org> |
---|---|
date | Thu, 06 Feb 2025 15:04:38 +0000 |
parent | 12975:d10957394a3c |
rev | line source |
---|---|
12975
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12763
diff
changeset
|
1 local queue = require "prosody.util.queue"; |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
2 |
11189
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
3 local s_byte, s_sub = string.byte, string.sub; |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
4 local dbuffer_methods = {}; |
11196
f243836c449a
util.dbuffer: Add __name to metatable
Matthew Wild <mwild1@gmail.com>
parents:
11190
diff
changeset
|
5 local dynamic_buffer_mt = { __name = "dbuffer", __index = dbuffer_methods }; |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
6 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
7 function dbuffer_methods:write(data) |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
8 if self.max_size and #data + self._length > self.max_size then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
9 return nil; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
10 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 local ok = self.items:push(data); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
12 if not ok then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
13 self:collapse(); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
14 ok = self.items:push(data); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
15 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
16 if not ok then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
17 return nil; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
18 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
19 self._length = self._length + #data; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
20 return true; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
21 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
22 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
23 function dbuffer_methods:read_chunk(requested_bytes) |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
24 local chunk, consumed = self.items:peek(), self.front_consumed; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
25 if not chunk then return; end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
26 local chunk_length = #chunk; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
27 local remaining_chunk_length = chunk_length - consumed; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
28 if not requested_bytes then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
29 requested_bytes = remaining_chunk_length; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
30 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
31 if remaining_chunk_length <= requested_bytes then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
32 self.front_consumed = 0; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
33 self._length = self._length - remaining_chunk_length; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
34 self.items:pop(); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
35 assert(#chunk:sub(consumed + 1, -1) == remaining_chunk_length); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
36 return chunk:sub(consumed + 1, -1), remaining_chunk_length; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
37 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
38 local end_pos = consumed + requested_bytes; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
39 self.front_consumed = end_pos; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
40 self._length = self._length - requested_bytes; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
41 assert(#chunk:sub(consumed + 1, end_pos) == requested_bytes); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
42 return chunk:sub(consumed + 1, end_pos), requested_bytes; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
43 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
44 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
45 function dbuffer_methods:read(requested_bytes) |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 local chunks; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
48 if requested_bytes and requested_bytes > self._length then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
49 return nil; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
50 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
51 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
52 local chunk, read_bytes = self:read_chunk(requested_bytes); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
53 if not requested_bytes then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
54 return chunk; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
55 elseif chunk then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
56 requested_bytes = requested_bytes - read_bytes; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
57 if requested_bytes == 0 then -- Already read everything we need |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
58 return chunk; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
59 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
60 chunks = {}; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 else |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
62 return nil; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
63 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 -- Need to keep reading more chunks |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 while chunk do |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
67 table.insert(chunks, chunk); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
68 if requested_bytes > 0 then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
69 chunk, read_bytes = self:read_chunk(requested_bytes); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
70 requested_bytes = requested_bytes - read_bytes; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 else |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 break; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
76 return table.concat(chunks); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
77 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 |
11636
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
79 -- Read to, and including, the specified character sequence (return nil if not found) |
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
80 function dbuffer_methods:read_until(char) |
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
81 local buffer_pos = 0; |
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
82 for i, chunk in self.items:items() do |
11637
19cddf92fcc2
util.dbuffer: Fix bugs, remove multi-char support (more complex than first thought)
Matthew Wild <mwild1@gmail.com>
parents:
11636
diff
changeset
|
83 local start = 1 + ((i == 1) and self.front_consumed or 0); |
11636
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
84 local char_pos = chunk:find(char, start, true); |
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
85 if char_pos then |
11637
19cddf92fcc2
util.dbuffer: Fix bugs, remove multi-char support (more complex than first thought)
Matthew Wild <mwild1@gmail.com>
parents:
11636
diff
changeset
|
86 return self:read(1 + buffer_pos + char_pos - start); |
11636
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
87 end |
11637
19cddf92fcc2
util.dbuffer: Fix bugs, remove multi-char support (more complex than first thought)
Matthew Wild <mwild1@gmail.com>
parents:
11636
diff
changeset
|
88 buffer_pos = buffer_pos + #chunk - (start - 1); |
11636
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
89 end |
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
90 return nil; |
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
91 end |
11e0a0a08da3
util.dbuffer: Add read_until() method
Matthew Wild <mwild1@gmail.com>
parents:
11196
diff
changeset
|
92 |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
93 function dbuffer_methods:discard(requested_bytes) |
12763
d26eefe98d09
util.dbuffer: Add efficient shortcuts for discard() in certain cases
Matthew Wild <mwild1@gmail.com>
parents:
12762
diff
changeset
|
94 if self._length == 0 then return true; end |
d26eefe98d09
util.dbuffer: Add efficient shortcuts for discard() in certain cases
Matthew Wild <mwild1@gmail.com>
parents:
12762
diff
changeset
|
95 if not requested_bytes or requested_bytes >= self._length then |
d26eefe98d09
util.dbuffer: Add efficient shortcuts for discard() in certain cases
Matthew Wild <mwild1@gmail.com>
parents:
12762
diff
changeset
|
96 self.front_consumed = 0; |
d26eefe98d09
util.dbuffer: Add efficient shortcuts for discard() in certain cases
Matthew Wild <mwild1@gmail.com>
parents:
12762
diff
changeset
|
97 self._length = 0; |
d26eefe98d09
util.dbuffer: Add efficient shortcuts for discard() in certain cases
Matthew Wild <mwild1@gmail.com>
parents:
12762
diff
changeset
|
98 for _ in self.items:consume() do end |
d26eefe98d09
util.dbuffer: Add efficient shortcuts for discard() in certain cases
Matthew Wild <mwild1@gmail.com>
parents:
12762
diff
changeset
|
99 return true; |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
100 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
101 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
102 local chunk, read_bytes = self:read_chunk(requested_bytes); |
12762
79b89f382290
util.dbuffer: Remove redundant code (read_chunk() cannot fail at this point)
Matthew Wild <mwild1@gmail.com>
parents:
11637
diff
changeset
|
103 requested_bytes = requested_bytes - read_bytes; |
79b89f382290
util.dbuffer: Remove redundant code (read_chunk() cannot fail at this point)
Matthew Wild <mwild1@gmail.com>
parents:
11637
diff
changeset
|
104 if requested_bytes == 0 then -- Already read everything we need |
79b89f382290
util.dbuffer: Remove redundant code (read_chunk() cannot fail at this point)
Matthew Wild <mwild1@gmail.com>
parents:
11637
diff
changeset
|
105 return true; |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
106 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
107 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
108 while chunk do |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
109 if requested_bytes > 0 then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
110 chunk, read_bytes = self:read_chunk(requested_bytes); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
111 requested_bytes = requested_bytes - read_bytes; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
112 else |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
113 break; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
114 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
115 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
116 return true; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
117 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
118 |
11189
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
119 -- Normalize i, j into absolute offsets within the |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
120 -- front chunk (accounting for front_consumed), and |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
121 -- ensure there is enough data in the first chunk |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
122 -- to cover any subsequent :sub() or :byte() operation |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
123 function dbuffer_methods:_prep_sub(i, j) |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
124 if j == nil then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
125 j = -1; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
126 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
127 if j < 0 then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
128 j = self._length + (j+1); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
129 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
130 if i < 0 then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
131 i = self._length + (i+1); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
132 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
133 if i < 1 then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
134 i = 1; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
135 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
136 if j > self._length then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
137 j = self._length; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
138 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
139 if i > j then |
11189
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
140 return nil; |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
141 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
142 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
143 self:collapse(j); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
144 |
11189
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
145 if self.front_consumed > 0 then |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
146 i = i + self.front_consumed; |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
147 j = j + self.front_consumed; |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
148 end |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
149 |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
150 return i, j; |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
151 end |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
152 |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
153 function dbuffer_methods:sub(i, j) |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
154 i, j = self:_prep_sub(i, j); |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
155 if not i then |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
156 return ""; |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
157 end |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
158 return s_sub(self.items:peek(), i, j); |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
159 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
160 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
161 function dbuffer_methods:byte(i, j) |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
162 i = i or 1; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
163 j = j or i; |
11189
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
164 i, j = self:_prep_sub(i, j); |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
165 if not i then |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
166 return; |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
167 end |
0ff148362a3d
util.dbuffer: Optimize :sub() and :byte()
Matthew Wild <mwild1@gmail.com>
parents:
11156
diff
changeset
|
168 return s_byte(self.items:peek(), i, j); |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
169 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
170 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
171 function dbuffer_methods:length() |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
172 return self._length; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
173 end |
11156
a8ef69f7fc35
util.dbuffer: Expose length as :len() method, like strings
Kim Alvefur <zash@zash.se>
parents:
11104
diff
changeset
|
174 dbuffer_methods.len = dbuffer_methods.length; -- strings have :len() |
11104
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
175 dynamic_buffer_mt.__len = dbuffer_methods.length; -- support # operator |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
176 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
177 function dbuffer_methods:collapse(bytes) |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
178 bytes = bytes or self._length; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
179 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
180 local front_chunk = self.items:peek(); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
181 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
182 if not front_chunk or #front_chunk - self.front_consumed >= bytes then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
183 return; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
184 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
185 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
186 local front_chunks = { front_chunk:sub(self.front_consumed+1) }; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
187 local front_bytes = #front_chunks[1]; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
188 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
189 while front_bytes < bytes do |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
190 self.items:pop(); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
191 local chunk = self.items:peek(); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
192 front_bytes = front_bytes + #chunk; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
193 table.insert(front_chunks, chunk); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
194 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
195 self.items:replace(table.concat(front_chunks)); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
196 self.front_consumed = 0; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
197 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
198 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
199 local function new(max_size, max_chunks) |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
200 if max_size and max_size <= 0 then |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
201 return nil; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
202 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
203 return setmetatable({ |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
204 front_consumed = 0; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
205 _length = 0; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
206 max_size = max_size; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
207 items = queue.new(max_chunks or 32); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
208 }, dynamic_buffer_mt); |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
209 end |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
210 |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
211 return { |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
212 new = new; |
6632acc96cf6
util.dbuffer: Fix :sub() not working with partially-consumed chunks (thanks Zash for test case)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
213 }; |