Skip to content

Commit

Permalink
Fix websocket data parsing if content is larger than read BUFSIZE; Is… (
Browse files Browse the repository at this point in the history
#184)

* Fix websocket data parsing if content is larger than read BUFSIZE; Issue #181

* Add test for websocket response with request larger than read BUFSIZE
  • Loading branch information
spaceone authored and prologic committed Nov 4, 2016
1 parent b0df3dd commit 3ec4b32
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 1 deletion.
4 changes: 4 additions & 0 deletions circuits/protocols/websocket.py
Expand Up @@ -49,6 +49,7 @@ def __init__(self, sock=None, data=bytearray(), *args, **kwargs):
self._pending_type = None
self._close_received = False
self._close_sent = False
self._buffer = bytearray()

messages = self._parse_messages(bytearray(data))
for message in messages:
Expand Down Expand Up @@ -90,6 +91,7 @@ def _parse_messages(self, data):
msgs = [] # one chunk of bytes may result in several messages
if self._close_received:
return msgs
data = self._buffer + data
while data:
# extract final flag, opcode and masking
final = bool(data[0] & 0x80 != 0)
Expand All @@ -111,7 +113,9 @@ def _parse_messages(self, data):
offset += 4
# if not enough bytes available yet, retry after next read
if len(data) - offset < payload_length:
self._buffer = data
break
self._buffer = bytearray()
# rest of _buffer is payload
msg = data[offset:offset + payload_length]
if masking: # unmask
Expand Down
8 changes: 7 additions & 1 deletion tests/web/test_websockets.py
Expand Up @@ -6,7 +6,7 @@

from circuits import Component
from circuits.web.controllers import Controller
from circuits.net.sockets import close, write
from circuits.net.sockets import close, write, BUFSIZE
from circuits.web.websockets import WebSocketClient, WebSocketsDispatcher


Expand Down Expand Up @@ -81,6 +81,12 @@ def test(manager, watcher, webapp):
assert watcher.wait("read", channel="ws")
assert client.response == "Received: Hello!"

for size in (BUFSIZE, BUFSIZE + 1, BUFSZIE * 2):
data = "A" * (size + 1)
client.fire(write(data), "ws")
assert watcher.wait("read", channel="ws")
assert client.response == "Received: %s" % (data,)

f = urlopen(webapp.server.http.base)
s = f.read()
assert s == b"Hello World!"
Expand Down

3 comments on commit 3ec4b32

@ri0t
Copy link
Contributor

@ri0t ri0t commented on 3ec4b32 Dec 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only fires the whole packet after a full buffer (can contain more than one packet actually!) has been filled. Not sure, where/how to check for a completed packet in a useful way.

@spaceone
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please give a detailed example which demonstrates this.

@spaceone
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use e.g. the test case as base for the example.

Please sign in to comment.