class HTTPResponse(schema.BinarySchema): head = schema.EndWith(b"\r\n\r\n") def __post_init__(self): first_line, *header_lines = self.head.split(b"\r\n") self.ver, self.code, *status = first_line.split(None, 2) self.status = status[0] if status else b"" self.header_lines = header_lines
class HTTPRequest(schema.BinarySchema): head = schema.EndWith(b"\r\n\r\n") def __post_init__(self): first_line, *header_lines = self.head.split(b"\r\n") self.method, self.path, self.ver = HTTP_LINE.fullmatch( first_line).groups() self.headers = dict([line.split(b": ", 1) for line in header_lines])
class ClientRequest(schema.BinarySchema): ver = schema.MustEqual(schema.uint8, 4) cmd = schema.SizedIntEnum(schema.uint8, Cmd) dst_port = schema.uint16be dst_ip = schema.Convert(schema.Bytes(4), encode=socket.inet_aton, decode=socket.inet_ntoa) user_id = schema.EndWith(b"\x00")
def test_schema(): G = schema.Group(a=schema.uint8, b=schema.int32) Dynamic = schema.Group( a=schema.LengthPrefixedBytes(schema.uint24be), b=schema.LengthPrefixedObject(schema.uint32, schema.EndWith(b"\n")), c=schema.LengthPrefixedObjectList(schema.uint16, schema.String(3)), d=schema.LengthPrefixedObjectList(schema.uint64, G), ) dynamic = Dynamic(b"abc", b"def", ["123", "456"], [G(3, 5), G(6, 10)]) check_schema(dynamic)
class Content(schema.BinarySchema): first_line = schema.EndWith(b"\r\n") string = schema.String(5, encoding="ascii")
dst_ip = schema.Convert(schema.Bytes(4), encode=socket.inet_aton, decode=socket.inet_ntoa) user_id = schema.EndWith(b"\x00") class Response(schema.BinarySchema): vn = schema.MustEqual(schema.Bytes(1), b"\x00") rep = schema.SizedIntEnum(schema.uint8, Rep) dst_port = schema.uint16be dst_ip = schema.Convert(schema.Bytes(4), encode=socket.inet_aton, decode=socket.inet_ntoa) domain = schema.EndWith(b"\x00") @iofree.parser def server(): parser = yield from iofree.get_parser() request = yield from ClientRequest.get_value() if request.dst_ip.startswith("0.0.0"): host = yield from domain.get_value() addr = (host, request.dst_port) else: addr = (request.dst_ip, request.dst_port) assert request.cmd is Cmd.connect parser.respond(result=addr) rep = yield from iofree.wait_event() parser.respond(data=Response(..., Rep(rep), 0, "0.0.0.0").binary)