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 22 namespace rtc { 23 24 /////////////////////////////////////////////////////////////////////////////// 25 // Win32Socket 26 /////////////////////////////////////////////////////////////////////////////// 27 28 // TODO: Move this to a common place where PhysicalSocketServer can 29 // share it. 30 // Standard MTUs 31 static 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 53 static const int IP_HEADER_SIZE = 20u; 54 static const int ICMP_HEADER_SIZE = 8u; 55 static const int ICMP_PING_TIMEOUT_MILLIS = 10000u; 56 57 // TODO: Enable for production builds also? Use FormatMessage? 58 #if !defined(NDEBUG) 59 LPCSTR 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 126 void 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 134 void 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 144 struct Win32Socket::DnsLookup { 145 HANDLE handle; 146 uint16_t port; 147 char buffer[MAXGETHOSTSTRUCT]; 148 }; 149 150 class 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 167 void Win32Socket::EventSink::Dispose() { 168 parent_ = NULL; 169 if (::IsWindow(handle())) { 170 ::DestroyWindow(handle()); 171 } else { 172 delete this; 173 } 174 } 175 176 bool 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 188 bool 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 206 bool 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 216 void 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 229 Win32Socket::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 234 Win32Socket::~Win32Socket() { 235 Close(); 236 } 237 238 bool 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 252 int 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 270 void Win32Socket::SetTimeout(int ms) { 271 if (sink_) 272 ::SetTimer(sink_->handle(), 1, ms, 0); 273 } 274 275 SocketAddress 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 290 SocketAddress 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 305 int 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 319 int 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 355 int 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 387 int Win32Socket::GetError() const { 388 return error_; 389 } 390 391 void Win32Socket::SetError(int error) { 392 error_ = error; 393 } 394 395 Socket::ConnState Win32Socket::GetState() const { 396 return state_; 397 } 398 399 int 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 410 int 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 420 int 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 429 int 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 441 int 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 450 int 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 465 int 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 476 Win32Socket* 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 492 int 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 515 int 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 546 void 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 554 bool 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 571 bool 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 580 void 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 587 void Win32Socket::UpdateLastError() { 588 error_ = WSAGetLastError(); 589 } 590 591 int 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 619 void 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 678 void 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 713 static UINT s_wm_wakeup_id = 0; 714 const TCHAR Win32SocketServer::kWindowName[] = L"libjingle Message Window"; 715 716 Win32SocketServer::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 728 Win32SocketServer::~Win32SocketServer() { 729 if (wnd_.handle() != NULL) { 730 KillTimer(wnd_.handle(), 1); 731 wnd_.Destroy(); 732 } 733 } 734 735 Socket* Win32SocketServer::CreateSocket(int type) { 736 return CreateSocket(AF_INET, type); 737 } 738 739 Socket* Win32SocketServer::CreateSocket(int family, int type) { 740 return CreateAsyncSocket(family, type); 741 } 742 743 AsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) { 744 return CreateAsyncSocket(AF_INET, type); 745 } 746 747 AsyncSocket* 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 756 void Win32SocketServer::SetMessageQueue(MessageQueue* queue) { 757 message_queue_ = queue; 758 } 759 760 bool 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 801 void 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 815 void 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 843 bool 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