1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/*
2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *
4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */
10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
11f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/win32socketserver.h"
12ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org
13ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org#include <algorithm>
14ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org#include <ws2tcpip.h>  // NOLINT
15ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org
16f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/byteorder.h"
17f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/common.h"
18f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/logging.h"
19f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/win32window.h"
20ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org#include "webrtc/base/winping.h"
21f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
22f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgnamespace rtc {
23f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
24f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
25f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Win32Socket
26f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
27f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
28f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// TODO: Move this to a common place where PhysicalSocketServer can
29f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// share it.
30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Standard MTUs
310c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmstatic const uint16_t PACKET_MAXIMUMS[] = {
320c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    65535,  // Theoretical maximum, Hyperchannel
330c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    32000,  // Nothing
340c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    17914,  // 16Mb IBM Token Ring
350c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    8166,   // IEEE 802.4
360c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    // 4464   // IEEE 802.5 (4Mb max)
370c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    4352,   // FDDI
380c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    // 2048,  // Wideband Network
390c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    2002,   // IEEE 802.5 (4Mb recommended)
400c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    // 1536,  // Expermental Ethernet Networks
410c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    // 1500,  // Ethernet, Point-to-Point (default)
420c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    1492,   // IEEE 802.3
430c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    1006,   // SLIP, ARPANET
440c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    // 576,   // X.25 Networks
450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    // 544,   // DEC IP Portal
460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    // 512,   // NETBIOS
470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    508,    // IEEE 802/Source-Rt Bridge, ARCNET
480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    296,    // Point-to-Point (low delay)
490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    68,     // Official minimum
500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    0,      // End of list marker
51f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
52f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
53f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstatic const int IP_HEADER_SIZE = 20u;
54f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstatic const int ICMP_HEADER_SIZE = 8u;
55f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstatic const int ICMP_PING_TIMEOUT_MILLIS = 10000u;
56f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
57f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// TODO: Enable for production builds also? Use FormatMessage?
58a41ab9326c8f0f7eb738e5d51a239a2b9e276361tfarina#if !defined(NDEBUG)
59f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgLPCSTR WSAErrorToString(int error, LPCSTR *description_result) {
60f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  LPCSTR string = "Unspecified";
61f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  LPCSTR description = "Unspecified description";
62f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  switch (error) {
63f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case ERROR_SUCCESS:
64f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "SUCCESS";
65f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Operation succeeded";
66f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
67f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAEWOULDBLOCK:
68f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAEWOULDBLOCK";
69f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Using a non-blocking socket, will notify later";
70f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
71f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAEACCES:
72f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAEACCES";
73f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Access denied, or sharing violation";
74f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
75f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAEADDRNOTAVAIL:
76f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAEADDRNOTAVAIL";
77f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Address is not valid in this context";
78f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
79f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAENETDOWN:
80f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAENETDOWN";
81f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Network is down";
82f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
83f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAENETUNREACH:
84f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAENETUNREACH";
85f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Network is up, but unreachable";
86f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
87f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAENETRESET:
88f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSANETRESET";
89f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Connection has been reset due to keep-alive activity";
90f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
91f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAECONNABORTED:
92f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAECONNABORTED";
93f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Aborted by host";
94f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
95f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAECONNRESET:
96f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAECONNRESET";
97f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Connection reset by host";
98f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
99f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAETIMEDOUT:
100f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAETIMEDOUT";
101f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Timed out, host failed to respond";
102f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
103f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAECONNREFUSED:
104f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAECONNREFUSED";
105f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Host actively refused connection";
106f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
107f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAEHOSTDOWN:
108f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAEHOSTDOWN";
109f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Host is down";
110f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
111f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAEHOSTUNREACH:
112f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAEHOSTUNREACH";
113f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "Host is unreachable";
114f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
115f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case WSAHOST_NOT_FOUND:
116f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      string = "WSAHOST_NOT_FOUND";
117f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      description = "No such host is known";
118f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
119f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
120f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (description_result) {
121f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    *description_result = description;
122f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
123f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return string;
124f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
125f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
126f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {
127f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  LPCSTR description_string;
128f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  LPCSTR error_string = WSAErrorToString(error, &description_string);
129f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  LOG(LS_INFO) << context << " = " << error
130f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    << " (" << error_string << ":" << description_string << ") ["
131f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    << address.ToString() << "]";
132f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
133f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#else
134f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {}
135f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#endif
136f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
137f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
138f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Win32Socket::EventSink
139f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
140f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
141f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define WM_SOCKETNOTIFY  (WM_USER + 50)
142f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define WM_DNSNOTIFY     (WM_USER + 51)
143f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
144f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstruct Win32Socket::DnsLookup {
145f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  HANDLE handle;
1460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint16_t port;
147f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  char buffer[MAXGETHOSTSTRUCT];
148f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
149f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
150f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass Win32Socket::EventSink : public Win32Window {
151f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
152f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  explicit EventSink(Win32Socket * parent) : parent_(parent) { }
153f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
154f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  void Dispose();
155f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
156f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
157f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                         LRESULT& result);
158f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  virtual void OnNcDestroy();
159f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
160f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org private:
161f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  bool OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result);
162f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  bool OnDnsNotify(WPARAM wParam, LPARAM lParam, LRESULT& result);
163f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
164f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Win32Socket * parent_;
165f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
166f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
167f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::EventSink::Dispose() {
168f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  parent_ = NULL;
169f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (::IsWindow(handle())) {
170f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ::DestroyWindow(handle());
171f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
172f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete this;
173f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
174f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
175f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
176f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam,
177f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                       LPARAM lParam, LRESULT& result) {
178f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  switch (uMsg) {
179f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  case WM_SOCKETNOTIFY:
180f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  case WM_TIMER:
181f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return OnSocketNotify(uMsg, wParam, lParam, result);
182f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  case WM_DNSNOTIFY:
183f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return OnDnsNotify(wParam, lParam, result);
184f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
185f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return false;
186f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
187f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
188f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam,
189f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                            LPARAM lParam, LRESULT& result) {
190f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  result = 0;
191f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
192f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int wsa_event = WSAGETSELECTEVENT(lParam);
193f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int wsa_error = WSAGETSELECTERROR(lParam);
194f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
195f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Treat connect timeouts as close notifications
196f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (uMsg == WM_TIMER) {
197f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    wsa_event = FD_CLOSE;
198f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    wsa_error = WSAETIMEDOUT;
199f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
200f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
201f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (parent_)
202f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    parent_->OnSocketNotify(static_cast<SOCKET>(wParam), wsa_event, wsa_error);
203f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return true;
204f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
205f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
206f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam,
207f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                         LRESULT& result) {
208f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  result = 0;
209f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
210f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int error = WSAGETASYNCERROR(lParam);
211f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (parent_)
212f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    parent_->OnDnsNotify(reinterpret_cast<HANDLE>(wParam), error);
213f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return true;
214f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
215f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
216f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::EventSink::OnNcDestroy() {
217f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (parent_) {
218f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LS_ERROR) << "EventSink hwnd is being destroyed, but the event sink"
219f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                     " hasn't yet been disposed.";
220f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
221f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete this;
222f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
223f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
224f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
225f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
226f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Win32Socket
227f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
228f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
229f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgWin32Socket::Win32Socket()
230f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED), connect_time_(0),
231f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      closing_(false), close_error_(0), sink_(NULL), dns_(NULL) {
232f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
233f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
234f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgWin32Socket::~Win32Socket() {
235f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Close();
236f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
237f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
238f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32Socket::CreateT(int family, int type) {
239f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Close();
240f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int proto = (SOCK_DGRAM == type) ? IPPROTO_UDP : IPPROTO_TCP;
241f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  socket_ = ::WSASocket(family, type, proto, NULL, NULL, 0);
242f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (socket_ == INVALID_SOCKET) {
243f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    UpdateLastError();
244f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return false;
245f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
246f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if ((SOCK_DGRAM == type) && !SetAsync(FD_READ | FD_WRITE)) {
247f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return false;
248f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
249f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return true;
250f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
251f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
252f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::Attach(SOCKET s) {
253f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ASSERT(socket_ == INVALID_SOCKET);
254f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (socket_ != INVALID_SOCKET)
255f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
256f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
257f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ASSERT(s != INVALID_SOCKET);
258f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (s == INVALID_SOCKET)
259f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
260f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
261f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  socket_ = s;
262f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  state_ = CS_CONNECTED;
263f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
264f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!SetAsync(FD_READ | FD_WRITE | FD_CLOSE))
265f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
266f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
267f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return 0;
268f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
269f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
270f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::SetTimeout(int ms) {
271f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (sink_)
272f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ::SetTimer(sink_->handle(), 1, ms, 0);
273f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
274f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
275f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocketAddress Win32Socket::GetLocalAddress() const {
276f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_storage addr = {0};
277f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  socklen_t addrlen = sizeof(addr);
278f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int result = ::getsockname(socket_, reinterpret_cast<sockaddr*>(&addr),
279f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                             &addrlen);
280f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SocketAddress address;
281f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (result >= 0) {
282f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SocketAddressFromSockAddrStorage(addr, &address);
283f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
284f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket="
285f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                    << socket_;
286f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
287f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return address;
288f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
289f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
290f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocketAddress Win32Socket::GetRemoteAddress() const {
291f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_storage addr = {0};
292f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  socklen_t addrlen = sizeof(addr);
293f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int result = ::getpeername(socket_, reinterpret_cast<sockaddr*>(&addr),
294f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                             &addrlen);
295f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SocketAddress address;
296f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (result >= 0) {
297f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SocketAddressFromSockAddrStorage(addr, &address);
298f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
299f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket="
300f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                    << socket_;
301f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
302f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return address;
303f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
304f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
305f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::Bind(const SocketAddress& addr) {
306f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ASSERT(socket_ != INVALID_SOCKET);
307f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (socket_ == INVALID_SOCKET)
308f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
309f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
310f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_storage saddr;
311f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  size_t len = addr.ToSockAddrStorage(&saddr);
312f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int err = ::bind(socket_,
313f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                   reinterpret_cast<sockaddr*>(&saddr),
314f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                   static_cast<int>(len));
315f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  UpdateLastError();
316f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return err;
317f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
318f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
319f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::Connect(const SocketAddress& addr) {
320f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (state_ != CS_CLOSED) {
321f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SetError(EALREADY);
322f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
323f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
324f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
325f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!addr.IsUnresolvedIP()) {
326f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return DoConnect(addr);
327f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
328f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
329f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  LOG_F(LS_INFO) << "async dns lookup (" << addr.hostname() << ")";
330f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  DnsLookup * dns = new DnsLookup;
331f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!sink_) {
332f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Explicitly create the sink ourselves here; we can't rely on SetAsync
333f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // because we don't have a socket_ yet.
334f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    CreateSink();
335f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
336f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // TODO: Replace with IPv6 compatible lookup.
337f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  dns->handle = WSAAsyncGetHostByName(sink_->handle(), WM_DNSNOTIFY,
338f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                      addr.hostname().c_str(), dns->buffer,
339f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                      sizeof(dns->buffer));
340f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
341f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!dns->handle) {
342f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG_F(LS_ERROR) << "WSAAsyncGetHostByName error: " << WSAGetLastError();
343f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete dns;
344f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    UpdateLastError();
345f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Close();
346f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
347f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
348f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
349f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  dns->port = addr.port();
350f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  dns_ = dns;
351f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  state_ = CS_CONNECTING;
352f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return 0;
353f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
354f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
355f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::DoConnect(const SocketAddress& addr) {
356f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if ((socket_ == INVALID_SOCKET) && !CreateT(addr.family(), SOCK_STREAM)) {
357f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
358f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
359f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!SetAsync(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE)) {
360f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
361f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
362f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
363f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_storage saddr = {0};
364f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  size_t len = addr.ToSockAddrStorage(&saddr);
365f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  connect_time_ = Time();
366f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int result = connect(socket_,
367f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                       reinterpret_cast<SOCKADDR*>(&saddr),
368f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                       static_cast<int>(len));
369f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (result != SOCKET_ERROR) {
370f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    state_ = CS_CONNECTED;
371f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
372f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    int code = WSAGetLastError();
373f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (code == WSAEWOULDBLOCK) {
374f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      state_ = CS_CONNECTING;
375f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    } else {
376f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      ReportWSAError("WSAAsync:connect", code, addr);
377f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      error_ = code;
378f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      Close();
379f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return SOCKET_ERROR;
380f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
381f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
382f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  addr_ = addr;
383f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
384f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return 0;
385f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
386f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
387f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::GetError() const {
388f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return error_;
389f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
390f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
391f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::SetError(int error) {
392f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  error_ = error;
393f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
394f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
395f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocket::ConnState Win32Socket::GetState() const {
396f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return state_;
397f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
398f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
399f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::GetOption(Option opt, int* value) {
400f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int slevel;
401f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int sopt;
402f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (TranslateOption(opt, &slevel, &sopt) == -1)
403f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return -1;
404f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
405f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  char* p = reinterpret_cast<char*>(value);
406f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int optlen = sizeof(value);
407f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return ::getsockopt(socket_, slevel, sopt, p, &optlen);
408f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
409f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
410f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::SetOption(Option opt, int value) {
411f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int slevel;
412f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int sopt;
413f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (TranslateOption(opt, &slevel, &sopt) == -1)
414f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return -1;
415f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
416f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  const char* p = reinterpret_cast<const char*>(&value);
417f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return ::setsockopt(socket_, slevel, sopt, p, sizeof(value));
418f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
419f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
420f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::Send(const void* buffer, size_t length) {
421f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int sent = ::send(socket_,
422f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                    reinterpret_cast<const char*>(buffer),
423f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                    static_cast<int>(length),
424f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                    0);
425f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  UpdateLastError();
426f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return sent;
427f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
428f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
429f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::SendTo(const void* buffer, size_t length,
430f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                        const SocketAddress& addr) {
431f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_storage saddr;
432f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  size_t addr_len = addr.ToSockAddrStorage(&saddr);
433f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int sent = ::sendto(socket_, reinterpret_cast<const char*>(buffer),
434f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                      static_cast<int>(length), 0,
435f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                      reinterpret_cast<sockaddr*>(&saddr),
436f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                      static_cast<int>(addr_len));
437f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  UpdateLastError();
438f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return sent;
439f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
440f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
441f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::Recv(void* buffer, size_t length) {
442f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int received = ::recv(socket_, static_cast<char*>(buffer),
443f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                        static_cast<int>(length), 0);
444f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  UpdateLastError();
445f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (closing_ && received <= static_cast<int>(length))
446f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    PostClosed();
447f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return received;
448f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
449f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
450f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::RecvFrom(void* buffer, size_t length,
451f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                          SocketAddress* out_addr) {
452f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_storage saddr;
453f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  socklen_t addr_len = sizeof(saddr);
454f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int received = ::recvfrom(socket_, static_cast<char*>(buffer),
455f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                            static_cast<int>(length), 0,
456f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                            reinterpret_cast<sockaddr*>(&saddr), &addr_len);
457f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  UpdateLastError();
458f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (received != SOCKET_ERROR)
459f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SocketAddressFromSockAddrStorage(saddr, out_addr);
460f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (closing_ && received <= static_cast<int>(length))
461f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    PostClosed();
462f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return received;
463f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
464f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
465f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::Listen(int backlog) {
466f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int err = ::listen(socket_, backlog);
467f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!SetAsync(FD_ACCEPT))
468f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
469f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
470f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  UpdateLastError();
471f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (err == 0)
472f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    state_ = CS_CONNECTING;
473f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return err;
474f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
475f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
476f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgWin32Socket* Win32Socket::Accept(SocketAddress* out_addr) {
477f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_storage saddr;
478f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  socklen_t addr_len = sizeof(saddr);
479f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SOCKET s = ::accept(socket_, reinterpret_cast<sockaddr*>(&saddr), &addr_len);
480f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  UpdateLastError();
481f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (s == INVALID_SOCKET)
482f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return NULL;
483f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (out_addr)
484f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SocketAddressFromSockAddrStorage(saddr, out_addr);
485f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Win32Socket* socket = new Win32Socket;
486f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (0 == socket->Attach(s))
487f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return socket;
488f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete socket;
489f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return NULL;
490f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
491f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
492f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::Close() {
493f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int err = 0;
494f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (socket_ != INVALID_SOCKET) {
495f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    err = ::closesocket(socket_);
496f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    socket_ = INVALID_SOCKET;
497f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    closing_ = false;
498f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    close_error_ = 0;
499f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    UpdateLastError();
500f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
501f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (dns_) {
502f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    WSACancelAsyncRequest(dns_->handle);
503f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete dns_;
504f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    dns_ = NULL;
505f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
506f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (sink_) {
507f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    sink_->Dispose();
508f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    sink_ = NULL;
509f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
510f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  addr_.Clear();
511f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  state_ = CS_CLOSED;
512f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return err;
513f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
514f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
5150c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmint Win32Socket::EstimateMTU(uint16_t* mtu) {
516f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SocketAddress addr = GetRemoteAddress();
5178ac544e811439f79b2ec0c676f383ddc51ef2ed5tfarina  if (addr.IsAnyIP()) {
518f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    error_ = ENOTCONN;
519f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return -1;
520f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
521f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
522f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  WinPing ping;
523f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!ping.IsValid()) {
524f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    error_ = EINVAL;  // can't think of a better error ID
525f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return -1;
526f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
527f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
528f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) {
5290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int32_t size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
530f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    WinPing::PingResult result = ping.Ping(addr.ipaddr(), size,
531f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                           ICMP_PING_TIMEOUT_MILLIS, 1, false);
532f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (result == WinPing::PING_FAIL) {
533f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      error_ = EINVAL;  // can't think of a better error ID
534f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return -1;
535f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
536f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (result != WinPing::PING_TOO_LARGE) {
537f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *mtu = PACKET_MAXIMUMS[level];
538f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return 0;
539f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
540f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
541f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
542f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ASSERT(false);
543f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return 0;
544f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
545f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
546f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::CreateSink() {
547f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ASSERT(NULL == sink_);
548f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
549f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Create window
550f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sink_ = new EventSink(this);
551f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10);
552f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
553f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
554f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32Socket::SetAsync(int events) {
555f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (NULL == sink_) {
556f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    CreateSink();
557f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ASSERT(NULL != sink_);
558f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
559f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
560f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // start the async select
561f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events)
562f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      == SOCKET_ERROR) {
563f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    UpdateLastError();
564f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Close();
565f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return false;
566f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
567f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
568f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return true;
569f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
570f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
571f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32Socket::HandleClosed(int close_error) {
572f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // WM_CLOSE will be received before all data has been read, so we need to
573f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // hold on to it until the read buffer has been drained.
574f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  char ch;
575f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  closing_ = true;
576f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  close_error_ = close_error;
577f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return (::recv(socket_, &ch, 1, MSG_PEEK) <= 0);
578f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
579f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
580f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::PostClosed() {
581f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // If we see that the buffer is indeed drained, then send the close.
582f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  closing_ = false;
583f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY,
584f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                socket_, WSAMAKESELECTREPLY(FD_CLOSE, close_error_));
585f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
586f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
587f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::UpdateLastError() {
588f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  error_ = WSAGetLastError();
589f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
590f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
591f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgint Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) {
592f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  switch (opt) {
593f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case OPT_DONTFRAGMENT:
594f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *slevel = IPPROTO_IP;
595f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *sopt = IP_DONTFRAGMENT;
596f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
597f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case OPT_RCVBUF:
598f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *slevel = SOL_SOCKET;
599f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *sopt = SO_RCVBUF;
600f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
601f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case OPT_SNDBUF:
602f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *slevel = SOL_SOCKET;
603f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *sopt = SO_SNDBUF;
604f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
605f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case OPT_NODELAY:
606f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *slevel = IPPROTO_TCP;
607f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      *sopt = TCP_NODELAY;
608f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
609f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case OPT_DSCP:
610f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      LOG(LS_WARNING) << "Socket::OPT_DSCP not supported.";
611f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return -1;
612f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    default:
613f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      ASSERT(false);
614f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return -1;
615f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
616f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return 0;
617f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
618f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
619f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::OnSocketNotify(SOCKET socket, int event, int error) {
620f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Ignore events if we're already closed.
621f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (socket != socket_)
622f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return;
623f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
624f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  error_ = error;
625f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  switch (event) {
626f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case FD_CONNECT:
627f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      if (error != ERROR_SUCCESS) {
628f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        ReportWSAError("WSAAsync:connect notify", error, addr_);
629a41ab9326c8f0f7eb738e5d51a239a2b9e276361tfarina#if !defined(NDEBUG)
6300c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        int32_t duration = TimeSince(connect_time_);
631f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        LOG(LS_INFO) << "WSAAsync:connect error (" << duration
632f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                     << " ms), faking close";
633f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#endif
634f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        state_ = CS_CLOSED;
635f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        // If you get an error connecting, close doesn't really do anything
636f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        // and it certainly doesn't send back any close notification, but
637f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        // we really only maintain a few states, so it is easiest to get
638f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        // back into a known state by pretending that a close happened, even
639f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        // though the connect event never did occur.
640f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        SignalCloseEvent(this, error);
641f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      } else {
642a41ab9326c8f0f7eb738e5d51a239a2b9e276361tfarina#if !defined(NDEBUG)
6430c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        int32_t duration = TimeSince(connect_time_);
644f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)";
645f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#endif
646f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        state_ = CS_CONNECTED;
647f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        SignalConnectEvent(this);
648f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      }
649f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
650f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
651f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case FD_ACCEPT:
652f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case FD_READ:
653f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      if (error != ERROR_SUCCESS) {
654f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        ReportWSAError("WSAAsync:read notify", error, addr_);
655f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      } else {
656f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        SignalReadEvent(this);
657f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      }
658f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
659f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
660f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case FD_WRITE:
661f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      if (error != ERROR_SUCCESS) {
662f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        ReportWSAError("WSAAsync:write notify", error, addr_);
663f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      } else {
664f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        SignalWriteEvent(this);
665f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      }
666f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
667f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
668f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    case FD_CLOSE:
669f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      if (HandleClosed(error)) {
670f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        ReportWSAError("WSAAsync:close notify", error, addr_);
671f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        state_ = CS_CLOSED;
672f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        SignalCloseEvent(this, error);
673f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      }
674f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      break;
675f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
676f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
677f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
678f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32Socket::OnDnsNotify(HANDLE task, int error) {
679f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!dns_ || dns_->handle != task)
680f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return;
681f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
6820c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t ip = 0;
683f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (error == 0) {
684f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    hostent* pHost = reinterpret_cast<hostent*>(dns_->buffer);
6850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint32_t net_ip = *reinterpret_cast<uint32_t*>(pHost->h_addr_list[0]);
686f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ip = NetworkToHost32(net_ip);
687f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
688f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
689f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  LOG_F(LS_INFO) << "(" << IPAddress(ip).ToSensitiveString()
690f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                 << ", " << error << ")";
691f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
692f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (error == 0) {
693f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SocketAddress address(ip, dns_->port);
694f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    error = DoConnect(address);
695f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
696f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Close();
697f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
698f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
699f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (error) {
700f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    error_ = error;
701f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SignalCloseEvent(this, error_);
702f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
703f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete dns_;
704f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    dns_ = NULL;
705f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
706f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
707f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
708f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
709f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Win32SocketServer
710f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Provides cricket base services on top of a win32 gui thread
711f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
712f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
713f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgstatic UINT s_wm_wakeup_id = 0;
714f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgconst TCHAR Win32SocketServer::kWindowName[] = L"libjingle Message Window";
715f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
716f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgWin32SocketServer::Win32SocketServer(MessageQueue* message_queue)
717f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    : message_queue_(message_queue),
718f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      wnd_(this),
719f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      posted_(false),
720f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      hdlg_(NULL) {
721f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (s_wm_wakeup_id == 0)
722f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP");
723f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!wnd_.Create(NULL, kWindowName, 0, 0, 0, 0, 0, 0)) {
724f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG_GLE(LS_ERROR) << "Failed to create message window.";
725f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
726f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
727f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
728f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgWin32SocketServer::~Win32SocketServer() {
729f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (wnd_.handle() != NULL) {
730f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    KillTimer(wnd_.handle(), 1);
731f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    wnd_.Destroy();
732f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
733f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
734f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
735f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocket* Win32SocketServer::CreateSocket(int type) {
736f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return CreateSocket(AF_INET, type);
737f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
738f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
739f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocket* Win32SocketServer::CreateSocket(int family, int type) {
740f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return CreateAsyncSocket(family, type);
741f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
742f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
743f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) {
744f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return CreateAsyncSocket(AF_INET, type);
745f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
746f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
747f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncSocket* Win32SocketServer::CreateAsyncSocket(int family, int type) {
748f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Win32Socket* socket = new Win32Socket;
749f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (socket->CreateT(family, type)) {
750f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return socket;
751f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
752f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete socket;
753f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return NULL;
754f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
755f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
756f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32SocketServer::SetMessageQueue(MessageQueue* queue) {
757f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  message_queue_ = queue;
758f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
759f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
760f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32SocketServer::Wait(int cms, bool process_io) {
761f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  BOOL b;
762f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (process_io) {
763f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Spin the Win32 message pump at least once, and as long as requested.
764f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // This is the Thread::ProcessMessages case.
7650c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint32_t start = Time();
766f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    do {
767f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      MSG msg;
768f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      SetTimer(wnd_.handle(), 0, cms, NULL);
769f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      // Get the next available message. If we have a modeless dialog, give
770f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      // give the message to IsDialogMessage, which will return true if it
771f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      // was a message for the dialog that it handled internally.
772f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      // Otherwise, dispatch as usual via Translate/DispatchMessage.
773f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      b = GetMessage(&msg, NULL, 0, 0);
774f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      if (b == -1) {
775f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        LOG_GLE(LS_ERROR) << "GetMessage failed.";
776f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        return false;
777f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      } else if(b) {
778f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        if (!hdlg_ || !IsDialogMessage(hdlg_, &msg)) {
779f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org          TranslateMessage(&msg);
780f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org          DispatchMessage(&msg);
781f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        }
782f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      }
783f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      KillTimer(wnd_.handle(), 0);
784f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    } while (b && TimeSince(start) < cms);
785f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else if (cms != 0) {
786f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Sit and wait forever for a WakeUp. This is the Thread::Send case.
787f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ASSERT(cms == -1);
788f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    MSG msg;
789f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    b = GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);
790f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    {
791f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      CritScope scope(&cs_);
792f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      posted_ = false;
793f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
794f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
795f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // No-op (cms == 0 && !process_io). This is the Pump case.
796f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    b = TRUE;
797f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
798f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return (b != FALSE);
799f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
800f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
801f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32SocketServer::WakeUp() {
802f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (wnd_.handle()) {
803f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Set the "message pending" flag, if not already set.
804f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    {
805f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      CritScope scope(&cs_);
806f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      if (posted_)
807f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        return;
808f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      posted_ = true;
809f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
810f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
811f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0);
812f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
813f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
814f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
815f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgvoid Win32SocketServer::Pump() {
816f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Clear the "message pending" flag.
817f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  {
818f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    CritScope scope(&cs_);
819f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    posted_ = false;
820f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
821f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
822f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Dispatch all the messages that are currently in our queue. If new messages
823f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // are posted during the dispatch, they will be handled in the next Pump.
824f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // We use max(1, ...) to make sure we try to dispatch at least once, since
825f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // this allow us to process "sent" messages, not included in the size() count.
826f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  Message msg;
827ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org  for (size_t max_messages_to_process =
828ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org           std::max<size_t>(1, message_queue_->size());
829f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org       max_messages_to_process > 0 && message_queue_->Get(&msg, 0, false);
830f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org       --max_messages_to_process) {
831f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    message_queue_->Dispatch(&msg);
832f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
833f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
834f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Anything remaining?
835f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int delay = message_queue_->GetDelay();
836f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (delay == -1) {
837f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    KillTimer(wnd_.handle(), 1);
838f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
839f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    SetTimer(wnd_.handle(), 1, delay, NULL);
840f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
841f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
842f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
843f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgbool Win32SocketServer::MessageWindow::OnMessage(UINT wm, WPARAM wp,
844f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                                 LPARAM lp, LRESULT& lr) {
845f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  bool handled = false;
846f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) {
847f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ss_->Pump();
848f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    lr = 0;
849f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    handled = true;
850f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
851f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return handled;
852f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
853f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
854f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}  // namespace rtc
855