line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "ServerParser.h" |
2
|
|
|
|
|
|
|
#include |
3
|
|
|
|
|
|
|
#include |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
namespace panda { namespace protocol { namespace websocket { |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
struct RequestFactory : http::RequestParser::IFactory { |
8
|
244
|
|
|
|
|
|
http::RequestSP new_request () override { |
9
|
244
|
|
|
|
|
|
return make_iptr(); |
10
|
|
|
|
|
|
|
} |
11
|
|
|
|
|
|
|
}; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
static RequestFactory request_factory; |
14
|
|
|
|
|
|
|
|
15
|
238
|
50
|
|
|
|
|
ServerParser::ServerParser (const Parser::Config& cfg) : Parser(true, cfg), _connect_parser(&request_factory) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
16
|
119
|
|
|
|
|
|
_connect_parser.max_body_size = 0; |
17
|
119
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
316
|
|
|
|
|
|
ConnectRequestSP ServerParser::accept (string& buf) { |
20
|
316
|
50
|
|
|
|
|
if (_flags[ACCEPT_PARSED]) throw Error("already parsed accept"); |
21
|
316
|
|
|
|
|
|
_connect_parser.max_headers_size = _max_handshake_size; |
22
|
|
|
|
|
|
|
|
23
|
632
|
50
|
|
|
|
|
http::RequestParser::Result res = _connect_parser.parse(buf); |
24
|
316
|
50
|
|
|
|
|
_connect_request = dynamic_pointer_cast(res.request); |
25
|
|
|
|
|
|
|
|
26
|
316
|
100
|
|
|
|
|
if (res.error) { |
27
|
3
|
50
|
|
|
|
|
_flags.set(ACCEPT_PARSED); |
28
|
3
|
50
|
|
|
|
|
_connect_request->error = res.error; |
29
|
3
|
|
|
|
|
|
return _connect_request; |
30
|
313
|
100
|
|
|
|
|
} else if (res.state != http::State::done) { |
31
|
72
|
|
|
|
|
|
return nullptr; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
241
|
50
|
|
|
|
|
_connect_request->process_headers(); |
35
|
241
|
50
|
|
|
|
|
_flags.set(ACCEPT_PARSED); |
36
|
|
|
|
|
|
|
|
37
|
241
|
100
|
|
|
|
|
if (!_connect_request->error) { |
38
|
235
|
50
|
|
|
|
|
if (res.position != buf.size()) { |
39
|
0
|
|
|
|
|
|
_connect_request->error = errc::garbage_after_connect; |
40
|
|
|
|
|
|
|
} else { |
41
|
235
|
50
|
|
|
|
|
_flags.set(ACCEPTED); |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
241
|
|
|
|
|
|
return _connect_request; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
7
|
|
|
|
|
|
string ServerParser::accept_error () { |
49
|
7
|
50
|
|
|
|
|
if (!_flags[ACCEPT_PARSED]) throw Error("accept not parsed yet"); |
50
|
7
|
50
|
|
|
|
|
if (established()) throw Error("already established"); |
51
|
7
|
50
|
|
|
|
|
if (!_connect_request->error) throw Error("no errors found"); |
52
|
|
|
|
|
|
|
|
53
|
14
|
50
|
|
|
|
|
http::ResponseSP res = new http::Response(); |
|
|
50
|
|
|
|
|
|
54
|
7
|
50
|
|
|
|
|
res->headers.add("Content-Type", "text/plain"); |
55
|
|
|
|
|
|
|
|
56
|
7
|
100
|
|
|
|
|
if (!_connect_request->ws_version_supported()) { |
57
|
3
|
|
|
|
|
|
res->code = 426; |
58
|
3
|
50
|
|
|
|
|
res->message = "Upgrade Required"; |
59
|
6
|
|
|
|
|
|
res->body.parts.push_back("426 Upgrade Required"); |
60
|
|
|
|
|
|
|
|
61
|
6
|
50
|
|
|
|
|
string svers(50); |
62
|
6
|
100
|
|
|
|
|
for (int v : supported_ws_versions) { |
63
|
3
|
50
|
|
|
|
|
svers += string::from_number(v); |
|
|
50
|
|
|
|
|
|
64
|
3
|
50
|
|
|
|
|
svers += ", "; |
65
|
|
|
|
|
|
|
} |
66
|
3
|
50
|
|
|
|
|
if (svers) svers.length(svers.length()-2); |
67
|
3
|
50
|
|
|
|
|
res->headers.add("Sec-WebSocket-Version", svers); |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
else { |
70
|
4
|
|
|
|
|
|
res->code = 400; |
71
|
4
|
50
|
|
|
|
|
res->message = "Bad Request"; |
72
|
8
|
|
|
|
|
|
res->body.parts.push_back("400 Bad Request\n"); |
73
|
8
|
50
|
|
|
|
|
res->body.parts.push_back(_connect_request->error.what()); |
74
|
|
|
|
|
|
|
} |
75
|
7
|
50
|
|
|
|
|
res->headers.set("Content-Length", panda::to_string(res->body.length())); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
14
|
50
|
|
|
|
|
return res->to_string(_connect_request); |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
3
|
|
|
|
|
|
string ServerParser::accept_error (http::Response* res) { |
81
|
3
|
50
|
|
|
|
|
if (!_flags[ACCEPT_PARSED]) throw Error("accept not parsed yet"); |
82
|
3
|
50
|
|
|
|
|
if (established()) throw Error("already established"); |
83
|
3
|
100
|
|
|
|
|
if (_connect_request->error) return accept_error(); |
84
|
|
|
|
|
|
|
|
85
|
2
|
50
|
|
|
|
|
if (!res->code) { |
86
|
0
|
|
|
|
|
|
res->code = 400; |
87
|
0
|
|
|
|
|
|
res->message = "Bad Request"; |
88
|
|
|
|
|
|
|
} |
89
|
2
|
50
|
|
|
|
|
else if (!res->message) res->message = "Unknown"; |
90
|
|
|
|
|
|
|
|
91
|
2
|
100
|
|
|
|
|
if (res->body.empty()) { |
92
|
2
|
50
|
|
|
|
|
res->body.parts.push_back(string::from_number(res->code) + ' ' + res->message); |
|
|
50
|
|
|
|
|
|
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
2
|
50
|
|
|
|
|
if (!res->headers.has("Content-Type")) res->headers.add("Content-Type", "text/plain"); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
96
|
2
|
50
|
|
|
|
|
if (!res->headers.has("Content-Length")) res->headers.add("Content-Length", panda::to_string(res->body.length())); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
3
|
|
|
|
|
|
return res->to_string(_connect_request); |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
228
|
|
|
|
|
|
string ServerParser::accept_response (ConnectResponse* res) { |
102
|
228
|
50
|
|
|
|
|
if (!accepted()) throw Error("client has not been accepted"); |
103
|
228
|
50
|
|
|
|
|
if (established()) throw Error("already established"); |
104
|
|
|
|
|
|
|
|
105
|
228
|
50
|
|
|
|
|
res->_ws_key = _connect_request->ws_key; |
106
|
228
|
100
|
|
|
|
|
if (!res->ws_protocol) res->ws_protocol = _connect_request->ws_protocol; |
|
|
50
|
|
|
|
|
|
107
|
228
|
100
|
|
|
|
|
if (!res->ws_extensions_set()) res->ws_extensions(_connect_request->ws_extensions()); |
|
|
50
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
109
|
228
|
|
|
|
|
|
const auto& exts = res->ws_extensions(); |
110
|
456
|
|
|
|
|
|
HeaderValues used_extensions; |
111
|
228
|
100
|
|
|
|
|
if (_deflate_cfg && exts.size()) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
112
|
|
|
|
|
|
|
// filter extensions |
113
|
87
|
|
|
|
|
|
auto role = DeflateExt::Role::SERVER; |
114
|
87
|
50
|
|
|
|
|
auto deflate_matches = DeflateExt::select(exts, *_deflate_cfg, role); |
115
|
87
|
100
|
|
|
|
|
if (deflate_matches) { |
116
|
87
|
50
|
|
|
|
|
_deflate_ext.reset(DeflateExt::uplift(deflate_matches, used_extensions, role)); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
} |
119
|
228
|
50
|
|
|
|
|
res->ws_extensions(std::move(used_extensions)); |
120
|
|
|
|
|
|
|
|
121
|
228
|
50
|
|
|
|
|
_flags.set(ESTABLISHED); |
122
|
228
|
|
|
|
|
|
_connect_request = NULL; |
123
|
456
|
50
|
|
|
|
|
return res->to_string(); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
131
|
|
|
|
|
|
void ServerParser::reset () { |
127
|
131
|
|
|
|
|
|
_connect_request = NULL; |
128
|
131
|
|
|
|
|
|
_connect_parser.reset(); |
129
|
131
|
|
|
|
|
|
Parser::reset(); |
130
|
131
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
432
|
50
|
|
|
|
|
ServerParser::~ServerParser() {} |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
}}} |