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