58 }; |
60 }; |
59 |
61 |
60 static void check(int result, std::string message) { |
62 static void check(int result, std::string message) { |
61 if (result == 0); // OK |
63 if (result == 0); // OK |
62 else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message); |
64 else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message); |
|
65 } |
|
66 |
|
67 template <typename T> static T* castAddress(addrinfo* ai, sa_family_t family) { |
|
68 if (ai && ai->ai_family == family && sizeof (T) == ai->ai_addrlen) return (T*) ai->ai_addr; |
|
69 else return nullptr; |
|
70 } |
|
71 |
|
72 static std::string ip2string(const addrinfo* ai) { |
|
73 //char buffer[INET_ADDRSTRLEN] = {0}; |
|
74 char buffer[INET6_ADDRSTRLEN] = {0}; |
|
75 //return inet_ntop(ai->ai_family, &ai->ai_addr, buffer, sizeof (buffer)); |
|
76 //return inet_ntop(ai->ai_family, &ai->ai_addr->sa_data, buffer, sizeof (buffer)); |
|
77 if (ai->ai_family == AF_INET) return inet_ntop(ai->ai_family, &((sockaddr_in const *) ai->ai_addr)->sin_addr, buffer, sizeof (buffer)); // TODO: check 0 result |
|
78 else if (ai->ai_family == AF_INET6) return inet_ntop(ai->ai_family, &((sockaddr_in6 const *) ai->ai_addr)->sin6_addr, buffer, sizeof (buffer)); // TODO: check 0 result |
|
79 else throw std::logic_error("Invalid address family: " + std::to_string(ai->ai_family)); |
|
80 } |
|
81 |
|
82 static in_addr_t getAddress(const std::string& host) { |
|
83 |
|
84 struct addrinfo* addrInfo; |
|
85 check(getaddrinfo(host.c_str(), "", nullptr, &addrInfo), "getaddrinfo"); |
|
86 |
|
87 std::cerr << "found: " << addrInfo << std::endl; |
|
88 if (addrInfo) { |
|
89 for (addrinfo* ai = addrInfo; ai; ai = ai->ai_next) { |
|
90 std::cerr << "address info: family=" << std::to_string(ai->ai_addr->sa_family); |
|
91 if (sockaddr_in * sa = castAddress<sockaddr_in>(ai, AF_INET)) std::cerr << " IPv4=" << ip2string(ai); |
|
92 else if (sockaddr_in6 * sa = castAddress<sockaddr_in6>(ai, AF_INET6)) std::cerr << " IPv6=" << ip2string(ai); |
|
93 std::cerr << std::endl; |
|
94 } |
|
95 } |
|
96 |
|
97 if (addrInfo) { |
|
98 for (addrinfo* ai = addrInfo; ai; ai = ai->ai_next) { |
|
99 if (sockaddr_in * sa = castAddress<sockaddr_in>(ai, AF_INET)) { |
|
100 in_addr_t address = sa->sin_addr.s_addr; |
|
101 freeaddrinfo(addrInfo); |
|
102 return address; |
|
103 |
|
104 } |
|
105 } |
|
106 } |
|
107 |
|
108 freeaddrinfo(addrInfo); |
|
109 |
|
110 // TODO: rather throw exception – requires IP address in the host string: |
|
111 return inet_addr(host.c_str()); |
63 } |
112 } |
64 |
113 |
65 class UDPClientSocket : public Socket { |
114 class UDPClientSocket : public Socket { |
66 private: |
115 private: |
67 struct sockaddr_in remoteAddress; |
116 struct sockaddr_in remoteAddress; |
71 |
120 |
72 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
121 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
73 std::shared_ptr<UDPClientSocket> s = std::make_shared<UDPClientSocket>(); |
122 std::shared_ptr<UDPClientSocket> s = std::make_shared<UDPClientSocket>(); |
74 memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); |
123 memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); |
75 s->remoteAddress.sin_family = AF_INET; |
124 s->remoteAddress.sin_family = AF_INET; |
76 s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) |
125 s->remoteAddress.sin_addr.s_addr = getAddress(findOption(options, OPTION_HOST, true)); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) |
77 s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true))); |
126 s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true))); |
78 |
127 |
79 auto protocol = findOption(options, OPTION_PROTOCOL); |
128 auto protocol = findOption(options, OPTION_PROTOCOL); |
80 if (protocol == PROTOCOL_SCTP) { |
129 if (protocol == PROTOCOL_SCTP) { |
81 s->protocol = IPPROTO_SCTP; |
130 s->protocol = IPPROTO_SCTP; |
104 |
153 |
105 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
154 static std::shared_ptr<Socket> open(const SocketOptions& options) { |
106 std::shared_ptr<TCPClientSocket> s = std::make_shared<TCPClientSocket>(); |
155 std::shared_ptr<TCPClientSocket> s = std::make_shared<TCPClientSocket>(); |
107 memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); |
156 memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); |
108 s->remoteAddress.sin_family = AF_INET; |
157 s->remoteAddress.sin_family = AF_INET; |
109 s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) |
158 s->remoteAddress.sin_addr.s_addr = getAddress(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) |
110 s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true))); |
159 s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true))); |
111 return s; |
160 return s; |
112 } |
161 } |
113 |
162 |
114 void send(const std::string& message) override { |
163 void send(const std::string& message) override { |
142 }; |
191 }; |
143 |
192 |
144 static std::vector<std::shared_ptr<SocketFactory>> factories |
193 static std::vector<std::shared_ptr<SocketFactory>> factories |
145 { |
194 { |
146 std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (), |
195 std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (), |
147 std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class |
196 std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class |
148 std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), |
197 std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), |
149 std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
198 std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
150 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
199 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
151 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
200 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
152 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
201 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
153 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
202 std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
154 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
203 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
155 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
204 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
156 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
205 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class |
157 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
206 std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class |
158 }; |
207 }; |
159 |
208 |
160 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) { |
209 std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) { |
161 for (auto f : factories) if (f->canHandle(options)) return f; |
210 for (auto f : factories) if (f->canHandle(options)) return f; |
162 throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options? |
211 throw std::logic_error("Unable to find a SocketFactory"); // TODO: add relevant options? |