File indexing completed on 2026-04-17 08:35:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef _THRIFT_TRANSPORT_SOCKETUTILS_H_
0021 #define _THRIFT_TRANSPORT_SOCKETUTILS_H_ 1
0022
0023 #include <memory>
0024 #include <string>
0025 #include <system_error>
0026 #include <vector>
0027
0028 #include <sys/types.h>
0029 #ifdef HAVE_SYS_SOCKET_H
0030 #include <sys/socket.h>
0031 #endif
0032 #ifdef HAVE_NETDB_H
0033 #include <netdb.h>
0034 #endif
0035
0036 #include <thrift/transport/PlatformSocket.h>
0037
0038 namespace apache {
0039 namespace thrift {
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 struct AddressResolutionHelper {
0054
0055 private:
0056 struct addrinfo_deleter {
0057 void operator()(addrinfo* addr) {
0058 ::freeaddrinfo(addr);
0059 }
0060 };
0061
0062 public:
0063 using PtrOwnedList = std::unique_ptr<addrinfo, addrinfo_deleter>;
0064
0065 struct Iter : std::iterator<std::forward_iterator_tag, const addrinfo*> {
0066 value_type ptr = nullptr;
0067
0068 Iter() = default;
0069 Iter(const addrinfo* head) : ptr(head) {}
0070
0071 value_type operator*() const { return ptr; }
0072
0073 bool operator==(const Iter& other) { return this->ptr == other.ptr; }
0074 bool operator!=(const Iter& other) { return this->ptr != other.ptr; }
0075
0076 operator bool() { return this->ptr != nullptr; }
0077 bool operator!() { return this->ptr == nullptr; }
0078
0079 Iter& operator++() {
0080 if (ptr == nullptr) {
0081 throw std::out_of_range("won't go pass end of linked list");
0082 }
0083 ptr = ptr->ai_next;
0084 return *this;
0085 }
0086 Iter operator++(int) {
0087 Iter tmp(*this);
0088 ++(*this);
0089 return tmp;
0090 }
0091 };
0092
0093 struct gai_error : std::error_category {
0094 virtual const char* name() const noexcept override { return "getaddrinfo"; }
0095 virtual std::string message(int code) const override { return THRIFT_GAI_STRERROR(code); }
0096 };
0097
0098 private:
0099 PtrOwnedList gai_results;
0100
0101 addrinfo* query(const std::string& host, const std::string& port, int socktype, int flags) {
0102 addrinfo hints{};
0103 hints.ai_flags = flags;
0104 hints.ai_family = AF_UNSPEC;
0105 hints.ai_socktype = socktype;
0106
0107 addrinfo* head;
0108 int ret = ::getaddrinfo(host.empty() ? NULL : host.c_str(), port.c_str(), &hints, &head);
0109 if (ret == 0) {
0110 return head;
0111 #ifdef _WIN32
0112 } else {
0113 throw std::system_error{THRIFT_GET_SOCKET_ERROR, std::system_category()};
0114 #else
0115 } else if (ret == EAI_SYSTEM) {
0116 throw std::system_error{THRIFT_GET_SOCKET_ERROR, std::system_category()};
0117 } else {
0118 throw std::system_error{ret, gai_error()};
0119 #endif
0120 }
0121 }
0122
0123 public:
0124
0125
0126
0127
0128
0129
0130
0131 AddressResolutionHelper(const std::string& host,
0132 const std::string& port,
0133 int socktype = SOCK_STREAM,
0134 int flags = AI_V4MAPPED | AI_ADDRCONFIG)
0135 : gai_results(query(host, port, socktype, flags)) {}
0136
0137 AddressResolutionHelper() = default;
0138
0139
0140
0141
0142
0143
0144
0145
0146 AddressResolutionHelper& resolve(const std::string& host,
0147 const std::string& port,
0148 int socktype = SOCK_STREAM,
0149 int flags = AI_V4MAPPED | AI_ADDRCONFIG) {
0150 gai_results.reset(query(host, port, socktype, flags));
0151 return *this;
0152 }
0153
0154
0155
0156
0157 Iter iterate() const { return Iter{gai_results.get()}; }
0158 };
0159
0160 }
0161 }
0162
0163 #endif