You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
9.6 KiB

/*==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 <http://www.gnu.org/licenses/>.
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<sockaddr*>(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<const sockaddr*>(addr),sizeof(sockaddr));
}
int plNet::Connect(const SOCKET sck, const sockaddr_in * addr)
{
return ::connect(sck, reinterpret_cast<const sockaddr*>(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<const sockaddr*>(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<sockaddr*>(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 <unistd.h>
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<sockaddr*>(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<const sockaddr*>(addr),sizeof(sockaddr));
}
int plNet::Connect(const SOCKET sck, const sockaddr_in * addr)
{
return ::connect(sck, reinterpret_cast<const sockaddr*>(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<const sockaddr*>(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<sockaddr*>(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