| 159 | } |
| 160 | |
| 161 | bool WSLPeer::_parse_client_request() { |
| 162 | Vector<String> psa = String::ascii(Span((const char *)handshake_buffer->get_data_array().ptr(), handshake_buffer->get_position() - 4)).split("\r\n"); |
| 163 | int len = psa.size(); |
| 164 | ERR_FAIL_COND_V_MSG(len < 4, false, "Not enough response headers, got: " + itos(len) + ", expected >= 4."); |
| 165 | |
| 166 | Vector<String> req = psa[0].split(" ", false); |
| 167 | ERR_FAIL_COND_V_MSG(req.size() < 2, false, "Invalid protocol or status code."); |
| 168 | |
| 169 | // Wrong protocol |
| 170 | ERR_FAIL_COND_V_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", false, "Invalid method or HTTP version."); |
| 171 | |
| 172 | HashMap<String, String> headers; |
| 173 | for (int i = 1; i < len; i++) { |
| 174 | Vector<String> header = psa[i].split(":", false, 1); |
| 175 | ERR_FAIL_COND_V_MSG(header.size() != 2, false, "Invalid header -> " + psa[i]); |
| 176 | String name = header[0].to_lower(); |
| 177 | String value = header[1].strip_edges(); |
| 178 | if (headers.has(name)) { |
| 179 | headers[name] += "," + value; |
| 180 | } else { |
| 181 | headers[name] = value; |
| 182 | } |
| 183 | } |
| 184 | requested_host = headers.has("host") ? headers.get("host") : ""; |
| 185 | requested_url = (use_tls ? "wss://" : "ws://") + requested_host + req[1]; |
| 186 | #define WSL_CHECK(NAME, VALUE) \ |
| 187 | ERR_FAIL_COND_V_MSG(!headers.has(NAME) || headers[NAME].to_lower() != VALUE, false, \ |
| 188 | "Missing or invalid header '" + String(NAME) + "'. Expected value '" + VALUE + "'."); |
| 189 | #define WSL_CHECK_EX(NAME) \ |
| 190 | ERR_FAIL_COND_V_MSG(!headers.has(NAME), false, "Missing header '" + String(NAME) + "'."); |
| 191 | WSL_CHECK("upgrade", "websocket"); |
| 192 | WSL_CHECK("sec-websocket-version", "13"); |
| 193 | WSL_CHECK_EX("sec-websocket-key"); |
| 194 | WSL_CHECK_EX("connection"); |
| 195 | #undef WSL_CHECK_EX |
| 196 | #undef WSL_CHECK |
| 197 | session_key = headers["sec-websocket-key"]; |
| 198 | if (headers.has("sec-websocket-protocol")) { |
| 199 | Vector<String> protos = headers["sec-websocket-protocol"].split(","); |
| 200 | for (int i = 0; i < protos.size(); i++) { |
| 201 | String proto = protos[i].strip_edges(); |
| 202 | // Check if we have the given protocol |
| 203 | for (int j = 0; j < supported_protocols.size(); j++) { |
| 204 | if (proto != supported_protocols[j]) { |
| 205 | continue; |
| 206 | } |
| 207 | selected_protocol = proto; |
| 208 | break; |
| 209 | } |
| 210 | // Found a protocol |
| 211 | if (!selected_protocol.is_empty()) { |
| 212 | break; |
| 213 | } |
| 214 | } |
| 215 | if (selected_protocol.is_empty()) { // Invalid protocol(s) requested |
| 216 | return false; |
| 217 | } |
| 218 | } else if (supported_protocols.size() > 0) { // No protocol requested, but we need one |
nothing calls this directly
no test coverage detected