1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file.
4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/socket_descriptor.h"
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_POSIX)
8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <sys/types.h>
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <sys/socket.h>
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/basictypes.h"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_WIN)
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <ws2tcpip.h>
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/win/windows_version.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/winsock_init.h"
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace net {
21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PlatformSocketFactory* g_socket_factory = NULL;
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PlatformSocketFactory::PlatformSocketFactory() {
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PlatformSocketFactory::~PlatformSocketFactory() {
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PlatformSocketFactory::SetInstance(PlatformSocketFactory* factory) {
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  g_socket_factory = factory;
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SocketDescriptor CreateSocketDefault(int family, int type, int protocol) {
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_WIN)
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EnsureWinsockInit();
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SocketDescriptor result = ::WSASocket(family, type, protocol, NULL, 0,
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                        WSA_FLAG_OVERLAPPED);
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (result != kInvalidSocket && family == AF_INET6 &&
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DWORD value = 0;
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (setsockopt(result, IPPROTO_IPV6, IPV6_V6ONLY,
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   reinterpret_cast<const char*>(&value), sizeof(value))) {
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      closesocket(result);
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return kInvalidSocket;
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return result;
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#else  // OS_WIN
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return ::socket(family, type, protocol);
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif  // OS_WIN
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SocketDescriptor CreatePlatformSocket(int family, int type, int protocol) {
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (g_socket_factory)
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return g_socket_factory->CreateSocket(family, type, protocol);
57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  else
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return CreateSocketDefault(family, type, protocol);
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace net
62