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