15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2005, Google Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/win32socketserver.h"
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/byteorder.h"
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h"
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h"
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/winping.h"
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/win32window.h"
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <ws2tcpip.h>  // NOLINT
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace talk_base {
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org///////////////////////////////////////////////////////////////////////////////
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Win32Socket
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org///////////////////////////////////////////////////////////////////////////////
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// TODO: Move this to a common place where PhysicalSocketServer can
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// share it.
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Standard MTUs
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const uint16 PACKET_MAXIMUMS[] = {
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  65535,    // Theoretical maximum, Hyperchannel
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  32000,    // Nothing
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  17914,    // 16Mb IBM Token Ring
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  8166,     // IEEE 802.4
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // 4464   // IEEE 802.5 (4Mb max)
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  4352,     // FDDI
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // 2048,  // Wideband Network
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  2002,     // IEEE 802.5 (4Mb recommended)
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // 1536,  // Expermental Ethernet Networks
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // 1500,  // Ethernet, Point-to-Point (default)
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  1492,     // IEEE 802.3
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  1006,     // SLIP, ARPANET
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // 576,   // X.25 Networks
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // 544,   // DEC IP Portal
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // 512,   // NETBIOS
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  508,      // IEEE 802/Source-Rt Bridge, ARCNET
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  296,      // Point-to-Point (low delay)
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  68,       // Official minimum
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  0,        // End of list marker
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int IP_HEADER_SIZE = 20u;
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int ICMP_HEADER_SIZE = 8u;
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const int ICMP_PING_TIMEOUT_MILLIS = 10000u;
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// TODO: Enable for production builds also? Use FormatMessage?
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef _DEBUG
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgLPCSTR WSAErrorToString(int error, LPCSTR *description_result) {
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LPCSTR string = "Unspecified";
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LPCSTR description = "Unspecified description";
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (error) {
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case ERROR_SUCCESS:
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "SUCCESS";
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Operation succeeded";
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAEWOULDBLOCK:
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAEWOULDBLOCK";
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Using a non-blocking socket, will notify later";
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAEACCES:
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAEACCES";
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Access denied, or sharing violation";
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAEADDRNOTAVAIL:
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAEADDRNOTAVAIL";
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Address is not valid in this context";
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAENETDOWN:
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAENETDOWN";
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Network is down";
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAENETUNREACH:
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAENETUNREACH";
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Network is up, but unreachable";
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAENETRESET:
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSANETRESET";
1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Connection has been reset due to keep-alive activity";
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAECONNABORTED:
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAECONNABORTED";
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Aborted by host";
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAECONNRESET:
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAECONNRESET";
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Connection reset by host";
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAETIMEDOUT:
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAETIMEDOUT";
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Timed out, host failed to respond";
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAECONNREFUSED:
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAECONNREFUSED";
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Host actively refused connection";
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAEHOSTDOWN:
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAEHOSTDOWN";
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Host is down";
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAEHOSTUNREACH:
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAEHOSTUNREACH";
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "Host is unreachable";
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case WSAHOST_NOT_FOUND:
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      string = "WSAHOST_NOT_FOUND";
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      description = "No such host is known";
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (description_result) {
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *description_result = description;
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return string;
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LPCSTR description_string;
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LPCSTR error_string = WSAErrorToString(error, &description_string);
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG(LS_INFO) << context << " = " << error
1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    << " (" << error_string << ":" << description_string << ") ["
1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    << address.ToString() << "]";
1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else
1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {}
1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif
1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/////////////////////////////////////////////////////////////////////////////
1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Win32Socket::EventSink
1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/////////////////////////////////////////////////////////////////////////////
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define WM_SOCKETNOTIFY  (WM_USER + 50)
1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define WM_DNSNOTIFY     (WM_USER + 51)
1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct Win32Socket::DnsLookup {
1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  HANDLE handle;
1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  uint16 port;
1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  char buffer[MAXGETHOSTSTRUCT];
1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass Win32Socket::EventSink : public Win32Window {
1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public:
1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  explicit EventSink(Win32Socket * parent) : parent_(parent) { }
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  void Dispose();
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         LRESULT& result);
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  virtual void OnNcDestroy();
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private:
1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result);
1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool OnDnsNotify(WPARAM wParam, LPARAM lParam, LRESULT& result);
1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Win32Socket * parent_;
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::EventSink::Dispose() {
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  parent_ = NULL;
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (::IsWindow(handle())) {
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ::DestroyWindow(handle());
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete this;
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam,
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                       LPARAM lParam, LRESULT& result) {
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (uMsg) {
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case WM_SOCKETNOTIFY:
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case WM_TIMER:
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return OnSocketNotify(uMsg, wParam, lParam, result);
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case WM_DNSNOTIFY:
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return OnDnsNotify(wParam, lParam, result);
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam,
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                            LPARAM lParam, LRESULT& result) {
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  result = 0;
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int wsa_event = WSAGETSELECTEVENT(lParam);
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int wsa_error = WSAGETSELECTERROR(lParam);
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Treat connect timeouts as close notifications
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (uMsg == WM_TIMER) {
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    wsa_event = FD_CLOSE;
2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    wsa_error = WSAETIMEDOUT;
2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (parent_)
2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    parent_->OnSocketNotify(static_cast<SOCKET>(wParam), wsa_event, wsa_error);
2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam,
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                         LRESULT& result) {
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  result = 0;
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int error = WSAGETASYNCERROR(lParam);
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (parent_)
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    parent_->OnDnsNotify(reinterpret_cast<HANDLE>(wParam), error);
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::EventSink::OnNcDestroy() {
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (parent_) {
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "EventSink hwnd is being destroyed, but the event sink"
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     " hasn't yet been disposed.";
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete this;
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/////////////////////////////////////////////////////////////////////////////
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Win32Socket
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/////////////////////////////////////////////////////////////////////////////
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWin32Socket::Win32Socket()
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED), connect_time_(0),
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      closing_(false), close_error_(0), sink_(NULL), dns_(NULL) {
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWin32Socket::~Win32Socket() {
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Close();
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32Socket::CreateT(int family, int type) {
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Close();
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int proto = (SOCK_DGRAM == type) ? IPPROTO_UDP : IPPROTO_TCP;
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socket_ = ::WSASocket(family, type, proto, NULL, NULL, 0);
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (socket_ == INVALID_SOCKET) {
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    UpdateLastError();
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if ((SOCK_DGRAM == type) && !SetAsync(FD_READ | FD_WRITE)) {
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::Attach(SOCKET s) {
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(socket_ == INVALID_SOCKET);
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (socket_ != INVALID_SOCKET)
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(s != INVALID_SOCKET);
2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (s == INVALID_SOCKET)
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socket_ = s;
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  state_ = CS_CONNECTED;
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!SetAsync(FD_READ | FD_WRITE | FD_CLOSE))
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return 0;
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::SetTimeout(int ms) {
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (sink_)
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ::SetTimer(sink_->handle(), 1, ms, 0);
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocketAddress Win32Socket::GetLocalAddress() const {
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sockaddr_storage addr = {0};
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socklen_t addrlen = sizeof(addr);
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int result = ::getsockname(socket_, reinterpret_cast<sockaddr*>(&addr),
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             &addrlen);
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SocketAddress address;
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (result >= 0) {
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SocketAddressFromSockAddrStorage(addr, &address);
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << socket_;
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return address;
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocketAddress Win32Socket::GetRemoteAddress() const {
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sockaddr_storage addr = {0};
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socklen_t addrlen = sizeof(addr);
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int result = ::getpeername(socket_, reinterpret_cast<sockaddr*>(&addr),
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             &addrlen);
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SocketAddress address;
3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (result >= 0) {
3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SocketAddressFromSockAddrStorage(addr, &address);
3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << socket_;
3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return address;
3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::Bind(const SocketAddress& addr) {
3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(socket_ != INVALID_SOCKET);
3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (socket_ == INVALID_SOCKET)
3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sockaddr_storage saddr;
3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t len = addr.ToSockAddrStorage(&saddr);
3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int err = ::bind(socket_,
3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                   reinterpret_cast<sockaddr*>(&saddr),
3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                   static_cast<int>(len));
3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateLastError();
3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return err;
3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::Connect(const SocketAddress& addr) {
3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (state_ != CS_CLOSED) {
3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetError(EALREADY);
3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!addr.IsUnresolvedIP()) {
3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return DoConnect(addr);
3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG_F(LS_INFO) << "async dns lookup (" << addr.hostname() << ")";
3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DnsLookup * dns = new DnsLookup;
3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!sink_) {
3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Explicitly create the sink ourselves here; we can't rely on SetAsync
3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // because we don't have a socket_ yet.
3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateSink();
3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO: Replace with IPv6 compatible lookup.
3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  dns->handle = WSAAsyncGetHostByName(sink_->handle(), WM_DNSNOTIFY,
3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                      addr.hostname().c_str(), dns->buffer,
3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                      sizeof(dns->buffer));
3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!dns->handle) {
3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG_F(LS_ERROR) << "WSAAsyncGetHostByName error: " << WSAGetLastError();
3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete dns;
3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    UpdateLastError();
3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Close();
3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  dns->port = addr.port();
3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  dns_ = dns;
3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  state_ = CS_CONNECTING;
3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return 0;
3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::DoConnect(const SocketAddress& addr) {
3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if ((socket_ == INVALID_SOCKET) && !CreateT(addr.family(), SOCK_STREAM)) {
3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!SetAsync(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE)) {
3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sockaddr_storage saddr = {0};
3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t len = addr.ToSockAddrStorage(&saddr);
3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  connect_time_ = Time();
3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int result = connect(socket_,
3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                       reinterpret_cast<SOCKADDR*>(&saddr),
3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                       static_cast<int>(len));
3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (result != SOCKET_ERROR) {
3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    state_ = CS_CONNECTED;
3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    int code = WSAGetLastError();
3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (code == WSAEWOULDBLOCK) {
3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      state_ = CS_CONNECTING;
3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ReportWSAError("WSAAsync:connect", code, addr);
3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      error_ = code;
3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      Close();
3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return SOCKET_ERROR;
3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  addr_ = addr;
3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return 0;
3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::GetError() const {
4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return error_;
4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::SetError(int error) {
4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  error_ = error;
4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocket::ConnState Win32Socket::GetState() const {
4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return state_;
4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::GetOption(Option opt, int* value) {
4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int slevel;
4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int sopt;
4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (TranslateOption(opt, &slevel, &sopt) == -1)
4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return -1;
4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  char* p = reinterpret_cast<char*>(value);
4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int optlen = sizeof(value);
4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ::getsockopt(socket_, slevel, sopt, p, &optlen);
4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::SetOption(Option opt, int value) {
4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int slevel;
4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int sopt;
4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (TranslateOption(opt, &slevel, &sopt) == -1)
4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return -1;
4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const char* p = reinterpret_cast<const char*>(&value);
4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ::setsockopt(socket_, slevel, sopt, p, sizeof(value));
4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::Send(const void* buffer, size_t length) {
4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int sent = ::send(socket_,
4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    reinterpret_cast<const char*>(buffer),
4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    static_cast<int>(length),
4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    0);
4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateLastError();
4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return sent;
4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::SendTo(const void* buffer, size_t length,
4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                        const SocketAddress& addr) {
4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sockaddr_storage saddr;
4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t addr_len = addr.ToSockAddrStorage(&saddr);
4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int sent = ::sendto(socket_, reinterpret_cast<const char*>(buffer),
4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      static_cast<int>(length), 0,
4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      reinterpret_cast<sockaddr*>(&saddr),
4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      static_cast<int>(addr_len));
4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateLastError();
4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return sent;
4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::Recv(void* buffer, size_t length) {
4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int received = ::recv(socket_, static_cast<char*>(buffer),
4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                        static_cast<int>(length), 0);
4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateLastError();
4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (closing_ && received <= static_cast<int>(length))
4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PostClosed();
4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return received;
4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::RecvFrom(void* buffer, size_t length,
4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          SocketAddress* out_addr) {
4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sockaddr_storage saddr;
4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socklen_t addr_len = sizeof(saddr);
4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int received = ::recvfrom(socket_, static_cast<char*>(buffer),
4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            static_cast<int>(length), 0,
4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            reinterpret_cast<sockaddr*>(&saddr), &addr_len);
4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateLastError();
4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (received != SOCKET_ERROR)
4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SocketAddressFromSockAddrStorage(saddr, out_addr);
4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (closing_ && received <= static_cast<int>(length))
4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PostClosed();
4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return received;
4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::Listen(int backlog) {
4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int err = ::listen(socket_, backlog);
4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!SetAsync(FD_ACCEPT))
4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return SOCKET_ERROR;
4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateLastError();
4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (err == 0)
4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    state_ = CS_CONNECTING;
4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return err;
4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWin32Socket* Win32Socket::Accept(SocketAddress* out_addr) {
4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sockaddr_storage saddr;
4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  socklen_t addr_len = sizeof(saddr);
4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SOCKET s = ::accept(socket_, reinterpret_cast<sockaddr*>(&saddr), &addr_len);
4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateLastError();
4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (s == INVALID_SOCKET)
4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (out_addr)
4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SocketAddressFromSockAddrStorage(saddr, out_addr);
4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Win32Socket* socket = new Win32Socket;
5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (0 == socket->Attach(s))
5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return socket;
5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  delete socket;
5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return NULL;
5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::Close() {
5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int err = 0;
5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (socket_ != INVALID_SOCKET) {
5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    err = ::closesocket(socket_);
5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    socket_ = INVALID_SOCKET;
5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    closing_ = false;
5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    close_error_ = 0;
5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    UpdateLastError();
5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (dns_) {
5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    WSACancelAsyncRequest(dns_->handle);
5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete dns_;
5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    dns_ = NULL;
5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (sink_) {
5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    sink_->Dispose();
5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    sink_ = NULL;
5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  addr_.Clear();
5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  state_ = CS_CLOSED;
5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return err;
5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::EstimateMTU(uint16* mtu) {
5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SocketAddress addr = GetRemoteAddress();
5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (addr.IsAny()) {
5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    error_ = ENOTCONN;
5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return -1;
5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  WinPing ping;
5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ping.IsValid()) {
5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    error_ = EINVAL;  // can't think of a better error ID
5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return -1;
5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                           ICMP_PING_TIMEOUT_MILLIS, 1, false);
5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (result == WinPing::PING_FAIL) {
5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      error_ = EINVAL;  // can't think of a better error ID
5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return -1;
5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (result != WinPing::PING_TOO_LARGE) {
5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *mtu = PACKET_MAXIMUMS[level];
5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return 0;
5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(false);
5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return 0;
5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::CreateSink() {
5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(NULL == sink_);
5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Create window
5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sink_ = new EventSink(this);
5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10);
5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32Socket::SetAsync(int events) {
5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (NULL == sink_) {
5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateSink();
5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(NULL != sink_);
5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // start the async select
5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events)
5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      == SOCKET_ERROR) {
5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    UpdateLastError();
5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Close();
5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32Socket::HandleClosed(int close_error) {
5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // WM_CLOSE will be received before all data has been read, so we need to
5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // hold on to it until the read buffer has been drained.
5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  char ch;
5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  closing_ = true;
5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  close_error_ = close_error;
5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (::recv(socket_, &ch, 1, MSG_PEEK) <= 0);
5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::PostClosed() {
5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // If we see that the buffer is indeed drained, then send the close.
5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  closing_ = false;
5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,
5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                socket_, WSAMAKESELECTREPLY(FD_CLOSE, close_error_));
5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::UpdateLastError() {
6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  error_ = WSAGetLastError();
6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) {
6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (opt) {
6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case OPT_DONTFRAGMENT:
6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *slevel = IPPROTO_IP;
6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *sopt = IP_DONTFRAGMENT;
6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case OPT_RCVBUF:
6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *slevel = SOL_SOCKET;
6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *sopt = SO_RCVBUF;
6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case OPT_SNDBUF:
6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *slevel = SOL_SOCKET;
6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *sopt = SO_SNDBUF;
6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case OPT_NODELAY:
6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *slevel = IPPROTO_TCP;
6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *sopt = TCP_NODELAY;
6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    default:
6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(false);
6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return -1;
6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return 0;
6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::OnSocketNotify(SOCKET socket, int event, int error) {
6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Ignore events if we're already closed.
6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (socket != socket_)
6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  error_ = error;
6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (event) {
6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case FD_CONNECT:
6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (error != ERROR_SUCCESS) {
6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ReportWSAError("WSAAsync:connect notify", error, addr_);
6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef _DEBUG
6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        int32 duration = TimeSince(connect_time_);
6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(LS_INFO) << "WSAAsync:connect error (" << duration
6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     << " ms), faking close";
6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif
6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        state_ = CS_CLOSED;
6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        // If you get an error connecting, close doesn't really do anything
6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        // and it certainly doesn't send back any close notification, but
6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        // we really only maintain a few states, so it is easiest to get
6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        // back into a known state by pretending that a close happened, even
6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        // though the connect event never did occur.
6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        SignalCloseEvent(this, error);
6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else {
6535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef _DEBUG
6545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        int32 duration = TimeSince(connect_time_);
6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)";
6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif
6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        state_ = CS_CONNECTED;
6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        SignalConnectEvent(this);
6595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case FD_ACCEPT:
6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case FD_READ:
6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (error != ERROR_SUCCESS) {
6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ReportWSAError("WSAAsync:read notify", error, addr_);
6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else {
6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        SignalReadEvent(this);
6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case FD_WRITE:
6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (error != ERROR_SUCCESS) {
6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ReportWSAError("WSAAsync:write notify", error, addr_);
6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else {
6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        SignalWriteEvent(this);
6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case FD_CLOSE:
6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (HandleClosed(error)) {
6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ReportWSAError("WSAAsync:close notify", error, addr_);
6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        state_ = CS_CLOSED;
6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        SignalCloseEvent(this, error);
6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32Socket::OnDnsNotify(HANDLE task, int error) {
6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!dns_ || dns_->handle != task)
6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  uint32 ip = 0;
6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (error == 0) {
6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    hostent* pHost = reinterpret_cast<hostent*>(dns_->buffer);
6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    uint32 net_ip = *reinterpret_cast<uint32*>(pHost->h_addr_list[0]);
6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ip = NetworkToHost32(net_ip);
6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG_F(LS_INFO) << "(" << IPAddress(ip).ToSensitiveString()
7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                 << ", " << error << ")";
7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (error == 0) {
7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SocketAddress address(ip, dns_->port);
7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    error = DoConnect(address);
7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Close();
7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (error) {
7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    error_ = error;
7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalCloseEvent(this, error_);
7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete dns_;
7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    dns_ = NULL;
7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org///////////////////////////////////////////////////////////////////////////////
7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Win32SocketServer
7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Provides cricket base services on top of a win32 gui thread
7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org///////////////////////////////////////////////////////////////////////////////
7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic UINT s_wm_wakeup_id = 0;
7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst TCHAR Win32SocketServer::kWindowName[] = L"libjingle Message Window";
7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWin32SocketServer::Win32SocketServer(MessageQueue* message_queue)
7285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    : message_queue_(message_queue),
7295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      wnd_(this),
7305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      posted_(false),
7315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      hdlg_(NULL) {
7325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (s_wm_wakeup_id == 0)
7335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP");
7345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!wnd_.Create(NULL, kWindowName, 0, 0, 0, 0, 0, 0)) {
7355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG_GLE(LS_ERROR) << "Failed to create message window.";
7365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWin32SocketServer::~Win32SocketServer() {
7405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (wnd_.handle() != NULL) {
7415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    KillTimer(wnd_.handle(), 1);
7425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    wnd_.Destroy();
7435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocket* Win32SocketServer::CreateSocket(int type) {
7475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return CreateSocket(AF_INET, type);
7485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSocket* Win32SocketServer::CreateSocket(int family, int type) {
7515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return CreateAsyncSocket(family, type);
7525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) {
7555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return CreateAsyncSocket(AF_INET, type);
7565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgAsyncSocket* Win32SocketServer::CreateAsyncSocket(int family, int type) {
7595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Win32Socket* socket = new Win32Socket;
7605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (socket->CreateT(family, type)) {
7615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return socket;
7625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  delete socket;
7645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return NULL;
7655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32SocketServer::SetMessageQueue(MessageQueue* queue) {
7685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  message_queue_ = queue;
7695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32SocketServer::Wait(int cms, bool process_io) {
7725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  BOOL b;
7735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (process_io) {
7745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Spin the Win32 message pump at least once, and as long as requested.
7755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // This is the Thread::ProcessMessages case.
7765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    uint32 start = Time();
7775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    do {
7785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      MSG msg;
7795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SetTimer(wnd_.handle(), 0, cms, NULL);
7805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // Get the next available message. If we have a modeless dialog, give
7815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // give the message to IsDialogMessage, which will return true if it
7825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // was a message for the dialog that it handled internally.
7835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // Otherwise, dispatch as usual via Translate/DispatchMessage.
7845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      b = GetMessage(&msg, NULL, 0, 0);
7855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (b == -1) {
7865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG_GLE(LS_ERROR) << "GetMessage failed.";
7875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        return false;
7885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else if(b) {
7895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        if (!hdlg_ || !IsDialogMessage(hdlg_, &msg)) {
7905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          TranslateMessage(&msg);
7915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          DispatchMessage(&msg);
7925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        }
7935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
7945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      KillTimer(wnd_.handle(), 0);
7955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } while (b && TimeSince(start) < cms);
7965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (cms != 0) {
7975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Sit and wait forever for a WakeUp. This is the Thread::Send case.
7985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(cms == -1);
7995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    MSG msg;
8005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    b = GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);
8015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    {
8025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      CritScope scope(&cs_);
8035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      posted_ = false;
8045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
8055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
8065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // No-op (cms == 0 && !process_io). This is the Pump case.
8075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    b = TRUE;
8085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (b != FALSE);
8105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32SocketServer::WakeUp() {
8135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (wnd_.handle()) {
8145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Set the "message pending" flag, if not already set.
8155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    {
8165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      CritScope scope(&cs_);
8175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (posted_)
8185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        return;
8195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      posted_ = true;
8205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
8215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0);
8235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Win32SocketServer::Pump() {
8275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Clear the "message pending" flag.
8285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
8295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CritScope scope(&cs_);
8305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    posted_ = false;
8315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Dispatch all the messages that are currently in our queue. If new messages
8345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // are posted during the dispatch, they will be handled in the next Pump.
8355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // We use max(1, ...) to make sure we try to dispatch at least once, since
8365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // this allow us to process "sent" messages, not included in the size() count.
8375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Message msg;
8385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t max_messages_to_process = _max<size_t>(1, message_queue_->size());
8395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       max_messages_to_process > 0 && message_queue_->Get(&msg, 0, false);
8405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       --max_messages_to_process) {
8415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    message_queue_->Dispatch(&msg);
8425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Anything remaining?
8455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int delay = message_queue_->GetDelay();
8465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (delay == -1) {
8475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    KillTimer(wnd_.handle(), 1);
8485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
8495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetTimer(wnd_.handle(), 1, delay, NULL);
8505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32SocketServer::MessageWindow::OnMessage(UINT wm, WPARAM wp,
8545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                 LPARAM lp, LRESULT& lr) {
8555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool handled = false;
8565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) {
8575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ss_->Pump();
8585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    lr = 0;
8595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    handled = true;
8605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return handled;
8625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace talk_base
865