1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/win32socketserver.h" 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/byteorder.h" 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h" 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/winping.h" 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/win32window.h" 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <ws2tcpip.h> // NOLINT 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Win32Socket 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// TODO: Move this to a common place where PhysicalSocketServer can 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// share it. 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Standard MTUs 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const uint16 PACKET_MAXIMUMS[] = { 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 65535, // Theoretical maximum, Hyperchannel 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 32000, // Nothing 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 17914, // 16Mb IBM Token Ring 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 8166, // IEEE 802.4 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 4464 // IEEE 802.5 (4Mb max) 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 4352, // FDDI 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 2048, // Wideband Network 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 2002, // IEEE 802.5 (4Mb recommended) 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 1536, // Expermental Ethernet Networks 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 1500, // Ethernet, Point-to-Point (default) 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 1492, // IEEE 802.3 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 1006, // SLIP, ARPANET 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 576, // X.25 Networks 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 544, // DEC IP Portal 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 512, // NETBIOS 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 508, // IEEE 802/Source-Rt Bridge, ARCNET 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 296, // Point-to-Point (low delay) 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 68, // Official minimum 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 0, // End of list marker 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}; 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const uint32 IP_HEADER_SIZE = 20; 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const uint32 ICMP_HEADER_SIZE = 8; 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// TODO: Enable for production builds also? Use FormatMessage? 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochLPCSTR WSAErrorToString(int error, LPCSTR *description_result) { 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPCSTR string = "Unspecified"; 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPCSTR description = "Unspecified description"; 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (error) { 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case ERROR_SUCCESS: 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "SUCCESS"; 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Operation succeeded"; 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAEWOULDBLOCK: 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAEWOULDBLOCK"; 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Using a non-blocking socket, will notify later"; 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAEACCES: 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAEACCES"; 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Access denied, or sharing violation"; 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAEADDRNOTAVAIL: 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAEADDRNOTAVAIL"; 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Address is not valid in this context"; 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAENETDOWN: 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAENETDOWN"; 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Network is down"; 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAENETUNREACH: 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAENETUNREACH"; 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Network is up, but unreachable"; 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAENETRESET: 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSANETRESET"; 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Connection has been reset due to keep-alive activity"; 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAECONNABORTED: 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAECONNABORTED"; 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Aborted by host"; 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAECONNRESET: 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAECONNRESET"; 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Connection reset by host"; 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAETIMEDOUT: 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAETIMEDOUT"; 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Timed out, host failed to respond"; 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAECONNREFUSED: 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAECONNREFUSED"; 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Host actively refused connection"; 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAEHOSTDOWN: 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAEHOSTDOWN"; 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Host is down"; 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAEHOSTUNREACH: 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAEHOSTUNREACH"; 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "Host is unreachable"; 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WSAHOST_NOT_FOUND: 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch string = "WSAHOST_NOT_FOUND"; 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch description = "No such host is known"; 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (description_result) { 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *description_result = description; 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return string; 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) { 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPCSTR description_string; 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPCSTR error_string = WSAErrorToString(error, &description_string); 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << context << " = " << error 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << " (" << error_string << ":" << description_string << ") [" 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << address.ToString() << "]"; 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {} 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch///////////////////////////////////////////////////////////////////////////// 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Win32Socket::EventSink 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch///////////////////////////////////////////////////////////////////////////// 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WM_SOCKETNOTIFY (WM_USER + 50) 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define WM_DNSNOTIFY (WM_USER + 51) 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstruct Win32Socket::DnsLookup { 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch HANDLE handle; 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint16 port; 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char buffer[MAXGETHOSTSTRUCT]; 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}; 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass Win32Socket::EventSink : public Win32Window { 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public: 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch explicit EventSink(Win32Socket * parent) : parent_(parent) { } 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch void Dispose(); 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LRESULT& result); 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch virtual void OnFinalMessage(HWND hWnd); 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private: 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result); 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool OnDnsNotify(WPARAM wParam, LPARAM lParam, LRESULT& result); 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Win32Socket * parent_; 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}; 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::EventSink::Dispose() { 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch parent_ = NULL; 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (::IsWindow(handle())) { 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::DestroyWindow(handle()); 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete this; 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam, 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPARAM lParam, LRESULT& result) { 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (uMsg) { 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WM_SOCKETNOTIFY: 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WM_TIMER: 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return OnSocketNotify(uMsg, wParam, lParam, result); 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case WM_DNSNOTIFY: 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return OnDnsNotify(wParam, lParam, result); 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam, 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPARAM lParam, LRESULT& result) { 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result = 0; 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int wsa_event = WSAGETSELECTEVENT(lParam); 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int wsa_error = WSAGETSELECTERROR(lParam); 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Treat connect timeouts as close notifications 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (uMsg == WM_TIMER) { 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch wsa_event = FD_CLOSE; 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch wsa_error = WSAETIMEDOUT; 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (parent_) 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch parent_->OnSocketNotify(static_cast<SOCKET>(wParam), wsa_event, wsa_error); 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam, 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LRESULT& result) { 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result = 0; 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int error = WSAGETASYNCERROR(lParam); 224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (parent_) 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch parent_->OnDnsNotify(reinterpret_cast<HANDLE>(wParam), error); 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::EventSink::OnFinalMessage(HWND hWnd) { 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete this; 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch///////////////////////////////////////////////////////////////////////////// 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Win32Socket 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch///////////////////////////////////////////////////////////////////////////// 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWin32Socket::Win32Socket() 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED), connect_time_(0), 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch closing_(false), close_error_(0), sink_(NULL), dns_(NULL) { 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWin32Socket::~Win32Socket() { 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Close(); 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Socket::CreateT(int type) { 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Close(); 248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int proto = (SOCK_DGRAM == type) ? IPPROTO_UDP : IPPROTO_TCP; 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket_ = ::WSASocket(AF_INET, type, proto, NULL, NULL, 0); 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (socket_ == INVALID_SOCKET) { 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((SOCK_DGRAM == type) && !SetAsync(FD_READ | FD_WRITE)) { 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::Attach(SOCKET s) { 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(socket_ == INVALID_SOCKET); 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (socket_ != INVALID_SOCKET) 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(s != INVALID_SOCKET); 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (s == INVALID_SOCKET) 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket_ = s; 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CONNECTED; 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!SetAsync(FD_READ | FD_WRITE | FD_CLOSE)) 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::SetTimeout(int ms) { 279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (sink_) 280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::SetTimer(sink_->handle(), 1, ms, 0); 281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocketAddress Win32Socket::GetLocalAddress() const { 284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sockaddr_in addr; 285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socklen_t addrlen = sizeof(addr); 286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int result = ::getsockname(socket_, reinterpret_cast<sockaddr*>(&addr), 287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch &addrlen); 288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SocketAddress address; 289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (result >= 0) { 290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(addrlen == sizeof(addr)); 291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch address.FromSockAddr(addr); 292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket=" 294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << socket_; 295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return address; 297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocketAddress Win32Socket::GetRemoteAddress() const { 300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sockaddr_in addr; 301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socklen_t addrlen = sizeof(addr); 302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int result = ::getpeername(socket_, reinterpret_cast<sockaddr*>(&addr), 303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch &addrlen); 304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(addrlen == sizeof(addr)); 305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SocketAddress address; 306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (result >= 0) { 307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(addrlen == sizeof(addr)); 308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch address.FromSockAddr(addr); 309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket=" 311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << socket_; 312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return address; 314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::Bind(const SocketAddress& addr) { 317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(socket_ != INVALID_SOCKET); 318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (socket_ == INVALID_SOCKET) 319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sockaddr_in saddr; 322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch addr.ToSockAddr(&saddr); 323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int err = ::bind(socket_, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr)); 324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return err; 326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::Connect(const SocketAddress& addr) { 329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((socket_ == INVALID_SOCKET) && !CreateT(SOCK_STREAM)) 330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!sink_ && !SetAsync(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE)) 333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If we have an IP address, connect now. 336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!addr.IsUnresolved()) { 337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return DoConnect(addr); 338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_INFO) << "async dns lookup (" << addr.IPAsString() << ")"; 341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DnsLookup * dns = new DnsLookup; 342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch dns->handle = WSAAsyncGetHostByName(sink_->handle(), WM_DNSNOTIFY, 343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch addr.IPAsString().c_str(), dns->buffer, sizeof(dns->buffer)); 344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!dns->handle) { 346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_ERROR) << "WSAAsyncGetHostByName error: " << WSAGetLastError(); 347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete dns; 348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Close(); 350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch dns->port = addr.port(); 354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch dns_ = dns; 355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CONNECTING; 356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::DoConnect(const SocketAddress& addr) { 360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sockaddr_in saddr; 361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch addr.ToSockAddr(&saddr); 362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch connect_time_ = Time(); 363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int result = connect(socket_, reinterpret_cast<SOCKADDR*>(&saddr), 364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sizeof(saddr)); 365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (result != SOCKET_ERROR) { 366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CONNECTED; 367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int code = WSAGetLastError(); 369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (code == WSAEWOULDBLOCK) { 370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CONNECTING; 371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ReportWSAError("WSAAsync:connect", code, addr); 373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = code; 374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Close(); 375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch addr_ = addr; 379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::GetError() const { 384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return error_; 385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::SetError(int error) { 388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = error; 389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocket::ConnState Win32Socket::GetState() const { 392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return state_; 393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::GetOption(Option opt, int* value) { 396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int slevel; 397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int sopt; 398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (TranslateOption(opt, &slevel, &sopt) == -1) 399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return -1; 400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char* p = reinterpret_cast<char*>(value); 402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int optlen = sizeof(value); 403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ::getsockopt(socket_, slevel, sopt, p, &optlen); 404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::SetOption(Option opt, int value) { 407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int slevel; 408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int sopt; 409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (TranslateOption(opt, &slevel, &sopt) == -1) 410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return -1; 411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char* p = reinterpret_cast<const char*>(&value); 413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ::setsockopt(socket_, slevel, sopt, p, sizeof(value)); 414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::Send(const void *pv, size_t cb) { 417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int sent = ::send(socket_, reinterpret_cast<const char*>(pv), cb, 0); 418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return sent; 420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::SendTo(const void *pv, size_t cb, 423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const SocketAddress& addr) { 424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sockaddr_in saddr; 425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch addr.ToSockAddr(&saddr); 426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int sent = ::sendto(socket_, reinterpret_cast<const char*>(pv), cb, 0, 427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr)); 428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return sent; 430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::Recv(void *pv, size_t cb) { 433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int received = ::recv(socket_, static_cast<char*>(pv), cb, 0); 434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (closing_ && received <= static_cast<int>(cb)) 436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PostClosed(); 437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return received; 438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::RecvFrom(void *pv, size_t cb, 441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SocketAddress *paddr) { 442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sockaddr_in saddr; 443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socklen_t cbAddr = sizeof(saddr); 444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int received = ::recvfrom(socket_, static_cast<char*>(pv), cb, 0, 445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch reinterpret_cast<sockaddr*>(&saddr), &cbAddr); 446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (received != SOCKET_ERROR) 448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch paddr->FromSockAddr(saddr); 449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (closing_ && received <= static_cast<int>(cb)) 450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PostClosed(); 451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return received; 452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::Listen(int backlog) { 455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int err = ::listen(socket_, backlog); 456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!SetAsync(FD_ACCEPT)) 457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return SOCKET_ERROR; 458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (err == 0) 461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CONNECTING; 462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return err; 463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWin32Socket* Win32Socket::Accept(SocketAddress *paddr) { 466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sockaddr_in saddr; 467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socklen_t cbAddr = sizeof(saddr); 468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SOCKET s = ::accept(socket_, reinterpret_cast<sockaddr*>(&saddr), &cbAddr); 469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (s == INVALID_SOCKET) 471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (paddr) 473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch paddr->FromSockAddr(saddr); 474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Win32Socket* socket = new Win32Socket; 475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 == socket->Attach(s)) 476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return socket; 477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete socket; 478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::Close() { 482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int err = 0; 483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (socket_ != INVALID_SOCKET) { 484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch err = ::closesocket(socket_); 485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket_ = INVALID_SOCKET; 486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch closing_ = false; 487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch close_error_ = 0; 488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (dns_) { 491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WSACancelAsyncRequest(dns_->handle); 492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete dns_; 493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch dns_ = NULL; 494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (sink_) { 496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sink_->Dispose(); 497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sink_ = NULL; 498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch addr_.Clear(); 500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CLOSED; 501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return err; 502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::EstimateMTU(uint16* mtu) { 505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SocketAddress addr = GetRemoteAddress(); 506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (addr.IsAny()) { 507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = ENOTCONN; 508f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return -1; 509f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 511f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WinPing ping; 512f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!ping.IsValid()) { 513f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = EINVAL; // can't think of a better error ID 514f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return -1; 515f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 516f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) { 518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE; 519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WinPing::PingResult result = ping.Ping(addr.ip(), size, 0, 1, false); 520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (result == WinPing::PING_FAIL) { 521f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = EINVAL; // can't think of a better error ID 522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return -1; 523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 524f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (result != WinPing::PING_TOO_LARGE) { 525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *mtu = PACKET_MAXIMUMS[level]; 526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(false); 531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 532f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 533f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 534f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Socket::SetAsync(int events) { 535f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(NULL == sink_); 536f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Create window 538f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sink_ = new EventSink(this); 539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10); 540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // start the async select 542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events) 543f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch == SOCKET_ERROR) { 544f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateLastError(); 545f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Close(); 546f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 547f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 548f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 549f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 550f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 551f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 552f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Socket::HandleClosed(int close_error) { 553f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // WM_CLOSE will be received before all data has been read, so we need to 554f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // hold on to it until the read buffer has been drained. 555f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char ch; 556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch closing_ = true; 557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch close_error_ = close_error; 558f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (::recv(socket_, &ch, 1, MSG_PEEK) <= 0); 559f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 560f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 561f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::PostClosed() { 562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If we see that the buffer is indeed drained, then send the close. 563f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch closing_ = false; 564f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY, 565f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch socket_, WSAMAKESELECTREPLY(FD_CLOSE, close_error_)); 566f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::UpdateLastError() { 569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = WSAGetLastError(); 570f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) { 573f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (opt) { 574f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case OPT_DONTFRAGMENT: 575f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *slevel = IPPROTO_IP; 576f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *sopt = IP_DONTFRAGMENT; 577f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 578f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case OPT_RCVBUF: 579f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *slevel = SOL_SOCKET; 580f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *sopt = SO_RCVBUF; 581f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 582f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case OPT_SNDBUF: 583f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *slevel = SOL_SOCKET; 584f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *sopt = SO_SNDBUF; 585f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 586f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case OPT_NODELAY: 587f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *slevel = IPPROTO_TCP; 588f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *sopt = TCP_NODELAY; 589f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 590f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch default: 591f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(false); 592f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return -1; 593f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 594f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 595f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 596f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 597f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::OnSocketNotify(SOCKET socket, int event, int error) { 598f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Ignore events if we're already closed. 599f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (socket != socket_) 600f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 601f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 602f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = error; 603f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (event) { 604f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FD_CONNECT: 605f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (error != ERROR_SUCCESS) { 606f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ReportWSAError("WSAAsync:connect notify", error, addr_); 607f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 608f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int32 duration = TimeSince(connect_time_); 609f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "WSAAsync:connect error (" << duration 610f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << " ms), faking close"; 611f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 612f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CLOSED; 613f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If you get an error connecting, close doesn't really do anything 614f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // and it certainly doesn't send back any close notification, but 615f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // we really only maintain a few states, so it is easiest to get 616f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // back into a known state by pretending that a close happened, even 617f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // though the connect event never did occur. 618f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalCloseEvent(this, error); 619f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 620f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 621f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int32 duration = TimeSince(connect_time_); 622f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)"; 623f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 624f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CONNECTED; 625f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalConnectEvent(this); 626f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 627f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 628f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 629f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FD_ACCEPT: 630f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FD_READ: 631f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (error != ERROR_SUCCESS) { 632f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ReportWSAError("WSAAsync:read notify", error, addr_); 633f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 634f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalReadEvent(this); 635f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 636f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 637f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 638f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FD_WRITE: 639f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (error != ERROR_SUCCESS) { 640f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ReportWSAError("WSAAsync:write notify", error, addr_); 641f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 642f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalWriteEvent(this); 643f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 644f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 645f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 646f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FD_CLOSE: 647f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (HandleClosed(error)) { 648f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ReportWSAError("WSAAsync:close notify", error, addr_); 649f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state_ = CS_CLOSED; 650f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalCloseEvent(this, error); 651f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 652f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 653f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 654f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 655f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 656f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32Socket::OnDnsNotify(HANDLE task, int error) { 657f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!dns_ || dns_->handle != task) 658f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 659f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 660f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 ip = 0; 661f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (error == 0) { 662f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch hostent* pHost = reinterpret_cast<hostent*>(dns_->buffer); 663f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 net_ip = *reinterpret_cast<uint32*>(pHost->h_addr_list[0]); 664f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ip = NetworkToHost32(net_ip); 665f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 666f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 667f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_F(LS_INFO) << "(" << SocketAddress::IPToString(ip) 668f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << ", " << error << ")"; 669f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 670f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (error == 0) { 671f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SocketAddress address(ip, dns_->port); 672f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error = DoConnect(address); 673f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 674f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Close(); 675f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 676f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 677f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (error) { 678f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch error_ = error; 679f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SignalCloseEvent(this, error_); 680f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 681f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete dns_; 682f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch dns_ = NULL; 683f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 684f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 685f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 686f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 687f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Win32SocketServer 688f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Provides cricket base services on top of a win32 gui thread 689f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////// 690f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 691f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic UINT s_wm_wakeup_id = 0; 692f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst TCHAR Win32SocketServer::kWindowName[] = L"libjingle Message Window"; 693f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 694f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWin32SocketServer::Win32SocketServer(MessageQueue *message_queue) 695f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : message_queue_(message_queue), wnd_(this), posted_(false) { 696f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (s_wm_wakeup_id == 0) 697f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP"); 698f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!wnd_.Create(NULL, kWindowName, 0, 0, 0, 0, 0, 0)) { 699f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_GLE(LS_ERROR) << "Failed to create message window."; 700f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 701f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 702f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 703f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWin32SocketServer::~Win32SocketServer() { 704f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (wnd_.handle() != NULL) { 705f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch KillTimer(wnd_.handle(), 1); 706f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch wnd_.Destroy(); 707f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 708f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 709f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 710f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocket* Win32SocketServer::CreateSocket(int type) { 711f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return CreateAsyncSocket(type); 712f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 713f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 714f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochAsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) { 715f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Win32Socket* socket = new Win32Socket; 716f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (socket->CreateT(type)) { 717f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return socket; 718f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 719f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete socket; 720f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 721f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 722f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 723f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32SocketServer::SetMessageQueue(MessageQueue* queue) { 724f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch message_queue_ = queue; 725f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 726f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 727f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32SocketServer::Wait(int cms, bool process_io) { 728f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch BOOL b; 729f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (process_io) { 730f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Spin the Win32 message pump at least once, and as long as requested. 731f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // This is the Thread::ProcessMessages case. 732f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 start = Time(); 733f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MSG msg; 734f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch do { 735f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetTimer(wnd_.handle(), 0, cms, NULL); 736f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch b = GetMessage(&msg, NULL, 0, 0); 737f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (b) { 738f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch TranslateMessage(&msg); 739f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DispatchMessage(&msg); 740f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 741f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch KillTimer(wnd_.handle(), 0); 742f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } while (b && TimeSince(start) < cms); 743f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (cms != 0) { 744f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Sit and wait forever for a WakeUp. This is the Thread::Send case. 745f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(cms == -1); 746f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MSG msg; 747f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch b = GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id); 748f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch { 749f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope scope(&cs_); 750f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch posted_ = false; 751f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 752f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 753f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // No-op (cms == 0 && !process_io). This is the Pump case. 754f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch b = TRUE; 755f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 756f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (b != FALSE); 757f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 758f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 759f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32SocketServer::WakeUp() { 760f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (wnd_.handle()) { 761f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Set the "message pending" flag, if not already set. 762f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch { 763f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope scope(&cs_); 764f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (posted_) 765f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 766f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch posted_ = true; 767f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 768f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 769f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0); 770f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 771f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 772f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 773f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Win32SocketServer::Pump() { 774f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Clear the "message pending" flag. 775f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch { 776f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope scope(&cs_); 777f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch posted_ = false; 778f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 779f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 780f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Dispatch all the messages that are currently in our queue. If new messages 781f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // are posted during the dispatch, they will be handled in the next Pump. 782f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We use max(1, ...) to make sure we try to dispatch at least once, since 783f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // this allow us to process "sent" messages, not included in the size() count. 784f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Message msg; 785f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t max_messages_to_process = _max<size_t>(1, message_queue_->size()); 786f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch max_messages_to_process > 0 && message_queue_->Get(&msg, 0, false); 787f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch --max_messages_to_process) { 788f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch message_queue_->Dispatch(&msg); 789f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 790f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 791f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Anything remaining? 792f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int delay = message_queue_->GetDelay(); 793f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (delay == -1) { 794f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch KillTimer(wnd_.handle(), 1); 795f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 796f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetTimer(wnd_.handle(), 1, delay, NULL); 797f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 798f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 799f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 800f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32SocketServer::MessageWindow::OnMessage(UINT wm, WPARAM wp, 801f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPARAM lp, LRESULT& lr) { 802f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool handled = false; 803f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) { 804f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ss_->Pump(); 805f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch lr = 0; 806f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch handled = true; 807f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 808f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return handled; 809f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 810f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 811f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base 812