diff --git a/httplib.h b/httplib.h index 0aa1c55fcd..dd6be7fc83 100644 --- a/httplib.h +++ b/httplib.h @@ -415,6 +415,7 @@ struct Request { std::string remote_addr; int remote_port = -1; + struct sockaddr_storage sockaddr; // for server std::string version; @@ -515,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 @@ -1778,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; @@ -1906,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'; @@ -2446,7 +2472,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: @@ -2475,7 +2502,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: @@ -2724,8 +2752,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 +2788,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 +2803,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); @@ -2864,13 +2892,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); } } @@ -4782,9 +4810,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_; } @@ -4809,8 +4838,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,7 +5818,7 @@ Server::process_request(Stream &strm, bool close_connection, 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)); @@ -7412,9 +7443,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_; }