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