possibly controversial commit: remove all windows sources, keeping only the windows cmake so that we can generate an sln to edit the code

This commit is contained in:
DarthArgus
2016-01-27 15:22:22 -06:00
parent 3dccead5d5
commit 48ba7961eb
201 changed files with 0 additions and 21403 deletions
@@ -1,410 +0,0 @@
// Address.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
//---------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "sharedNetwork/Address.h"
#include <cstdio>
#include <winsock.h>
//---------------------------------------------------------------------
/**
@brief Construct an empty address (INADDR_ANY)
@author Justin Randall
*/
Address::Address() :
addr4(new struct sockaddr_in),
hostAddress("0.0.0.0")
{
memset(addr4, 0, sizeof(struct sockaddr_in));
addr4->sin_family = AF_INET;
}
//---------------------------------------------------------------------
/**
@brief construct an address from a human readable dotted-decimal
host address and port
Care should be taken when using this constructor. It could potentially
invoke gethostbyname() and block while the resolver returns a
valid ip address.
@author Justin Randall
@todo Add a static resolver cache to Address to reduce potential
calls to gethostbyname()
*/
Address::Address(const std::string & newHostAddress, const unsigned short newHostPort) :
addr4(new struct sockaddr_in),
hostAddress(newHostAddress)
{
HOSTENT * h;
unsigned long u;
memset(addr4, 0, sizeof(struct sockaddr_in));
addr4->sin_port = htons(newHostPort);
addr4->sin_family = AF_INET;
// was an address supplied?
if(hostAddress.size() > 0)
{
// Is the first byte a number? (IP names begin with an alpha)
if(!isdigit(hostAddress[0]))
{
// The first byte is a letter, resolve it
if( (h = gethostbyname(hostAddress.c_str())) != 0)
{
int i = 0;
while (h->h_addr_list[i] != 0) {
memcpy(&addr4->sin_addr, h->h_addr_list[i++], sizeof(addr4->sin_addr));
//addr4->sin_addr = *(u_long *) h->h_addr_list[i++];
//printf("\tIP Address #%d: %s\n", i, inet_ntoa(addr));
}
//memcpy(&addr4->sin_addr, h->h_addr_list[0], sizeof(addr4->sin_addr));
}
else
{
// boom! grab the entry from the h_addr member instead!
if( (h = gethostbyname(hostAddress.c_str())) != 0)
{
memcpy(&addr4->sin_addr, h->h_addr, sizeof(addr4->sin_addr));
}
else
{
// no resolution, INADDR_ANY
// could be that the network needs a kick in the ass
memset(&addr4->sin_addr, 0, sizeof(addr4->sin_addr));
}
}
// extract IP bytes from ipv4add4
const unsigned char * ip;
char name[17] = {"\0"};
ip = reinterpret_cast<const unsigned char *>(&addr4->sin_addr);
_snprintf(name, 17, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); //lint !e534
hostAddress = name;
}
else
{
// A dotted decimal ip number string was supplied. Convert for sin_addr
u = inet_addr(hostAddress.c_str());
memcpy(&addr4->sin_addr, &u, sizeof(addr4->sin_addr));
}
}
else
{
// nothing was supplied, assign INADDR_ANY
addr4->sin_addr.s_addr = INADDR_ANY;
}
convertFromSockAddr(*addr4);
}
//---------------------------------------------------------------------
/**
@brief Address copy constructor
@author Justin Randall
*/
Address::Address(const Address & source) :
addr4(new struct sockaddr_in),
hostAddress(source.hostAddress)
{
*addr4 = *source.addr4;
}
//---------------------------------------------------------------------
/**
@brief Constructs an address from a BSD sockaddr structure
@author Justin Randall
*/
Address::Address(const struct sockaddr_in & ipv4addr) :
addr4(new struct sockaddr_in),
hostAddress()
{
convertFromSockAddr(ipv4addr);
}
//---------------------------------------------------------------------
/**
@brief Destroy an address
@author Justin Randall
*/
Address::~Address()
{
delete addr4;
}
//---------------------------------------------------------------------
/**
@brief Aassign an address to anothe address
*/
Address & Address::operator = (const Address & rhs)
{
if(this != &rhs)
{
hostAddress = rhs.hostAddress;
*addr4 = *rhs.addr4;
}
return *this;
}
//---------------------------------------------------------------------
/**
@brief Assign an address to a BSD sockaddr_in structure
@author Justin Randall
*/
Address & Address::operator = (const struct sockaddr_in & rhs)
{
convertFromSockAddr(rhs);
return *this;
}
//---------------------------------------------------------------------
void Address::convertFromSockAddr(const struct sockaddr_in & source)
{
// extract IP bytes from ipv4add4
const unsigned char * ip;
char name[17] = {"\0"};
ip = reinterpret_cast<const unsigned char *>(&source.sin_addr);
_snprintf(name, 17, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); //lint !e534
hostAddress = name;
if(addr4 != &source)
*addr4 = source;
}
//---------------------------------------------------------------------
/**
@brief get a human readable host address
Example:
\code
void foo(struct sockaddr_in & a)
{
Address b(a);
printf("address = %%s\\n", b.getHostAddress().c_str());
}
\endcode
@return A human readable host address string
@author Justin Randall
*/
const std::string & Address::getHostAddress() const
{
return hostAddress;
}
//---------------------------------------------------------------------
/**
@brief get the port associated with this address
Example:
\code
void foo(struct sockaddr_in & a)
{
Address b(a);
printf("port = %%i\\n", b.getHostPort());
}
\endcode
@return A human readable port in host-byte order associated with
this address.
@author Justin Randall
*/
const unsigned short Address::getHostPort() const
{
return ntohs(addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief get the BSD sockaddr describing this address
Example:
\code
void foo(SOCKET s, unsigned char * d, int l, const Address & a)
{
int t = sizeof(struct sockaddr_in);
sendto(s, s, l, 0, reinterpret_cast<const struct sockaddr *>(&(a.getSockAddr4())), t);
}
\endcode
@return a BSD sockaddr that describes this IPv4 address
@author Justin Randall
*/
const struct sockaddr_in & Address::getSockAddr4() const
{
return *addr4;
}
//---------------------------------------------------------------------
/**
@brief equality operator
The equality operator compares the ip address, ip port,
and address family to establish equality.
Example:
\code
Address a("127.0.0.1", 55443);
Address b;
b = a;
\endcode
@return True of the right hand side is equal to this address
@author Justin Randall
*/
const bool Address::operator == (const Address & rhs) const
{
return (addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr &&
addr4->sin_family == rhs.addr4->sin_family &&
addr4->sin_port == rhs.addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief less-than comparison operator
The < comparison operator compares the IP number and port. If
the IP numbers are identical, but the left hand side port is
less than the right hand side port, the operator will return
true.
@return true if the left hand side's IP number is less than
the right hand side IP number. If the numbers are equal, it
will return true if the left hand side IP port is less
than the right hand side port. Otherwise it returns false.
@author Justin Randall
*/
const bool Address::operator < (const Address & rhs) const
{
return(addr4->sin_addr.s_addr < rhs.addr4->sin_addr.s_addr ||
addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr &&
addr4->sin_port < rhs.addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief inequality operator
Leverages the equality operator, so whenever == returns true,
this returns false, and visa versa.
@return true if the right hand side is not equal to the left
hand side. False if they are equal.
@see Adress::operator==
@author Justin Randall
*/
const bool Address::operator != (const Address & rhs) const
{
return(! (rhs == *this));
}
//---------------------------------------------------------------------
/**
@brief greater-than comparison operator
The > comparison operator compares the IP number and port. If
the IP numbers are identical, but the right hand side port is
lesser than the left hand side port, the operator will return
true.
@return true if the left hand side's IP number is greater than
the right hand side IP number. If the numbers are equal, it
will return true if the left hand side IP port is greater
than the right hand side port. Otherwise it returns false.
@author Justin Randall
*/
const bool Address::operator > (const Address & rhs) const
{
return(addr4->sin_addr.s_addr > rhs.addr4->sin_addr.s_addr ||
addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr &&
addr4->sin_port > rhs.addr4->sin_port);
}
//---------------------------------------------------------------------
/**
@brief a hash_map support routine
The STL hash_map (present in most STL implementations) requires
a size_t return from a hash function to identify which bucket
a particular value should reside in. On 32 bit or better platforms
the sockaddr_in.sin_addr.s_addr member is small enough to
qualify as a hash-result, provides reasonably unique values
and is reproducable given an address input.
Example:
\code
typedef std::hash_map<Address, Connection *, Address::HashFunction, Address::EqualFunction> AddressMap;
\endcode
@return the ip number member of a sockaddr_in struct
@author Justin Randall
*/
size_t Address::hashFunction() const
{
return addr4->sin_addr.s_addr;
}
//---------------------------------------------------------------------
/**
@brief STL map support routine
STL maps (including hash_maps) require unique keys, and therefore
need to compare a key for equality with an existing target.
The functor uses Address::operator = for the comparison.
Example:
\code
typedef std::unordered_map<Address, Connection *, Address::HashFunction, Address::EqualFunction> AddressMap;
\endcode
@return true if the left hand side and right hand side are equal
using Address::operator =
@see Address::operator=
*/
bool Address::EqualFunction::operator () (const Address & lhs, const Address & rhs) const
{
return lhs == rhs;
}
//---------------------------------------------------------------------
/**
@brief STL hash_map support routine
The HashFunction::operator() invokes Address::hashFunction to
determine an appropriate hash for the address.
Example:
\code
typedef std::hash_map<Address, Connection *, Address::HashFunction, Address::EqualFunction> AddressMap;
\endcode
@see Address::hashFunction
@author Justin Randall
*/
size_t Address::HashFunction::operator () (const Address & a) const
{
return a.hashFunction();
}
//---------------------------------------------------------------------
@@ -1,9 +0,0 @@
// FirstSharedNetwork.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
//-----------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
//-----------------------------------------------------------------------
@@ -1,67 +0,0 @@
// NetworkGetHostName.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
//-----------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "sharedNetwork/Address.h"
#include "sharedNetwork/NetworkHandler.h"
#include <winsock.h>
//-----------------------------------------------------------------------
struct HN
{
HN();
std::string hostName;
};
//-----------------------------------------------------------------------
HN::HN()
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
char name[512] = {"\0"};
if(gethostname(name, sizeof(name)) == 0)
{
Address a(name, 0);
hostName = a.getHostAddress();//name;
}
}
//-----------------------------------------------------------------------
const std::string & NetworkHandler::getHostName()
{
static HN hn;
return hn.hostName;
}
const std::string & NetworkHandler::getHumanReadableHostName()
{
char name[512] = {"\0"};
static std::string nameString;
if(nameString.empty())
{
if(gethostname(name, sizeof(name)) == 0)
{
name[sizeof(name) - 1] = 0;
//hostName = name;
nameString = name;
}
}
return nameString;
}
//-----------------------------------------------------------------------
const std::vector<std::pair<std::string, std::string> > & NetworkHandler::getInterfaceAddresses()
{
static std::vector<std::pair<std::string, std::string> > s;
return s;
}
//-----------------------------------------------------------------------
@@ -1,85 +0,0 @@
// OverlappedTcp.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "OverlappedTcp.h"
#include <vector>
#include "TcpClient.h"
#include "TcpServer.h"
//---------------------------------------------------------------------
OverlappedTcp::~OverlappedTcp()
{
delete[] m_acceptData;
delete[] m_recvBuf.buf;
}
//---------------------------------------------------------------------
struct OverlappedFreeList
{
~OverlappedFreeList();
std::vector<OverlappedTcp *> allOverlapped;
std::vector<OverlappedTcp *> freeOverlapped;
};
//---------------------------------------------------------------------
OverlappedFreeList::~OverlappedFreeList()
{
std::vector<OverlappedTcp *>::const_iterator i;
for(i = allOverlapped.begin(); i != allOverlapped.end(); ++i)
{
OverlappedTcp * t = (*i);
delete t;
}
}
//---------------------------------------------------------------------
OverlappedFreeList overlappedFreeList;
//---------------------------------------------------------------------
OverlappedTcp * getFreeOverlapped()
{
OverlappedTcp * result = NULL;
if(! overlappedFreeList.freeOverlapped.empty())
{
result = overlappedFreeList.freeOverlapped.back();
overlappedFreeList.freeOverlapped.pop_back();
}
else
{
result = new OverlappedTcp;
result->m_bytes = 0;
memset(&result->m_overlapped, 0, sizeof(OVERLAPPED));
result->m_recvBuf.buf = new char[1024];
result->m_recvBuf.len = 1024;
result->m_tcpClient = 0;
result->m_tcpServer = 0;
result->m_acceptData = 0;
overlappedFreeList.allOverlapped.push_back(result);
}
return result;
}
//---------------------------------------------------------------------
void releaseOverlapped(OverlappedTcp * o)
{
o->m_bytes = 0;
o->m_tcpClient = 0;
o->m_tcpServer = 0;
o->m_acceptData = 0;
memset(&o->m_overlapped, 0, sizeof(OVERLAPPED));
overlappedFreeList.freeOverlapped.push_back(o);
}
//-----------------------------------------------------------------------
@@ -1,47 +0,0 @@
// OverlappedTcp.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_OverlappedTcp_H
#define _INCLUDED_OverlappedTcp_H
//-----------------------------------------------------------------------
#include <winsock2.h>
//-----------------------------------------------------------------------
class TcpClient;
class TcpServer;
//-----------------------------------------------------------------------
struct OverlappedTcp
{
~OverlappedTcp();
OVERLAPPED m_overlapped;
enum OPERATIONS
{
INVALID,
ACCEPT,
SEND,
RECV
};
unsigned char * m_acceptData; // getting peer name during accept
DWORD m_bytes;
enum OPERATIONS m_operation;
const TcpServer * m_tcpServer;
TcpClient * m_tcpClient; // accepted sock when operation is accept
WSABUF m_recvBuf;
};
//---------------------------------------------------------------------
OverlappedTcp * getFreeOverlapped();
void releaseOverlapped(OverlappedTcp *);
//-----------------------------------------------------------------------
#endif // _INCLUDED_OverlappedTcp_H
@@ -1,366 +0,0 @@
// Sock.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
//---------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "sharedNetwork/Sock.h"
#include <winsock.h>
struct WinsockStartupObject
{
WinsockStartupObject();
~WinsockStartupObject();
};
WinsockStartupObject::WinsockStartupObject()
{
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD(2,0);
int err;
err = WSAStartup(wVersionRequested, &wsaData);
}
WinsockStartupObject::~WinsockStartupObject()
{
WSACleanup();
}
WinsockStartupObject wso;
//---------------------------------------------------------------------
/**
@brief construct a Sock
This constructor sets handle to INVALID_SOCKET, lastError to
Sock::SOCK_NO_ERROR and the bindAddress to the default Address.
@see Address
@author Justin Randall
*/
Sock::Sock() :
handle(INVALID_SOCKET),
lastError(Sock::SOCK_NO_ERROR),
bindAddress()
{
}
//---------------------------------------------------------------------
/**
@brief destroy the Sock object
checks for a valid socket close. It is an error to close a socket
that will fail a close operation.
Also resets handle to INVALID_SOCKET
@author Justin Randall
*/
Sock::~Sock()
{
// ensure we don't block, and that pending
// data is sent with a graceful shutdown
int err;
err = closesocket(handle);
if(err == SOCKET_ERROR)
{
OutputDebugString(getLastError().c_str());
}
handle = INVALID_SOCKET;
}
//---------------------------------------------------------------------
/**
@brief Bind the socket to the specified local address
*/
bool Sock::bind(const Address & newBindAddress)
{
bool result = false;
int enable = 1;
setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&enable), sizeof(enable));
bindAddress = newBindAddress;
int namelen = sizeof(struct sockaddr_in);
int err = ::bind(handle, reinterpret_cast<const struct sockaddr *>(&(bindAddress.getSockAddr4())), namelen);
if(err == 0)
{
result = true;
struct sockaddr_in a;
int r;
r = getsockname(handle, reinterpret_cast<struct sockaddr *>(&a), &namelen);
bindAddress = a;
}
else
{
result = false;
OutputDebugString(getLastError().c_str());
OutputDebugString("\n");
}
return result;
}
//---------------------------------------------------------------------
/**
@brief bind the socket to the first available local address
as provided by the operating system.
This bind call is useful for client sockets, or server sockets that
can report their new address to a locator service.
@author Justin Randall
*/
bool Sock::bind()
{
bool result = false;
struct sockaddr_in a;
int namelen = sizeof(struct sockaddr_in);
memset(&a, 0, sizeof(struct sockaddr_in));
a.sin_family = AF_INET;
a.sin_port = 0;
a.sin_addr.s_addr = INADDR_ANY;
int err = ::bind(handle, reinterpret_cast<struct sockaddr *>(&a), namelen);
if(err == 0)
{
result = true;
int r;
r = getsockname(handle, reinterpret_cast<struct sockaddr *>(&a), &namelen);
bindAddress = a;
}
return result;
}
//---------------------------------------------------------------------
/**
@brief determine if a socket is ready to receive
On Win32, select is invoked. On Linux, the poll() system call is
used to deterine readability of a socket.
@return true if the socket can read data without blocking.
@author Justin Randall
@todo Win32 should be using WSAEventSelect and WSAEnumNetworkEvents
if they outperform select.
*/
bool Sock::canRecv() const
{
struct timeval tv;
fd_set r;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&r);
#pragma warning (disable : 4127)
FD_SET(handle, &r); //lint !e717 // I have no idea why MS makes this a do { .. } while(0); macro?! Pointless.
return (select(1, &r, 0, 0, &tv) > 0);
}
//---------------------------------------------------------------------
/**
@brief determine writeability of the socket
Win32 systems use select, Linux use poll.
@return true if the socket can send data without blocking.
@author Justin Randall
@todo Win32 should be using WSAEventSelect and WSAEnumNetworkEvents
if they outperform select.
*/
bool Sock::canSend() const
{
struct timeval tv;
fd_set w;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&w);
FD_SET(handle, &w); //lint !e717 // I have no idea why MS makes this a do { .. } while(0); macro?! Pointless.
return (select(1, 0, &w, 0, &tv) > 0);
}
//---------------------------------------------------------------------
/**
@brief determine the number of bytes pending on the socket
Uses ioctl (ioctlsocket on win32) to determine the number
of bytes pending.
@return the number of unread bytes pending on the socket
@author Justin Randall
*/
const unsigned int Sock::getInputBytesPending() const
{
unsigned long int bytes = 0;
int err;
err = ioctlsocket(handle, FIONREAD, &bytes); //lint !e1924 (I don't know WHAT Microsoft is doing here!)
return bytes;
}
//---------------------------------------------------------------------
/**
@brief determine the error state of the socket
This routine also sets the lastError member of the Sock object, which
is used to determine common errors (connection failure, connection
closed, connection reset, etc..)
@return an STL string that describes the error state of the socket,
@author Justin Randall
*/
const std::string Sock::getLastError() const
{
std::string errString;
int iErr = WSAGetLastError();
switch(iErr)
{
case WSAENOPROTOOPT:
errString = "Bad protocol option. An unknown, invalid or unsupported option or level was specified in a getsockopt or setsockopt call.";
break;
case WSAENETDOWN:
errString = "The network subsystem has failed.";
break;
case WSAEFAULT:
errString = "The buf parameter is not completely contained in a valid part of the user address space.";
break;
case WSAENOTCONN:
errString = "The socket is not connected.";
lastError = Sock::CONNECTION_FAILED;
break;
case WSAEINTR:
errString = "The (blocking) call was canceled through WSACancelBlockingCall.";
break;
case WSAEINPROGRESS:
errString = "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.";
break;
case WSAENETRESET:
errString = "The connection has been broken due to the keep-alive activity detecting a failure while the operation was in progress.";
break;
case WSAENOTSOCK:
errString = "The descriptor is not a socket.";
break;
case WSAEOPNOTSUPP:
errString = "MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, out-of-band data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations.";
break;
case WSAESHUTDOWN:
errString = "The socket has been shut down; it is not possible to recv on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH.";
break;
case WSAEWOULDBLOCK:
errString = "The socket is marked as nonblocking and the receive operation would block.";
break;
case WSAEMSGSIZE:
errString = "The message was too large to fit into the specified buffer and was truncated.";
break;
case WSAEINVAL:
errString = "The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled or (for byte stream sockets only) len was zero or negative.";
break;
case WSAECONNABORTED:
errString = "The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no longer usable.";
lastError = Sock::CONNECTION_RESET;
break;
case WSAETIMEDOUT:
errString = "The connection has been dropped because of a network failure or because the peer system failed to respond.";
break;
case WSAECONNRESET:
errString = "The virtual circuit was reset by the remote side executing a \"hard\" or \"abortive\" close. The application should close the socket as it is no longer usable. On a UDP datagram socket this error would indicate that a previous send operation resulted in an ICMP \"Port Unreachable\" message.";
lastError = Sock::CONNECTION_RESET;
break;
case WSAECONNREFUSED:
errString = "No connection could be made because the target machine actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host - i.e. one with no server application running. ";
lastError = Sock::CONNECTION_FAILED;
break;
default:
errString = "An unknown socket error has occurred.";
break;
}
return errString;
}
//-----------------------------------------------------------------------
/** @brief determine the maximum message size that may be sent on this socket
*/
const unsigned int Sock::getMaxMessageSendSize() const
{
/*
int maxMsgSize = 400;
int optlen = sizeof(int);
int result = getsockopt(handle, SOL_SOCKET, SO_MAX_MSG_SIZE, reinterpret_cast<char *>(&maxMsgSize), &optlen);
if(result != 0)
{
int errCode = WSAGetLastError();
switch(errCode)
{
case WSANOTINITIALISED:
OutputDebugString("A successful WSAStartup call must occur before using this function. ");
break;
case WSAENETDOWN:
OutputDebugString("The network subsystem has failed. ");
break;
case WSAEFAULT:
OutputDebugString("One of the optval or the optlen parameters is not a valid part of the user address space, or the optlen parameter is too small. ");
case WSAEINPROGRESS:
OutputDebugString("A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. ");
break;
case WSAEINVAL:
OutputDebugString("The level parameter is unknown or invalid. ");
break;
case WSAENOPROTOOPT:
OutputDebugString("The option is unknown or unsupported by the indicated protocol family. ");
break;
case WSAENOTSOCK:
OutputDebugString("The descriptor is not a socket. ");
break;
default:
OutputDebugString("An unknown error occurred while processing getsockopt");
break;
}
}
*/
return 400;
}
//---------------------------------------------------------------------
/**
@brief get a BSD sockaddr struct describing the remote address
of a socket
@param target a BSD sockaddr struct that will receive the peer
address
@param s the socket to query for the peername
@author Justin Randall
*/
void Sock::getPeerName(struct sockaddr_in & target, SOCKET s)
{
int namelen = sizeof(struct sockaddr_in);
int err;
err = getpeername(s, reinterpret_cast<sockaddr *>(&(target)), &namelen);
}
//---------------------------------------------------------------------
/** @brief a support routine to place the socket in non-blocking mode
@author Justin Randall
*/
void Sock::setNonBlocking() const
{
unsigned long int nb = 1;
int err;
err = ioctlsocket(handle, FIONBIO, &nb); //lint !e569 // loss of precision in the FIONBIO macro, beyond my control
if(err == SOCKET_ERROR)
OutputDebugString(getLastError().c_str());
}
//---------------------------------------------------------------------
@@ -1,129 +0,0 @@
// ======================================================================
//
// Sock.h
//
// Copyright 2003 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Sock_H
#define INCLUDED_Sock_H
// ======================================================================
#include "sharedNetwork/Address.h"
// ======================================================================
const unsigned int SOCK_ERROR = 0xFFFFFFFF;
typedef unsigned int SOCKET;
/**
@brief a BSD socket abstraction
Sock abstracts BSD sockets for platform independant operation. It
also provides common socket operations to simplify socket management.
@see BroadcastSock
@see TcpSock
@see UdpSock
@author Justin Randall
*/
class Sock
{
public:
/**
@brief failure states for a socket
*/
enum ErrorCodes
{
SOCK_NO_ERROR,
CONNECTION_FAILED,
CONNECTION_CLOSED,
CONNECTION_RESET
};
Sock();
virtual ~Sock() = 0;
bool bind(const Address & bindAddress);
bool bind();
bool canSend() const;
bool canRecv() const;
const Address & getBindAddress() const;
const SOCKET getHandle() const;
const unsigned int getInputBytesPending() const;
const std::string getLastError() const;
const enum ErrorCodes getLastErrorCode() const;
const unsigned int getMaxMessageSendSize() const;
static void getPeerName(struct sockaddr_in & target, SOCKET s);
private:
// disabled
Sock(const Sock & source);
Sock & operator= (const Sock & source);
protected:
void setNonBlocking() const;
protected:
int handle;
/**
@brief support for setting/getting last error from derived
sock classes
*/
mutable enum ErrorCodes lastError;
private:
Address bindAddress;
};
//---------------------------------------------------------------------
/**
@brief return the local address of the socket
Until a socket is bound, the bind address may be reported as
0.0.0.0:0
@return a const Address reference describing the local address
of the socket.
@author Justin Randall
*/
inline const Address & Sock::getBindAddress() const
{
return bindAddress;
}
//---------------------------------------------------------------------
/**
@brief return the platform specific socket handle
the handle returned is not portable and should only be used locally
for Sock specific operations.
@author Justin Randall
*/
inline const SOCKET Sock::getHandle() const
{
return handle;
}
//---------------------------------------------------------------------
/**
@brief get the last error code on the socket
@return the last error code on the socket
@see Sock::ErrorCodes
@author Justin Randall
*/
inline const enum Sock::ErrorCodes Sock::getLastErrorCode() const
{
return lastError;
}
//---------------------------------------------------------------------
#endif // _Sock_H
@@ -1,631 +0,0 @@
// TcpClient.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "Archive/Archive.h"
#include "Archive/ByteStream.h"
#include "sharedFoundation/Clock.h"
#include "sharedNetwork/Address.h"
#include "sharedNetwork/ConfigSharedNetwork.h"
#include "sharedNetwork/Connection.h"
#include "sharedNetwork/Service.h"
#include "OverlappedTcp.h"
#include "TcpClient.h"
#include <set>
#include <vector>
//-----------------------------------------------------------------------
const unsigned long KEEPALIVE_MS = 1000;
//-----------------------------------------------------------------------
namespace TcpClientNamespace
{
std::set<TcpClient *> s_pendingConnectionSends;
std::set<TcpClient *> s_pendingConnectionRemoves;
std::set<TcpClient *> s_tcpClients;
QOS s_sqos;
QOS s_gqos;
}
using namespace TcpClientNamespace;
//-----------------------------------------------------------------------
TcpClient::TcpClient(HANDLE parentIOCP) :
m_connectEvent(INVALID_HANDLE_VALUE),
m_socket(),
m_tcpServer(0),
m_localIOCP(INVALID_HANDLE_VALUE),
m_pendingSend(),
m_connection(0),
m_refCount(0),
m_connected(false),
m_ownHandle(false),
m_lastSendTime(0),
m_bindPort(0),
m_rawTCP( false )
{
static PROTOENT * p = getprotobyname ("tcp");
if (p)
{
static int entry = p->p_proto;
m_socket = WSASocket (AF_INET, SOCK_STREAM, entry, NULL, 0, WSA_FLAG_OVERLAPPED);
char optval = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
unsigned long opt = 1;
ioctlsocket(m_socket, FIONBIO, &opt);
struct sockaddr_in bindAddr;
int addrLen = sizeof(struct sockaddr_in);
if(getsockname(m_socket, reinterpret_cast<struct sockaddr *>(&bindAddr), &addrLen) == 0)
{
m_bindPort = ntohs(bindAddr.sin_port);
}
m_localIOCP = CreateIoCompletionPort (reinterpret_cast<HANDLE> (m_socket), parentIOCP, 0, 0);
queueReceive();
}
s_tcpClients.insert(this);
}
//-----------------------------------------------------------------------
TcpClient::TcpClient(const std::string & remoteAddress, const unsigned short remotePort) :
m_connectEvent(INVALID_HANDLE_VALUE),
m_socket(),
m_localIOCP(INVALID_HANDLE_VALUE),
m_connection(0),
m_refCount(0),
m_connected(false),
m_ownHandle(true),
m_lastSendTime(0),
m_rawTCP( false )
{
static PROTOENT * p = getprotobyname ("tcp");
if (p)
{
static int entry = p->p_proto;
m_socket = WSASocket (AF_INET, SOCK_STREAM, entry, NULL, 0, WSA_FLAG_OVERLAPPED);
if (m_socket != INVALID_SOCKET)
{
int nameLen = sizeof (struct sockaddr_in);
static WSABUF emptyBuf;
emptyBuf.buf = 0;
emptyBuf.len = 0;
Address a(remoteAddress, remotePort);
char optval = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
unsigned long opt = 1;
ioctlsocket(m_socket, FIONBIO, &opt);
int result;
result = WSAConnect (m_socket, reinterpret_cast<const struct sockaddr *> (&a.getSockAddr4 () ), nameLen, 0, &emptyBuf, &s_sqos, &s_gqos);
m_connectEvent = WSACreateEvent ();
WSAEventSelect (m_socket, m_connectEvent, FD_CONNECT);
m_localIOCP = CreateIoCompletionPort (reinterpret_cast<HANDLE> (m_socket), 0, 0, 0);
struct sockaddr_in bindAddr;
int addrLen = sizeof(struct sockaddr_in);
if(getsockname(m_socket, reinterpret_cast<struct sockaddr *>(&bindAddr), &addrLen) == 0)
{
m_bindPort = ntohs(bindAddr.sin_port);
}
}
}
s_tcpClients.insert(this);
}
//-----------------------------------------------------------------------
TcpClient::~TcpClient()
{
s_pendingConnectionRemoves.insert(this);
std::set<TcpClient *>::iterator f = s_tcpClients.find(this);
if(f != s_tcpClients.end())
s_tcpClients.erase(f);
closesocket (m_socket);
if(m_ownHandle)
CloseHandle(m_localIOCP);
}
//-----------------------------------------------------------------------
void TcpClient::addRef()
{
m_refCount++;
}
//-----------------------------------------------------------------------
unsigned short TcpClient::getBindPort() const
{
return m_bindPort;
}
//-----------------------------------------------------------------------
std::string const &TcpClient::getRemoteAddress() const
{
// TODO: implement this
static std::string dummy;
return dummy;
}
//-----------------------------------------------------------------------
unsigned short TcpClient::getRemotePort() const
{
// TODO: implement this
return 0;
}
//-----------------------------------------------------------------------
void TcpClient::commit(const unsigned char * const buffer, const int bufferLen)
{
WSABUF wsaBuf;
// yuck, docs say this is actually going to be const for the send,
// but WSABUF::buf is not const!
wsaBuf.buf = (char *)buffer;
wsaBuf.len = bufferLen;
OverlappedTcp * op = getFreeOverlapped ();
if (op)
{
op->m_operation = OverlappedTcp::SEND;
op->m_tcpClient = const_cast<TcpClient *>(this);
int sent;
sent = WSASend (m_socket, &wsaBuf, 1, &op->m_bytes, 0, &op->m_overlapped, NULL);
if(sent == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
char * err;
if(errCode != WSA_IO_PENDING)
{
switch(errCode)
{
case WSANOTINITIALISED:
err = "A successful WSAStartup must occur before using this function.";
break;
case WSAENETDOWN:
err = "The network subsystem has failed.";
break;
case WSAENOTCONN:
err = "The socket is not connected.";
break;
case WSAEINTR:
err = "The (blocking) call was canceled through WSACancelBlockingCall. \n";
break;
case WSAEINPROGRESS:
err = "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. \n";
break;
case WSAENETRESET:
err = "The connection has been broken due to \"keep-alive\" activity detecting a failure while the operation was in progress.";
break;
case WSAENOTSOCK:
err = "The descriptor is not a socket.";
break;
case WSAEFAULT:
err = "The lpBuffers parameter is not completely contained in a valid part of the user address space.";
break;
case WSAEOPNOTSUPP:
err = "MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, out-of-band data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations.";
break;
case WSAESHUTDOWN:
err = "The socket has been shut down; it is not possible to call WSARecv on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. \n";
break;
case WSAEWOULDBLOCK:
err = "Overlapped sockets: There are too many outstanding overlapped I/O requests. Nonoverlapped sockets: The socket is marked as nonblocking and the receive operation cannot be completed immediately. \n";
break;
case WSAEMSGSIZE:
err = "The message was too large to fit into the specified buffer and (for unreliable protocols only) any trailing portion of the message that did not fit into the buffer has been discarded.";
break;
case WSAEINVAL:
err = "The socket has not been bound (for example, with bind).";
break;
case WSAECONNABORTED:
err = "The virtual circuit was terminated due to a time-out or other failure. \n";
break;
case WSAECONNRESET:
err = "The virtual circuit was reset by the remote side. \n";
break;
case WSAEDISCON:
err = "Socket s is message oriented and the virtual circuit was gracefully closed by the remote side. \n";
break;
case WSA_IO_PENDING:
err = "An overlapped operation was successfully initiated and completion will be indicated at a later time. \n";
break;
case WSA_OPERATION_ABORTED:
err = "The overlapped operation has been canceled due to the closure of the socket. \n";
break;
default:
err = "An unknown error occured while processing WSARecv().";
break;
}
onConnectionClosed();
}
}
}
}
//-----------------------------------------------------------------------
void TcpClient::flush()
{
if(m_connected && m_pendingSend.getSize() > 0)
{
// put it on the wire
commit(m_pendingSend.getBuffer(), m_pendingSend.getSize());
m_pendingSend.clear ();
}
}
//-----------------------------------------------------------------------
void TcpClient::flushPendingWrites()
{
std::set<TcpClient *>::iterator f;
std::set<TcpClient *>::iterator i;
for(i = s_pendingConnectionSends.begin(); i != s_pendingConnectionSends.end(); ++i)
{
if(s_pendingConnectionRemoves.empty())
{
(*i)->flush();
}
else
{
f = s_pendingConnectionRemoves.find((*i));
if(f == s_pendingConnectionRemoves.end())
(*i)->flush();
}
}
s_pendingConnectionSends.clear();
}
//-----------------------------------------------------------------------
SOCKET TcpClient::getSocket() const
{
return m_socket;
}
//-----------------------------------------------------------------------
void TcpClient::install()
{
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
s_sqos.ProviderSpecific.buf = 0;
s_sqos.ProviderSpecific.len = 0;
s_sqos.ReceivingFlowspec.DelayVariation = 0;
s_sqos.ReceivingFlowspec.Latency = 0;
s_sqos.ReceivingFlowspec.MaxSduSize = 0;
s_sqos.ReceivingFlowspec.MinimumPolicedSize = 0;
s_sqos.ReceivingFlowspec.PeakBandwidth = 0;
s_sqos.ReceivingFlowspec.ServiceType = 0;
s_sqos.ReceivingFlowspec.TokenBucketSize = 0;
s_sqos.ReceivingFlowspec.TokenRate = 0;
s_sqos.SendingFlowspec.DelayVariation = 0;
s_sqos.SendingFlowspec.Latency = 0;
s_sqos.SendingFlowspec.MaxSduSize = 0;
s_sqos.SendingFlowspec.MinimumPolicedSize = 0;
s_sqos.SendingFlowspec.PeakBandwidth = 0;
s_sqos.SendingFlowspec.ServiceType = 0;
s_sqos.SendingFlowspec.TokenBucketSize = 0;
s_sqos.SendingFlowspec.TokenRate = 0;
s_gqos.ProviderSpecific.buf = 0;
s_gqos.ProviderSpecific.len = 0;
s_gqos.ReceivingFlowspec.DelayVariation = 0;
s_gqos.ReceivingFlowspec.Latency = 0;
s_gqos.ReceivingFlowspec.MaxSduSize = 0;
s_gqos.ReceivingFlowspec.MinimumPolicedSize = 0;
s_gqos.ReceivingFlowspec.PeakBandwidth = 0;
s_gqos.ReceivingFlowspec.ServiceType = 0;
s_gqos.ReceivingFlowspec.TokenBucketSize = 0;
s_gqos.ReceivingFlowspec.TokenRate = 0;
s_gqos.SendingFlowspec.DelayVariation = 0;
s_gqos.SendingFlowspec.Latency = 0;
s_gqos.SendingFlowspec.MaxSduSize = 0;
s_gqos.SendingFlowspec.MinimumPolicedSize = 0;
s_gqos.SendingFlowspec.PeakBandwidth = 0;
s_gqos.SendingFlowspec.ServiceType = 0;
s_gqos.SendingFlowspec.TokenBucketSize = 0;
s_gqos.SendingFlowspec.TokenRate = 0;
}
//-----------------------------------------------------------------------
void TcpClient::onConnectionClosed()
{
m_connected = false;
if(m_connection)
{
NetworkHandler::onTerminate(m_connection);
}
}
//-----------------------------------------------------------------------
void TcpClient::onConnectionOpened()
{
m_connected = true;
queueReceive();
flush();
if(m_connection)
m_connection->onConnectionOpened();
}
//-----------------------------------------------------------------------
void TcpClient::onReceive(const unsigned char * const buffer, const int length)
{
queueReceive();
if(m_connection)
{
m_connection->receive(buffer, length);
}
}
//-----------------------------------------------------------------------
void TcpClient::queryConnect()
{
bool result = false;
WSANETWORKEVENTS w;
if (WSAEnumNetworkEvents (m_socket, m_connectEvent, &w) != SOCKET_ERROR)
{
if (w.lNetworkEvents == FD_CONNECT)
{
if (w.iErrorCode[FD_CONNECT_BIT] == 0)
{
CloseHandle (m_connectEvent);
result = true;
onConnectionOpened();
}
else
{
onConnectionClosed();
}
}
}
}
//-----------------------------------------------------------------------
void TcpClient::queueReceive()
{
OverlappedTcp * op = getFreeOverlapped();
op->m_operation = OverlappedTcp::RECV;
op->m_tcpClient = const_cast<TcpClient *>(this);
DWORD flags = 0;
int result;
result = WSARecv(m_socket, &op->m_recvBuf, 1, &op->m_bytes, &flags, &op->m_overlapped, NULL);
if(result == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
char * err;
if(errCode != WSA_IO_PENDING)
{
switch(errCode)
{
case WSANOTINITIALISED:
err = "A successful WSAStartup must occur before using this function.";
break;
case WSAENETDOWN:
err = "The network subsystem has failed.";
break;
case WSAENOTCONN:
err = "The socket is not connected.";
break;
case WSAEINTR:
err = "The (blocking) call was canceled through WSACancelBlockingCall. \n";
break;
case WSAEINPROGRESS:
err = "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. \n";
break;
case WSAENETRESET:
err = "The connection has been broken due to \"keep-alive\" activity detecting a failure while the operation was in progress.";
break;
case WSAENOTSOCK:
err = "The descriptor is not a socket.";
break;
case WSAEFAULT:
err = "The lpBuffers parameter is not completely contained in a valid part of the user address space.";
break;
case WSAEOPNOTSUPP:
err = "MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, out-of-band data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations.";
break;
case WSAESHUTDOWN:
err = "The socket has been shut down; it is not possible to call WSARecv on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. \n";
break;
case WSAEWOULDBLOCK:
err = "Overlapped sockets: There are too many outstanding overlapped I/O requests. Nonoverlapped sockets: The socket is marked as nonblocking and the receive operation cannot be completed immediately. \n";
break;
case WSAEMSGSIZE:
err = "The message was too large to fit into the specified buffer and (for unreliable protocols only) any trailing portion of the message that did not fit into the buffer has been discarded.";
break;
case WSAEINVAL:
err = "The socket has not been bound (for example, with bind).";
break;
case WSAECONNABORTED:
err = "The virtual circuit was terminated due to a time-out or other failure. \n";
break;
case WSAECONNRESET:
err = "The virtual circuit was reset by the remote side. \n";
break;
case WSAEDISCON:
err = "Socket s is message oriented and the virtual circuit was gracefully closed by the remote side. \n";
break;
case WSA_IO_PENDING:
err = "An overlapped operation was successfully initiated and completion will be indicated at a later time. \n";
break;
case WSA_OPERATION_ABORTED:
err = "The overlapped operation has been canceled due to the closure of the socket. \n";
break;
default:
err = "An unknown error occured while processing WSARecv().";
break;
}
}
}
}
//-----------------------------------------------------------------------
void TcpClient::send(const unsigned char * const buffer, const int length)
{
if (length)
{
m_lastSendTime = Clock::getFrameStartTimeMs();
s_pendingConnectionSends.insert(this);
if( !m_rawTCP )
Archive::put(m_pendingSend, length);
m_pendingSend.put(buffer, length);
static int const tcpMinimumFrame = ConfigSharedNetwork::getTcpMinimumFrame();
if (static_cast<int>(m_pendingSend.getSize()) >= tcpMinimumFrame)
flush();
}
}
//-----------------------------------------------------------------------
void TcpClient::setConnection(Connection * c)
{
m_connection = c;
}
//---------------------------------------------------------------------
void TcpClient::update()
{
OVERLAPPED * overlapped = 0;
OverlappedTcp * op = 0;
unsigned long int bytesTransferred = 0;
unsigned long int completionKey = 0;
bool success = false;
if (m_connected)
{
unsigned long timeNow = Clock::getFrameStartTimeMs();
if (timeNow-m_lastSendTime > KEEPALIVE_MS)
{
m_lastSendTime = timeNow;
s_pendingConnectionSends.insert(this);
Archive::put(m_pendingSend, 0);
}
}
if(! m_connected)
queryConnect();
//PlatformTcpClient::queryConnects();
do
{
success = false;
int ok = GetQueuedCompletionStatus(
m_localIOCP, // completion port of interest
&bytesTransferred, // number of bytes sent or received
&completionKey,
&overlapped,
0 // timeout immediately if there are no completions
);
if(ok)
{
op = reinterpret_cast<OverlappedTcp *>(overlapped);
if(op)
{
switch(op->m_operation)
{
case OverlappedTcp::RECV:
{
if(op->m_tcpClient != 0)
{
if(bytesTransferred > 0)
{
op->m_tcpClient->onReceive((const unsigned char * const)op->m_recvBuf.buf, bytesTransferred);
success = true;
}
}
}
break;
case OverlappedTcp::SEND:
success = true;
break;
default:
break;
}
releaseOverlapped(op);
}
}
} while(success);
}
//-----------------------------------------------------------------------
void TcpClient::setRawTCP( bool bNewValue )
{
m_rawTCP = bNewValue;
}
//-----------------------------------------------------------------------
void TcpClient::release()
{
m_refCount--;
if(m_refCount < 1)
{
if(m_connected)
onConnectionClosed();
delete this;
}
}
//-----------------------------------------------------------------------
void TcpClient::remove()
{
std::set<TcpClient *>::iterator i;
for(i = s_tcpClients.begin(); i != s_tcpClients.end(); ++i)
{
TcpClient * c = (*i);
delete c;
}
s_tcpClients.clear();
WSACleanup();
}
//-----------------------------------------------------------------------
void TcpClient::checkKeepalive()
{
unsigned long const timeNow = Clock::getFrameStartTimeMs();
if (timeNow-m_lastSendTime > KEEPALIVE_MS)
{
m_lastSendTime = timeNow;
s_pendingConnectionSends.insert(this);
Archive::put(m_pendingSend, 0);
}
}
//-----------------------------------------------------------------------
@@ -1,87 +0,0 @@
// TcpClient.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TcpClient_H
#define _INCLUDED_TcpClient_H
//-----------------------------------------------------------------------
#include <winsock2.h>
#include "Archive/ByteStream.h"
#include <vector>
//-----------------------------------------------------------------------
class Connection;
//-----------------------------------------------------------------------
class TcpClient
{
public:
explicit TcpClient(HANDLE parentIOCP);
TcpClient(const std::string & address, const unsigned short port);
~TcpClient();
static void install();
static void remove();
void send(const unsigned char * const buffer, const int length);
unsigned short getBindPort() const;
std::string const &getRemoteAddress() const;
unsigned short getRemotePort() const;
void setPendingSendAllocatedSizeLimit(unsigned int limit);
// only used by clients
void update();
static void flushPendingWrites();
protected:
friend TcpServer;
friend Connection;
void addRef();
void commit(const unsigned char * const buffer, const int bufferLen);
SOCKET getSocket() const;
void onConnectionClosed();
void onConnectionOpened();
void onReceive(const unsigned char * const recvBuf, const int bytes);
void queryConnect();
void queueReceive();
void release();
void setConnection(Connection *);
void checkKeepalive();
void setRawTCP( bool bNewValue );
private:
TcpClient & operator = (const TcpClient & rhs);
TcpClient(const TcpClient & source);
void flush ();
WSAEVENT m_connectEvent;
SOCKET m_socket;
TcpServer * m_tcpServer;
HANDLE m_localIOCP;
Archive::ByteStream m_pendingSend;
Connection * m_connection;
int m_refCount;
bool m_connected;
bool m_ownHandle;
unsigned long m_lastSendTime;
unsigned short m_bindPort;
bool m_rawTCP;
};
//-----------------------------------------------------------------------
inline void TcpClient::setPendingSendAllocatedSizeLimit(const unsigned int limit)
{
m_pendingSend.setAllocatedSizeLimit(limit);
}
//-----------------------------------------------------------------------
#endif // _INCLUDED_TcpClient_H
@@ -1,194 +0,0 @@
// TcpServer.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include <winsock2.h>
#include <mswsock.h>
#include "sharedNetwork/Address.h"
#include "sharedNetwork/Service.h"
#include "OverlappedTcp.h"
#include "TcpClient.h"
#include "TcpServer.h"
//-----------------------------------------------------------------------
TcpServer::TcpServer(Service * service, const std::string & bindAddress, const unsigned short bindPort) :
m_handle(),
m_localIOCP(),
m_pendingConnections(),
m_bindAddress(bindAddress),
m_bindPort(bindPort),
m_service(service)
{
static PROTOENT * p = getprotobyname("tcp");
if(p)
{
static int entry = p->p_proto;
m_handle = WSASocket(AF_INET, SOCK_STREAM, entry, NULL, 0, WSA_FLAG_OVERLAPPED);
if(m_handle != INVALID_SOCKET)
{
m_localIOCP = CreateIoCompletionPort(reinterpret_cast<HANDLE>(m_handle), 0, 0, 0);
Address a(bindAddress, bindPort);
int result = bind(m_handle, reinterpret_cast<const sockaddr *>(&a.getSockAddr4()), sizeof(struct sockaddr_in));
if(result == 0)
{
struct sockaddr_in b;
int addrlen = sizeof(struct sockaddr_in);
getsockname(m_handle, (struct sockaddr *)(&b), &addrlen);
m_bindPort = ntohs(b.sin_port);
result = listen(m_handle, 256);
queueAccept();
}
}
}
}
//-----------------------------------------------------------------------
TcpServer::~TcpServer()
{
closesocket(m_handle);
CloseHandle(m_localIOCP);
}
//-----------------------------------------------------------------------
TcpClient * TcpServer::accept()
{
TcpClient * result = 0;
if(! m_pendingConnections.empty())
{
result = m_pendingConnections.back();
m_pendingConnections.pop_back();
}
return result;
}
//-----------------------------------------------------------------------
const unsigned short TcpServer::getBindPort() const
{
return m_bindPort;
}
//-----------------------------------------------------------------------
void TcpServer::onConnectionClosed(TcpClient *)
{
}
//-----------------------------------------------------------------------
void TcpServer::queueAccept()
{
OverlappedTcp * op = getFreeOverlapped();
// this will contain struct sockaddr data with additional
// book keeping when Windows returns an overlapped
// accept operation (nevermind that +16 or * 2, I don't have the MS
// kb article handy, but it's a gross workaround for the documented
// API and what acceptData really expects to have).
op->m_acceptData = new unsigned char[(sizeof( struct sockaddr_in ) + 16 ) * 2];
op->m_operation = OverlappedTcp::ACCEPT;
op->m_tcpServer = this;
op->m_tcpClient = new TcpClient(m_localIOCP);
AcceptEx(
m_handle,
op->m_tcpClient->getSocket(),
op->m_acceptData,
0,
sizeof(struct sockaddr_in) + 16,
sizeof(struct sockaddr_in) + 16,
&op->m_bytes,
&op->m_overlapped);
}
//-----------------------------------------------------------------------
void TcpServer::update()
{
OVERLAPPED * overlapped = 0;
OverlappedTcp * op = 0;
unsigned long int bytesTransferred = 0;
unsigned long int completionKey = 0;
bool success = false;
do
{
success = false;
int ok = GetQueuedCompletionStatus(
m_localIOCP, // completion port of interest
&bytesTransferred, // number of bytes sent or received
&completionKey,
&overlapped,
0 // timeout immediately if there are no completions
);
if(ok)
{
op = reinterpret_cast<OverlappedTcp *>(overlapped);
if(op)
{
switch(op->m_operation)
{
case OverlappedTcp::ACCEPT:
{
if(op->m_tcpServer == this)
{
if(op->m_acceptData != 0)
{
// Extremely lame hack to keep things safe from Winsock stacktrashing
//struct sockaddr_in local;
//struct sockaddr_in remote;
//memcpy(&local, reinterpret_cast<struct sockaddr_in *>(op->m_acceptData + 10), sizeof(struct sockaddr_in));
//memcpy(&remote, reinterpret_cast<struct sockaddr_in *>(op->m_acceptData + 38), sizeof(struct sockaddr_in));
delete[] op->m_acceptData;
TcpClient * newClient = op->m_tcpClient;
newClient->addRef();
newClient->onConnectionOpened();
m_pendingConnections.push_back(newClient);
success = true;
queueAccept();
if(m_service)
{
m_service->onConnectionOpened(newClient);
}
newClient->release();
}
}
}
break;
case OverlappedTcp::RECV:
{
if(op->m_tcpClient != 0)
{
op->m_tcpClient->onReceive((const unsigned char * const)op->m_recvBuf.buf, bytesTransferred);
}
}
success = true;
break;
case OverlappedTcp::SEND:
success = true;
break;
default:
break;
}
releaseOverlapped(op);
}
}
} while(success);
}
//-----------------------------------------------------------------------
const std::string & TcpServer::getBindAddress() const
{
return m_bindAddress;
}
//---------------------------------------------------------------------
@@ -1,50 +0,0 @@
// TcpServer.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TcpServer_H
#define _INCLUDED_TcpServer_H
//-----------------------------------------------------------------------
#include <winsock2.h>
#include <string>
#include <vector>
//-----------------------------------------------------------------------
class Service;
class TcpClient;
//-----------------------------------------------------------------------
class TcpServer
{
public:
TcpServer(Service * service, const std::string & bindAddress, const unsigned short bindPort);
~TcpServer();
TcpClient * accept ();
const std::string & getBindAddress () const;
const unsigned short getBindPort () const;
void onConnectionClosed (TcpClient *);
void update ();
private:
TcpServer & operator = (const TcpServer & rhs);
TcpServer(const TcpServer & source);
void queueAccept ();
private:
SOCKET m_handle;
HANDLE m_localIOCP;
std::vector<TcpClient *> m_pendingConnections;
std::string m_bindAddress;
unsigned short m_bindPort;
Service * m_service;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_TcpServer_H
@@ -1,108 +0,0 @@
// UdpSock.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
//---------------------------------------------------------------------
#include "sharedNetwork/FirstSharedNetwork.h"
#include "sharedNetwork/UdpSock.h"
#include <winsock.h>
//---------------------------------------------------------------------
/**
@brief construct a UdpSock object
Allocates the socket descriptor, sets it to non-blocking mode.
@author Justin Randall
*/
UdpSock::UdpSock() :
Sock()
{
handle = socket(AF_INET, SOCK_DGRAM, 0);
setNonBlocking();
}
//---------------------------------------------------------------------
/**
@brief destroy the UdpSock object
Doesn't do anything special.
@author Justin Randall
*/
UdpSock::~UdpSock()
{
}
//---------------------------------------------------------------------
/**
@brief receive a datagram
Receives a datagram and populates the outAddr parameter with the
source address of the message.
Calling Sock::getInputBytesPending can provide a hint before
allocating the user supplied target buffer.
@param outAddr target Address reference that receives
the message source IP address
@param targetBuffer a user supplied buffer to receive the data.
@param targetBufferSize the size of the user supplied buffer
@author Justin Randall
*/
const unsigned int UdpSock::recvFrom(Address & outAddr, void * targetBuffer, const unsigned int bufferSize) const
{
int fromLen = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
unsigned int result = ::recvfrom(handle, static_cast<char *>(targetBuffer), static_cast<int>(bufferSize), 0, reinterpret_cast<struct sockaddr *>(&addr), &fromLen); //lint !e732 // MS wants an int, should be unsigned IMO
outAddr = addr;
if(result == SOCK_ERROR)
{
OutputDebugString(getLastError().c_str());
}
return result;
}
//---------------------------------------------------------------------
/**
@brief send a datagram to a remote system
sendTo sends a datagram to a remote system.
@param targetAddress System to receive the datagram
@param sourceBuffer A user supplied buffer containint the data
to be sent
@param length The amount of data in the source buffer to
send
@return The number of bytes sent on success
@author Justin Randall
*/
const unsigned int UdpSock::sendTo(const Address & targetAddress, const void * sourceBuffer, const unsigned int length) const
{
unsigned int bytesSent = 0;
if(canSend())
{
int toLen = sizeof(struct sockaddr_in);
bytesSent = ::sendto(handle, static_cast<const char *>(sourceBuffer), static_cast<int>(length), 0, reinterpret_cast<const struct sockaddr *>(&(targetAddress.getSockAddr4())), toLen); //lint !e732 // MS wants an int, should be unsigned IMO
if(bytesSent != length)
{
OutputDebugString(getLastError().c_str());
}
}
return bytesSent;
}
//-----------------------------------------------------------------------
void UdpSock::enableBroadcast()
{
char optval = 1;
int err;
err = setsockopt(getHandle(), SOL_SOCKET, SO_BROADCAST, &optval, sizeof(char));
}
//---------------------------------------------------------------------