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