147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2008 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/nethelpers.h" 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN) 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <ws2spi.h> 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <ws2tcpip.h> 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h" 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/byteorder.h" 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/signalthread.h" 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint ResolveHostname(const std::string& hostname, int family, 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org std::vector<IPAddress>* addresses) { 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef __native_client__ 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false); 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "ResolveHostname() is not implemented for NaCl"; 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else // __native_client__ 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!addresses) { 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addresses->clear(); 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org struct addrinfo* result = NULL; 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org struct addrinfo hints = {0}; 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO(djw): For now this is IPv4 only so existing users remain unaffected. 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org hints.ai_family = AF_INET; 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org hints.ai_flags = AI_ADDRCONFIG; 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int ret = getaddrinfo(hostname.c_str(), NULL, &hints, &result); 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ret != 0) { 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ret; 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org struct addrinfo* cursor = result; 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (; cursor; cursor = cursor->ai_next) { 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (family == AF_UNSPEC || cursor->ai_family == family) { 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org IPAddress ip; 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (IPFromAddrInfo(cursor, &ip)) { 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addresses->push_back(ip); 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org freeaddrinfo(result); 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif // !__native_client__ 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// AsyncResolver 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncResolver::AsyncResolver() : error_(-1) { 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid AsyncResolver::Start(const SocketAddress& addr) { 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr_ = addr; 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SignalThred Start will kickoff the resolve process. 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalThread::Start(); 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool AsyncResolver::GetResolvedAddress(int family, SocketAddress* addr) const { 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error_ != 0 || addresses_.empty()) 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *addr = addr_; 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (size_t i = 0; i < addresses_.size(); ++i) { 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (family == addresses_[i].family()) { 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr->SetResolvedIP(addresses_[i]); 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid AsyncResolver::DoWork() { 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = ResolveHostname(addr_.hostname().c_str(), addr_.family(), 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &addresses_); 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid AsyncResolver::OnWorkDone() { 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalDone(this); 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst char* inet_ntop(int af, const void *src, char* dst, socklen_t size) { 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN) 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return win32_inet_ntop(af, src, dst, size); 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ::inet_ntop(af, src, dst, size); 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint inet_pton(int af, const char* src, void *dst) { 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN) 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return win32_inet_pton(af, src, dst); 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ::inet_pton(af, src, dst); 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool HasIPv6Enabled() { 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if !defined(WEBRTC_WIN) 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We only need to check this for Windows XP (so far). 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (IsWindowsVistaOrLater()) { 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!IsWindowsXpOrLater()) { 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DWORD protbuff_size = 4096; 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org scoped_ptr<char[]> protocols; 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPWSAPROTOCOL_INFOW protocol_infos = NULL; 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int requested_protocols[2] = {AF_INET6, 0}; 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int err = 0; 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int ret = 0; 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Check for protocols in a do-while loop until we provide a buffer large 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // enough. (WSCEnumProtocols sets protbuff_size to its desired value). 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // It is extremely unlikely that this will loop more than once. 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org do { 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org protocols.reset(new char[protbuff_size]); 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org protocol_infos = reinterpret_cast<LPWSAPROTOCOL_INFOW>(protocols.get()); 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret = WSCEnumProtocols(requested_protocols, protocol_infos, 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &protbuff_size, &err); 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } while (ret == SOCKET_ERROR && err == WSAENOBUFS); 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ret == SOCKET_ERROR) { 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Even if ret is positive, check specifically for IPv6. 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Non-IPv6 enabled WinXP will still return a RAW protocol. 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (int i = 0; i < ret; ++i) { 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (protocol_infos[i].iAddressFamily == AF_INET6) { 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 151