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