File Coverage

src/panda/protocol/websocket/ConnectResponse.cc
Criterion Covered Total %
statement 40 40 100.0
branch 64 120 53.3
condition n/a
subroutine n/a
pod n/a
total 104 160 65.0


line stmt bran cond sub pod time code
1             #include "ConnectResponse.h"
2             #include "Error.h"
3             #include "utils.h"
4             #include
5             #include
6              
7             namespace panda { namespace protocol { namespace websocket {
8              
9 90           void ConnectResponse::process_headers () {
10 90 100         if (code == 426) {
11 2 50         _ws_version = headers.get("Sec-WebSocket-Version");
    50          
12 2           error = errc::unsupported_version;
13 90           return;
14             }
15              
16 88 100         if (code != 101) {
17 1           error = errc::response_code_101;
18 1           return;
19             }
20              
21 87 50         auto it = headers.find("Connection");
22 261 50         if (it == headers.end() || !string_contains_ci(it->value, "upgrade")) {
    50          
    100          
    50          
    50          
    100          
    0          
    0          
23 1           error = errc::connection_mustbe_upgrade;
24 1           return;
25             }
26              
27 86 50         it = headers.find("Upgrade");
28 258 50         if (it == headers.end() || !string_contains_ci(it->value, "websocket")) {
    50          
    100          
    50          
    50          
    100          
    0          
    0          
29 1           error = errc::upgrade_mustbe_websocket;
30 1           return;
31             }
32              
33 85 50         it = headers.find("Sec-WebSocket-Accept");
34 255 50         if (it == headers.end() || it->value != _calc_accept_key(_ws_key)) {
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    100          
    0          
    0          
    0          
35 1           error = errc::sec_accept_missing;
36 1           return;
37             }
38 84 50         else _ws_accept_key = it->value;
39              
40              
41 84 50         auto ext_range = headers.get_multi("Sec-WebSocket-Extensions");
42 149 50         for (auto& val : ext_range) {
    50          
    50          
    100          
    50          
    50          
43 65 50         parse_header_value(val, _ws_extensions);
44             }
45              
46 84 50         ws_protocol = headers.get("Sec-WebSocket-Protocol");
    50          
47             }
48              
49 313           string ConnectResponse::_calc_accept_key (string ws_key) {
50 626 50         auto key_base = ws_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
51             unsigned char sha1bin[21];
52 313 50         SHA1((const unsigned char*)key_base.data(), key_base.length(), sha1bin);
53 626 50         return panda::encode::encode_base64(string_view((const char*)sha1bin, 20), false, true);
54             }
55              
56 228           string ConnectResponse::to_string() {
57 228           code = 101;
58 228           message = "Switching Protocols";
59 228 50         headers.add("Upgrade", "websocket");
60 228 50         headers.add("Connection", "Upgrade");
61              
62 228 100         if (ws_protocol) headers.add("Sec-WebSocket-Protocol", ws_protocol);
    50          
63              
64 228 50         headers.add("Sec-WebSocket-Accept", _calc_accept_key(_ws_key));
    50          
65 228 50         if (!headers.has("Server")) headers.add("Server", "Panda-WebSocket");
    50          
    50          
66              
67 228 100         if (_ws_extensions.size()) headers.add("Sec-WebSocket-Extensions", compile_header_value(_ws_extensions));
    50          
68              
69 228           body.parts.clear(); // body not supported in WS responses
70              
71 228           return http::Response::to_string();
72             }
73              
74             }}}