Browse Source

Return TcpListener pointers rather than objects

It is easier to control object life time and avoid magical socket
duplication by having a single TcpListener object to pass around.
We have to be more careful about deleting the object though.
tags/v1.5.90
Pierre Ossman 8 years ago
parent
commit
f7aa3f9bd3

+ 46
- 78
common/network/TcpSocket.cxx View File

@@ -118,23 +118,6 @@ static void initSockets() {
}


// -=- Socket duplication help for Windows
static int dupsocket(int fd)
{
#ifdef WIN32
int ret;
WSAPROTOCOL_INFO info;
ret = WSADuplicateSocket(fd, GetCurrentProcessId(), &info);
if (ret != 0)
throw SocketException("unable to duplicate socket", errorNumber);
return WSASocket(info.iAddressFamily, info.iSocketType, info.iProtocol,
&info, 0, 0);
#else
return dup(fd);
#endif
}


// -=- TcpSocket

TcpSocket::TcpSocket(int sock, bool close)
@@ -411,23 +394,6 @@ TcpListener::TcpListener(int sock)
fd = sock;
}

TcpListener::TcpListener(const TcpListener& other)
{
fd = dupsocket (other.fd);
// Hope TcpListener::shutdown(other) doesn't get called...
}

TcpListener& TcpListener::operator= (const TcpListener& other)
{
if (this != &other)
{
closesocket (fd);
fd = dupsocket (other.fd);
// Hope TcpListener::shutdown(other) doesn't get called...
}
return *this;
}

TcpListener::TcpListener(const struct sockaddr *listenaddr,
socklen_t listenaddrlen)
{
@@ -570,57 +536,41 @@ int TcpListener::getMyPort() {
}


void network::createLocalTcpListeners(std::list<TcpListener> *listeners,
void network::createLocalTcpListeners(std::list<TcpListener*> *listeners,
int port)
{
std::list<TcpListener> new_listeners;
vnc_sockaddr_t sa;
struct addrinfo ai[2];
vnc_sockaddr_t sa[2];

initSockets();
memset(ai, 0, sizeof(ai));
memset(sa, 0, sizeof(sa));

if (UseIPv6) {
sa.u.sin6.sin6_family = AF_INET6;
sa.u.sin6.sin6_port = htons (port);
sa.u.sin6.sin6_addr = in6addr_loopback;
try {
new_listeners.push_back (TcpListener (&sa.u.sa, sizeof (sa.u.sin6)));
} catch (SocketException& e) {
// Ignore this if it is due to lack of address family support on
// the interface or on the system
if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT)
// Otherwise, report the error
throw;
}
}
if (UseIPv4) {
sa.u.sin.sin_family = AF_INET;
sa.u.sin.sin_port = htons (port);
sa.u.sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
try {
new_listeners.push_back (TcpListener (&sa.u.sa, sizeof (sa.u.sin)));
} catch (SocketException& e) {
// Ignore this if it is due to lack of address family support on
// the interface or on the system
if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT)
// Otherwise, report the error
throw;
}
}
sa[0].u.sin.sin_family = AF_INET;
sa[0].u.sin.sin_port = htons (port);
sa[0].u.sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

if (new_listeners.empty ())
throw SocketException("createLocalTcpListeners: no addresses available",
EADDRNOTAVAIL);
ai[0].ai_family = sa[0].u.sin.sin_family;
ai[0].ai_addr = &sa[0].u.sa;
ai[0].ai_addrlen = sizeof(sa[0].u.sin);
ai[0].ai_next = &ai[1];

listeners->splice (listeners->end(), new_listeners);
sa[1].u.sin6.sin6_family = AF_INET6;
sa[1].u.sin6.sin6_port = htons (port);
sa[1].u.sin6.sin6_addr = in6addr_loopback;

ai[1].ai_family = sa[1].u.sin6.sin6_family;
ai[1].ai_addr = &sa[1].u.sa;
ai[1].ai_addrlen = sizeof(sa[1].u.sin6);
ai[1].ai_next = NULL;

createTcpListeners(listeners, ai);
}

