Index: third_party/libjingle/files/talk/base/win32socketserver.cc |
diff --git a/third_party/libjingle/files/talk/base/win32socketserver.cc b/third_party/libjingle/files/talk/base/win32socketserver.cc |
deleted file mode 100644 |
index bbec42e46e5ea2211a0a82c1b7c662f2c3b4c30b..0000000000000000000000000000000000000000 |
--- a/third_party/libjingle/files/talk/base/win32socketserver.cc |
+++ /dev/null |
@@ -1,769 +0,0 @@ |
-/* |
- * libjingle |
- * Copyright 2004--2005, Google Inc. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions are met: |
- * |
- * 1. Redistributions of source code must retain the above copyright notice, |
- * this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright notice, |
- * this list of conditions and the following disclaimer in the documentation |
- * and/or other materials provided with the distribution. |
- * 3. The name of the author may not be used to endorse or promote products |
- * derived from this software without specific prior written permission. |
- * |
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#include "talk/base/byteorder.h" |
-#include "talk/base/common.h" |
-#include "talk/base/logging.h" |
-#include "talk/base/winping.h" |
-#include "talk/base/winsock_initializer.h" |
-#include "talk/base/win32socketserver.h" |
-#include "talk/base/win32window.h" |
-#include <ws2tcpip.h> |
- |
-namespace talk_base { |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// Win32Socket |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-static const int kfRead = 0x0001; |
-static const int kfWrite = 0x0002; |
- |
-// Standard MTUs |
-static const uint16 PACKET_MAXIMUMS[] = { |
- 65535, // Theoretical maximum, Hyperchannel |
- 32000, // Nothing |
- 17914, // 16Mb IBM Token Ring |
- 8166, // IEEE 802.4 |
- //4464, // IEEE 802.5 (4Mb max) |
- 4352, // FDDI |
- //2048, // Wideband Network |
- 2002, // IEEE 802.5 (4Mb recommended) |
- //1536, // Expermental Ethernet Networks |
- //1500, // Ethernet, Point-to-Point (default) |
- 1492, // IEEE 802.3 |
- 1006, // SLIP, ARPANET |
- //576, // X.25 Networks |
- //544, // DEC IP Portal |
- //512, // NETBIOS |
- 508, // IEEE 802/Source-Rt Bridge, ARCNET |
- 296, // Point-to-Point (low delay) |
- 68, // Official minimum |
- 0, // End of list marker |
-}; |
- |
-static const uint32 IP_HEADER_SIZE = 20; |
-static const uint32 ICMP_HEADER_SIZE = 8; |
- |
-#ifdef DEBUG |
-LPCSTR WSAErrorToString(int error, LPCSTR *description_result) { |
- LPCSTR string = "Unspecified"; |
- LPCSTR description = "Unspecified description"; |
- switch (error) { |
- case ERROR_SUCCESS: |
- string = "SUCCESS"; |
- description = "Operation succeeded"; |
- break; |
- case WSAEWOULDBLOCK: |
- string = "WSAEWOULDBLOCK"; |
- description = "Using a non-blocking socket, will notify later"; |
- break; |
- case WSAEACCES: |
- string = "WSAEACCES"; |
- description = "Access denied, or sharing violation"; |
- break; |
- case WSAEADDRNOTAVAIL: |
- string = "WSAEADDRNOTAVAIL"; |
- description = "Address is not valid in this context"; |
- break; |
- case WSAENETDOWN: |
- string = "WSAENETDOWN"; |
- description = "Network is down"; |
- break; |
- case WSAENETUNREACH: |
- string = "WSAENETUNREACH"; |
- description = "Network is up, but unreachable"; |
- break; |
- case WSAENETRESET: |
- string = "WSANETRESET"; |
- description = "Connection has been reset due to keep-alive activity"; |
- break; |
- case WSAECONNABORTED: |
- string = "WSAECONNABORTED"; |
- description = "Aborted by host"; |
- break; |
- case WSAECONNRESET: |
- string = "WSAECONNRESET"; |
- description = "Connection reset by host"; |
- break; |
- case WSAETIMEDOUT: |
- string = "WSAETIMEDOUT"; |
- description = "Timed out, host failed to respond"; |
- break; |
- case WSAECONNREFUSED: |
- string = "WSAECONNREFUSED"; |
- description = "Host actively refused connection"; |
- break; |
- case WSAEHOSTDOWN: |
- string = "WSAEHOSTDOWN"; |
- description = "Host is down"; |
- break; |
- case WSAEHOSTUNREACH: |
- string = "WSAEHOSTUNREACH"; |
- description = "Host is unreachable"; |
- break; |
- case WSAHOST_NOT_FOUND: |
- string = "WSAHOST_NOT_FOUND"; |
- description = "No such host is known"; |
- break; |
- } |
- if (description_result) { |
- *description_result = description; |
- } |
- return string; |
-} |
- |
-void ReportWSAError(LPCSTR context, int error, const sockaddr_in& addr) { |
- talk_base::SocketAddress address; |
- address.FromSockAddr(addr); |
- LPCSTR description_string; |
- LPCSTR error_string = WSAErrorToString(error, &description_string); |
- LOG(LS_INFO) << context << " = " << error |
- << " (" << error_string << ":" << description_string << ") [" |
- << address.ToString() << "]"; |
-} |
-#else |
-void ReportWSAError(LPCSTR context, int error, const sockaddr_in& addr) { } |
-#endif |
- |
-///////////////////////////////////////////////////////////////////////////// |
-// Win32Socket::EventSink |
-///////////////////////////////////////////////////////////////////////////// |
- |
-#define WM_SOCKETNOTIFY (WM_USER + 50) |
-#define WM_DNSNOTIFY (WM_USER + 51) |
- |
-struct Win32Socket::DnsLookup { |
- HANDLE handle; |
- uint16 port; |
- char buffer[MAXGETHOSTSTRUCT]; |
-}; |
- |
-class Win32Socket::EventSink : public Win32Window { |
-public: |
- EventSink(Win32Socket * parent) : parent_(parent) { } |
- |
- void Dispose(); |
- |
- virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, |
- LRESULT& result); |
- virtual void OnFinalMessage(HWND hWnd); |
- |
-private: |
- bool OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result); |
- bool OnDnsNotify(WPARAM wParam, LPARAM lParam, LRESULT& result); |
- |
- Win32Socket * parent_; |
-}; |
- |
-void |
-Win32Socket::EventSink::Dispose() { |
- parent_ = NULL; |
- if (::IsWindow(handle())) { |
- ::DestroyWindow(handle()); |
- } else { |
- delete this; |
- } |
-} |
- |
-bool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, |
- LRESULT& result) { |
- switch (uMsg) { |
- case WM_SOCKETNOTIFY: |
- case WM_TIMER: |
- return OnSocketNotify(uMsg, wParam, lParam, result); |
- case WM_DNSNOTIFY: |
- return OnDnsNotify(wParam, lParam, result); |
- } |
- return false; |
-} |
- |
-bool |
-Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, |
- LRESULT& result) { |
- result = 0; |
- |
- // Make sure the socket isn't already closed |
- if (!parent_ || (parent_->socket_ == INVALID_SOCKET)) |
- return true; |
- |
- int event = WSAGETSELECTEVENT(lParam); |
- int wsa_error = WSAGETSELECTERROR(lParam); |
- |
- if (uMsg == WM_TIMER) { |
- event = FD_CLOSE; |
- wsa_error = WSAETIMEDOUT; |
- } else if (event == FD_CLOSE) { |
- char ch; |
- if (::recv(parent_->socket_, &ch, 1, MSG_PEEK) > 0) { |
- parent_->signal_close_ = true; |
- return true; |
- } |
- } |
- |
- parent_->OnSocketNotify(event, wsa_error); |
- return true; |
-} |
- |
-bool |
-Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam, |
- LRESULT& result) { |
- result = 0; |
- |
- if (!parent_) |
- return true; |
- |
- if (!parent_->dns_ || |
- (parent_->dns_->handle != reinterpret_cast<HANDLE>(wParam))) { |
- ASSERT(false); |
- return true; |
- } |
- |
- uint32 ip = 0; |
- int error = WSAGETASYNCERROR(lParam); |
- |
- if (error == 0) { |
- hostent * pHost = reinterpret_cast<hostent *>(parent_->dns_->buffer); |
- uint32 net_ip = *reinterpret_cast<uint32 *>(pHost->h_addr_list[0]); |
- ip = talk_base::NetworkToHost32(net_ip); |
- } |
- |
- parent_->OnDnsNotify(ip, error); |
- return true; |
-} |
- |
-void |
-Win32Socket::EventSink::OnFinalMessage(HWND hWnd) { |
- delete this; |
-} |
- |
-///////////////////////////////////////////////////////////////////////////// |
-// Win32Socket |
-///////////////////////////////////////////////////////////////////////////// |
- |
-Win32Socket::Win32Socket() |
- : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED), |
- signal_close_(false), sink_(NULL), dns_(NULL) { |
- talk_base::EnsureWinsockInit(); |
- // TODO: replace addr_ with SocketAddress |
- memset(&addr_, 0, sizeof(addr_)); |
-} |
- |
-Win32Socket::~Win32Socket() { |
- Close(); |
-} |
- |
-int |
-Win32Socket::Attach(SOCKET s) { |
- ASSERT(socket_ == INVALID_SOCKET); |
- if (socket_ != INVALID_SOCKET) |
- return SOCKET_ERROR; |
- |
- ASSERT(s != INVALID_SOCKET); |
- if (s == INVALID_SOCKET) |
- return SOCKET_ERROR; |
- |
- socket_ = s; |
- state_ = CS_CONNECTED; |
- |
- if (!Create(FD_READ | FD_WRITE | FD_CLOSE)) |
- return SOCKET_ERROR; |
- |
- return 0; |
-} |
- |
-void |
-Win32Socket::SetTimeout(int ms) { |
- if (sink_) |
- ::SetTimer(sink_->handle(), 1, ms, 0); |
-} |
- |
-talk_base::SocketAddress |
-Win32Socket::GetLocalAddress() const { |
- sockaddr_in addr; |
- socklen_t addrlen = sizeof(addr); |
- int result = ::getsockname(socket_, (sockaddr*)&addr, &addrlen); |
- ASSERT(addrlen == sizeof(addr)); |
- talk_base::SocketAddress address; |
- if (result >= 0) { |
- address.FromSockAddr(addr); |
- } else { |
- ASSERT(result >= 0); |
- } |
- return address; |
-} |
- |
-talk_base::SocketAddress |
-Win32Socket::GetRemoteAddress() const { |
- sockaddr_in addr; |
- socklen_t addrlen = sizeof(addr); |
- int result = ::getpeername(socket_, (sockaddr*)&addr, &addrlen); |
- ASSERT(addrlen == sizeof(addr)); |
- talk_base::SocketAddress address; |
- if (result >= 0) { |
- address.FromSockAddr(addr); |
- } else { |
- ASSERT(errno == ENOTCONN); |
- } |
- return address; |
-} |
- |
-int |
-Win32Socket::Bind(const talk_base::SocketAddress& addr) { |
- ASSERT(socket_ == INVALID_SOCKET); |
- if (socket_ != INVALID_SOCKET) |
- return SOCKET_ERROR; |
- |
- if (!Create(FD_ACCEPT | FD_CLOSE)) |
- return SOCKET_ERROR; |
- |
- sockaddr_in saddr; |
- addr.ToSockAddr(&saddr); |
- int err = ::bind(socket_, (sockaddr*)&saddr, sizeof(saddr)); |
- UpdateLastError(); |
- return err; |
-} |
- |
-int |
-Win32Socket::Connect(const talk_base::SocketAddress& addr) { |
- ASSERT(socket_ == INVALID_SOCKET); |
- if (socket_ != INVALID_SOCKET) |
- return SOCKET_ERROR; |
- |
- if (!Create(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE)) |
- return SOCKET_ERROR; |
- |
- if (!addr.IsUnresolved()) { |
- sockaddr_in saddr; |
- addr.ToSockAddr(&saddr); |
- |
- // now connect |
- return DoConnect(saddr); |
- } |
- |
- LOG_F(LS_INFO) << "async dns lookup (" << addr.IPAsString() << ")"; |
- DnsLookup * dns = new DnsLookup; |
- dns->handle = WSAAsyncGetHostByName(sink_->handle(), WM_DNSNOTIFY, |
- addr.IPAsString().c_str(), dns->buffer, sizeof(dns->buffer)); |
- |
- if (!dns->handle) { |
- LOG_F(LS_ERROR) << "WSAAsyncGetHostByName error: " << WSAGetLastError(); |
- delete dns; |
- UpdateLastError(); |
- Close(); |
- return SOCKET_ERROR; |
- } |
- |
- dns->port = addr.port(); |
- dns_ = dns; |
- state_ = CS_CONNECTING; |
- return 0; |
-} |
- |
-int |
-Win32Socket::DoConnect(const sockaddr_in& addr) { |
- connect_time_ = talk_base::GetMillisecondCount(); |
- int result = connect(socket_, (SOCKADDR*)&addr, sizeof(addr)); |
- if (result == SOCKET_ERROR) { |
- int code = WSAGetLastError(); |
- if (code != WSAEWOULDBLOCK) { |
- ReportWSAError("WSAAsync:connect", code, addr); |
- error_ = code; |
- Close(); |
- return SOCKET_ERROR; |
- } |
- } |
- addr_ = addr; |
- state_ = CS_CONNECTING; |
- return 0; |
-} |
- |
-void |
-Win32Socket::OnSocketNotify(int event, int error) { |
- error_ = error; |
- switch (event) { |
- case FD_CONNECT: |
- if (error != ERROR_SUCCESS) { |
- ReportWSAError("WSAAsync:connect notify", error, addr_); |
-#ifdef DEBUG |
- int32 duration = talk_base::TimeDiff(talk_base::GetMillisecondCount(), |
- connect_time_); |
- LOG(LS_INFO) << "WSAAsync:connect error (" << duration |
- << " ms), faking close"; |
-#endif |
- Close(); |
- // If you get an error connecting, close doesn't really do anything |
- // and it certainly doesn't send back any close notification, but |
- // we really only maintain a few states, so it is easiest to get |
- // back into a known state by pretending that a close happened, even |
- // though the connect event never did occur. |
- SignalCloseEvent(this, error); |
- } else { |
-#ifdef DEBUG |
- int32 duration = talk_base::TimeDiff(talk_base::GetMillisecondCount(), |
- connect_time_); |
- LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)"; |
-#endif |
- state_ = CS_CONNECTED; |
- SignalConnectEvent(this); |
- } |
- break; |
- |
- case FD_ACCEPT: |
- case FD_READ: |
- if (error != ERROR_SUCCESS) { |
- ReportWSAError("WSAAsync:read notify", error, addr_); |
- Close(); |
- } else { |
- SignalReadEvent(this); |
- } |
- break; |
- |
- case FD_WRITE: |
- if (error != ERROR_SUCCESS) { |
- ReportWSAError("WSAAsync:write notify", error, addr_); |
- Close(); |
- } else { |
- SignalWriteEvent(this); |
- } |
- break; |
- |
- case FD_CLOSE: |
- ReportWSAError("WSAAsync:close notify", error, addr_); |
- Close(); |
- SignalCloseEvent(this, error); |
- break; |
- } |
-} |
- |
-void |
-Win32Socket::OnDnsNotify(int ip, int error) { |
- LOG_F(LS_INFO) << "(" << talk_base::SocketAddress::IPToString(ip) |
- << ", " << error << ")"; |
- if (error == 0) { |
- talk_base::SocketAddress address(ip, dns_->port); |
- sockaddr_in addr; |
- address.ToSockAddr(&addr); |
- error = DoConnect(addr); |
- } else { |
- Close(); |
- } |
- |
- if (error) { |
- error_ = error; |
- SignalCloseEvent(this, error_); |
- } else { |
- delete dns_; |
- dns_ = NULL; |
- } |
-} |
- |
-int |
-Win32Socket::GetError() const { |
- return error_; |
-} |
- |
-void |
-Win32Socket::SetError(int error) { |
- error_ = error; |
-} |
- |
-Socket::ConnState |
-Win32Socket::GetState() const { |
- return state_; |
-} |
- |
-int |
-Win32Socket::SetOption(Option opt, int value) { |
- ASSERT(opt == OPT_DONTFRAGMENT); |
- value = (value == 0) ? 0 : 1; |
- return ::setsockopt(socket_, IPPROTO_IP, IP_DONTFRAGMENT, |
- reinterpret_cast<char*>(&value), sizeof(value)); |
-} |
- |
-int |
-Win32Socket::Send(const void *pv, size_t cb) { |
- int sent = ::send(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0); |
- UpdateLastError(); |
- return sent; |
-} |
- |
-int |
-Win32Socket::SendTo(const void *pv, size_t cb, |
- const talk_base::SocketAddress& addr) { |
- sockaddr_in saddr; |
- addr.ToSockAddr(&saddr); |
- int sent = ::sendto(socket_, reinterpret_cast<const char *>(pv), (int)cb, 0, |
- (sockaddr*)&saddr, sizeof(saddr)); |
- UpdateLastError(); |
- return sent; |
-} |
- |
-int |
-Win32Socket::Recv(void *pv, size_t cb) { |
- int received = ::recv(socket_, (char *)pv, (int)cb, 0); |
- UpdateLastError(); |
- if (signal_close_ && (received > 0)) { |
- char ch; |
- if (::recv(socket_, &ch, 1, MSG_PEEK) <= 0) { |
- signal_close_ = false; |
- ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY, |
- WSAMAKESELECTREPLY(FD_CLOSE, 0), 0); |
- } |
- } |
- return received; |
-} |
- |
-int |
-Win32Socket::RecvFrom(void *pv, size_t cb, talk_base::SocketAddress *paddr) { |
- sockaddr_in saddr; |
- socklen_t cbAddr = sizeof(saddr); |
- int received = ::recvfrom(socket_, (char *)pv, (int)cb, 0, (sockaddr*)&saddr, |
- &cbAddr); |
- UpdateLastError(); |
- if (received != SOCKET_ERROR) |
- paddr->FromSockAddr(saddr); |
- if (signal_close_ && (received > 0)) { |
- char ch; |
- if (::recv(socket_, &ch, 1, MSG_PEEK) <= 0) { |
- signal_close_ = false; |
- ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY, |
- WSAMAKESELECTREPLY(FD_CLOSE, 0), 0); |
- } |
- } |
- return received; |
-} |
- |
-int |
-Win32Socket::Listen(int backlog) { |
- int err = ::listen(socket_, backlog); |
- UpdateLastError(); |
- if (err == 0) |
- state_ = CS_CONNECTING; |
- return err; |
-} |
- |
-talk_base::Socket* |
-Win32Socket::Accept(talk_base::SocketAddress *paddr) { |
- sockaddr_in saddr; |
- socklen_t cbAddr = sizeof(saddr); |
- SOCKET s = ::accept(socket_, (sockaddr*)&saddr, &cbAddr); |
- UpdateLastError(); |
- if (s == INVALID_SOCKET) |
- return NULL; |
- if (paddr) |
- paddr->FromSockAddr(saddr); |
- Win32Socket* socket = new Win32Socket; |
- if (0 == socket->Attach(s)) |
- return socket; |
- delete socket; |
- return NULL; |
-} |
- |
-int |
-Win32Socket::Close() { |
- int err = 0; |
- if (socket_ != INVALID_SOCKET) { |
- err = ::closesocket(socket_); |
- socket_ = INVALID_SOCKET; |
- signal_close_ = false; |
- UpdateLastError(); |
- } |
- if (dns_) { |
- WSACancelAsyncRequest(dns_->handle); |
- delete dns_; |
- dns_ = NULL; |
- } |
- if (sink_) { |
- sink_->Dispose(); |
- sink_ = NULL; |
- } |
- memset(&addr_, 0, sizeof(addr_)); // no longer connected, zero ip/port |
- state_ = CS_CLOSED; |
- return err; |
-} |
- |
-int |
-Win32Socket::EstimateMTU(uint16* mtu) { |
- talk_base::SocketAddress addr = GetRemoteAddress(); |
- if (addr.IsAny()) { |
- error_ = ENOTCONN; |
- return -1; |
- } |
- |
- talk_base::WinPing ping; |
- if (!ping.IsValid()) { |
- error_ = EINVAL; // can't think of a better error ID |
- return -1; |
- } |
- |
- for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) { |
- int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE; |
- talk_base::WinPing::PingResult result = |
- ping.Ping(addr.ip(), size, 0, 1, false); |
- if (result == talk_base::WinPing::PING_FAIL) { |
- error_ = EINVAL; // can't think of a better error ID |
- return -1; |
- } |
- if (result != talk_base::WinPing::PING_TOO_LARGE) { |
- *mtu = PACKET_MAXIMUMS[level]; |
- return 0; |
- } |
- } |
- |
- ASSERT(false); |
- return 0; |
-} |
- |
-bool |
-Win32Socket::Create(long events) { |
- ASSERT(NULL == sink_); |
- |
- if (INVALID_SOCKET == socket_) { |
- socket_ = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, 0); |
- if (socket_ == INVALID_SOCKET) { |
- UpdateLastError(); |
- return false; |
- } |
- } |
- |
- // Create window |
- sink_ = new EventSink(this); |
- sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10); |
- |
- // start the async select |
- if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events) |
- == SOCKET_ERROR) { |
- UpdateLastError(); |
- Close(); |
- return false; |
- } |
- |
- return true; |
-} |
- |
-void |
-Win32Socket::UpdateLastError() { |
- error_ = WSAGetLastError(); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// Win32SocketServer |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-static UINT s_wm_wakeup_id; |
- |
-LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp); |
- |
-// A socket server that provides cricket base services on top of a win32 gui thread |
- |
-Win32SocketServer::Win32SocketServer(MessageQueue *message_queue) { |
- if (s_wm_wakeup_id == 0) |
- s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP"); |
- message_queue_ = message_queue; |
- hwnd_ = NULL; |
- CreateDummyWindow(); |
-} |
- |
-Win32SocketServer::~Win32SocketServer() { |
- if (hwnd_ != NULL) { |
- KillTimer(hwnd_, 1); |
- ::DestroyWindow(hwnd_); |
- } |
-} |
- |
-Socket* Win32SocketServer::CreateSocket(int type) { |
- ASSERT(SOCK_STREAM == type); |
- return new Win32Socket; |
-} |
- |
-AsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) { |
- ASSERT(SOCK_STREAM == type); |
- return new Win32Socket; |
-} |
- |
-bool Win32SocketServer::Wait(int cms, bool process_io) { |
- ASSERT(!process_io || (cms == 0)); // Should only be used for Thread::Send, or in Pump, below |
- if (cms == -1) { |
- MSG msg; |
- GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id); |
- } else if (cms != 0) { |
- Sleep(cms); |
- } |
- return true; |
-} |
- |
-void Win32SocketServer::WakeUp() { |
- // Always post for every wakeup, so there are no |
- // critical sections |
- if (hwnd_ != NULL) |
- PostMessage(hwnd_, s_wm_wakeup_id, 0, 0); |
-} |
- |
-void Win32SocketServer::Pump() { |
- // Process messages |
- Message msg; |
- while (message_queue_->Get(&msg, 0)) |
- message_queue_->Dispatch(&msg); |
- |
- // Anything remaining? |
- int delay = message_queue_->GetDelay(); |
- if (delay == -1) { |
- KillTimer(hwnd_, 1); |
- } else { |
- SetTimer(hwnd_, 1, delay, NULL); |
- } |
-} |
- |
-void Win32SocketServer::CreateDummyWindow() |
-{ |
- static bool s_registered; |
- if (!s_registered) { |
- ::WNDCLASSW wc; |
- memset(&wc, 0, sizeof(wc)); |
- wc.cbWndExtra = sizeof(this); |
- wc.lpszClassName = L"Dummy"; |
- wc.lpfnWndProc = DummyWndProc; |
- ::RegisterClassW(&wc); |
- s_registered = true; |
- } |
- |
- hwnd_ = ::CreateWindowW(L"Dummy", L"", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); |
- SetWindowLong(hwnd_, GWL_USERDATA, (LONG)(LONG_PTR)this); |
-} |
- |
-LRESULT CALLBACK DummyWndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp) |
-{ |
- if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) { |
- Win32SocketServer *ss = (Win32SocketServer *)(LONG_PTR)GetWindowLong(hwnd, GWL_USERDATA); |
- ss->Pump(); |
- return 0; |
- } |
- return ::DefWindowProc(hwnd, wm, wp, lp); |
-} |
- |
-} // namespace talk_base |