-
Notifications
You must be signed in to change notification settings - Fork 193
Fixed to read out all data for buffering in BufferedSocket when Data Frame payload is quite large #80
Conversation
So this is a tricky issue.
In the case in question, we have room in the buffer and Because of the way You're correct that the That's implemented in This change as-is would remove that function, because any frame being read must be read it its entirety. What we need, I think, is a |
Thank you for complaisant explanation! I have learned the socket behavior about what was happening. I understand that improving the loop function in I'll investigate more and re-implement this solution. |
Thanks @t2y! Your work here is extremely valued. =) 🍰 |
I re-implemented without changing BufferedSocket behavior. However, there's something wrong in testing? |
ah, maybe it would need coverage 100. I'll try. $ coverage report -m --fail-under 100 |
Before I write some test code, is my changes what you expect? |
@t2y It's closer! I think a few small changes and we should get there. Three notes. First, the The second problem is that this change allows a DoS attack if the server emits part of a frame and blocks on the rest. That's probably OK in an early version, but we should note it. You don't need to make a change here, just add a comment to mention the DoS risk. The final problem is that we do a lot of copying of data in this line:
I think at this point we may want to refactor the code a bit to avoid the copies. I suggest using an Let me know if it's not clear what that last point means and I'll write a bit of sample code to show what I mean. =) Again, @t2y, thanks for this! You're doing fantastic work! |
oops! I'll revert the changes.
I'd like you to write the comment after I finished to fix. Because, I'm not native English writer, so please 😓
Yes. I think so, too. I'll improve it. |
@t2y I'm happy to write the comment for you. =) |
7a79c61
to
8d83109
Compare
According to https://docs.python.org/3.4/library/array.html, it seems that array module cannot handle |
Alright, now we're really getting close! This would be merge-able as-is, but I'd like us to try to simplify the code a bit now, so that I can remember what it's doing when I come back in a few months. I think that, rather than having an The second thing is that we should avoid the use of _buffer_view[_end:_end + data_length] = _data.tobytes() becomes this: _buffer_view[_end:_end + data_length] = _data[:] This avoids creating an intermediate Again, please let me know if any of that was unclear. =) |
You mean like this? def _recv_payload(self, length):
if not length:
return memoryview(b'')
buffer = bytearray(length)
buffer_view = memoryview(buffer)
index = 0
# _sock.recv(length) might not read out all data if the given length is
# very large. So it should be to retrieve from socket repeatedly.
while True:
data = self._sock.recv(length)
data_length = len(data)
end = index + data_length
buffer_view[index:end] = data[:]
length -= data_length
if length == 0 or data_length == 0:
break
index = end
return buffer_view[:end]
Oh, sounds good. I learned an efficient idiom. |
Glad to hear it! As for your loop, I think we can go one better. Rather than using while True:
...
if length == 0 or data_length == 0:
break becomes while length and data_length:
... |
…te large like SETTINGS_MAX_FRAME_SIZE
Exactly, that excites me.
Absolutely, I didn't notice at that time. 😓 You give me awareness and it is helpful. Try again. def _recv_payload(self, length):
if not length:
return memoryview(b'')
buffer = bytearray(length)
buffer_view = memoryview(buffer)
index = 0
data_length = -1
# _sock.recv(length) might not read out all data if the given length
# is very large. So it should be to retrieve from socket repeatedly.
while length and data_length:
data = self._sock.recv(length)
data_length = len(data)
end = index + data_length
buffer_view[index:end] = data[:]
length -= data_length
index = end
return buffer_view[:end] |
@t2y Hurrah! This looks great! 🍰 Thank you so much. |
Fixed to read out all data for buffering in BufferedSocket when Data Frame payload is quite large
FYI, you've earned your contributors spot here. =D 🍰 ⭐ |
I'm learning http2 with pleasure. Thank you, too! 😄 |
Could you confirm whether accessing www.google.co.uk would occur as below?
My environment is OS X Yosemite 10.10.1 (x86_64) and use MacPorts to install Python 3.4.2.
The buffering issue in
BufferedSocket
causes this error. In my environmentself._sck.recv_into(_buffer)
read data only 1135 bytes in spite of_buffer
size is 65535 bytes when target length (amt) is 16384 bytes. I'm not sure whether socket.recv() would ensure to read the buffer given length.So, I changed to read data from socket until
count == 0
(it means no data) orself._bytes_in_buffer == amt
.