/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "plNet.h" //////////////////////////////////////////////////// plNet plNet::_; //////////////////////////////////////////////////// // Windows socket interface #if HS_BUILD_FOR_WIN32 plNet::plNet() { static struct WSAData wsa; WSAStartup(0x0101, &wsa); } plNet::~plNet() { WSACleanup(); } SOCKET plNet::NewUDP() { return ::socket(AF_INET, SOCK_DGRAM, 0); } SOCKET plNet::NewTCP() { SOCKET x = ::socket(AF_INET, SOCK_STREAM, 0); unsigned int timeoutval; timeoutval = kDefaultSocketTimeout; setsockopt(x, SOL_SOCKET, (int)SO_RCVTIMEO,(const char*)&timeoutval,sizeof(timeoutval)); timeoutval = kDefaultSocketTimeout; setsockopt(x, SOL_SOCKET, (int)SO_SNDTIMEO,(const char*)&timeoutval,sizeof(timeoutval)); return x; } int plNet::GetError() { return WSAGetLastError(); } int plNet::Read(const SOCKET sck, char * buf, const int size) { return ::recv(sck,buf,size,0); } int plNet::Write(const SOCKET sck, const char * buf, const int len) { return ::send(sck,buf,len,0); } int plNet::ReadFrom(const SOCKET sck, char * buf, int len, sockaddr_in * addr) { int addrlen = sizeof(sockaddr); return ::recvfrom(sck,buf,len,0,reinterpret_cast(addr),&addrlen); } int plNet::WriteTo(const SOCKET sck, const char * buf, const int len, sockaddr_in * addr) { return ::sendto(sck,buf,len,0,reinterpret_cast(addr),sizeof(sockaddr)); } int plNet::Connect(const SOCKET sck, const sockaddr_in * addr) { return ::connect(sck, reinterpret_cast(addr), sizeof(sockaddr)); } int plNet::Close(const SOCKET sck) { return ::closesocket(sck); } int plNet::Bind(const SOCKET sck, const sockaddr_in * addr) { return ::bind(sck,reinterpret_cast(addr),sizeof(sockaddr)); } int plNet::Listen(const SOCKET sck, const int qsize) { return ::listen(sck,qsize); } int plNet::Accept(const SOCKET sck, sockaddr_in * addr) { int addrlen = sizeof(sockaddr); return ::accept(sck,reinterpret_cast(addr),&addrlen); } int plNet::Ioctl(const SOCKET sck, const long flags, unsigned long * val) { return ::ioctlsocket(sck,flags,val); } // static const char * plNet::GetErrorMsg(int error) { switch(error) { case WSAEINTR: return "Interrupted system call"; break; case WSAEBADF: return "Bad file number"; break; case WSAEACCES: return "Permission denied"; break; case WSAEFAULT: return "Bad address"; break; case WSAEINVAL: return "Invalid argument"; break; case WSAEMFILE: return "Too many open sockets"; break; case WSAEWOULDBLOCK: return "Operation would block"; break; case WSAEINPROGRESS: return "Operation now in progress"; break; case WSAEALREADY: return "Operation already in progress"; break; case WSAENOTSOCK: return "Socket operation on non-socket"; break; case WSAEDESTADDRREQ: return "Destination address required"; break; case WSAEMSGSIZE: return "Message too long"; break; case WSAEPROTOTYPE: return "Protocol wrong type for socket"; break; case WSAENOPROTOOPT: return "Bad protocol option"; break; case WSAEPROTONOSUPPORT: return "Protocol not supported"; break; case WSAESOCKTNOSUPPORT: return "Socket type not supported"; break; case WSAEOPNOTSUPP: return "Operation not supported on socket"; break; case WSAEPFNOSUPPORT: return "Protocol family not supported"; break; case WSAEAFNOSUPPORT: return "Address family not supported"; break; case WSAEADDRINUSE: return "Address already in use"; break; case WSAEADDRNOTAVAIL: return "Can't assign requested address"; break; case WSAENETDOWN: return "Network is down"; break; case WSAENETUNREACH: return "Network is unreachable"; break; case WSAENETRESET: return "Net connection reset"; break; case WSAECONNABORTED: return "Software caused connection abort"; break; case WSAECONNRESET: return "Connection reset by peer"; break; case WSAENOBUFS: return "No buffer space available"; break; case WSAEISCONN: return "Socket is already connected"; break; case WSAENOTCONN: return "Socket is not connected"; break; case WSAESHUTDOWN: return "Can't send after socket shutdown"; break; case WSAETOOMANYREFS: return "Too many references, can't splice"; break; case WSAETIMEDOUT: return "Connection timed out"; break; case WSAECONNREFUSED: return "Connection refused"; break; case WSAELOOP: return "Too many levels of symbolic links"; break; case WSAENAMETOOLONG: return "File name too long"; break; case WSAEHOSTDOWN: return "Host is down"; break; case WSAEHOSTUNREACH: return "No route to host"; break; case WSAENOTEMPTY: return "Directory not empty"; break; case WSAEPROCLIM: return "Too many processes"; break; case WSAEUSERS: return "Too many users"; break; case WSAEDQUOT: return "Disc quota exceeded"; break; case WSAESTALE: return "Stale NFS file handle"; break; case WSAEREMOTE: return "Too many levels of remote in path"; break; case WSASYSNOTREADY: return "Network subsystem is unavailable"; break; case WSAVERNOTSUPPORTED: return "Winsock version not supported"; break; case WSANOTINITIALISED: return "Winsock not yet initialized"; break; case WSAHOST_NOT_FOUND: return "Host not found"; break; case WSATRY_AGAIN: return "Non-authoritative host not found"; break; case WSANO_RECOVERY: return "Non-recoverable errors"; break; case WSANO_DATA: return "Valid name, no data record of requested type"; break; case WSAEDISCON: return "Graceful disconnect in progress"; break; case WSASYSCALLFAILURE: return "System call failure"; break; case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available"; break; case WSA_OPERATION_ABORTED: return "Overlapped operation aborted"; break; case WSA_IO_INCOMPLETE: return "Overlapped I/O object not signalled"; break; case WSA_IO_PENDING: return "Overlapped I/O will complete later"; break; //case WSAINVALIDPROCTABLE: return "Invalid proc. table from service provider"; break; //case WSAINVALIDPROVIDER: return "Invalid service provider version number"; break; //case WSAPROVIDERFAILEDINIT, return "Unable to init service provider"; break; case WSA_INVALID_PARAMETER: return "One or more parameters are invalid"; break; case WSA_INVALID_HANDLE: return "Event object handle not valid"; break; }; return "\0"; } //////////////////////////////////////////////////// // UNIX socket interface #elif HS_BUILD_FOR_UNIX #include plNet::plNet() { } plNet::~plNet() { } SOCKET plNet::NewUDP() { return ::socket(AF_INET, SOCK_DGRAM, 0); } SOCKET plNet::NewTCP() { SOCKET x = ::socket(AF_INET, SOCK_STREAM, 0); unsigned int timeoutval; timeoutval = kDefaultSocketTimeout; setsockopt(x, SOL_SOCKET, (int)SO_RCVTIMEO,(const char*)&timeoutval,sizeof(timeoutval)); timeoutval = kDefaultSocketTimeout; setsockopt(x, SOL_SOCKET, (int)SO_SNDTIMEO,(const char*)&timeoutval,sizeof(timeoutval)); return x; } int plNet::GetError() { return errno; } int plNet::Read(const SOCKET sck, char * buf, const int size) { return ::recv(sck,buf,size,0); } int plNet::Write(const SOCKET sck, const char * buf, const int len) { return ::send(sck,buf,len,0); } int plNet::ReadFrom(const SOCKET sck, char * buf, int len, sockaddr_in * addr) { unsigned addrlen = sizeof(sockaddr); return ::recvfrom(sck,buf,len,0,reinterpret_cast(addr),&addrlen); } int plNet::WriteTo(const SOCKET sck, const char * buf, const int len, sockaddr_in * addr) { return ::sendto(sck,buf,len,0,reinterpret_cast(addr),sizeof(sockaddr)); } int plNet::Connect(const SOCKET sck, const sockaddr_in * addr) { return ::connect(sck, reinterpret_cast(addr), sizeof(sockaddr)); } int plNet::Close(const SOCKET sck) { return ::close(sck); } int plNet::Bind(const SOCKET sck, const sockaddr_in * addr) { return ::bind(sck,reinterpret_cast(addr),sizeof(sockaddr)); } int plNet::Listen(const SOCKET sck, const int qsize) { return ::listen(sck,qsize); } int plNet::Accept(const SOCKET sck, sockaddr_in * addr) { unsigned addrlen = sizeof(sockaddr); return ::accept(sck,reinterpret_cast(addr),&addrlen); } int plNet::Ioctl(const SOCKET sck, const long flags, unsigned long * val) { return ::ioctl(sck,flags,val); } #else #error "plNet: Sockets not ported" #endif