147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32socketserver.h" 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/byteorder.h" 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h" 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/winping.h" 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32window.h" 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <ws2tcpip.h> // NOLINT 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Win32Socket 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// TODO: Move this to a common place where PhysicalSocketServer can 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// share it. 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Standard MTUs 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const uint16 PACKET_MAXIMUMS[] = { 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 65535, // Theoretical maximum, Hyperchannel 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32000, // Nothing 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17914, // 16Mb IBM Token Ring 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8166, // IEEE 802.4 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 4464 // IEEE 802.5 (4Mb max) 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4352, // FDDI 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 2048, // Wideband Network 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2002, // IEEE 802.5 (4Mb recommended) 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 1536, // Expermental Ethernet Networks 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 1500, // Ethernet, Point-to-Point (default) 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1492, // IEEE 802.3 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1006, // SLIP, ARPANET 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 576, // X.25 Networks 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 544, // DEC IP Portal 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 512, // NETBIOS 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 508, // IEEE 802/Source-Rt Bridge, ARCNET 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 296, // Point-to-Point (low delay) 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68, // Official minimum 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 0, // End of list marker 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int IP_HEADER_SIZE = 20u; 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int ICMP_HEADER_SIZE = 8u; 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const int ICMP_PING_TIMEOUT_MILLIS = 10000u; 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// TODO: Enable for production builds also? Use FormatMessage? 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgLPCSTR WSAErrorToString(int error, LPCSTR *description_result) { 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPCSTR string = "Unspecified"; 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPCSTR description = "Unspecified description"; 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (error) { 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case ERROR_SUCCESS: 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "SUCCESS"; 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Operation succeeded"; 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAEWOULDBLOCK: 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAEWOULDBLOCK"; 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Using a non-blocking socket, will notify later"; 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAEACCES: 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAEACCES"; 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Access denied, or sharing violation"; 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAEADDRNOTAVAIL: 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAEADDRNOTAVAIL"; 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Address is not valid in this context"; 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAENETDOWN: 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAENETDOWN"; 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Network is down"; 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAENETUNREACH: 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAENETUNREACH"; 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Network is up, but unreachable"; 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAENETRESET: 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSANETRESET"; 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Connection has been reset due to keep-alive activity"; 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAECONNABORTED: 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAECONNABORTED"; 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Aborted by host"; 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAECONNRESET: 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAECONNRESET"; 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Connection reset by host"; 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAETIMEDOUT: 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAETIMEDOUT"; 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Timed out, host failed to respond"; 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAECONNREFUSED: 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAECONNREFUSED"; 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Host actively refused connection"; 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAEHOSTDOWN: 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAEHOSTDOWN"; 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Host is down"; 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAEHOSTUNREACH: 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAEHOSTUNREACH"; 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "Host is unreachable"; 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WSAHOST_NOT_FOUND: 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org string = "WSAHOST_NOT_FOUND"; 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org description = "No such host is known"; 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (description_result) { 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *description_result = description; 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return string; 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) { 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPCSTR description_string; 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPCSTR error_string = WSAErrorToString(error, &description_string); 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << context << " = " << error 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << " (" << error_string << ":" << description_string << ") [" 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << address.ToString() << "]"; 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid ReportWSAError(LPCSTR context, int error, const SocketAddress& address) {} 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Win32Socket::EventSink 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define WM_SOCKETNOTIFY (WM_USER + 50) 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define WM_DNSNOTIFY (WM_USER + 51) 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstruct Win32Socket::DnsLookup { 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org HANDLE handle; 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org uint16 port; 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char buffer[MAXGETHOSTSTRUCT]; 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass Win32Socket::EventSink : public Win32Window { 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public: 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org explicit EventSink(Win32Socket * parent) : parent_(parent) { } 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void Dispose(); 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LRESULT& result); 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void OnNcDestroy(); 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private: 15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool OnSocketNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result); 15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool OnDnsNotify(WPARAM wParam, LPARAM lParam, LRESULT& result); 16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Win32Socket * parent_; 16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::EventSink::Dispose() { 16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org parent_ = NULL; 16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (::IsWindow(handle())) { 16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ::DestroyWindow(handle()); 16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete this; 17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Socket::EventSink::OnMessage(UINT uMsg, WPARAM wParam, 17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPARAM lParam, LRESULT& result) { 17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (uMsg) { 17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WM_SOCKETNOTIFY: 17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WM_TIMER: 17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return OnSocketNotify(uMsg, wParam, lParam, result); 17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case WM_DNSNOTIFY: 18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return OnDnsNotify(wParam, lParam, result); 18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Socket::EventSink::OnSocketNotify(UINT uMsg, WPARAM wParam, 18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPARAM lParam, LRESULT& result) { 18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org result = 0; 18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int wsa_event = WSAGETSELECTEVENT(lParam); 19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int wsa_error = WSAGETSELECTERROR(lParam); 19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Treat connect timeouts as close notifications 19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (uMsg == WM_TIMER) { 19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org wsa_event = FD_CLOSE; 19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org wsa_error = WSAETIMEDOUT; 19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (parent_) 19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org parent_->OnSocketNotify(static_cast<SOCKET>(wParam), wsa_event, wsa_error); 20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Socket::EventSink::OnDnsNotify(WPARAM wParam, LPARAM lParam, 20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LRESULT& result) { 20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org result = 0; 20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int error = WSAGETASYNCERROR(lParam); 20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (parent_) 20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org parent_->OnDnsNotify(reinterpret_cast<HANDLE>(wParam), error); 21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::EventSink::OnNcDestroy() { 21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (parent_) { 21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "EventSink hwnd is being destroyed, but the event sink" 21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org " hasn't yet been disposed."; 21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete this; 21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Win32Socket 22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgWin32Socket::Win32Socket() 22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : socket_(INVALID_SOCKET), error_(0), state_(CS_CLOSED), connect_time_(0), 22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org closing_(false), close_error_(0), sink_(NULL), dns_(NULL) { 22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgWin32Socket::~Win32Socket() { 23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Socket::CreateT(int family, int type) { 23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int proto = (SOCK_DGRAM == type) ? IPPROTO_UDP : IPPROTO_TCP; 23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_ = ::WSASocket(family, type, proto, NULL, NULL, 0); 23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket_ == INVALID_SOCKET) { 24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((SOCK_DGRAM == type) && !SetAsync(FD_READ | FD_WRITE)) { 24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::Attach(SOCKET s) { 25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(socket_ == INVALID_SOCKET); 25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket_ != INVALID_SOCKET) 25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(s != INVALID_SOCKET); 25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (s == INVALID_SOCKET) 25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_ = s; 25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTED; 26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!SetAsync(FD_READ | FD_WRITE | FD_CLOSE)) 26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::SetTimeout(int ms) { 26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (sink_) 26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ::SetTimer(sink_->handle(), 1, ms, 0); 27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress Win32Socket::GetLocalAddress() const { 27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage addr = {0}; 27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addrlen = sizeof(addr); 27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int result = ::getsockname(socket_, reinterpret_cast<sockaddr*>(&addr), 27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &addrlen); 27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress address; 27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result >= 0) { 27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(addr, &address); 28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "GetLocalAddress: unable to get local addr, socket=" 28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << socket_; 28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return address; 28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress Win32Socket::GetRemoteAddress() const { 28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage addr = {0}; 28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addrlen = sizeof(addr); 29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int result = ::getpeername(socket_, reinterpret_cast<sockaddr*>(&addr), 29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &addrlen); 29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress address; 29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result >= 0) { 29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(addr, &address); 29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "GetRemoteAddress: unable to get remote addr, socket=" 29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << socket_; 29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return address; 30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::Bind(const SocketAddress& addr) { 30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(socket_ != INVALID_SOCKET); 30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket_ == INVALID_SOCKET) 30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t len = addr.ToSockAddrStorage(&saddr); 30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int err = ::bind(socket_, 31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<sockaddr*>(&saddr), 31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int>(len)); 31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::Connect(const SocketAddress& addr) { 31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != CS_CLOSED) { 31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetError(EALREADY); 31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!addr.IsUnresolvedIP()) { 32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return DoConnect(addr); 32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_F(LS_INFO) << "async dns lookup (" << addr.hostname() << ")"; 32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DnsLookup * dns = new DnsLookup; 32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!sink_) { 32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Explicitly create the sink ourselves here; we can't rely on SetAsync 33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // because we don't have a socket_ yet. 33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CreateSink(); 33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO: Replace with IPv6 compatible lookup. 33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org dns->handle = WSAAsyncGetHostByName(sink_->handle(), WM_DNSNOTIFY, 33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr.hostname().c_str(), dns->buffer, 33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sizeof(dns->buffer)); 33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!dns->handle) { 33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_F(LS_ERROR) << "WSAAsyncGetHostByName error: " << WSAGetLastError(); 34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete dns; 34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org dns->port = addr.port(); 34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org dns_ = dns; 34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTING; 34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::DoConnect(const SocketAddress& addr) { 35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((socket_ == INVALID_SOCKET) && !CreateT(addr.family(), SOCK_STREAM)) { 35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!SetAsync(FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE)) { 35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr = {0}; 36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t len = addr.ToSockAddrStorage(&saddr); 36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org connect_time_ = Time(); 36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int result = connect(socket_, 36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<SOCKADDR*>(&saddr), 36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int>(len)); 36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result != SOCKET_ERROR) { 36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTED; 36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int code = WSAGetLastError(); 37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (code == WSAEWOULDBLOCK) { 37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTING; 37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ReportWSAError("WSAAsync:connect", code, addr); 37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = code; 37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr_ = addr; 38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::GetError() const { 38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return error_; 38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::SetError(int error) { 38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = error; 39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket::ConnState Win32Socket::GetState() const { 39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return state_; 39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::GetOption(Option opt, int* value) { 39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int slevel; 39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int sopt; 39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (TranslateOption(opt, &slevel, &sopt) == -1) 40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char* p = reinterpret_cast<char*>(value); 40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int optlen = sizeof(value); 40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ::getsockopt(socket_, slevel, sopt, p, &optlen); 40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::SetOption(Option opt, int value) { 40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int slevel; 40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int sopt; 41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (TranslateOption(opt, &slevel, &sopt) == -1) 41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const char* p = reinterpret_cast<const char*>(&value); 41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ::setsockopt(socket_, slevel, sopt, p, sizeof(value)); 41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::Send(const void* buffer, size_t length) { 41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int sent = ::send(socket_, 41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<const char*>(buffer), 42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int>(length), 42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 0); 42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return sent; 42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::SendTo(const void* buffer, size_t length, 42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SocketAddress& addr) { 42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t addr_len = addr.ToSockAddrStorage(&saddr); 43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int sent = ::sendto(socket_, reinterpret_cast<const char*>(buffer), 43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int>(length), 0, 43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<sockaddr*>(&saddr), 43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int>(addr_len)); 43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return sent; 43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::Recv(void* buffer, size_t length) { 43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int received = ::recv(socket_, static_cast<char*>(buffer), 44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int>(length), 0); 44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (closing_ && received <= static_cast<int>(length)) 44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PostClosed(); 44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return received; 44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::RecvFrom(void* buffer, size_t length, 44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress* out_addr) { 44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addr_len = sizeof(saddr); 45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int received = ::recvfrom(socket_, static_cast<char*>(buffer), 45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int>(length), 0, 45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<sockaddr*>(&saddr), &addr_len); 45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (received != SOCKET_ERROR) 45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(saddr, out_addr); 45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (closing_ && received <= static_cast<int>(length)) 45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PostClosed(); 45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return received; 46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::Listen(int backlog) { 46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int err = ::listen(socket_, backlog); 46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!SetAsync(FD_ACCEPT)) 46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (err == 0) 46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTING; 47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgWin32Socket* Win32Socket::Accept(SocketAddress* out_addr) { 47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sockaddr_storage saddr; 47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socklen_t addr_len = sizeof(saddr); 47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SOCKET s = ::accept(socket_, reinterpret_cast<sockaddr*>(&saddr), &addr_len); 47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (s == INVALID_SOCKET) 47947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 48047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (out_addr) 48147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddressFromSockAddrStorage(saddr, out_addr); 48247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Win32Socket* socket = new Win32Socket; 48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (0 == socket->Attach(s)) 48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket; 48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete socket; 48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 48847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 48947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::Close() { 49047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int err = 0; 49147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket_ != INVALID_SOCKET) { 49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org err = ::closesocket(socket_); 49347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_ = INVALID_SOCKET; 49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org closing_ = false; 49547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org close_error_ = 0; 49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (dns_) { 49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org WSACancelAsyncRequest(dns_->handle); 50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete dns_; 50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org dns_ = NULL; 50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 50347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (sink_) { 50447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sink_->Dispose(); 50547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sink_ = NULL; 50647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 50747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org addr_.Clear(); 50847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CLOSED; 50947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 51047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 51147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 51247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::EstimateMTU(uint16* mtu) { 51347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress addr = GetRemoteAddress(); 51447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (addr.IsAny()) { 51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = ENOTCONN; 51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 51947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org WinPing ping; 52047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!ping.IsValid()) { 52147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = EINVAL; // can't think of a better error ID 52247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 52347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 52447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 52547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (int level = 0; PACKET_MAXIMUMS[level + 1] > 0; ++level) { 52647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int32 size = PACKET_MAXIMUMS[level] - IP_HEADER_SIZE - ICMP_HEADER_SIZE; 52747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org WinPing::PingResult result = ping.Ping(addr.ipaddr(), size, 52847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ICMP_PING_TIMEOUT_MILLIS, 1, false); 52947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result == WinPing::PING_FAIL) { 53047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = EINVAL; // can't think of a better error ID 53147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 53247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 53347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (result != WinPing::PING_TOO_LARGE) { 53447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *mtu = PACKET_MAXIMUMS[level]; 53547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 53647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 53747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 53847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 53947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false); 54047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 54147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 54247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 54347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::CreateSink() { 54447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(NULL == sink_); 54547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 54647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Create window 54747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sink_ = new EventSink(this); 54847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sink_->Create(NULL, L"EventSink", 0, 0, 0, 0, 10, 10); 54947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 55047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 55147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Socket::SetAsync(int events) { 55247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == sink_) { 55347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CreateSink(); 55447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(NULL != sink_); 55547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 55647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 55747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // start the async select 55847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (WSAAsyncSelect(socket_, sink_->handle(), WM_SOCKETNOTIFY, events) 55947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org == SOCKET_ERROR) { 56047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UpdateLastError(); 56147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 56247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 56347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 56447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 56547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 56647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 56747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 56847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Socket::HandleClosed(int close_error) { 56947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // WM_CLOSE will be received before all data has been read, so we need to 57047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // hold on to it until the read buffer has been drained. 57147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char ch; 57247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org closing_ = true; 57347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org close_error_ = close_error; 57447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return (::recv(socket_, &ch, 1, MSG_PEEK) <= 0); 57547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 57647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 57747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::PostClosed() { 57847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If we see that the buffer is indeed drained, then send the close. 57947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org closing_ = false; 58047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ::PostMessage(sink_->handle(), WM_SOCKETNOTIFY, 58147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org socket_, WSAMAKESELECTREPLY(FD_CLOSE, close_error_)); 58247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 58347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 58447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::UpdateLastError() { 58547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = WSAGetLastError(); 58647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 58747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 58847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint Win32Socket::TranslateOption(Option opt, int* slevel, int* sopt) { 58947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (opt) { 59047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case OPT_DONTFRAGMENT: 59147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *slevel = IPPROTO_IP; 59247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *sopt = IP_DONTFRAGMENT; 59347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 59447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case OPT_RCVBUF: 59547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *slevel = SOL_SOCKET; 59647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *sopt = SO_RCVBUF; 59747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 59847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case OPT_SNDBUF: 59947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *slevel = SOL_SOCKET; 60047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *sopt = SO_SNDBUF; 60147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 60247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case OPT_NODELAY: 60347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *slevel = IPPROTO_TCP; 60447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *sopt = TCP_NODELAY; 60547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 60647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case OPT_DSCP: 60747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "Socket::OPT_DSCP not supported."; 60847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 60947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 61047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false); 61147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -1; 61247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 61347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 61447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 61547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 61647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::OnSocketNotify(SOCKET socket, int event, int error) { 61747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Ignore events if we're already closed. 61847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket != socket_) 61947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 62047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 62147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = error; 62247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (event) { 62347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case FD_CONNECT: 62447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error != ERROR_SUCCESS) { 62547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ReportWSAError("WSAAsync:connect notify", error, addr_); 62647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG 62747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int32 duration = TimeSince(connect_time_); 62847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "WSAAsync:connect error (" << duration 62947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << " ms), faking close"; 63047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 63147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CLOSED; 63247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If you get an error connecting, close doesn't really do anything 63347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // and it certainly doesn't send back any close notification, but 63447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // we really only maintain a few states, so it is easiest to get 63547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // back into a known state by pretending that a close happened, even 63647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // though the connect event never did occur. 63747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalCloseEvent(this, error); 63847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 63947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG 64047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int32 duration = TimeSince(connect_time_); 64147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "WSAAsync:connect (" << duration << " ms)"; 64247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 64347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CONNECTED; 64447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalConnectEvent(this); 64547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 64647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 64747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 64847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case FD_ACCEPT: 64947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case FD_READ: 65047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error != ERROR_SUCCESS) { 65147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ReportWSAError("WSAAsync:read notify", error, addr_); 65247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 65347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalReadEvent(this); 65447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 65547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 65647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 65747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case FD_WRITE: 65847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error != ERROR_SUCCESS) { 65947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ReportWSAError("WSAAsync:write notify", error, addr_); 66047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 66147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalWriteEvent(this); 66247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 66347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 66447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 66547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case FD_CLOSE: 66647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (HandleClosed(error)) { 66747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ReportWSAError("WSAAsync:close notify", error, addr_); 66847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = CS_CLOSED; 66947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalCloseEvent(this, error); 67047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 67147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 67247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 67347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 67447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 67547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32Socket::OnDnsNotify(HANDLE task, int error) { 67647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!dns_ || dns_->handle != task) 67747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 67847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 67947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org uint32 ip = 0; 68047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error == 0) { 68147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org hostent* pHost = reinterpret_cast<hostent*>(dns_->buffer); 68247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org uint32 net_ip = *reinterpret_cast<uint32*>(pHost->h_addr_list[0]); 68347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ip = NetworkToHost32(net_ip); 68447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 68547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_F(LS_INFO) << "(" << IPAddress(ip).ToSensitiveString() 68747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ", " << error << ")"; 68847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error == 0) { 69047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SocketAddress address(ip, dns_->port); 69147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error = DoConnect(address); 69247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 69347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Close(); 69447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 69547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 69647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (error) { 69747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org error_ = error; 69847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalCloseEvent(this, error_); 69947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 70047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete dns_; 70147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org dns_ = NULL; 70247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 70347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 70447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 70547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 70647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Win32SocketServer 70747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Provides cricket base services on top of a win32 gui thread 70847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 70947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 71047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic UINT s_wm_wakeup_id = 0; 71147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst TCHAR Win32SocketServer::kWindowName[] = L"libjingle Message Window"; 71247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 71347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgWin32SocketServer::Win32SocketServer(MessageQueue* message_queue) 71447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : message_queue_(message_queue), 71547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org wnd_(this), 71647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org posted_(false), 71747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org hdlg_(NULL) { 71847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (s_wm_wakeup_id == 0) 71947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org s_wm_wakeup_id = RegisterWindowMessage(L"WM_WAKEUP"); 72047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!wnd_.Create(NULL, kWindowName, 0, 0, 0, 0, 0, 0)) { 72147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_GLE(LS_ERROR) << "Failed to create message window."; 72247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 72347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 72447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 72547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgWin32SocketServer::~Win32SocketServer() { 72647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (wnd_.handle() != NULL) { 72747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KillTimer(wnd_.handle(), 1); 72847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org wnd_.Destroy(); 72947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 73047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 73147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 73247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket* Win32SocketServer::CreateSocket(int type) { 73347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return CreateSocket(AF_INET, type); 73447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 73547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 73647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket* Win32SocketServer::CreateSocket(int family, int type) { 73747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return CreateAsyncSocket(family, type); 73847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 73947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 74047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncSocket* Win32SocketServer::CreateAsyncSocket(int type) { 74147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return CreateAsyncSocket(AF_INET, type); 74247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 74347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 74447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAsyncSocket* Win32SocketServer::CreateAsyncSocket(int family, int type) { 74547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Win32Socket* socket = new Win32Socket; 74647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket->CreateT(family, type)) { 74747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return socket; 74847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 74947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete socket; 75047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 75147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 75247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 75347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32SocketServer::SetMessageQueue(MessageQueue* queue) { 75447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org message_queue_ = queue; 75547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 75647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 75747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32SocketServer::Wait(int cms, bool process_io) { 75847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org BOOL b; 75947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (process_io) { 76047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Spin the Win32 message pump at least once, and as long as requested. 76147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // This is the Thread::ProcessMessages case. 76247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org uint32 start = Time(); 76347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org do { 76447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org MSG msg; 76547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetTimer(wnd_.handle(), 0, cms, NULL); 76647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Get the next available message. If we have a modeless dialog, give 76747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // give the message to IsDialogMessage, which will return true if it 76847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // was a message for the dialog that it handled internally. 76947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Otherwise, dispatch as usual via Translate/DispatchMessage. 77047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org b = GetMessage(&msg, NULL, 0, 0); 77147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (b == -1) { 77247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_GLE(LS_ERROR) << "GetMessage failed."; 77347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 77447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if(b) { 77547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!hdlg_ || !IsDialogMessage(hdlg_, &msg)) { 77647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org TranslateMessage(&msg); 77747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DispatchMessage(&msg); 77847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 77947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 78047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KillTimer(wnd_.handle(), 0); 78147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } while (b && TimeSince(start) < cms); 78247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (cms != 0) { 78347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Sit and wait forever for a WakeUp. This is the Thread::Send case. 78447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(cms == -1); 78547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org MSG msg; 78647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org b = GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id); 78747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org { 78847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CritScope scope(&cs_); 78947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org posted_ = false; 79047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 79147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 79247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // No-op (cms == 0 && !process_io). This is the Pump case. 79347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org b = TRUE; 79447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 79547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return (b != FALSE); 79647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 79747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 79847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32SocketServer::WakeUp() { 79947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (wnd_.handle()) { 80047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Set the "message pending" flag, if not already set. 80147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org { 80247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CritScope scope(&cs_); 80347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (posted_) 80447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 80547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org posted_ = true; 80647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 80747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 80847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0); 80947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 81047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 81147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 81247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Win32SocketServer::Pump() { 81347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Clear the "message pending" flag. 81447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org { 81547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CritScope scope(&cs_); 81647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org posted_ = false; 81747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 81847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 81947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Dispatch all the messages that are currently in our queue. If new messages 82047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // are posted during the dispatch, they will be handled in the next Pump. 82147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We use max(1, ...) to make sure we try to dispatch at least once, since 82247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // this allow us to process "sent" messages, not included in the size() count. 82347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Message msg; 82447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (size_t max_messages_to_process = _max<size_t>(1, message_queue_->size()); 82547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org max_messages_to_process > 0 && message_queue_->Get(&msg, 0, false); 82647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org --max_messages_to_process) { 82747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org message_queue_->Dispatch(&msg); 82847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 82947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 83047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Anything remaining? 83147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int delay = message_queue_->GetDelay(); 83247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (delay == -1) { 83347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KillTimer(wnd_.handle(), 1); 83447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 83547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetTimer(wnd_.handle(), 1, delay, NULL); 83647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 83747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 83847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 83947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32SocketServer::MessageWindow::OnMessage(UINT wm, WPARAM wp, 84047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPARAM lp, LRESULT& lr) { 84147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool handled = false; 84247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (wm == s_wm_wakeup_id || (wm == WM_TIMER && wp == 1)) { 84347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ss_->Pump(); 84447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org lr = 0; 84547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org handled = true; 84647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 84747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return handled; 84847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 84947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 85047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 851