Skip to content
This repository has been archived by the owner on Jan 13, 2021. It is now read-only.

Commit

Permalink
Fixed to read out all data from socket when Data Frame payload is qui…
Browse files Browse the repository at this point in the history
…te large like SETTINGS_MAX_FRAME_SIZE
  • Loading branch information
t2y committed Jan 27, 2015
1 parent 7978b2a commit 9bc162e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
26 changes: 23 additions & 3 deletions hyper/http20/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,11 +483,31 @@ def _consume_single_frame(self):
frame, length = Frame.parse_frame_header(header)

# Read the remaining data from the socket.
if length:
data = self._recv_payload(length)
self._consume_frame_payload(frame, data)

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)
else:
data = memoryview(b'')
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]

def _consume_frame_payload(self, frame, data):
frame.parse_body(data)

log.info(
Expand Down
26 changes: 26 additions & 0 deletions test/test_hyper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,23 @@ def test_we_can_read_from_the_socket(self):
s = c.recent_stream
assert s.data == [b'testdata']

def test_we_can_read_fitfully_from_the_socket(self):
sock = DummyFitfullySocket()
sock.buffer = BytesIO(
b'\x00\x00\x18\x00\x01\x00\x00\x00\x01'
b'testdata'
b'+payload'
)

c = HTTP20Connection('www.google.com')
c._sock = sock
c.putrequest('GET', '/')
c.endheaders()
c._recv_cb()

s = c.recent_stream
assert s.data == [b'testdata+payload']

def test_putrequest_sends_data(self):
sock = DummySocket()

Expand Down Expand Up @@ -2045,6 +2062,15 @@ def recv(self, l):
def close(self):
pass


class DummyFitfullySocket(DummySocket):
def recv(self, l):
length = l
if l != 9 and l >= 4:
length = int(round(l / 2))
return memoryview(self.buffer.read(length))


class DummyStream(object):
def __init__(self, data, trailers=None):
self.data = data
Expand Down

0 comments on commit 9bc162e

Please sign in to comment.