2015-05-15 23:31:53 +00:00
|
|
|
import os
|
2015-05-02 04:17:00 +00:00
|
|
|
import netlib.websockets
|
2015-05-02 22:11:51 +00:00
|
|
|
import pyparsing as pp
|
2015-05-02 20:02:13 +00:00
|
|
|
from . import base, generators, actions, message
|
2015-05-02 04:17:00 +00:00
|
|
|
|
2015-05-02 09:27:11 +00:00
|
|
|
"""
|
|
|
|
wf:ctext:b'foo'
|
|
|
|
wf:c15:r'foo'
|
|
|
|
wf:fin:rsv1:rsv2:rsv3:mask
|
|
|
|
wf:-fin:-rsv1:-rsv2:-rsv3:-mask
|
2015-05-15 21:42:47 +00:00
|
|
|
wf:l234
|
2015-05-17 03:38:13 +00:00
|
|
|
|
2015-05-16 23:31:02 +00:00
|
|
|
wf:mask:r"foo
|
2015-05-02 09:27:11 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
class WF(base.CaselessLiteral):
|
|
|
|
TOK = "wf"
|
|
|
|
|
2015-05-02 04:17:00 +00:00
|
|
|
|
2015-05-03 22:48:35 +00:00
|
|
|
class OpCode(base.IntField):
|
2015-05-03 01:54:52 +00:00
|
|
|
names = {
|
|
|
|
"continue": netlib.websockets.OPCODE.CONTINUE,
|
|
|
|
"text": netlib.websockets.OPCODE.TEXT,
|
|
|
|
"binary": netlib.websockets.OPCODE.BINARY,
|
|
|
|
"close": netlib.websockets.OPCODE.CLOSE,
|
|
|
|
"ping": netlib.websockets.OPCODE.PING,
|
|
|
|
"pong": netlib.websockets.OPCODE.PONG,
|
|
|
|
}
|
|
|
|
max = 15
|
|
|
|
preamble = "c"
|
|
|
|
|
|
|
|
|
2015-05-03 00:54:25 +00:00
|
|
|
class Body(base.Value):
|
2015-05-02 09:42:09 +00:00
|
|
|
preamble = "b"
|
|
|
|
|
|
|
|
|
2015-05-17 03:38:13 +00:00
|
|
|
class RawBody(base.Value):
|
|
|
|
unique_name = "Body"
|
|
|
|
preamble = "r"
|
|
|
|
|
|
|
|
|
2015-05-03 22:48:35 +00:00
|
|
|
class Fin(base.Boolean):
|
|
|
|
name = "fin"
|
|
|
|
|
|
|
|
|
|
|
|
class RSV1(base.Boolean):
|
|
|
|
name = "rsv1"
|
|
|
|
|
|
|
|
|
|
|
|
class RSV2(base.Boolean):
|
|
|
|
name = "rsv2"
|
|
|
|
|
|
|
|
|
|
|
|
class RSV3(base.Boolean):
|
|
|
|
name = "rsv3"
|
|
|
|
|
|
|
|
|
|
|
|
class Mask(base.Boolean):
|
|
|
|
name = "mask"
|
|
|
|
|
|
|
|
|
2015-05-15 21:42:47 +00:00
|
|
|
class Key(base.FixedLengthValue):
|
|
|
|
preamble = "k"
|
|
|
|
length = 4
|
|
|
|
|
|
|
|
|
2015-05-16 23:04:53 +00:00
|
|
|
class KeyNone(base.CaselessLiteral):
|
|
|
|
unique_name = "Key"
|
|
|
|
TOK = "knone"
|
|
|
|
|
|
|
|
|
2015-05-16 23:31:02 +00:00
|
|
|
class Length(base.Integer):
|
2015-05-17 03:38:13 +00:00
|
|
|
bounds = (0, 1 << 64)
|
2015-05-16 23:31:02 +00:00
|
|
|
preamble = "l"
|
|
|
|
|
|
|
|
|
2015-05-17 03:38:13 +00:00
|
|
|
class Times(base.Integer):
|
|
|
|
preamble = "x"
|
|
|
|
|
|
|
|
|
2015-05-02 20:02:13 +00:00
|
|
|
class WebsocketFrame(message.Message):
|
2015-05-02 04:17:00 +00:00
|
|
|
comps = (
|
2015-05-03 22:48:35 +00:00
|
|
|
OpCode,
|
2015-05-16 23:31:02 +00:00
|
|
|
Length,
|
2015-05-03 22:48:35 +00:00
|
|
|
# Bit flags
|
|
|
|
Fin,
|
|
|
|
RSV1,
|
|
|
|
RSV2,
|
|
|
|
RSV3,
|
|
|
|
Mask,
|
2015-05-02 20:02:13 +00:00
|
|
|
actions.PauseAt,
|
|
|
|
actions.DisconnectAt,
|
2015-05-03 22:48:35 +00:00
|
|
|
actions.InjectAt,
|
2015-05-16 23:04:53 +00:00
|
|
|
KeyNone,
|
2015-05-15 21:42:47 +00:00
|
|
|
Key,
|
2015-05-17 03:38:13 +00:00
|
|
|
Times,
|
|
|
|
|
|
|
|
Body,
|
|
|
|
RawBody,
|
2015-05-02 04:17:00 +00:00
|
|
|
)
|
|
|
|
logattrs = ["body"]
|
2015-05-02 20:02:13 +00:00
|
|
|
@property
|
|
|
|
def actions(self):
|
|
|
|
return self.toks(actions._Action)
|
2015-05-02 04:17:00 +00:00
|
|
|
|
2015-05-02 09:42:09 +00:00
|
|
|
@property
|
|
|
|
def body(self):
|
|
|
|
return self.tok(Body)
|
|
|
|
|
2015-05-17 03:38:13 +00:00
|
|
|
@property
|
|
|
|
def rawbody(self):
|
|
|
|
return self.tok(RawBody)
|
|
|
|
|
2015-05-03 01:54:52 +00:00
|
|
|
@property
|
2015-05-03 22:48:35 +00:00
|
|
|
def opcode(self):
|
|
|
|
return self.tok(OpCode)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def fin(self):
|
|
|
|
return self.tok(Fin)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def rsv1(self):
|
|
|
|
return self.tok(RSV1)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def rsv2(self):
|
|
|
|
return self.tok(RSV2)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def rsv3(self):
|
|
|
|
return self.tok(RSV3)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def mask(self):
|
|
|
|
return self.tok(Mask)
|
2015-05-03 01:54:52 +00:00
|
|
|
|
2015-05-15 23:31:53 +00:00
|
|
|
@property
|
|
|
|
def key(self):
|
|
|
|
return self.tok(Key)
|
|
|
|
|
2015-05-16 23:04:53 +00:00
|
|
|
@property
|
|
|
|
def knone(self):
|
|
|
|
return self.tok(KeyNone)
|
|
|
|
|
2015-05-17 03:49:16 +00:00
|
|
|
@property
|
|
|
|
def times(self):
|
|
|
|
return self.tok(Times)
|
|
|
|
|
2015-05-16 23:31:02 +00:00
|
|
|
@property
|
|
|
|
def toklength(self):
|
|
|
|
return self.tok(Length)
|
|
|
|
|
2015-05-02 04:17:00 +00:00
|
|
|
@classmethod
|
|
|
|
def expr(klass):
|
|
|
|
parts = [i.expr() for i in klass.comps]
|
|
|
|
atom = pp.MatchFirst(parts)
|
|
|
|
resp = pp.And(
|
|
|
|
[
|
2015-05-02 09:27:11 +00:00
|
|
|
WF.expr(),
|
2015-05-02 04:17:00 +00:00
|
|
|
base.Sep,
|
|
|
|
pp.ZeroOrMore(base.Sep + atom)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
resp = resp.setParseAction(klass)
|
|
|
|
return resp
|
|
|
|
|
2015-05-15 23:31:53 +00:00
|
|
|
def resolve(self, settings, msg=None):
|
|
|
|
tokens = self.tokens[:]
|
|
|
|
if not self.mask and settings.is_client:
|
|
|
|
tokens.append(
|
|
|
|
Mask(True)
|
|
|
|
)
|
2015-05-16 23:04:53 +00:00
|
|
|
if not self.knone and self.mask and self.mask.value and not self.key:
|
2015-05-15 23:31:53 +00:00
|
|
|
tokens.append(
|
|
|
|
Key(base.TokValueLiteral(os.urandom(4)))
|
|
|
|
)
|
|
|
|
return self.__class__(
|
|
|
|
[i.resolve(settings, self) for i in tokens]
|
|
|
|
)
|
|
|
|
|
2015-05-02 04:17:00 +00:00
|
|
|
def values(self, settings):
|
|
|
|
if self.body:
|
|
|
|
bodygen = self.body.value.get_generator(settings)
|
|
|
|
length = len(self.body.value.get_generator(settings))
|
2015-05-17 03:38:13 +00:00
|
|
|
elif self.rawbody:
|
|
|
|
bodygen = self.rawbody.value.get_generator(settings)
|
|
|
|
length = len(self.rawbody.value.get_generator(settings))
|
2015-05-02 04:17:00 +00:00
|
|
|
else:
|
|
|
|
bodygen = None
|
|
|
|
length = 0
|
2015-05-16 23:31:02 +00:00
|
|
|
if self.toklength:
|
|
|
|
length = int(self.toklength.value)
|
2015-05-03 01:54:52 +00:00
|
|
|
frameparts = dict(
|
2015-05-02 04:17:00 +00:00
|
|
|
payload_length = length
|
|
|
|
)
|
2015-05-15 23:31:53 +00:00
|
|
|
if self.mask and self.mask.value:
|
|
|
|
frameparts["mask"] = True
|
2015-05-16 23:04:53 +00:00
|
|
|
if self.knone:
|
|
|
|
frameparts["masking_key"] = None
|
|
|
|
elif self.key:
|
2015-05-15 23:31:53 +00:00
|
|
|
key = self.key.values(settings)[0][:]
|
|
|
|
frameparts["masking_key"] = key
|
2015-05-03 22:48:35 +00:00
|
|
|
for i in ["opcode", "fin", "rsv1", "rsv2", "rsv3", "mask"]:
|
|
|
|
v = getattr(self, i, None)
|
|
|
|
if v is not None:
|
|
|
|
frameparts[i] = v.value
|
2015-05-03 01:54:52 +00:00
|
|
|
frame = netlib.websockets.FrameHeader(**frameparts)
|
2015-05-02 04:17:00 +00:00
|
|
|
vals = [frame.to_bytes()]
|
2015-05-15 23:31:53 +00:00
|
|
|
if bodygen:
|
2015-05-17 03:38:13 +00:00
|
|
|
if frame.masking_key and not self.rawbody:
|
2015-05-15 23:31:53 +00:00
|
|
|
masker = netlib.websockets.Masker(frame.masking_key)
|
|
|
|
vals.append(
|
|
|
|
generators.TransformGenerator(
|
|
|
|
bodygen,
|
|
|
|
masker.mask
|
|
|
|
)
|
2015-05-02 04:17:00 +00:00
|
|
|
)
|
2015-05-15 23:31:53 +00:00
|
|
|
else:
|
|
|
|
vals.append(bodygen)
|
2015-05-02 04:17:00 +00:00
|
|
|
return vals
|
|
|
|
|
|
|
|
def spec(self):
|
|
|
|
return ":".join([i.spec() for i in self.tokens])
|