// Copyright (c) 2002 David Muse
// See the COPYING file for more information
#include <rudiments/inetserversocket.h>
#include <rudiments/inetclientsocket.h>
#include <rudiments/charstring.h>
#include <rudiments/rawbuffer.h>
#include <rudiments/error.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifdef RUDIMENTS_NAMESPACE
namespace rudiments {
#endif
class inetserversocketprivate {
friend class inetserversocket;
private:
};
inetserversocket::inetserversocket() : serversocket(), inetsocketutil() {
pvt=new inetserversocketprivate;
translateByteOrder();
type("inetserversocket");
}
inetserversocket::inetserversocket(const inetserversocket &i) :
serversocket(i), inetsocketutil(i) {
pvt=new inetserversocketprivate;
type("inetserversocket");
}
inetserversocket &inetserversocket::operator=(const inetserversocket &i) {
if (this!=&i) {
serversocket::operator=(i);
inetsocketutil::operator=(i);
}
return *this;
}
inetserversocket::~inetserversocket() {
delete pvt;
}
unsigned short inetserversocket::getPort() {
return *_port();
}
bool inetserversocket::listen(const char *address, unsigned short port,
int backlog) {
initialize(address,port);
return (bind() && listen(backlog));
}
bool inetserversocket::initialize(const char *address, unsigned short port) {
inetsocketutil::initialize(address,port);
// initialize a socket address structure
rawbuffer::zero(_sin(),sizeof(sockaddr_in));
_sin()->sin_family=AF_INET;
_sin()->sin_port=htons(port);
// if a specific address was passed in, bind to it only,
// otherwise bind to all addresses
if (address && address[0] && charstring::compare(address,"0.0.0.0")) {
in_addr ia;
if (!inet_aton(address,&ia)) {
return false;
}
_sin()->sin_addr.s_addr=ia.s_addr;
} else {
_sin()->sin_addr.s_addr=htonl(INADDR_ANY);
}
// create the socket
do {
fd(::socket(AF_INET,SOCK_STREAM,0));
} while (fd()==-1 && error::getErrorNumber()==EINTR);
return (fd()!=-1);
}
bool inetserversocket::bind() {
// bind the socket
int result;
do {
result=::bind(fd(),reinterpret_cast<struct sockaddr *>(_sin()),
sizeof(sockaddr_in));
} while (result==-1 && error::getErrorNumber()==EINTR);
if (result==-1) {
return false;
}
// get the actual port number if an arbitrary port was requested
if (!*_port()) {
// initialize a socket address structure
sockaddr_in socknamesin;
socklen_t size=sizeof(socknamesin);
rawbuffer::zero(&socknamesin,sizeof(socknamesin));
int result;
do {
result=getsockname(fd(),
reinterpret_cast<struct sockaddr *>
(&socknamesin),
&size);
} while (result==-1 && error::getErrorNumber()==EINTR);
if (result!=-1) {
*_port()=static_cast<unsigned short int>(
ntohs(socknamesin.sin_port));
}
}
return true;
}
bool inetserversocket::listen(int backlog) {
int result;
do {
result=::listen(fd(),backlog);
} while (result==-1 && error::getErrorNumber()==EINTR);
return !result;
}
filedescriptor *inetserversocket::accept() {
// initialize a socket address structure
sockaddr_in clientsin;
socklen_t size=sizeof(clientsin);
rawbuffer::zero(&clientsin,sizeof(clientsin));
// accept on the socket
int clientsock;
do {
clientsock=::accept(fd(),
reinterpret_cast<struct sockaddr *>(&clientsin),
&size);
} while (clientsock==-1 && error::getErrorNumber()==EINTR);
if (clientsock==-1) {
return NULL;
}
inetclientsocket *returnsock=new inetclientsocket;
returnsock->setFileDescriptor(clientsock);
#ifdef RUDIMENTS_HAS_SSL
if (!sslAccept(returnsock)) {
delete returnsock;
return NULL;
}
#endif
return returnsock;
}
#ifdef RUDIMENTS_NAMESPACE
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1