This commit is contained in:
liris
2013-09-03 08:40:47 +09:00
parent c53e474ad8
commit 38a9e9d3d6
2 changed files with 35 additions and 6 deletions

View File

@@ -23,15 +23,16 @@ import websocket as ws
# [1]: https://tools.ietf.org/html/rfc6455#section-5.4
# "RFC6455: 5.4. Fragmentation"
#
TEST_FRAGMENTATION=False
TEST_FRAGMENTATION = True
TRACABLE = False
TRACABLE=False
def create_mask_key(n):
return "abcd"
class SockMock(object):
class SockMock(object):
def __init__(self):
self.data = []
self.sent = []
@@ -247,6 +248,14 @@ class WebSocketTest(unittest.TestCase):
with self.assertRaises(ws.WebSocketConnectionClosedException):
sock.recv()
@unittest.skipUnless(TEST_FRAGMENTATION, "fragmentation not implemented")
def testRecvContFragmentation(self):
sock = ws.WebSocket()
s = sock.sock = SockMock()
# OPCODE=CONT, FIN=1, MSG="the soul of wit"
s.add_packet("\x80\x8fabcd\x15\n\x06D\x12\r\x16\x08A\r\x05D\x16\x0b\x17")
self.assertRaises(ws.WebSocketException, sock.recv)
@unittest.skipUnless(TEST_FRAGMENTATION, "fragmentation not implemented")
def testRecvWithProlongedFragmentation(self):
sock = ws.WebSocket()

View File

@@ -228,6 +228,7 @@ class ABNF(object):
"""
# operation code values.
OPCODE_CONT = 0x0
OPCODE_TEXT = 0x1
OPCODE_BINARY = 0x2
OPCODE_CLOSE = 0x8
@@ -235,11 +236,12 @@ class ABNF(object):
OPCODE_PONG = 0xa
# available operation code value tuple
OPCODES = (OPCODE_TEXT, OPCODE_BINARY, OPCODE_CLOSE,
OPCODES = (OPCODE_CONT, OPCODE_TEXT, OPCODE_BINARY, OPCODE_CLOSE,
OPCODE_PING, OPCODE_PONG)
# opcode human readable string
OPCODE_MAP = {
OPCODE_CONT: "cont",
OPCODE_TEXT: "text",
OPCODE_BINARY: "binary",
OPCODE_CLOSE: "close",
@@ -267,6 +269,11 @@ class ABNF(object):
self.data = data
self.get_mask_key = os.urandom
def __str__(self):
return "fin=" + str(self.fin) \
+ " opcode=" + str(self.opcode) \
+ " data=" + str(self.data)
@staticmethod
def create_frame(data, opcode):
"""
@@ -379,6 +386,7 @@ class WebSocket(object):
self._frame_header = None
self._frame_length = None
self._frame_mask = None
self._cont_data = None
def fileno(self):
return self.sock.fileno()
@@ -552,11 +560,13 @@ class WebSocket(object):
if self.get_mask_key:
frame.get_mask_key = self.get_mask_key
data = frame.format()
length = len(data)
if traceEnabled:
logger.debug("send: " + repr(data))
while data:
l = self._send(data)
data = data[l:]
return length
def send_binary(self, payload):
return self.send(payload, ABNF.OPCODE_BINARY)
@@ -598,8 +608,18 @@ class WebSocket(object):
# handle error:
# 'NoneType' object has no attribute 'opcode'
raise WebSocketException("Not a valid frame %s" % frame)
elif frame.opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY):
return (frame.opcode, frame.data)
elif frame.opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY, ABNF.OPCODE_CONT):
if frame.opcode == ABNF.OPCODE_CONT and not self._cont_data:
raise WebSocketException("Illegal frame")
if self._cont_data:
self._cont_data[1] += frame.data
else:
self._cont_data = [frame.opcode, frame.data]
if frame.fin:
data = self._cont_data
self._cont_data = None
return data
elif frame.opcode == ABNF.OPCODE_CLOSE:
self.send_close()
return (frame.opcode, None)