websockets: lINTEGER to specify payload length
This commit is contained in:
parent
cd2fb13b3e
commit
bddf81edfc
|
@ -357,19 +357,34 @@ class OptionsOrValue(_Component):
|
||||||
|
|
||||||
|
|
||||||
class Integer(_Component):
|
class Integer(_Component):
|
||||||
|
bounds = (None, None)
|
||||||
|
preamble = ""
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
|
v = int(value)
|
||||||
|
outofbounds = any([
|
||||||
|
self.bounds[0] is not None and v < self.bounds[0],
|
||||||
|
self.bounds[1] is not None and v > self.bounds[1]
|
||||||
|
])
|
||||||
|
if outofbounds:
|
||||||
|
raise exceptions.ParseException(
|
||||||
|
"Integer value must be between %s and %s."%self.bounds,
|
||||||
|
0, 0
|
||||||
|
)
|
||||||
self.value = str(value)
|
self.value = str(value)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = v_integer.copy()
|
e = v_integer.copy()
|
||||||
|
if klass.preamble:
|
||||||
|
e = pp.Literal(klass.preamble).suppress() + e
|
||||||
return e.setParseAction(lambda x: klass(*x))
|
return e.setParseAction(lambda x: klass(*x))
|
||||||
|
|
||||||
def values(self, settings):
|
def values(self, settings):
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
def spec(self):
|
def spec(self):
|
||||||
return "%s"%(self.value)
|
return "%s%s"%(self.preamble, self.value)
|
||||||
|
|
||||||
def freeze(self, settings):
|
def freeze(self, settings):
|
||||||
return self
|
return self
|
||||||
|
|
|
@ -10,6 +10,7 @@ from . import base, generators, actions, message
|
||||||
wf:-fin:-rsv1:-rsv2:-rsv3:-mask
|
wf:-fin:-rsv1:-rsv2:-rsv3:-mask
|
||||||
|
|
||||||
wf:l234
|
wf:l234
|
||||||
|
wf:mask:r"foo
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,11 +65,17 @@ class KeyNone(base.CaselessLiteral):
|
||||||
TOK = "knone"
|
TOK = "knone"
|
||||||
|
|
||||||
|
|
||||||
|
class Length(base.Integer):
|
||||||
|
bounds = (0, 1<<64)
|
||||||
|
preamble = "l"
|
||||||
|
|
||||||
|
|
||||||
class WebsocketFrame(message.Message):
|
class WebsocketFrame(message.Message):
|
||||||
comps = (
|
comps = (
|
||||||
Body,
|
Body,
|
||||||
|
|
||||||
OpCode,
|
OpCode,
|
||||||
|
Length,
|
||||||
# Bit flags
|
# Bit flags
|
||||||
Fin,
|
Fin,
|
||||||
RSV1,
|
RSV1,
|
||||||
|
@ -122,6 +129,10 @@ class WebsocketFrame(message.Message):
|
||||||
def knone(self):
|
def knone(self):
|
||||||
return self.tok(KeyNone)
|
return self.tok(KeyNone)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def toklength(self):
|
||||||
|
return self.tok(Length)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
parts = [i.expr() for i in klass.comps]
|
parts = [i.expr() for i in klass.comps]
|
||||||
|
@ -157,6 +168,8 @@ class WebsocketFrame(message.Message):
|
||||||
else:
|
else:
|
||||||
bodygen = None
|
bodygen = None
|
||||||
length = 0
|
length = 0
|
||||||
|
if self.toklength:
|
||||||
|
length = int(self.toklength.value)
|
||||||
frameparts = dict(
|
frameparts = dict(
|
||||||
payload_length = length
|
payload_length = length
|
||||||
)
|
)
|
||||||
|
|
|
@ -53,6 +53,14 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> l<a href="#valuespec">INTEGER</a> </td>
|
||||||
|
<td>
|
||||||
|
Set the payload length in the frame header, regardless of the
|
||||||
|
actual body length.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td> [-]mask </td>
|
<td> [-]mask </td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -305,6 +305,17 @@ def test_integer():
|
||||||
|
|
||||||
assert v.freeze({}).value == v.value
|
assert v.freeze({}).value == v.value
|
||||||
|
|
||||||
|
class BInt(base.Integer):
|
||||||
|
bounds = (1, 5)
|
||||||
|
|
||||||
|
tutils.raises("must be between", BInt, 0)
|
||||||
|
tutils.raises("must be between", BInt, 6)
|
||||||
|
assert BInt(5)
|
||||||
|
assert BInt(1)
|
||||||
|
assert BInt(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TBoolean(base.Boolean):
|
class TBoolean(base.Boolean):
|
||||||
name = "test"
|
name = "test"
|
||||||
|
|
|
@ -15,6 +15,7 @@ class TestWebsocketFrame:
|
||||||
"wf",
|
"wf",
|
||||||
"wf:dr",
|
"wf:dr",
|
||||||
"wf:b'foo'",
|
"wf:b'foo'",
|
||||||
|
"wf:l1024:b'foo'",
|
||||||
"wf:cbinary",
|
"wf:cbinary",
|
||||||
"wf:c1",
|
"wf:c1",
|
||||||
"wf:mask:knone",
|
"wf:mask:knone",
|
||||||
|
@ -106,3 +107,10 @@ class TestWebsocketFrame:
|
||||||
self.fr,
|
self.fr,
|
||||||
"wf:b'foo':mask:knone",
|
"wf:b'foo':mask:knone",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_length(self):
|
||||||
|
assert self.fr("wf:l3:b'foo'").header.payload_length == 3
|
||||||
|
frm = self.fr("wf:l2:b'foo'")
|
||||||
|
assert frm.header.payload_length == 2
|
||||||
|
assert frm.payload == "fo"
|
||||||
|
tutils.raises("expected 1024 bytes", self.fr, "wf:l1024:b'foo'")
|
||||||
|
|
Loading…
Reference in New Issue