aboutsummaryrefslogtreecommitdiffstats
path: root/libpathod/language/__init__.py
blob: 3cc7dfbe20802b4182879c72d9c67ad7630099d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import time

import pyparsing as pp

from . import base, http, websockets, writer, exceptions

from exceptions import *
from base import Settings
assert Settings  # prevent pyflakes from messing with this


def parse_response(s):
    """
        May raise ParseException
    """
    try:
        s = s.decode("ascii")
    except UnicodeError:
        raise exceptions.ParseException("Spec must be valid ASCII.", 0, 0)
    try:
        return http.Response.expr().parseString(s, parseAll=True)[0]
    except pp.ParseException as v:
        raise exceptions.ParseException(v.msg, v.line, v.col)


def parse_requests(s):
    """
        May raise ParseException
    """
    try:
        s = s.decode("ascii")
    except UnicodeError:
        raise exceptions.ParseException("Spec must be valid ASCII.", 0, 0)
    try:
        reqs = pp.OneOrMore(
            pp.Or(
                [
                    websockets.WebsocketFrame.expr(),
                    http.Request.expr(),
                ]
            )
        ).parseString(s, parseAll=True)
    except pp.ParseException as v:
        raise exceptions.ParseException(v.msg, v.line, v.col)
    expanded = []
    for i in reqs:
        if i.times:
            for j in range(int(i.times.value)):
                expanded.append(i.strike_token("times"))
        else:
            expanded.append(i)
    return expanded


def serve(msg, fp, settings):
    """
        fp: The file pointer to write to.

        request_host: If this a request, this is the connecting host. If
        None, we assume it's a response. Used to decide what standard
        modifications to make if raw is not set.

        Calling this function may modify the object.
    """
    msg = msg.resolve(settings)
    started = time.time()

    vals = msg.values(settings)
    vals.reverse()

    actions = sorted(msg.actions[:])
    actions.reverse()
    actions = [i.intermediate(settings) for i in actions]

    disconnect = writer.write_values(fp, vals, actions[:])
    duration = time.time() - started
    ret = dict(
        disconnect = disconnect,
        started = started,
        duration = duration,
    )
    ret.update(msg.log(settings))
    return ret