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