Browse Source

Merge pull request #888 from paullouisageneau/move-http-utils

Move HTTP utils to their own file
Paul-Louis Ageneau 2 years ago
parent
commit
0abde70beb
7 changed files with 113 additions and 73 deletions
  1. 2 0
      CMakeLists.txt
  2. 66 0
      src/impl/http.cpp
  3. 30 0
      src/impl/http.hpp
  4. 2 2
      src/impl/httpproxytransport.cpp
  5. 4 55
      src/impl/utils.cpp
  6. 3 11
      src/impl/utils.hpp
  7. 6 5
      src/impl/wshandshake.cpp

+ 2 - 0
CMakeLists.txt

@@ -136,6 +136,7 @@ set(LIBDATACHANNEL_IMPL_SOURCES
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/sha.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/pollinterrupter.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/pollservice.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/http.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/httpproxytransport.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/tcpserver.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/tcptransport.cpp
@@ -169,6 +170,7 @@ set(LIBDATACHANNEL_IMPL_HEADERS
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/sha.hpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/pollinterrupter.hpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/pollservice.hpp
+	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/http.hpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/httpproxytransport.hpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/tcpserver.hpp
 	${CMAKE_CURRENT_SOURCE_DIR}/src/impl/tcptransport.hpp

+ 66 - 0
src/impl/http.cpp

@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2020-2023 Paul-Louis Ageneau
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include "http.hpp"
+
+#include <algorithm>
+
+namespace rtc::impl {
+
+bool isHttpRequest(const byte *buffer, size_t size) {
+	// Check the buffer starts with a valid-looking HTTP method
+	for (size_t i = 0; i < size; ++i) {
+		char c = static_cast<char>(buffer[i]);
+		if (i > 0 && c == ' ')
+			break;
+		else if (i >= 8 || c < 'A' || c > 'Z')
+			return false;
+	}
+	return true;
+}
+
+size_t parseHttpLines(const byte *buffer, size_t size, std::list<string> &lines) {
+	lines.clear();
+	auto begin = reinterpret_cast<const char *>(buffer);
+	auto end = begin + size;
+	auto cur = begin;
+	while (true) {
+		auto last = cur;
+		cur = std::find(cur, end, '\n');
+		if (cur == end)
+			return 0;
+		string line(last, cur != begin && *std::prev(cur) == '\r' ? std::prev(cur++) : cur++);
+		if (line.empty())
+			break;
+		lines.emplace_back(std::move(line));
+	}
+
+	return cur - begin;
+}
+
+std::multimap<string, string> parseHttpHeaders(const std::list<string> &lines) {
+	std::multimap<string, string> headers;
+	for (const auto &line : lines) {
+		if (size_t pos = line.find_first_of(':'); pos != string::npos) {
+			string key = line.substr(0, pos);
+			string value = "";
+			if (size_t subPos = line.find_first_not_of(' ', pos + 1); subPos != string::npos) {
+				value = line.substr(subPos);
+			}
+			std::transform(key.begin(), key.end(), key.begin(),
+			               [](char c) { return std::tolower(c); });
+			headers.emplace(std::move(key), std::move(value));
+		} else {
+			headers.emplace(line, "");
+		}
+	}
+
+	return headers;
+}
+
+} // namespace rtc::impl

+ 30 - 0
src/impl/http.hpp

@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2020-2023 Paul-Louis Ageneau
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef RTC_IMPL_HTTP_H
+#define RTC_IMPL_HTTP_H
+
+#include "common.hpp"
+
+#include <list>
+#include <map>
+
+namespace rtc::impl {
+
+// Check the buffer contains the beginning of an HTTP request
+bool isHttpRequest(const byte *buffer, size_t size);
+
+// Parse an http message into lines
+size_t parseHttpLines(const byte *buffer, size_t size, std::list<string> &lines);
+
+// Parse headers of a http message
+std::multimap<string, string> parseHttpHeaders(const std::list<string> &lines);
+
+} // namespace rtc::impl
+
+#endif

+ 2 - 2
src/impl/httpproxytransport.cpp

@@ -9,7 +9,7 @@
 
 #include "httpproxytransport.hpp"
 #include "tcptransport.hpp"
-#include "utils.hpp"
+#include "http.hpp"
 
 #if RTC_ENABLE_WEBSOCKET
 
@@ -103,7 +103,7 @@ string HttpProxyTransport::generateHttpRequest() {
 
 size_t HttpProxyTransport::parseHttpResponse(std::byte *buffer, size_t size) {
 	std::list<string> lines;
-	size_t length = utils::parseHttpLines(buffer, size, lines);
+	size_t length = parseHttpLines(buffer, size, lines);
 	if (length == 0)
 		return 0;
 

+ 4 - 55
src/impl/utils.cpp

@@ -135,57 +135,6 @@ std::seed_seq random_seed() {
 	return std::seed_seq(seed.begin(), seed.end());
 }
 
-bool IsHttpRequest(const byte *buffer, size_t size) {
-	// Check the buffer starts with a valid-looking HTTP method
-	for (size_t i = 0; i < size; ++i) {
-		char c = static_cast<char>(buffer[i]);
-		if (i > 0 && c == ' ')
-			break;
-		else if (i >= 8 || c < 'A' || c > 'Z')
-			return false;
-	}
-	return true;
-}
-
-size_t parseHttpLines(const byte *buffer, size_t size, std::list<string> &lines) {
-	lines.clear();
-	auto begin = reinterpret_cast<const char *>(buffer);
-	auto end = begin + size;
-	auto cur = begin;
-	while (true) {
-		auto last = cur;
-		cur = std::find(cur, end, '\n');
-		if (cur == end)
-			return 0;
-		string line(last, cur != begin && *std::prev(cur) == '\r' ? std::prev(cur++) : cur++);
-		if (line.empty())
-			break;
-		lines.emplace_back(std::move(line));
-	}
-
-	return cur - begin;
-}
-
-std::multimap<string, string> parseHttpHeaders(const std::list<string> &lines) {
-	std::multimap<string, string> headers;
-	for (const auto &line : lines) {
-		if (size_t pos = line.find_first_of(':'); pos != string::npos) {
-			string key = line.substr(0, pos);
-			string value = "";
-			if (size_t subPos = line.find_first_not_of(' ', pos + 1); subPos != string::npos) {
-				value = line.substr(subPos);
-			}
-			std::transform(key.begin(), key.end(), key.begin(),
-			               [](char c) { return std::tolower(c); });
-			headers.emplace(std::move(key), std::move(value));
-		} else {
-			headers.emplace(line, "");
-		}
-	}
-
-	return headers;
-}
-
 namespace {
 
 void thread_set_name_self(const char *name) {
@@ -205,9 +154,9 @@ void thread_set_name_self(const char *name) {
 } // namespace
 
 namespace this_thread {
-	void set_name(const string &name) {
-		thread_set_name_self(name.c_str());
-	}
-}
+
+void set_name(const string &name) { thread_set_name_self(name.c_str()); }
+
+} // namespace this_thread
 
 } // namespace rtc::impl::utils

+ 3 - 11
src/impl/utils.hpp

@@ -13,7 +13,6 @@
 
 #include <climits>
 #include <limits>
-#include <list>
 #include <map>
 #include <random>
 #include <vector>
@@ -34,15 +33,6 @@ string base64_encode(const binary &data);
 // Return a random seed sequence
 std::seed_seq random_seed();
 
-// Check the buffer contains the beginning of an HTTP request
-bool IsHttpRequest(const byte *buffer, size_t size);
-
-// Parse an http message into lines
-size_t parseHttpLines(const byte *buffer, size_t size, std::list<string> &lines);
-
-// Parse headers of a http message
-std::multimap<string, string> parseHttpHeaders(const std::list<string> &lines);
-
 template <typename Generator, typename Result = typename Generator::result_type>
 struct random_engine_wrapper {
 	Generator &engine;
@@ -71,8 +61,10 @@ template <typename Generator = std::mt19937> auto random_bytes_engine() {
 }
 
 namespace this_thread {
+
 void set_name(const string &name);
-}
+
+} // namespace this_thread
 
 } // namespace rtc::impl::utils
 

+ 6 - 5
src/impl/wshandshake.cpp

@@ -10,6 +10,7 @@
 #include "internals.hpp"
 #include "sha.hpp"
 #include "utils.hpp"
+#include "http.hpp"
 
 #if RTC_ENABLE_WEBSOCKET
 
@@ -131,12 +132,12 @@ string WsHandshake::generateHttpError(int responseCode) {
 }
 
 size_t WsHandshake::parseHttpRequest(const byte *buffer, size_t size) {
-	if (!utils::IsHttpRequest(buffer, size))
+	if (!isHttpRequest(buffer, size))
 		throw RequestError("Invalid HTTP request for WebSocket", 400);
 
 	std::unique_lock lock(mMutex);
 	std::list<string> lines;
-	size_t length = utils::parseHttpLines(buffer, size, lines);
+	size_t length = parseHttpLines(buffer, size, lines);
 	if (length == 0)
 		return 0;
 
@@ -154,7 +155,7 @@ size_t WsHandshake::parseHttpRequest(const byte *buffer, size_t size) {
 
 	mPath = std::move(path);
 
-	auto headers = utils::parseHttpHeaders(lines);
+	auto headers = parseHttpHeaders(lines);
 
 	auto h = headers.find("host");
 	if (h == headers.end())
@@ -188,7 +189,7 @@ size_t WsHandshake::parseHttpRequest(const byte *buffer, size_t size) {
 size_t WsHandshake::parseHttpResponse(const byte *buffer, size_t size) {
 	std::unique_lock lock(mMutex);
 	std::list<string> lines;
-	size_t length = utils::parseHttpLines(buffer, size, lines);
+	size_t length = parseHttpLines(buffer, size, lines);
 	if (length == 0)
 		return 0;
 
@@ -205,7 +206,7 @@ size_t WsHandshake::parseHttpResponse(const byte *buffer, size_t size) {
 	if (code != 101)
 		throw std::runtime_error("Unexpected response code " + to_string(code) + " for WebSocket");
 
-	auto headers = utils::parseHttpHeaders(lines);
+	auto headers = parseHttpHeaders(lines);
 
 	auto h = headers.find("upgrade");
 	if (h == headers.end())