Files
barrier/lib/net/CNetwork.cpp
crs fee4095624 Reorganized source tree. Moved client.cpp into cmd/synergy as
synergy.cpp and server.cpp into cmd/synergyd as synergyd.cpp.
Moved and renamed related files.  Moved remaining source files
into lib/....  Modified and added makefiles as appropriate.
Result is that library files are under lib with each library
in its own directory and program files are under cmd with each
command in its own directory.
2002-07-30 16:52:46 +00:00

431 lines
15 KiB
C++

#include "CNetwork.h"
#include "XNetwork.h"
#include "CLog.h"
//
// CNetwork
//
CNetwork::Socket (PASCAL FAR *CNetwork::accept)(CNetwork::Socket s, CNetwork::Address FAR *addr, CNetwork::AddressLength FAR *addrlen);
int (PASCAL FAR *CNetwork::bind)(CNetwork::Socket s, const CNetwork::Address FAR *addr, CNetwork::AddressLength namelen);
int (PASCAL FAR *CNetwork::close)(CNetwork::Socket s);
int (PASCAL FAR *CNetwork::connect)(CNetwork::Socket s, const CNetwork::Address FAR *name, CNetwork::AddressLength namelen);
int (PASCAL FAR *CNetwork::ioctl)(CNetwork::Socket s, int cmd, void FAR *);
int (PASCAL FAR *CNetwork::getpeername)(CNetwork::Socket s, CNetwork::Address FAR *name, CNetwork::AddressLength FAR * namelen);
int (PASCAL FAR *CNetwork::getsockname)(CNetwork::Socket s, CNetwork::Address FAR *name, CNetwork::AddressLength FAR * namelen);
int (PASCAL FAR *CNetwork::getsockopt)(CNetwork::Socket s, int level, int optname, void FAR * optval, CNetwork::AddressLength FAR *optlen);
unsigned long (PASCAL FAR *CNetwork::inet_addr)(const char FAR * cp);
char FAR * (PASCAL FAR *CNetwork::inet_ntoa)(struct in_addr in);
int (PASCAL FAR *CNetwork::listen)(CNetwork::Socket s, int backlog);
ssize_t (PASCAL FAR *CNetwork::read)(CNetwork::Socket s, void FAR * buf, size_t len);
ssize_t (PASCAL FAR *CNetwork::recv)(CNetwork::Socket s, void FAR * buf, size_t len, int flags);
ssize_t (PASCAL FAR *CNetwork::recvfrom)(CNetwork::Socket s, void FAR * buf, size_t len, int flags, CNetwork::Address FAR *from, CNetwork::AddressLength FAR * fromlen);
int (PASCAL FAR *CNetwork::poll)(CNetwork::PollEntry fds[], int nfds, int timeout);
ssize_t (PASCAL FAR *CNetwork::send)(CNetwork::Socket s, const void FAR * buf, size_t len, int flags);
ssize_t (PASCAL FAR *CNetwork::sendto)(CNetwork::Socket s, const void FAR * buf, size_t len, int flags, const CNetwork::Address FAR *to, CNetwork::AddressLength tolen);
int (PASCAL FAR *CNetwork::setsockopt)(CNetwork::Socket s, int level, int optname, const void FAR * optval, CNetwork::AddressLength optlen);
int (PASCAL FAR *CNetwork::shutdown)(CNetwork::Socket s, int how);
CNetwork::Socket (PASCAL FAR *CNetwork::socket)(int af, int type, int protocol);
ssize_t (PASCAL FAR *CNetwork::write)(CNetwork::Socket s, const void FAR * buf, size_t len);
struct hostent FAR * (PASCAL FAR *CNetwork::gethostbyaddr)(const char FAR * addr, int len, int type);
struct hostent FAR * (PASCAL FAR *CNetwork::gethostbyname)(const char FAR * name);
int (PASCAL FAR *CNetwork::gethostname)(char FAR * name, int namelen);
struct servent FAR * (PASCAL FAR *CNetwork::getservbyport)(int port, const char FAR * proto);
struct servent FAR * (PASCAL FAR *CNetwork::getservbyname)(const char FAR * name, const char FAR * proto);
struct protoent FAR * (PASCAL FAR *CNetwork::getprotobynumber)(int proto);
struct protoent FAR * (PASCAL FAR *CNetwork::getprotobyname)(const char FAR * name);
int (PASCAL FAR *CNetwork::getsockerror)(void);
int (PASCAL FAR *CNetwork::gethosterror)(void);
int (PASCAL FAR *CNetwork::setblocking)(CNetwork::Socket s, bool blocking);
#if WINDOWS_LIKE
int (PASCAL FAR *CNetwork::select)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout);
int (PASCAL FAR *CNetwork::WSACleanup)(void);
int (PASCAL FAR *CNetwork::__WSAFDIsSet)(CNetwork::Socket, fd_set FAR *);
const int CNetwork::Error = SOCKET_ERROR;
const CNetwork::Socket CNetwork::Null = INVALID_SOCKET;
#undef FD_ISSET
#define FD_ISSET(fd, set) CNetwork::__WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set))
static HMODULE s_networkModule = NULL;
static
FARPROC
netGetProcAddress(HMODULE module, LPCSTR name)
{
FARPROC func = ::GetProcAddress(module, name);
if (!func) {
throw XNetworkFunctionUnavailable(name);
}
return func;
}
void
CNetwork::init()
{
assert(WSACleanup == NULL);
assert(s_networkModule == NULL);
// try winsock 2
HMODULE module = (HMODULE)::LoadLibrary("ws2_32.dll");
if (module == NULL) {
log((CLOG_NOTE "ws2_32.dll not found"));
}
else {
try {
init2(module);
return;
}
catch (XNetwork& e) {
log((CLOG_NOTE "ws2_32.dll error: %s", e.what()));
}
}
// try winsock 1
module = (HMODULE)::LoadLibrary("wsock32.dll");
if (module == NULL) {
log((CLOG_NOTE "wsock32.dll not found"));
}
else {
try {
init2(module);
return;
}
catch (XNetwork& e) {
log((CLOG_NOTE "wsock32.dll error: %s", e.what()));
}
}
// no networking
throw XNetworkUnavailable();
}
void
CNetwork::cleanup()
{
if (s_networkModule != NULL) {
WSACleanup();
::FreeLibrary(s_networkModule);
WSACleanup = NULL;
s_networkModule = NULL;
}
}
UInt32
CNetwork::swaphtonl(UInt32 v)
{
static const union { UInt16 s; UInt8 b[2]; } s_endian = { 0x1234 };
if (s_endian.b[0] == 0x34) {
return ((v & 0xff000000lu) >> 24) |
((v & 0x00ff0000lu) >> 8) |
((v & 0x0000ff00lu) << 8) |
((v & 0x000000fflu) << 24);
}
else {
return v;
}
}
UInt16
CNetwork::swaphtons(UInt16 v)
{
static const union { UInt16 s; UInt8 b[2]; } s_endian = { 0x1234 };
if (s_endian.b[0] == 0x34) {
return static_cast<UInt16>( ((v & 0xff00u) >> 8) |
((v & 0x00ffu) << 8));
}
else {
return v;
}
}
UInt32
CNetwork::swapntohl(UInt32 v)
{
return swaphtonl(v);
}
UInt16
CNetwork::swapntohs(UInt16 v)
{
return swaphtons(v);
}
#define setfunc(var, name, type) var = (type)netGetProcAddress(module, #name)
void
CNetwork::init2(
HMODULE module)
{
assert(module != NULL);
// get startup function address
int (PASCAL FAR *startup)(WORD, LPWSADATA);
setfunc(startup, WSAStartup, int(PASCAL FAR*)(WORD, LPWSADATA));
// startup network library
WORD version = MAKEWORD(1 /*major*/, 1 /*minor*/);
WSADATA data;
int err = startup(version, &data);
if (data.wVersion != version) {
throw XNetworkVersion(LOBYTE(data.wVersion), HIBYTE(data.wVersion));
}
if (err != 0) {
throw XNetworkFailed();
}
// get function addresses
setfunc(accept, accept, Socket (PASCAL FAR *)(Socket s, Address FAR *addr, AddressLength FAR *addrlen));
setfunc(bind, bind, int (PASCAL FAR *)(Socket s, const Address FAR *addr, AddressLength namelen));
setfunc(close, closesocket, int (PASCAL FAR *)(Socket s));
setfunc(connect, connect, int (PASCAL FAR *)(Socket s, const Address FAR *name, AddressLength namelen));
setfunc(ioctl, ioctlsocket, int (PASCAL FAR *)(Socket s, int cmd, void FAR *));
setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen));
setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp));
setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog));
setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags));
setfunc(recvfrom, recvfrom, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen));
setfunc(send, send, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags));
setfunc(sendto, sendto, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags, const Address FAR *to, AddressLength tolen));
setfunc(setsockopt, setsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, const void FAR * optval, AddressLength optlen));
setfunc(shutdown, shutdown, int (PASCAL FAR *)(Socket s, int how));
setfunc(socket, socket, Socket (PASCAL FAR *)(int af, int type, int protocol));
setfunc(gethostbyaddr, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type));
setfunc(gethostbyname, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name));
setfunc(gethostname, gethostname, int (PASCAL FAR *)(char FAR * name, int namelen));
setfunc(getservbyport, getservbyport, struct servent FAR * (PASCAL FAR *)(int port, const char FAR * proto));
setfunc(getservbyname, getservbyname, struct servent FAR * (PASCAL FAR *)(const char FAR * name, const char FAR * proto));
setfunc(getprotobynumber, getprotobynumber, struct protoent FAR * (PASCAL FAR *)(int proto));
setfunc(getprotobyname, getprotobyname, struct protoent FAR * (PASCAL FAR *)(const char FAR * name));
setfunc(getsockerror, WSAGetLastError, int (PASCAL FAR *)(void));
setfunc(gethosterror, WSAGetLastError, int (PASCAL FAR *)(void));
setfunc(WSACleanup, WSACleanup, int (PASCAL FAR *)(void));
setfunc(__WSAFDIsSet, __WSAFDIsSet, int (PASCAL FAR *)(CNetwork::Socket, fd_set FAR *));
setfunc(select, select, int (PASCAL FAR *)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout));
poll = poll2;
read = read2;
write = write2;
setblocking = setblocking2;
s_networkModule = module;
}
int PASCAL FAR
CNetwork::poll2(PollEntry fd[], int nfds, int timeout)
{
int i;
// prepare sets for select
fd_set readSet, writeSet, errSet;
fd_set* readSetP = NULL;
fd_set* writeSetP = NULL;
fd_set* errSetP = NULL;
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
FD_ZERO(&errSet);
for (i = 0; i < nfds; ++i) {
if (fd[i].events & kPOLLIN) {
FD_SET(fd[i].fd, &readSet);
readSetP = &readSet;
}
if (fd[i].events & kPOLLOUT) {
FD_SET(fd[i].fd, &writeSet);
writeSetP = &writeSet;
}
if (true) {
FD_SET(fd[i].fd, &errSet);
errSetP = &errSet;
}
}
// prepare timeout for select
struct timeval timeout2;
struct timeval* timeout2P;
if (timeout < 0) {
timeout2P = NULL;
}
else {
timeout2P = &timeout2;
timeout2.tv_sec = timeout / 1000;
timeout2.tv_usec = 1000 * (timeout % 1000);
}
// do the select. note that winsock ignores the first argument.
int n = select(0, readSetP, writeSetP, errSetP, timeout2P);
// handle results
if (n == Error) {
return Error;
}
if (n == 0) {
return 0;
}
n = 0;
for (i = 0; i < nfds; ++i) {
fd[i].revents = 0;
if (FD_ISSET(fd[i].fd, &readSet)) {
fd[i].revents |= kPOLLIN;
}
if (FD_ISSET(fd[i].fd, &writeSet)) {
fd[i].revents |= kPOLLOUT;
}
if (FD_ISSET(fd[i].fd, &errSet)) {
fd[i].revents |= kPOLLERR;
}
if (fd[i].revents != 0) {
++n;
}
}
return n;
}
ssize_t PASCAL FAR
CNetwork::read2(Socket s, void FAR* buf, size_t len)
{
return recv(s, buf, len, 0);
}
ssize_t PASCAL FAR
CNetwork::write2(Socket s, const void FAR* buf, size_t len)
{
return send(s, buf, len, 0);
}
int PASCAL FAR
CNetwork::setblocking2(CNetwork::Socket s, bool blocking)
{
int flag = blocking ? 0 : 1;
return ioctl(s, FIONBIO, &flag);
}
#endif
#if UNIX_LIKE
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
// FIXME -- use reentrant versions of non-reentrant functions
#define setfunc(var, name, type) var = (type)::name
UInt32
CNetwork::swaphtonl(UInt32 v)
{
return htonl(v);
}
UInt16
CNetwork::swaphtons(UInt16 v)
{
return htons(v);
}
UInt32
CNetwork::swapntohl(UInt32 v)
{
return ntohl(v);
}
UInt16
CNetwork::swapntohs(UInt16 v)
{
return ntohs(v);
}
static
int
myerrno()
{
return errno;
}
static
int
myherrno()
{
return h_errno;
}
static
int
mygethostname(char* name, int namelen)
{
return gethostname(name, namelen);
}
static
int
mysetblocking(CNetwork::Socket s, bool blocking)
{
int mode = fcntl(s, F_GETFL, 0);
if (mode == -1) {
return -1;
}
if (blocking) {
mode &= ~O_NDELAY;
}
else {
mode |= O_NDELAY;
}
if (fcntl(s, F_SETFL, mode) < 0) {
return -1;
}
return 0;
}
const int CNetwork::Error = -1;
const CNetwork::Socket CNetwork::Null = -1;
void
CNetwork::init()
{
setfunc(accept, accept, Socket (PASCAL FAR *)(Socket s, Address FAR *addr, AddressLength FAR *addrlen));
setfunc(bind, bind, int (PASCAL FAR *)(Socket s, const Address FAR *addr, AddressLength namelen));
setfunc(close, close, int (PASCAL FAR *)(Socket s));
setfunc(connect, connect, int (PASCAL FAR *)(Socket s, const Address FAR *name, AddressLength namelen));
setfunc(ioctl, ioctl, int (PASCAL FAR *)(Socket s, int cmd, void FAR *));
setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen));
setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp));
setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog));
setfunc(poll, poll, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout));
setfunc(read, read, ssize_t (PASCAL FAR *)(CNetwork::Socket s, void FAR * buf, size_t len));
setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags));
setfunc(recvfrom, recvfrom, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen));
setfunc(send, send, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags));
setfunc(sendto, sendto, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags, const Address FAR *to, AddressLength tolen));
setfunc(setsockopt, setsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, const void FAR * optval, AddressLength optlen));
setfunc(shutdown, shutdown, int (PASCAL FAR *)(Socket s, int how));
setfunc(socket, socket, Socket (PASCAL FAR *)(int af, int type, int protocol));
setfunc(write, write, ssize_t (PASCAL FAR *)(CNetwork::Socket s, const void FAR * buf, size_t len));
setfunc(gethostbyaddr, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type));
setfunc(gethostbyname, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name));
setfunc(gethostname, mygethostname, int (PASCAL FAR *)(char FAR * name, int namelen));
setfunc(getservbyport, getservbyport, struct servent FAR * (PASCAL FAR *)(int port, const char FAR * proto));
setfunc(getservbyname, getservbyname, struct servent FAR * (PASCAL FAR *)(const char FAR * name, const char FAR * proto));
setfunc(getprotobynumber, getprotobynumber, struct protoent FAR * (PASCAL FAR *)(int proto));
setfunc(getprotobyname, getprotobyname, struct protoent FAR * (PASCAL FAR *)(const char FAR * name));
setfunc(getsockerror, myerrno, int (PASCAL FAR *)(void));
setfunc(gethosterror, myherrno, int (PASCAL FAR *)(void));
setfunc(setblocking, mysetblocking, int (PASCAL FAR *)(Socket, bool));
}
void
CNetwork::cleanup()
{
// do nothing
}
#endif