Chromium Code Reviews| Index: net/dns/address_sorter_win.cc |
| diff --git a/net/dns/address_sorter_win.cc b/net/dns/address_sorter_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..248788d4aa2463fb2c49f0a7e0c15d39cf70b54e |
| --- /dev/null |
| +++ b/net/dns/address_sorter_win.cc |
| @@ -0,0 +1,81 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "net/dns/address_sorter.h" |
| + |
| +#include <winsock2.h> |
| + |
| +#include "base/logging.h" |
| +#include "net/base/address_list.h" |
| +#include "net/base/ip_endpoint.h" |
| + |
| +namespace net { |
| + |
| +namespace { |
| + |
| +class AddressSorterWin : public AddressSorter { |
| + public: |
| + AddressSorterWin() {} |
| + |
| + virtual ~AddressSorterWin() {} |
| + |
| + virtual bool Sort(AddressList* list) const OVERRIDE { |
| + // TODO(szym): Windows XP does not like V4MAPPED IPv6 addresses. |
| + size_t heap_size = sizeof(SOCKET_ADDRESS_LIST) + |
| + list->size() * (sizeof(SOCKET_ADDRESS) + sizeof(SOCKADDR_STORAGE)); |
| + scoped_ptr_malloc<SOCKET_ADDRESS_LIST> heap_in( |
| + reinterpret_cast<SOCKET_ADDRESS_LIST*>(malloc(heap_size))); |
| + |
| + SOCKET_ADDRESS_LIST* sort_list = heap_in.get(); |
| + sort_list->iAddressCount = list->size(); |
| + SOCKADDR_STORAGE* storage = reinterpret_cast<SOCKADDR_STORAGE*>( |
| + sort_list->Address + sort_list->iAddressCount); |
| + |
| + for (size_t i = 0; i < list->size(); ++i) { |
| + IPEndPoint& ipe = (*list)[i]; |
| + // Addresses must be sockaddr_in6. |
| + if (ipe.GetFamily() == AF_INET) { |
| + ipe = IPEndPoint(ConvertIPv4NumberToIPv6Number(ipe.address()), |
| + ipe.port()); |
| + } |
| + |
| + struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(storage + i); |
| + socklen_t addr_len = sizeof(SOCKADDR_STORAGE); |
| + bool result = ipe.ToSockAddr(addr, &addr_len); |
| + DCHECK(result); |
| + sort_list->Address[i].lpSockaddr = addr; |
| + sort_list->Address[i].iSockaddrLength = addr_len; |
| + } |
| + |
| + SOCKET sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); |
|
mmenke
2012/06/07 18:32:34
I believe we technically need to call closesocket
|
| + DCHECK_NE(INVALID_SOCKET, sock); |
| + DWORD result_size = 0; |
| + int result = WSAIoctl(sock, SIO_ADDRESS_LIST_SORT, sort_list, heap_size, |
| + sort_list, heap_size, &result_size, NULL, NULL); |
|
mmenke
2012/06/07 18:32:34
I do wonder about doing this on the IO thread. Su
|
| + if (result == SOCKET_ERROR) { |
| + printf("FAILED %d\n", WSAGetLastError()); |
|
mmenke
2012/06/07 18:32:34
You could make a NetLog entry or something here, i
|
| + return false; // Unsorted. |
| + } |
| + list->clear(); |
| + for (int i = 0; i < sort_list->iAddressCount; ++i) { |
| + IPEndPoint endpoint; |
| + endpoint.FromSockAddr(sort_list->Address[i].lpSockaddr, |
| + sort_list->Address[i].iSockaddrLength); |
| + list->push_back(endpoint); |
| + } |
| + return true; |
| + } |
| + |
| + DISALLOW_COPY_AND_ASSIGN(AddressSorterWin); |
| +}; |
| + |
| +} // namespace |
| + |
| +// static |
| +scoped_ptr<AddressSorter> AddressSorter::CreateAddressSorter() { |
| + return scoped_ptr<AddressSorter>(new AddressSorterWin()); |
| +} |
| + |
| +} // namespace net |
| + |