Home | History | Annotate | Download | only in base
      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