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 
     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