1 #include "StunClient.h"
2 #include "NetworkMgrMain.h"
26 #define STUN_DEFAULT_WAIT_INTERVAL 2000 //miliseconds
27 #define STUN_DEFAULT_MAX_ATTEMPTS 30
34 static int constexpr binding_requests_max = 9;
35 static std::chrono::milliseconds binding_requests_wait_time_max(1600);
37 static char const * family_to_string(
int family) {
38 if (family == AF_INET)
40 if (family == AF_INET6)
52 operator int()
const {
return m_fd; }
58 void dump_buffer(
char const * prefix, buffer
const & buff)
62 for (uint8_t b : buff)
69 #define STUN_TRACE(format, ...) printf("STUN:" format __VA_OPT__(,) __VA_ARGS__)
71 #define STUN_TRACE(format, ...)
75 void throw_error(
char const * format, ...)
81 vsnprintf(buff,
sizeof(buff) - 1, format, ap);
85 #ifdef __cpp_exceptions
86 throw std::runtime_error(buff);
92 template<
typename iterator>
93 inline void random_fill(iterator begin, iterator end) {
94 std::random_device rdev;
95 std::default_random_engine random_engine(rdev());
96 std::uniform_int_distribution<uint8_t> uniform_dist(0, std::numeric_limits<uint8_t>::max());
98 *begin++ = uniform_dist(random_engine);
101 sockaddr_storage get_interface_address(std::string
const & iface,
int family)
103 bool found_iface_info =
false;
104 sockaddr_storage iface_info = {};
106 struct ifaddrs * address_list =
nullptr;
107 if (getifaddrs(&address_list) == -1) {
108 details::throw_error(
"getifaddrs failed. %s", strerror(errno));
112 for (
auto * addr = address_list; addr !=
nullptr; addr = addr->ifa_next) {
113 if (iface != addr->ifa_name)
115 if (family != addr->ifa_addr->sa_family)
117 iface_info = *
reinterpret_cast<sockaddr_storage *
>(addr->ifa_addr);
118 iface_info.ss_family = addr->ifa_addr->sa_family;
119 found_iface_info =
true;
124 freeifaddrs(address_list);
126 if (!found_iface_info) {
127 details::throw_error(
"failed to find ip for interface:%s", iface.c_str());
130 STUN_TRACE(
"local_addr:%s\n", sockaddr_to_string(iface_info).c_str());
135 uint16_t sockaddr_get_port(sockaddr_storage
const & addr)
138 if (addr.ss_family== AF_INET) {
139 sockaddr_in
const * v4 =
reinterpret_cast< sockaddr_in
const *
>(&addr);
140 port = htons(v4->sin_port);
142 else if (addr.ss_family == AF_INET6) {
143 sockaddr_in6
const * v6 =
reinterpret_cast< sockaddr_in6
const *
>(&addr);
144 port = htons(v6->sin6_port);
147 throw_error(
"can't convert address with family:%d to a string.", addr.ss_family);
152 std::string sockaddr_to_string2(sockaddr
const * addr,
int family)
154 char buff[INET6_ADDRSTRLEN] = {};
156 char const * p =
nullptr;
158 if (family == AF_INET) {
159 sockaddr_in
const * v4 =
reinterpret_cast< sockaddr_in
const *
>(addr);
160 p = inet_ntop(AF_INET, &v4->sin_addr, buff, INET6_ADDRSTRLEN);
162 else if (family == AF_INET6) {
163 sockaddr_in6
const * v6 =
reinterpret_cast< sockaddr_in6
const *
>(addr);
164 p = inet_ntop(AF_INET6, &v6->sin6_addr, buff, INET6_ADDRSTRLEN);
167 throw_error(
"can't convert address with family:%d to a string.", family);
170 throw_error(
"failed to convert address to string");
172 buff[INET6_ADDRSTRLEN - 1] =
'\0';
173 return std::string(buff);
176 std::vector<sockaddr_storage> resolve_hostname(std::string
const & host, uint16_t port, stun::protocol proto)
178 std::vector<sockaddr_storage> addrs;
179 std::set<std::string> already_seen;
181 struct addrinfo * stun_addrs =
nullptr;
182 int ret = getaddrinfo(host.c_str(),
nullptr,
nullptr, &stun_addrs);
184 std::stringstream error_message;
185 error_message <<
"getaddrinfo failed. ";
186 if (ret == EAI_SYSTEM)
187 error_message << strerror(errno);
189 error_message << gai_strerror(ret);
190 throw_error(error_message.str().c_str());
194 if (proto == stun::protocol::af_inet)
195 protocol_family = AF_INET;
196 else if (proto == stun::protocol::af_inet6)
197 protocol_family = AF_INET6;
199 throw_error(
"invalid protocol family");
201 for (
struct addrinfo * addr = stun_addrs; addr; addr = addr->ai_next) {
202 if (addr->ai_family != AF_INET && addr->ai_family != AF_INET6)
204 if (addr->ai_family != protocol_family)
207 std::string
const s = sockaddr_to_string2(addr->ai_addr, addr->ai_family);
209 if (already_seen.find(s) == std::end(already_seen)) {
210 struct sockaddr_storage temp = {};
211 memcpy(&temp, addr->ai_addr, addr->ai_addrlen);
213 if (addr->ai_family == AF_INET) {
214 sockaddr_in * v4 =
reinterpret_cast< sockaddr_in *
>(&temp);
215 v4->sin_port = ntohs(port);
217 else if (addr->ai_family == AF_INET6) {
218 sockaddr_in6 * v6 =
reinterpret_cast< sockaddr_in6 *
>(&temp);
219 v6->sin6_port = ntohs(port);
222 addrs.push_back(temp);
223 already_seen.insert(s);
228 freeaddrinfo(stun_addrs);
233 socklen_t socket_length(sockaddr_storage
const & addr)
235 if (addr.ss_family == AF_INET)
236 return sizeof(sockaddr_in);
237 if (addr.ss_family == AF_INET6)
238 return sizeof(sockaddr_in6);
244 attribute
const * message::find_attribute(uint16_t attr_type)
const
246 std::vector<attribute>::const_iterator itr = std::find_if (
247 std::begin(m_attrs), std::end(m_attrs), [attr_type](attribute
const & attr) {
248 return attr_type == attr.type;
250 if (itr == m_attrs.end())
252 attribute
const & temp = *itr;
257 buffer message::encode()
const
260 encoder::encode_u16(bytes, m_header.message_type);
261 encoder::encode_u16(bytes, m_header.message_length);
262 for (uint8_t b : m_header.transaction_id)
263 bytes.push_back(
static_cast<uint8_t
>(b));
264 for (attribute
const & v : m_attrs) {
265 encoder::encode_u16(bytes, v.type);
266 encoder::encode_u16(bytes, v.length);
267 bytes.insert(std::end(bytes), std::begin(v.value), std::end(v.value));
272 message * message_factory::create_binding_request()
274 message * change_request =
new message();
275 change_request->m_header.message_type = 1;
276 change_request->m_header.message_length = 8;
277 details::random_fill(std::begin(change_request->m_header.transaction_id),
278 std::end(change_request->m_header.transaction_id));
281 change_request->m_attrs.push_back({3, 4, {0, 0, 0, 0}});
283 return change_request;
289 , m_protocol(protocol::af_inet)
291 , m_cache_timeout(30)
292 , m_last_cache_time()
306 std::string
const & hostname,
308 std::string
const & interface,
310 uint16_t bind_timeout,
311 uint16_t cache_timeout,
318 if(m_server.hostname != hostname)
320 m_server.hostname = hostname;
324 if(m_server.port != port)
326 m_server.port = port;
330 if(m_interface != interface)
332 m_interface = interface;
336 if(m_protocol != proto)
342 if(m_bind_timeout != bind_timeout)
344 m_bind_timeout = bind_timeout;
348 if(m_cache_timeout != cache_timeout)
350 m_cache_timeout = cache_timeout;
354 LOG_WARN(
"stun::client::bind enter: server=%s port=%u iface=%s ipv6=%u timeout=%u cache_timeout=%u dirty=%u",
355 hostname.c_str(), port, interface.c_str(), proto == stun::protocol::af_inet6, bind_timeout, cache_timeout, dirty);
356 verbose(
"client::bind enter: server=%s port=%u iface=%s ipv6=%u timeout=%u cache_timeout=%u dirty=%u\n",
357 hostname.c_str(), port, interface.c_str(), proto == stun::protocol::af_inet6, bind_timeout, cache_timeout, dirty);
359 if(m_cache_timeout > 0
361 && m_last_result.is_valid())
363 auto time_in_cache = std::chrono::duration_cast<std::chrono::seconds>(
364 std::chrono::steady_clock::now() - m_last_cache_time);
366 LOG_DBG(
"stun::client::bind cache time=%lld", time_in_cache.count());
367 verbose(
"client::bind cache time=%lld\n", time_in_cache.count());
369 if(time_in_cache.count() < m_cache_timeout)
371 result = m_last_result;
373 LOG_DBG(
"stun::client::bind returning cached result: %s", result.public_ip.c_str());
374 verbose(
"client::bind returning cached result: %s\n", result.public_ip.c_str());
379 LOG_DBG(
"stun::client::bind cached result expired");
380 verbose(
"client::client::bind cached result expired\n");
384 #ifdef __cpp_exceptions
388 int interval_wait_time = STUN_DEFAULT_WAIT_INTERVAL;
389 int num_attempts = STUN_DEFAULT_MAX_ATTEMPTS;
393 std::chrono::milliseconds wait_time(interval_wait_time);
394 for (
int i = 0; i < num_attempts && total_time < m_bind_timeout; ++i)
396 LOG_DBG(
"stun::client::bind sending bind request");
397 verbose(
"client::bind sending bind request\n");
399 std::unique_ptr<stun::message> binding_response = send_binding_request(wait_time);
401 total_time += interval_wait_time;
405 if (total_time + sleep_time > m_bind_timeout)
406 sleep_time = m_bind_timeout - total_time;
410 total_time += sleep_time;
414 if (binding_response)
416 stun::attribute const * mapped_address = binding_response->find_attribute(stun::attribute_type::mapped_address);
421 result.public_ip = m_last_result.public_ip = stun::sockaddr_to_string(addr);
423 m_last_cache_time = std::chrono::steady_clock::now();
425 LOG_DBG(
"stun::client::bind success: public_ip=%s", result.public_ip.c_str());
426 verbose(
"client::bind success: public_ip=%s\n", result.public_ip.c_str());
432 LOG_ERR(
"stun::client::bind failed: ip missing from binding response");
433 verbose(
"client::bind failed: ip missing from binding response\n");
438 LOG_ERR(
"stun::client::bind failed: no response received from server");
439 verbose(
"client::bind failed: no response received from server\n");
443 #ifdef __cpp_exceptions
444 catch (std::exception
const & err)
446 LOG_ERR(
"stun fail: %s", err.what());
447 verbose(
"client::bind failed: %s\n", err.what());
463 void client::create_udp_socket(
int inet_family)
465 if (inet_family != AF_INET && inet_family != AF_INET6)
466 details::throw_error(
"invalid inet family:%d", inet_family);
468 verbose(
"creating udp/%s socket\n", details::family_to_string(inet_family));
470 int soc = socket(inet_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
472 details::throw_error(
"error creating socket. %s", strerror(errno));
474 #ifdef _SUN_USE_MSGHDR
476 setsockopt(soc, IPPROTO_IP, IP_PKTINFO, &optval,
sizeof(
int));
479 if (!m_interface.empty()) {
483 LOG_ERR(
"stb %d ipaddress not found.", inet_family);
487 verbose(
"interface:%s, ipaddres:%s, netmask:%s\n", m_interface.c_str(), param.ipaddress, param.netmask);
488 struct sockaddr_in serv_addr;
489 struct sockaddr_in6 serv_ipv6;
490 struct in_addr addrptr;
491 if(inet_family == AF_INET) {
492 inet_aton(param.ipaddress, &addrptr);
493 serv_addr.sin_family = inet_family;
494 serv_addr.sin_port = htons(m_server.port);
495 serv_addr.sin_addr = addrptr;
496 ret = ::bind(soc, (
struct sockaddr *)&serv_addr,
sizeof(serv_addr));
497 }
else if(inet_family == AF_INET6) {
498 inet_pton(AF_INET6, param.ipaddress, &serv_ipv6.sin6_addr);
499 serv_ipv6.sin6_family = inet_family;
500 serv_ipv6.sin6_port = htons(m_server.port);
501 ret = ::bind(soc, (
struct sockaddr *)&serv_ipv6,
sizeof(serv_ipv6));
506 details::throw_error(
"failed to bind socket to local address '%s'. %s",
507 param.ipaddress, strerror(err));
511 sockaddr_storage local_endpoint;
512 socklen_t socklen =
sizeof(sockaddr_storage);
513 int ret = getsockname(soc,
reinterpret_cast<sockaddr *
>(&local_endpoint), &socklen);
515 verbose(
"local endpoint %s/%d\n", sockaddr_to_string(local_endpoint).c_str(),
516 details::sockaddr_get_port(local_endpoint));
521 verbose(
"no local interface supplied to bind to\n");
528 message * client::send_message(sockaddr_storage
const & remote_addr, message
const & req,
529 std::chrono::milliseconds wait_time,
int * local_iface_index)
534 buffer bytes = req.encode();
536 STUN_TRACE(
"remote_addr:%s\n", sockaddr_to_string(remote_addr).c_str());
542 verbose(
"sending messsage\n");
544 ssize_t n = sendto(m_fd, &bytes[0], bytes.size(), 0, (sockaddr *) &remote_addr, details::socket_length(remote_addr));
546 details::throw_error(
"failed to send packet. %s", strerror(errno));
552 sockaddr_storage from_addr = {};
559 timeout.tv_usec = 1000 * wait_time.count();
562 constexpr decltype(timeout.tv_sec) kMicrosecondsPerSecond = 1000000;
563 if (timeout.tv_usec > kMicrosecondsPerSecond) {
564 timeout.tv_sec = (timeout.tv_usec / kMicrosecondsPerSecond);
565 timeout.tv_usec -= (timeout.tv_sec * kMicrosecondsPerSecond);
567 verbose(
"waiting for response, timeout set to %lus - %luus\n", timeout.tv_sec, timeout.tv_usec);
568 int ret = select(m_fd + 1, &rfds,
nullptr,
nullptr, &timeout);
570 STUN_TRACE(
"select timeout out\n");
587 #ifdef _STUN_USE_MSGHDR
591 uint8_t control_data[256];
593 struct msghdr msg = {};
594 struct iovec iov = {};
596 iov.iov_base = &bytes[0];
597 iov.iov_len = bytes.size();
602 msg.msg_control = control_data;
603 msg.msg_controllen =
sizeof(control_data);
604 msg.msg_name = &from_addr;
605 msg.msg_namelen =
sizeof(from_addr);
607 n = recvmsg(m_fd, &msg, 0);
608 if ((n > 0) && local_iface_index) {
609 for (cmsghdr * cptr = CMSG_FIRSTHDR(&msg); cptr; cptr = CMSG_NXTHDR(&msg, cptr)) {
610 if (cptr->cmsg_level == IPPROTO_IP) {
611 if (cptr->cmsg_type == IP_PKTINFO)
612 *local_iface_index =
reinterpret_cast<in_pktinfo *
>(CMSG_DATA(cptr))->ipi_ifindex;
613 else if (cptr->cmsg_type == IPV6_PKTINFO)
614 *local_iface_index =
reinterpret_cast<in6_pktinfo *
>(CMSG_DATA(cptr))->ipi6_ifindex;
618 }
while (n < 0 && errno == EINTR);
621 socklen_t len =
sizeof(sockaddr_storage);
622 n = recvfrom(m_fd, &bytes[0], bytes.size(), MSG_WAITALL, (sockaddr *) &from_addr, &len);
623 }
while (n == -2 && errno == EINTR);
627 details::throw_error(
"error receiving on socket. %s", strerror(errno));
635 return decoder::decode_message(bytes,
nullptr);
638 void client::verbose(
char const * format, ...)
643 va_start(ap, format);
649 network_access_type client::discover_network_access_type(server
const & srv)
651 std::chrono::milliseconds wait_time(250);
652 std::vector<sockaddr_storage> addrs = details::resolve_hostname(srv.hostname, srv.port, m_protocol);
654 sockaddr_storage server_addr = {};
656 std::unique_ptr<message> binding_response;
657 for (sockaddr_storage
const & addr : addrs) {
658 binding_response = this->send_binding_request(addr, wait_time);
659 if (binding_response) {
664 wait_time = std::min(wait_time * 2, details::binding_requests_wait_time_max);
667 if (!binding_response)
668 return network_access_type::udp_blocked;
672 sockaddr_storage local_endpoint;
673 socklen_t socklen =
sizeof(sockaddr_storage);
674 int ret = getsockname(m_fd,
reinterpret_cast<sockaddr *
>(&local_endpoint), &socklen);
676 details::throw_error(
"failed to get local socket name:%s", strerror(errno));
678 local_endpoint.ss_family = AF_INET;
679 std::string s = sockaddr_to_string(local_endpoint);
681 return network_access_type::unknown;
684 std::unique_ptr<message> client::send_binding_request(std::chrono::milliseconds wait_time)
686 std::unique_ptr<message> binding_response;
687 std::vector<sockaddr_storage> addrs = details::resolve_hostname(m_server.hostname, m_server.port, m_protocol);
688 for (sockaddr_storage
const & addr : addrs) {
689 binding_response = this->send_binding_request(addr, wait_time);
690 if (binding_response)
693 wait_time = std::min(wait_time * 2, details::binding_requests_wait_time_max);
695 return binding_response;
698 std::unique_ptr<message> client::send_binding_request(sockaddr_storage
const & addr,
699 std::chrono::milliseconds wait_time)
701 this->verbose(
"sending binding request with wait time:%lld ms\n", wait_time.count());
702 this->create_udp_socket(addr.ss_family);
703 std::unique_ptr<message> binding_request(message_factory::create_binding_request());
704 std::unique_ptr<message> binding_response(this->send_message(addr, *binding_request, wait_time));
705 return binding_response;
708 attributes::address::address(attribute
const & attr)
714 uint16_t family = decoder::decode_u16(attr.value, &offset);
716 sockaddr_in * v4 =
reinterpret_cast<sockaddr_in *
>(&m_addr);
717 v4->sin_port = decoder::decode_u16(attr.value, &offset);
718 v4->sin_addr.s_addr = htonl(decoder::decode_u32(attr.value, &offset));
719 m_addr = *
reinterpret_cast<sockaddr_storage *
>(v4);
720 m_addr.ss_family = AF_INET;
722 else if (family == 2) {
723 sockaddr_in6 * v6 =
reinterpret_cast<sockaddr_in6 *
>(&m_addr);
724 v6->sin6_port = decoder::decode_u16(attr.value, &offset);
725 for (
int i = 0; i < 16; ++i)
726 v6->sin6_addr.s6_addr[i] = attr.value[offset + i];
727 m_addr = *
reinterpret_cast<sockaddr_storage *
>(v6);
728 m_addr.ss_family = AF_INET6;
731 details::throw_error(
"invalid mapped address family:%d", family);
734 uint32_t decoder::decode_u32(buffer
const & buff,
size_t * offset)
736 uint32_t
const * p =
reinterpret_cast<uint32_t
const *
>(&buff[*offset]);
737 uint32_t value = ntohl(*p);
742 uint16_t decoder::decode_u16(buffer
const & buff,
size_t * offset)
744 uint16_t
const * p =
reinterpret_cast<uint16_t
const *
>(&buff[*offset]);
745 uint16_t value = ntohs(*p);
750 message * decoder::decode_message(buffer
const & buff,
size_t * offset)
752 size_t temp_offset = 0;
754 temp_offset = *offset;
759 message * new_message =
nullptr;
760 message_header header;
761 header.message_type = decoder::decode_u16(buff, &temp_offset);
762 header.message_length = decoder::decode_u16(buff, &temp_offset);
763 if (header.message_type == message_type::binding_response) {
764 for (
size_t i = 0, n = header.transaction_id.size(); i < n; ++i)
765 header.transaction_id[i] = buff[temp_offset++ + i];
766 new_message =
new message();
767 new_message->m_header = header;
768 while (temp_offset < buff.size())
769 new_message->m_attrs.push_back(decoder::decode_attr(buff, &temp_offset));
776 *offset = temp_offset;
781 attribute decoder::decode_attr(buffer
const & buff,
size_t * offset)
784 t.type = decoder::decode_u16(buff, offset);
785 t.length = decoder::decode_u16(buff, offset);
786 t.value.insert(std::end(t.value), std::begin(buff) + *offset,
787 std::begin(buff) + *offset + t.length);
788 *offset += t.value.size();
792 void encoder::encode_u16(buffer & buff, uint16_t n)
794 uint16_t temp = htons(n);
795 uint8_t * p =
reinterpret_cast< uint8_t *
>(&temp);
796 buff.push_back(p[0]);
797 buff.push_back(p[1]);
800 void encoder::encode_u32(buffer & buff, uint32_t n)
802 uint32_t temp = htons(n);
803 uint8_t * p =
reinterpret_cast<uint8_t *
>(&temp);
804 buff.push_back(p[0]);
805 buff.push_back(p[1]);
806 buff.push_back(p[2]);
807 buff.push_back(p[3]);
810 std::string sockaddr_to_string(sockaddr_storage
const & addr)
812 sockaddr
const * temp =
reinterpret_cast<sockaddr
const *
>(&addr);
813 return details::sockaddr_to_string2(temp, addr.ss_family);