void network::createTcpListeners(std::list<TcpListener> *listeners,
void network::createTcpListeners(std::list<TcpListener*> *listeners,
const char *addr,
int port)
{
std::list<TcpListener> new_listeners;

struct addrinfo *ai, *current, hints;
struct addrinfo *ai, hints;
char service[16];
int result;

@@ -640,6 +590,22 @@ void network::createTcpListeners(std::list<TcpListener> *listeners,
throw rdr::Exception("unable to resolve listening address: %s",
gai_strerror(result));

try {
createTcpListeners(listeners, ai);
} catch(...) {
freeaddrinfo(ai);
throw;
}
}

void network::createTcpListeners(std::list<TcpListener*> *listeners,
const struct addrinfo *ai)
{
const struct addrinfo *current;
std::list<TcpListener*> new_listeners;

initSockets();

for (current = ai; current != NULL; current = current->ai_next) {
switch (current->ai_family) {
case AF_INET:
@@ -657,19 +623,21 @@ void network::createTcpListeners(std::list<TcpListener> *listeners,
}

try {
new_listeners.push_back(TcpListener (current->ai_addr,
current->ai_addrlen));
new_listeners.push_back(new TcpListener(current->ai_addr,
current->ai_addrlen));
} catch (SocketException& e) {
// Ignore this if it is due to lack of address family support on
// the interface or on the system
if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT) {
// Otherwise, report the error
freeaddrinfo(ai);
while (!new_listeners.empty()) {
delete new_listeners.back();
new_listeners.pop_back();
}
throw;
}
}
}
freeaddrinfo(ai);

if (new_listeners.empty ())
throw SocketException("createTcpListeners: no addresses available",

+ 4
- 4
common/network/TcpSocket.h View File

@@ -76,8 +76,6 @@ namespace network {
public:
TcpListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen);
TcpListener(int sock);
TcpListener(const TcpListener& other);
TcpListener& operator= (const TcpListener& other);
virtual ~TcpListener();

virtual void shutdown();
@@ -87,11 +85,13 @@ namespace network {
int getMyPort();
};

void createLocalTcpListeners(std::list<TcpListener> *listeners,
void createLocalTcpListeners(std::list<TcpListener*> *listeners,
int port);
void createTcpListeners(std::list<TcpListener> *listeners,
void createTcpListeners(std::list<TcpListener*> *listeners,
const char *addr,
int port);
void createTcpListeners(std::list<TcpListener*> *listeners,
const struct addrinfo *ai);

typedef struct vnc_sockaddr {
union {

+ 8
- 8
unix/x0vncserver/x0vncserver.cxx View File

@@ -477,7 +477,7 @@ int main(int argc, char** argv)
signal(SIGINT, CleanupSignalHandler);
signal(SIGTERM, CleanupSignalHandler);

std::list<TcpListener> listeners;
std::list<TcpListener*> listeners;

try {
TXWindow::init(dpy,"x0vncserver");
@@ -499,10 +499,10 @@ int main(int argc, char** argv)
const char *hostsData = hostsFile.getData();
FileTcpFilter fileTcpFilter(hostsData);
if (strlen(hostsData) != 0)
for (std::list<TcpListener>::iterator i = listeners.begin();
for (std::list<TcpListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
(*i).setFilter(&fileTcpFilter);
(*i)->setFilter(&fileTcpFilter);
delete[] hostsData;

PollingScheduler sched((int)pollingCycle, (int)maxProcessorUsage);
@@ -518,10 +518,10 @@ int main(int argc, char** argv)

FD_ZERO(&rfds);
FD_SET(ConnectionNumber(dpy), &rfds);
for (std::list<TcpListener>::iterator i = listeners.begin();
for (std::list<TcpListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
FD_SET((*i).getFd(), &rfds);
FD_SET((*i)->getFd(), &rfds);

server.getSockets(&sockets);
int clients_connected = 0;
@@ -567,11 +567,11 @@ int main(int argc, char** argv)
}

// Accept new VNC connections
for (std::list<TcpListener>::iterator i = listeners.begin();
for (std::list<TcpListener*>::iterator i = listeners.begin();
i != listeners.end();
i++) {
if (FD_ISSET((*i).getFd(), &rfds)) {
Socket* sock = (*i).accept();
if (FD_ISSET((*i)->getFd(), &rfds)) {
Socket* sock = (*i)->accept();
if (sock) {
server.addSocket(sock);
} else {

+ 5
- 2
unix/xserver/hw/vnc/RFBGlue.cc View File

@@ -190,9 +190,12 @@ int vncIsTCPPortUsed(int port)
{
try {
// Attempt to create TCPListeners on that port.
// They go out of scope immediately and are destroyed.
std::list<network::TcpListener> dummy;
std::list<network::TcpListener*> dummy;
network::createTcpListeners (&dummy, 0, port);
while (!dummy.empty()) {
delete dummy.back();
dummy.pop_back();
}
} catch (rdr::Exception& e) {
return 1;
}

+ 23
- 15
unix/xserver/hw/vnc/XserverDesktop.cc View File

@@ -91,8 +91,8 @@ public:


XserverDesktop::XserverDesktop(int screenIndex_,
std::list<network::TcpListener> listeners_,
std::list<network::TcpListener> httpListeners_,
std::list<network::TcpListener*> listeners_,
std::list<network::TcpListener*> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
int width, int height,
void* fbptr, int stride)
@@ -114,6 +114,14 @@ XserverDesktop::XserverDesktop(int screenIndex_,

XserverDesktop::~XserverDesktop()
{
while (!listeners.empty()) {
delete listeners.back();
listeners.pop_back();
}
while (!httpListeners.empty()) {
delete httpListeners.back();
httpListeners.pop_back();
}
if (!directFbptr)
delete [] data;
delete httpServer;
@@ -222,7 +230,7 @@ char* XserverDesktop::substitute(const char* varName)
}
if (strcmp(varName, "$PORT") == 0) {
char* str = new char[10];
sprintf(str, "%d", listeners.empty () ? 0 : (*listeners.begin ()).getMyPort());
sprintf(str, "%d", listeners.empty () ? 0 : (*listeners.begin ())->getMyPort());
return str;
}
if (strcmp(varName, "$WIDTH") == 0) {
@@ -393,14 +401,14 @@ void XserverDesktop::readBlockHandler(fd_set* fds, struct timeval ** timeout)

// Add all sockets we want read events for, after purging
// any closed sockets.
for (std::list<network::TcpListener>::iterator i = listeners.begin();
for (std::list<network::TcpListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
FD_SET((*i).getFd(), fds);
for (std::list<network::TcpListener>::iterator i = httpListeners.begin();
FD_SET((*i)->getFd(), fds);
for (std::list<network::TcpListener*>::iterator i = httpListeners.begin();
i != httpListeners.end();
i++)
FD_SET((*i).getFd(), fds);
FD_SET((*i)->getFd(), fds);

std::list<Socket*> sockets;
std::list<Socket*>::iterator i;
@@ -456,24 +464,24 @@ void XserverDesktop::readWakeupHandler(fd_set* fds, int nfds)
// First check for file descriptors with something to do
if (nfds >= 1) {

for (std::list<network::TcpListener>::iterator i = listeners.begin();
for (std::list<network::TcpListener*>::iterator i = listeners.begin();
i != listeners.end();
i++) {
if (FD_ISSET((*i).getFd(), fds)) {
FD_CLR((*i).getFd(), fds);
Socket* sock = (*i).accept();
if (FD_ISSET((*i)->getFd(), fds)) {
FD_CLR((*i)->getFd(), fds);
Socket* sock = (*i)->accept();
sock->outStream().setBlocking(false);
server->addSocket(sock);
vlog.debug("new client, sock %d",sock->getFd());
}
}

for (std::list<network::TcpListener>::iterator i = httpListeners.begin();
for (std::list<network::TcpListener*>::iterator i = httpListeners.begin();
i != httpListeners.end();
i++) {
if (FD_ISSET((*i).getFd(), fds)) {
FD_CLR((*i).getFd(), fds);
Socket* sock = (*i).accept();
if (FD_ISSET((*i)->getFd(), fds)) {
FD_CLR((*i)->getFd(), fds);
Socket* sock = (*i)->accept();
sock->outStream().setBlocking(false);
httpServer->addSocket(sock);
vlog.debug("new http client, sock %d",sock->getFd());

+ 4
- 4
unix/xserver/hw/vnc/XserverDesktop.h View File

@@ -51,8 +51,8 @@ class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
public:

XserverDesktop(int screenIndex,
std::list<network::TcpListener> listeners_,
std::list<network::TcpListener> httpListeners_,
std::list<network::TcpListener*> listeners_,
std::list<network::TcpListener*> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
int width, int height, void* fbptr, int stride);
virtual ~XserverDesktop();
@@ -113,8 +113,8 @@ private:
int screenIndex;
rfb::VNCServerST* server;
rfb::HTTPServer* httpServer;
std::list<network::TcpListener> listeners;
std::list<network::TcpListener> httpListeners;
std::list<network::TcpListener*> listeners;
std::list<network::TcpListener*> httpListeners;
bool deferredUpdateTimerSet;
bool directFbptr;
struct timeval dixTimeout;

+ 3
- 3
unix/xserver/hw/vnc/vncExtInit.cc View File

@@ -134,13 +134,13 @@ void vncExtensionInit(void)
for (int scr = 0; scr < vncGetScreenCount(); scr++) {

if (!desktop[scr]) {
std::list<network::TcpListener> listeners;
std::list<network::TcpListener> httpListeners;
std::list<network::TcpListener*> listeners;
std::list<network::TcpListener*> httpListeners;
if (scr == 0 && vncInetdSock != -1) {
if (network::TcpSocket::isSocket(vncInetdSock) &&
!network::TcpSocket::isConnected(vncInetdSock))
{
listeners.push_back (network::TcpListener(vncInetdSock));
listeners.push_back(new network::TcpListener(vncInetdSock));
vlog.info("inetd wait");
}
} else {

+ 10
- 6
vncviewer/vncviewer.cxx View File

@@ -525,7 +525,7 @@ int main(int argc, char** argv)
#endif

if (listenMode) {
std::list<TcpListener> listeners;
std::list<TcpListener*> listeners;
try {
int port = 5500;
if (isdigit(vncServerName[0]))
@@ -539,10 +539,10 @@ int main(int argc, char** argv)
while (sock == NULL) {
fd_set rfds;
FD_ZERO(&rfds);
for (std::list<TcpListener>::iterator i = listeners.begin();
for (std::list<TcpListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
FD_SET((*i).getFd(), &rfds);
FD_SET((*i)->getFd(), &rfds);

int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
if (n < 0) {
@@ -554,11 +554,11 @@ int main(int argc, char** argv)
}
}

for (std::list<TcpListener>::iterator i = listeners.begin ();
for (std::list<TcpListener*>::iterator i = listeners.begin ();
i != listeners.end();
i++)
if (FD_ISSET((*i).getFd(), &rfds)) {
sock = (*i).accept();
if (FD_ISSET((*i)->getFd(), &rfds)) {
sock = (*i)->accept();
if (sock)
/* Got a connection */
break;
@@ -571,6 +571,10 @@ int main(int argc, char** argv)
return 1;
}

while (!listeners.empty()) {
delete listeners.back();
listeners.pop_back();
}
} else {
if (vncServerName[0] == '\0') {
ServerDialog::run(defaultServerName, vncServerName);

+ 8
- 8
win/winvnc/ManagedListener.cxx View File

@@ -31,9 +31,9 @@ ManagedListener::ManagedListener(SocketManager* mgr)

ManagedListener::~ManagedListener() {
if (!sockets.empty()) {
std::list<network::TcpListener>::iterator iter;
std::list<network::TcpListener*>::iterator iter;
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
manager->remListener(&*iter);
manager->remListener(*iter);
sockets.clear();
}
delete filter;
@@ -62,9 +62,9 @@ void ManagedListener::setFilter(const char* filterStr) {
delete filter;
filter = new network::TcpFilter(filterStr);
if (!sockets.empty() && !localOnly) {
std::list<network::TcpListener>::iterator iter;
std::list<network::TcpListener*>::iterator iter;
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
iter->setFilter(filter);
(*iter)->setFilter(filter);
}
}

@@ -80,10 +80,10 @@ bool ManagedListener::isListening() {
}

void ManagedListener::refresh() {
std::list<network::TcpListener>::iterator iter;
std::list<network::TcpListener*>::iterator iter;
if (!sockets.empty()) {
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
manager->remListener(&*iter);
manager->remListener(*iter);
sockets.clear();
}
if (!server)
@@ -101,11 +101,11 @@ void ManagedListener::refresh() {
if (!sockets.empty()) {
if (!localOnly) {
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
iter->setFilter(filter);
(*iter)->setFilter(filter);
}
try {
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
manager->addListener(&*iter, server, addrChangeNotifier);
manager->addListener(*iter, server, addrChangeNotifier);
} catch (...) {
// FIXME: Should unwind what we've added
sockets.clear();

+ 1
- 1
win/winvnc/ManagedListener.h View File

@@ -45,7 +45,7 @@ namespace winvnc {

protected:
void refresh();
std::list<network::TcpListener> sockets;
std::list<network::TcpListener*> sockets;
network::TcpFilter* filter;
rfb::win32::SocketManager* manager;
rfb::win32::SocketManager::AddressChangeNotifier* addrChangeNotifier;

Loading…
Cancel
Save