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 |
+ |