📄 physicalsocketserver.cxx
字号:
/* * 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. */#if defined(_MSC_VER) && _MSC_VER < 1300
#pragma warning(disable:4786 4530)
#endif#include <cassert>#include "basictypes.h"#include "byteorder.h"#include "common.h"#include "physicalsocketserver.h"#include "time.h"#include <winsock2.h>#include <ws2tcpip.h>#define _WINSOCKAPI_#include <windows.h>#undef SetPort#include <algorithm>class WinsockInitializer {public: WinsockInitializer() { WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1, 0); err_ = WSAStartup(wVersionRequested, &wsaData); } ~WinsockInitializer() { WSACleanup(); } int error() { return err_; }private: int err_;};WinsockInitializer g_winsockinit;namespace cricket {const int kfRead = 0x0001;const int kfWrite = 0x0002;const int kfConnect = 0x0004;const int kfClose = 0x0008;// Standard MTUsconst 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};const uint32 IP_HEADER_SIZE = 20;const uint32 ICMP_HEADER_SIZE = 8;class PhysicalSocket : public AsyncSocket {public: PhysicalSocket(PhysicalSocketServer* ss, SOCKET s = INVALID_SOCKET) : ss_(ss), s_(s), enabled_events_(0), error_(0), state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED) { if (s != INVALID_SOCKET) enabled_events_ = kfRead | kfWrite; } virtual ~PhysicalSocket() { Close(); } // Creates the underlying OS socket (same as the "socket" function). virtual bool Create(int type) { Close(); s_ = ::socket(AF_INET, type, 0); UpdateLastError(); enabled_events_ = kfRead | kfWrite; return s_ != INVALID_SOCKET; } SocketAddress GetLocalAddress() const { struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); int result = ::getsockname(s_, (struct sockaddr*)&addr, &addrlen); assert(addrlen == sizeof(addr)); if (result >= 0) { return SocketAddress(NetworkToHost32(addr.sin_addr.s_addr), NetworkToHost16(addr.sin_port)); } else { return SocketAddress(); } } SocketAddress GetRemoteAddress() const { struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); int result = ::getpeername(s_, (struct sockaddr*)&addr, &addrlen); assert(addrlen == sizeof(addr)); if (result >= 0) { return SocketAddress( NetworkToHost32(addr.sin_addr.s_addr), NetworkToHost16(addr.sin_port)); } else { // assert(errno == ENOTCONN); return SocketAddress(); } } int Bind(const SocketAddress& addr) { struct sockaddr_in saddr; IP2SA(&addr, &saddr); int err = ::bind(s_, (struct sockaddr*)&saddr, sizeof(saddr)); UpdateLastError(); return err; } int Connect(const SocketAddress& addr) { // TODO: Implicit creation is required to reconnect... // ...but should we make it more explicit? if ((s_ == INVALID_SOCKET) && !Create(SOCK_STREAM)) return SOCKET_ERROR; SocketAddress addr2(addr); if (addr2.IsUnresolved()) { addr2.Resolve(); // TODO: Do this async later? } struct sockaddr_in saddr; IP2SA(&addr2, &saddr); int err = ::connect(s_, (struct sockaddr*)&saddr, sizeof(saddr)); UpdateLastError(); //LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] Connect(" << addr2.ToString() << ") Ret: " << err << " Error: " << error_; if (err == 0) { state_ = CS_CONNECTED; } else if (IsBlockingError(error_)) { state_ = CS_CONNECTING; enabled_events_ |= kfConnect; } return err; } int GetError() const { return error_; } void SetError(int error) { error_ = error; } ConnState GetState() const { return state_; } int SetOption(Option opt, int value) { assert(opt == OPT_DONTFRAGMENT);
value = (value == 0) ? 0 : 1; return ::setsockopt( s_, IPPROTO_IP, IP_DONTFRAGMENT, reinterpret_cast<char*>(&value), sizeof(value)); } int Send(const void *pv, size_t cb) { int sent = ::send(s_, reinterpret_cast<const char *>(pv), (int)cb, 0); UpdateLastError(); //LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] Send(" << cb << ") Ret: " << sent << " Error: " << error_; ASSERT(sent <= static_cast<int>(cb)); // We have seen minidumps where this may be false if ((sent < 0) && IsBlockingError(error_)) { enabled_events_ |= kfWrite; } return sent; } int SendTo(const void *pv, size_t cb, const SocketAddress& addr) { struct sockaddr_in saddr; IP2SA(&addr, &saddr); int sent = ::sendto( s_, (const char *)pv, (int)cb, 0, (struct sockaddr*)&saddr, sizeof(saddr)); UpdateLastError(); ASSERT(sent <= static_cast<int>(cb)); // We have seen minidumps where this may be false if ((sent < 0) && IsBlockingError(error_)) { enabled_events_ |= kfWrite; } return sent; } int Recv(void *pv, size_t cb) { int received = ::recv(s_, (char *)pv, (int)cb, 0); if ((received == 0) && (cb != 0)) { // Note: on graceful shutdown, recv can return 0. In this case, we // pretend it is blocking, and then signal close, so that simplifying // assumptions can be made about Recv. error_ = EWOULDBLOCK; return SOCKET_ERROR; } UpdateLastError(); if ((received >= 0) || IsBlockingError(error_)) { enabled_events_ |= kfRead; } return received; } int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) { struct sockaddr saddr; socklen_t cbAddr = sizeof(saddr); int received = ::recvfrom(s_, (char *)pv, (int)cb, 0, &saddr, &cbAddr); UpdateLastError(); if ((received >= 0) && (paddr != NULL)) SA2IP(&saddr, paddr); if ((received >= 0) || IsBlockingError(error_)) { enabled_events_ |= kfRead; } return received; } int Listen(int backlog) { int err = ::listen(s_, backlog); UpdateLastError(); if (err == 0) state_ = CS_CONNECTING; return err; } Socket* Accept(SocketAddress *paddr) { struct sockaddr saddr; socklen_t cbAddr = sizeof(saddr); SOCKET s = ::accept(s_, &saddr, &cbAddr); UpdateLastError(); if (s == INVALID_SOCKET) return NULL; if (paddr != NULL) SA2IP(&saddr, paddr); return ss_->WrapSocket(s); } int Close() { if (s_ == INVALID_SOCKET) return 0; int err = ::closesocket(s_); UpdateLastError(); //LOG(INFO) << "SOCK[" << static_cast<int>(s_) << "] Close() Ret: " << err << " Error: " << error_; s_ = INVALID_SOCKET; state_ = CS_CLOSED; enabled_events_ = 0; return err; } int EstimateMTU(uint16* mtu) { SocketAddress addr = GetRemoteAddress(); if (addr.IsAny()) { error_ = ENOTCONN; return -1; }
// TODO: no support
return -1; } SocketServer* socketserver() { return ss_; } protected: PhysicalSocketServer* ss_; SOCKET s_; uint32 enabled_events_; int error_; ConnState state_; void UpdateLastError() { error_ = WSAGetLastError(); } void IP2SA(const SocketAddress *paddr, struct sockaddr_in *psaddr) { memset(psaddr, 0, sizeof(*psaddr)); psaddr->sin_family = AF_INET; psaddr->sin_port = HostToNetwork16(paddr->port()); if (paddr->ip() == 0) psaddr->sin_addr.s_addr = INADDR_ANY; else psaddr->sin_addr.s_addr = HostToNetwork32(paddr->ip()); } void SA2IP(const struct sockaddr *psaddr, SocketAddress *paddr) { const struct sockaddr_in *psaddr_in = reinterpret_cast<const struct sockaddr_in*>(psaddr); paddr->SetIP(NetworkToHost32(psaddr_in->sin_addr.s_addr)); paddr->SetPort(NetworkToHost16(psaddr_in->sin_port)); }};class Dispatcher {public: virtual uint32 GetRequestedEvents() = 0; virtual void OnPreEvent(uint32 ff) = 0; virtual void OnEvent(uint32 ff, int err) = 0; virtual WSAEVENT GetWSAEvent() = 0; virtual SOCKET GetSocket() = 0; virtual bool CheckSignalClose() = 0;};uint32 FlagsToEvents(uint32 events) { uint32 ffFD = FD_CLOSE | FD_ACCEPT; if (events & kfRead) ffFD |= FD_READ; if (events & kfWrite) ffFD |= FD_WRITE; if (events & kfConnect) ffFD |= FD_CONNECT; return ffFD;}class EventDispatcher : public Dispatcher {public: EventDispatcher(PhysicalSocketServer *ss) : ss_(ss) { if (hev_ = WSACreateEvent()) { ss_->Add(this); } } ~EventDispatcher() { if (hev_ != NULL) { ss_->Remove(this); WSACloseEvent(hev_); hev_ = NULL; } } virtual void Signal() { if (hev_ != NULL) WSASetEvent(hev_); } virtual uint32 GetRequestedEvents() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -