From 5c34eda7b4f807720adf89f052fb0726f2a798fb Mon Sep 17 00:00:00 2001 From: ksenonadv Date: Tue, 23 Aug 2022 13:08:13 +0300 Subject: [PATCH 1/4] enable specification of interface address for clients on Windows and Android too Co-Authored-By: Hual <1867646+Hual@users.noreply.github.com> --- httplib.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/httplib.h b/httplib.h index 0aa1c55fcd..db9d093066 100644 --- a/httplib.h +++ b/httplib.h @@ -2724,8 +2724,8 @@ inline bool bind_ip_address(socket_t sock, const std::string &host) { #define USE_IF2IP #endif -#ifdef USE_IF2IP inline std::string if2ip(int address_family, const std::string &ifn) { +#ifdef USE_IF2IP struct ifaddrs *ifap; getifaddrs(&ifap); std::string addr_candidate; @@ -2760,8 +2760,10 @@ inline std::string if2ip(int address_family, const std::string &ifn) { } freeifaddrs(ifap); return addr_candidate; -} +#else + return std::string(); #endif +} inline socket_t create_client_socket( const std::string &host, const std::string &ip, int port, @@ -2773,14 +2775,12 @@ inline socket_t create_client_socket( host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options), [&](socket_t sock2, struct addrinfo &ai) -> bool { if (!intf.empty()) { -#ifdef USE_IF2IP auto ip_from_if = if2ip(address_family, intf); if (ip_from_if.empty()) { ip_from_if = intf; } if (!bind_ip_address(sock2, ip_from_if.c_str())) { error = Error::BindIPAddress; return false; } -#endif } set_nonblocking(sock2, true); From e462bd8b374855cda897d80910ffb092cdd3bd8e Mon Sep 17 00:00:00 2001 From: ksenonadv Date: Tue, 23 Aug 2022 13:33:44 +0300 Subject: [PATCH 2/4] add socket struct member to request --- httplib.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/httplib.h b/httplib.h index db9d093066..00bed93f40 100644 --- a/httplib.h +++ b/httplib.h @@ -415,6 +415,7 @@ struct Request { std::string remote_addr; int remote_port = -1; + socket_t socket; // for server std::string version; @@ -5786,10 +5787,11 @@ Server::process_request(Stream &strm, bool close_connection, req.get_header_value("Connection") != "Keep-Alive") { connection_closed = true; } - + strm.get_remote_ip_and_port(req.remote_addr, req.remote_port); req.set_header("REMOTE_ADDR", req.remote_addr); req.set_header("REMOTE_PORT", std::to_string(req.remote_port)); + req.socket = strm.socket(); if (req.has_header("Range")) { const auto &range_header_value = req.get_header_value("Range"); From 8ede85b1274991960b7ea36bd5d436fa058e15fc Mon Sep 17 00:00:00 2001 From: ksenonadv Date: Fri, 26 Aug 2022 13:50:10 +0300 Subject: [PATCH 3/4] add sockaddr to request --- httplib.h | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/httplib.h b/httplib.h index 00bed93f40..62d77c8be5 100644 --- a/httplib.h +++ b/httplib.h @@ -415,7 +415,7 @@ struct Request { std::string remote_addr; int remote_port = -1; - socket_t socket; + struct sockaddr_storage sockaddr; // for server std::string version; @@ -516,7 +516,8 @@ class Stream { virtual ssize_t read(char *ptr, size_t size) = 0; virtual ssize_t write(const char *ptr, size_t size) = 0; - virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0; + virtual void get_remote_ip_and_port(struct sockaddr_storage &sockaddr, + std::string &ip, int &port) const = 0; virtual socket_t socket() const = 0; template @@ -1779,7 +1780,8 @@ class BufferStream : public Stream { bool is_writable() const override; ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; + void get_remote_ip_and_port(struct sockaddr_storage &sockaddr, + std::string &ip, int &port) const override; socket_t socket() const override; const std::string &get_buffer() const; @@ -2447,7 +2449,8 @@ class SocketStream : public Stream { bool is_writable() const override; ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; + void get_remote_ip_and_port(struct sockaddr_storage &sockaddr, + std::string &ip, int &port) const override; socket_t socket() const override; private: @@ -2476,7 +2479,8 @@ class SSLSocketStream : public Stream { bool is_writable() const override; ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; - void get_remote_ip_and_port(std::string &ip, int &port) const override; + void get_remote_ip_and_port(struct sockaddr_storage &sockaddr, + std::string &ip, int &port) const override; socket_t socket() const override; private: @@ -2762,7 +2766,7 @@ inline std::string if2ip(int address_family, const std::string &ifn) { freeifaddrs(ifap); return addr_candidate; #else - return std::string(); + return std::string(); #endif } @@ -2865,13 +2869,13 @@ inline bool get_remote_ip_and_port(const struct sockaddr_storage &addr, return true; } -inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) { - struct sockaddr_storage addr; - socklen_t addr_len = sizeof(addr); - - if (!getpeername(sock, reinterpret_cast(&addr), +inline void get_remote_ip_and_port(socket_t sock, + struct sockaddr_storage &sockaddr, + std::string &ip, int &port) { + socklen_t addr_len = sizeof(sockaddr); + if (!getpeername(sock, reinterpret_cast(&sockaddr), &addr_len)) { - get_remote_ip_and_port(addr, addr_len, ip, port); + get_remote_ip_and_port(sockaddr, addr_len, ip, port); } } @@ -4783,9 +4787,10 @@ inline ssize_t SocketStream::write(const char *ptr, size_t size) { return send_socket(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS); } -inline void SocketStream::get_remote_ip_and_port(std::string &ip, - int &port) const { - return detail::get_remote_ip_and_port(sock_, ip, port); +inline void +SocketStream::get_remote_ip_and_port(struct sockaddr_storage &sockaddr, + std::string &ip, int &port) const { + return detail::get_remote_ip_and_port(sock_, sockaddr, ip, port); } inline socket_t SocketStream::socket() const { return sock_; } @@ -4810,8 +4815,10 @@ inline ssize_t BufferStream::write(const char *ptr, size_t size) { return static_cast(size); } -inline void BufferStream::get_remote_ip_and_port(std::string & /*ip*/, - int & /*port*/) const {} +inline void +BufferStream::get_remote_ip_and_port(struct sockaddr_storage & /*sockaddr*/, + std::string & /*ip*/, + int & /*port*/) const {} inline socket_t BufferStream::socket() const { return 0; } @@ -5787,11 +5794,10 @@ Server::process_request(Stream &strm, bool close_connection, req.get_header_value("Connection") != "Keep-Alive") { connection_closed = true; } - - strm.get_remote_ip_and_port(req.remote_addr, req.remote_port); + + strm.get_remote_ip_and_port(req.sockaddr, req.remote_addr, req.remote_port); req.set_header("REMOTE_ADDR", req.remote_addr); req.set_header("REMOTE_PORT", std::to_string(req.remote_port)); - req.socket = strm.socket(); if (req.has_header("Range")) { const auto &range_header_value = req.get_header_value("Range"); @@ -7414,9 +7420,9 @@ inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) { return -1; } -inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, +inline void SSLSocketStream::get_remote_ip_and_port(struct sockaddr_storage &sockaddr, std::string &ip, int &port) const { - detail::get_remote_ip_and_port(sock_, ip, port); + detail::get_remote_ip_and_port(sock_, sockaddr, ip, port); } inline socket_t SSLSocketStream::socket() const { return sock_; } From 12a865dad322c51bdfe3f78e2f5fee0e0ba8cb36 Mon Sep 17 00:00:00 2001 From: iAmir Date: Fri, 28 Jun 2024 17:50:31 +0330 Subject: [PATCH 4/4] add internal_error_to_string --- httplib.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/httplib.h b/httplib.h index 62d77c8be5..dd6be7fc83 100644 --- a/httplib.h +++ b/httplib.h @@ -1909,6 +1909,29 @@ class stream_line_reader { namespace detail { +inline std::string internal_error_to_string(const Error error) { + switch (error) { + case Error::Success: return "Success (no error)"; + case Error::Connection: return "Could not establish connection"; + case Error::BindIPAddress: return "Failed to bind IP address"; + case Error::Read: return "Failed to read connection"; + case Error::Write: return "Failed to write connection"; + case Error::ExceedRedirectCount: return "Maximum redirect count exceeded"; + case Error::Canceled: return "Connection handling canceled"; + case Error::SSLConnection: return "SSL connection failed"; + case Error::SSLLoadingCerts: return "SSL certificate loading failed"; + case Error::SSLServerVerification: return "SSL server verification failed"; + case Error::UnsupportedMultipartBoundaryChars: + return "Unsupported HTTP multipart boundary characters"; + case Error::Compression: return "Compression failed"; + case Error::ConnectionTimeout: return "Connection timed out"; + case Error::Unknown: return "Unknown"; + default: break; + } + + return "Invalid"; +} + inline bool is_hex(char c, int &v) { if (0x20 <= c && isdigit(c)) { v = c - '0';