Browse Source

Merge branch 'unix' of https://github.com/CendioOssman/tigervnc

tags/v1.8.90
Pierre Ossman 6 years ago
parent
commit
fe2e5fca21

+ 8
- 1
common/network/CMakeLists.txt View File

@@ -1,8 +1,15 @@
include_directories(${CMAKE_SOURCE_DIR}/common)

add_library(network STATIC
set(NETWORK_SOURCES
Socket.cxx
TcpSocket.cxx)

if(NOT WIN32)
set(NETWORK_SOURCES ${NETWORK_SOURCES} UnixSocket.cxx)
endif()

add_library(network STATIC ${NETWORK_SOURCES})

if(WIN32)
target_link_libraries(network ws2_32)
endif()

+ 183
- 0
common/network/Socket.cxx View File

@@ -0,0 +1,183 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This 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 2 of the License, or
* (at your option) any later version.
*
* This software 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 software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef WIN32
//#include <io.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define errorNumber WSAGetLastError()
#else
#define errorNumber errno
#define closesocket close
#include <sys/socket.h>
#endif

#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>

#include <network/Socket.h>

using namespace network;

// -=- Socket initialisation
static bool socketsInitialised = false;
void network::initSockets() {
if (socketsInitialised)
return;
#ifdef WIN32
WORD requiredVersion = MAKEWORD(2,0);
WSADATA initResult;
if (WSAStartup(requiredVersion, &initResult) != 0)
throw SocketException("unable to initialise Winsock2", errorNumber);
#else
signal(SIGPIPE, SIG_IGN);
#endif
socketsInitialised = true;
}

bool network::isSocketListening(int sock)
{
int listening = 0;
socklen_t listening_size = sizeof(listening);
if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN,
(char *)&listening, &listening_size) < 0)
return false;
return listening != 0;
}

Socket::Socket(int fd)
: instream(0), outstream(0),
isShutdown_(false), queryConnection(false)
{
initSockets();
setFd(fd);
}

Socket::Socket()
: instream(0), outstream(0),
isShutdown_(false), queryConnection(false)
{
initSockets();
}

Socket::~Socket()
{
if (instream && outstream)
closesocket(getFd());
delete instream;
delete outstream;
}

// if shutdown() is overridden then the override MUST call on to here
void Socket::shutdown()
{
isShutdown_ = true;
::shutdown(getFd(), 2);
}

bool Socket::isShutdown() const
{
return isShutdown_;
}

// Was there a "?" in the ConnectionFilter used to accept this Socket?
void Socket::setRequiresQuery()
{
queryConnection = true;
}

bool Socket::requiresQuery() const
{
return queryConnection;
}

void Socket::setFd(int fd)
{
#ifndef WIN32
// - By default, close the socket on exec()
fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif

instream = new rdr::FdInStream(fd);
outstream = new rdr::FdOutStream(fd);
isShutdown_ = false;
}

SocketListener::SocketListener(int fd)
: fd(fd), filter(0)
{
initSockets();
}

SocketListener::SocketListener()
: fd(-1), filter(0)
{
initSockets();
}

SocketListener::~SocketListener()
{
if (fd != -1)
closesocket(fd);
}

void SocketListener::shutdown()
{
#ifdef WIN32
closesocket(fd);
fd = -1;
#else
::shutdown(fd, 2);
#endif
}

Socket* SocketListener::accept() {
int new_sock = -1;

// Accept an incoming connection
if ((new_sock = ::accept(fd, 0, 0)) < 0)
throw SocketException("unable to accept new connection", errorNumber);

// Create the socket object & check connection is allowed
Socket* s = createSocket(new_sock);
if (filter && !filter->verifyConnection(s)) {
delete s;
return NULL;
}

return s;
}

void SocketListener::listen(int sock)
{
// - Set it to be a listening socket
if (::listen(sock, 5) < 0) {
int e = errorNumber;
closesocket(sock);
throw SocketException("unable to set socket to listening mode", e);
}

fd = sock;
}

+ 33
- 33
common/network/Socket.h View File

@@ -30,52 +30,40 @@

namespace network {

void initSockets();

bool isSocketListening(int sock);

class Socket {
public:
Socket(int fd)
: instream(new rdr::FdInStream(fd)),
outstream(new rdr::FdOutStream(fd)),
ownStreams(true), isShutdown_(false),
queryConnection(false) {}
virtual ~Socket() {
if (ownStreams) {
delete instream;
delete outstream;
}
}
Socket(int fd);
virtual ~Socket();

rdr::FdInStream &inStream() {return *instream;}
rdr::FdOutStream &outStream() {return *outstream;}
int getFd() {return outstream->getFd();}

// if shutdown() is overridden then the override MUST call on to here
virtual void shutdown() {isShutdown_ = true;}
bool isShutdown() const {return isShutdown_;}
virtual bool cork(bool enable) = 0;
void shutdown();
bool isShutdown() const;

// information about this end of the socket
virtual int getMyPort() = 0;
virtual bool cork(bool enable) = 0;

// information about the remote end of the socket
virtual char* getPeerAddress() = 0; // a string e.g. "192.168.0.1"
virtual int getPeerPort() = 0;
virtual char* getPeerEndpoint() = 0; // <address>::<port>

// Is the remote end on the same machine?
virtual bool sameMachine() = 0;

// Was there a "?" in the ConnectionFilter used to accept this Socket?
void setRequiresQuery() {queryConnection = true;}
bool requiresQuery() const {return queryConnection;}
void setRequiresQuery();
bool requiresQuery() const;

protected:
Socket() : instream(0), outstream(0), ownStreams(false),
isShutdown_(false), queryConnection(false) {}
Socket(rdr::FdInStream* i, rdr::FdOutStream* o, bool own)
: instream(i), outstream(o), ownStreams(own),
isShutdown_(false), queryConnection(false) {}
Socket();
void setFd(int fd);
private:
rdr::FdInStream* instream;
rdr::FdOutStream* outstream;
bool ownStreams;
bool isShutdown_;
bool queryConnection;
};
@@ -88,20 +76,32 @@ namespace network {

class SocketListener {
public:
SocketListener() : fd(0), filter(0) {}
virtual ~SocketListener() {}
SocketListener(int fd);
virtual ~SocketListener();

// shutdown() stops the socket from accepting further connections
virtual void shutdown() = 0;
void shutdown();

// accept() returns a new Socket object if there is a connection
// attempt in progress AND if the connection passes the filter
// if one is installed. Otherwise, returns 0.
virtual Socket* accept() = 0;
Socket* accept();

virtual int getMyPort() = 0;

// setFilter() applies the specified filter to all new connections
void setFilter(ConnectionFilter* f) {filter = f;}
int getFd() {return fd;}

protected:
SocketListener();

void listen(int fd);

// createSocket() should create a new socket of the correct class
// for the given file descriptor
virtual Socket* createSocket(int fd) = 0;

protected:
int fd;
ConnectionFilter* filter;

+ 39
- 170
common/network/TcpSocket.cxx View File

@@ -28,21 +28,17 @@
#else
#define errorNumber errno
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#endif

#include <stdlib.h>
#include <unistd.h>

#include <network/TcpSocket.h>
#include <rfb/util.h>
#include <rfb/LogWriter.h>
#include <rfb/Configuration.h>

@@ -99,40 +95,35 @@ int network::findFreeTcpPort (void)
return ntohs(addr.sin_port);
}

int network::getSockPort(int sock)
{
vnc_sockaddr_t sa;
socklen_t sa_size = sizeof(sa);
if (getsockname(sock, &sa.u.sa, &sa_size) < 0)
return 0;

// -=- Socket initialisation
static bool socketsInitialised = false;
static void initSockets() {
if (socketsInitialised)
return;
#ifdef WIN32
WORD requiredVersion = MAKEWORD(2,0);
WSADATA initResult;
if (WSAStartup(requiredVersion, &initResult) != 0)
throw SocketException("unable to initialise Winsock2", errorNumber);
#else
signal(SIGPIPE, SIG_IGN);
#endif
socketsInitialised = true;
switch (sa.u.sa.sa_family) {
case AF_INET6:
return ntohs(sa.u.sin6.sin6_port);
default:
return ntohs(sa.u.sin.sin_port);
}
}


// -=- TcpSocket

TcpSocket::TcpSocket(int sock, bool close)
: Socket(new FdInStream(sock), new FdOutStream(sock), true), closeFd(close)
TcpSocket::TcpSocket(int sock) : Socket(sock)
{
// Disable Nagle's algorithm, to reduce latency
enableNagles(false);
}

TcpSocket::TcpSocket(const char *host, int port)
: closeFd(true)
{
int sock, err, result;
struct addrinfo *ai, *current, hints;

// - Create a socket
initSockets();

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
@@ -214,27 +205,11 @@ TcpSocket::TcpSocket(const char *host, int port)
throw SocketException("unable connect to socket", err);
}

#ifndef WIN32
// - By default, close the socket on exec()
fcntl(sock, F_SETFD, FD_CLOEXEC);
#endif
// Take proper ownership of the socket
setFd(sock);

// Disable Nagle's algorithm, to reduce latency
enableNagles(sock, false);

// Create the input and output streams
instream = new FdInStream(sock);
outstream = new FdOutStream(sock);
ownStreams = true;
}

TcpSocket::~TcpSocket() {
if (closeFd)
closesocket(getFd());
}

int TcpSocket::getMyPort() {
return getSockPort(getFd());
enableNagles(false);
}

char* TcpSocket::getPeerAddress() {
@@ -281,25 +256,20 @@ char* TcpSocket::getPeerAddress() {
return rfb::strDup("");
}

int TcpSocket::getPeerPort() {
char* TcpSocket::getPeerEndpoint() {
rfb::CharArray address; address.buf = getPeerAddress();
vnc_sockaddr_t sa;
socklen_t sa_size = sizeof(sa);
int port;

getpeername(getFd(), &sa.u.sa, &sa_size);

switch (sa.u.sa.sa_family) {
case AF_INET6:
return ntohs(sa.u.sin6.sin6_port);
case AF_INET:
return ntohs(sa.u.sin.sin_port);
default:
return 0;
}
}

char* TcpSocket::getPeerEndpoint() {
rfb::CharArray address; address.buf = getPeerAddress();
int port = getPeerPort();
if (sa.u.sa.sa_family == AF_INET6)
port = ntohs(sa.u.sin6.sin6_port);
else if (sa.u.sa.sa_family == AF_INET)
port = ntohs(sa.u.sin.sin_port);
else
port = 0;

int buflen = strlen(address.buf) + 32;
char* buffer = new char[buflen];
@@ -307,40 +277,9 @@ char* TcpSocket::getPeerEndpoint() {
return buffer;
}

bool TcpSocket::sameMachine() {
vnc_sockaddr_t peeraddr, myaddr;
socklen_t addrlen;

addrlen = sizeof(peeraddr);
if (getpeername(getFd(), &peeraddr.u.sa, &addrlen) < 0)
throw SocketException ("unable to get peer address", errorNumber);

addrlen = sizeof(myaddr); /* need to reset, since getpeername overwrote */
if (getsockname(getFd(), &myaddr.u.sa, &addrlen) < 0)
throw SocketException ("unable to get my address", errorNumber);

if (peeraddr.u.sa.sa_family != myaddr.u.sa.sa_family)
return false;

if (peeraddr.u.sa.sa_family == AF_INET6)
return IN6_ARE_ADDR_EQUAL(&peeraddr.u.sin6.sin6_addr,
&myaddr.u.sin6.sin6_addr);
if (peeraddr.u.sa.sa_family == AF_INET)
return (peeraddr.u.sin.sin_addr.s_addr == myaddr.u.sin.sin_addr.s_addr);

// No idea what this is. Assume we're on different machines.
return false;
}

void TcpSocket::shutdown()
{
Socket::shutdown();
::shutdown(getFd(), 2);
}

bool TcpSocket::enableNagles(int sock, bool enable) {
bool TcpSocket::enableNagles(bool enable) {
int one = enable ? 0 : 1;
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
if (setsockopt(getFd(), IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
int e = errorNumber;
vlog.error("unable to setsockopt TCP_NODELAY: %d", e);
@@ -360,34 +299,8 @@ bool TcpSocket::cork(bool enable) {
#endif
}

bool TcpSocket::isListening(int sock)
TcpListener::TcpListener(int sock) : SocketListener(sock)
{
int listening = 0;
socklen_t listening_size = sizeof(listening);
if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN,
(char *)&listening, &listening_size) < 0)
return false;
return listening != 0;
}

int TcpSocket::getSockPort(int sock)
{
vnc_sockaddr_t sa;
socklen_t sa_size = sizeof(sa);
if (getsockname(sock, &sa.u.sa, &sa_size) < 0)
return 0;

switch (sa.u.sa.sa_family) {
case AF_INET6:
return ntohs(sa.u.sin6.sin6_port);
default:
return ntohs(sa.u.sin.sin_port);
}
}

TcpListener::TcpListener(int sock)
{
fd = sock;
}

TcpListener::TcpListener(const struct sockaddr *listenaddr,
@@ -397,8 +310,6 @@ TcpListener::TcpListener(const struct sockaddr *listenaddr,
vnc_sockaddr_t sa;
int sock;

initSockets();

if ((sock = socket (listenaddr->sa_family, SOCK_STREAM, 0)) < 0)
throw SocketException("unable to create listening socket", errorNumber);

@@ -436,53 +347,11 @@ TcpListener::TcpListener(const struct sockaddr *listenaddr,
throw SocketException("failed to bind socket", e);
}

// - Set it to be a listening socket
if (listen(sock, 5) < 0) {
int e = errorNumber;
closesocket(sock);
throw SocketException("unable to set socket to listening mode", e);
}

fd = sock;
listen(sock);
}

TcpListener::~TcpListener() {
closesocket(fd);
}

void TcpListener::shutdown()
{
#ifdef WIN32
closesocket(getFd());
#else
::shutdown(getFd(), 2);
#endif
}


Socket*
TcpListener::accept() {
int new_sock = -1;

// Accept an incoming connection
if ((new_sock = ::accept(fd, 0, 0)) < 0)
throw SocketException("unable to accept new connection", errorNumber);

#ifndef WIN32
// - By default, close the socket on exec()
fcntl(new_sock, F_SETFD, FD_CLOEXEC);
#endif

// Disable Nagle's algorithm, to reduce latency
TcpSocket::enableNagles(new_sock, false);

// Create the socket object & check connection is allowed
TcpSocket* s = new TcpSocket(new_sock);
if (filter && !filter->verifyConnection(s)) {
delete s;
return 0;
}
return s;
Socket* TcpListener::createSocket(int fd) {
return new TcpSocket(fd);
}

void TcpListener::getMyAddresses(std::list<char*>* result) {
@@ -528,11 +397,11 @@ void TcpListener::getMyAddresses(std::list<char*>* result) {
}

int TcpListener::getMyPort() {
return TcpSocket::getSockPort(getFd());
return getSockPort(getFd());
}


void network::createLocalTcpListeners(std::list<TcpListener*> *listeners,
void network::createLocalTcpListeners(std::list<SocketListener*> *listeners,
int port)
{
struct addrinfo ai[2];
@@ -562,7 +431,7 @@ void network::createLocalTcpListeners(std::list<TcpListener*> *listeners,
createTcpListeners(listeners, ai);
}

void network::createTcpListeners(std::list<TcpListener*> *listeners,
void network::createTcpListeners(std::list<SocketListener*> *listeners,
const char *addr,
int port)
{
@@ -594,11 +463,11 @@ void network::createTcpListeners(std::list<TcpListener*> *listeners,
}
}

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

initSockets();


+ 12
- 19
common/network/TcpSocket.h View File

@@ -48,48 +48,41 @@ namespace network {
/* Tunnelling support. */
int findFreeTcpPort (void);

int getSockPort(int sock);

class TcpSocket : public Socket {
public:
TcpSocket(int sock, bool close=true);
TcpSocket(int sock);
TcpSocket(const char *name, int port);
virtual ~TcpSocket();

virtual int getMyPort();

virtual char* getPeerAddress();
virtual int getPeerPort();
virtual char* getPeerEndpoint();
virtual bool sameMachine();

virtual void shutdown();
virtual bool cork(bool enable);

static bool enableNagles(int sock, bool enable);
static bool isListening(int sock);
static int getSockPort(int sock);
private:
bool closeFd;
protected:
bool enableNagles(bool enable);
};

class TcpListener : public SocketListener {
public:
TcpListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen);
TcpListener(int sock);
virtual ~TcpListener();

virtual void shutdown();
virtual Socket* accept();
virtual int getMyPort();

static void getMyAddresses(std::list<char*>* result);
int getMyPort();

protected:
virtual Socket* createSocket(int fd);
};

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

typedef struct vnc_sockaddr {

+ 171
- 0
common/network/UnixSocket.cxx View File

@@ -0,0 +1,171 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (c) 2012 University of Oslo. All Rights Reserved.
*
* This 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 2 of the License, or
* (at your option) any later version.
*
* This software 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 software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stddef.h>

#include <network/UnixSocket.h>
#include <rfb/LogWriter.h>

using namespace network;
using namespace rdr;

static rfb::LogWriter vlog("UnixSocket");

// -=- UnixSocket

UnixSocket::UnixSocket(int sock) : Socket(sock)
{
}

UnixSocket::UnixSocket(const char *path)
{
int sock, err, result;
sockaddr_un addr;
socklen_t salen;

if (strlen(path) >= sizeof(addr.sun_path))
throw SocketException("socket path is too long", ENAMETOOLONG);

// - Create a socket
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1)
throw SocketException("unable to create socket", errno);

// - Attempt to connect
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, path);
salen = sizeof(addr);
while ((result = connect(sock, (sockaddr *)&addr, salen)) == -1) {
err = errno;
close(sock);
break;
}

if (result == -1)
throw SocketException("unable connect to socket", err);

setFd(sock);
}

char* UnixSocket::getPeerAddress() {
struct sockaddr_un addr;
socklen_t salen;

// AF_UNIX only has a single address (the server side).
// Unfortunately we don't know which end we are, so we'll have to
// test a bit.

salen = sizeof(addr);
if (getpeername(getFd(), (struct sockaddr *)&addr, &salen) != 0) {
vlog.error("unable to get peer name for socket");
return rfb::strDup("");
}

if (salen > offsetof(struct sockaddr_un, sun_path))
return rfb::strDup(addr.sun_path);

salen = sizeof(addr);
if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) != 0) {
vlog.error("unable to get local name for socket");
return rfb::strDup("");
}

if (salen > offsetof(struct sockaddr_un, sun_path))
return rfb::strDup(addr.sun_path);

// socketpair() will create unnamed sockets

return rfb::strDup("(unnamed UNIX socket)");
}

char* UnixSocket::getPeerEndpoint() {
return getPeerAddress();
}

bool UnixSocket::cork(bool enable)
{
return true;
}

UnixListener::UnixListener(const char *path, int mode)
{
struct sockaddr_un addr;
mode_t saved_umask;
int err, result;

if (strlen(path) >= sizeof(addr.sun_path))
throw SocketException("socket path is too long", ENAMETOOLONG);

// - Create a socket
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
throw SocketException("unable to create listening socket", errno);

// - Delete existing socket (ignore result)
unlink(path);

// - Attempt to bind to the requested path
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, path);
saved_umask = umask(0777);
result = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
err = errno;
umask(saved_umask);
if (result < 0) {
close(fd);
throw SocketException("unable to bind listening socket", err);
}

// - Set socket mode
if (chmod(path, mode) < 0) {
err = errno;
close(fd);
throw SocketException("unable to set socket mode", err);
}

listen(fd);
}

UnixListener::~UnixListener()
{
struct sockaddr_un addr;
socklen_t salen = sizeof(addr);

if (getsockname(getFd(), (struct sockaddr *)&addr, &salen) == 0)
unlink(addr.sun_path);
}

Socket* UnixListener::createSocket(int fd) {
return new UnixSocket(fd);
}

int UnixListener::getMyPort() {
return 0;
}

+ 60
- 0
common/network/UnixSocket.h View File

@@ -0,0 +1,60 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (c) 2012 University of Oslo. All Rights Reserved.
*
* This 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 2 of the License, or
* (at your option) any later version.
*
* This software 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 software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

// -=- UnixSocket.h - base-class for UNIX stream sockets.
// This header also defines the UnixListener class, used
// to listen for incoming socket connections over UNIX
//
// NB: Any file descriptors created by the UnixSocket or
// UnixListener classes are close-on-exec if the OS supports
// it. UnixSockets initialised with a caller-supplied fd
// are NOT set to close-on-exec.

#ifndef __NETWORK_UNIX_SOCKET_H__
#define __NETWORK_UNIX_SOCKET_H__

#include <network/Socket.h>

namespace network {

class UnixSocket : public Socket {
public:
UnixSocket(int sock);
UnixSocket(const char *name);

virtual char* getPeerAddress();
virtual char* getPeerEndpoint();

virtual bool cork(bool enable);
};

class UnixListener : public SocketListener {
public:
UnixListener(const char *listenaddr, int mode);
virtual ~UnixListener();

int getMyPort();

protected:
virtual Socket* createSocket(int fd);
};

}

#endif // __NETWORK_UNIX_SOCKET_H__

+ 1
- 1
common/rfb/Configuration.cxx View File

@@ -338,7 +338,7 @@ bool
IntParameter::setParam(const char* v) {
if (immutable) return true;
vlog.debug("set %s(Int) to %s", getName(), v);
int i = atoi(v);
int i = strtol(v, NULL, 0);
if (i < minValue || i > maxValue)
return false;
value = i;

+ 14
- 6
unix/x0vncserver/x0vncserver.cxx View File

@@ -31,6 +31,7 @@
#include <rfb/Configuration.h>
#include <rfb/Timer.h>
#include <network/TcpSocket.h>
#include <network/UnixSocket.h>

#include <vncconfig/QueryConnectDialog.h>

@@ -58,6 +59,8 @@ IntParameter maxProcessorUsage("MaxProcessorUsage", "Maximum percentage of "
"CPU time to be consumed", 35);
StringParameter displayname("display", "The X display", "");
IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",5900);
StringParameter rfbunixpath("rfbunixpath", "Unix socket to listen for RFB protocol", "");
IntParameter rfbunixmode("rfbunixmode", "Unix socket access mode", 0600);
IntParameter queryConnectTimeout("QueryConnectTimeout",
"Number of seconds to show the Accept Connection dialog before "
"rejecting the connection",
@@ -291,7 +294,7 @@ int main(int argc, char** argv)
signal(SIGINT, CleanupSignalHandler);
signal(SIGTERM, CleanupSignalHandler);

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

try {
TXWindow::init(dpy,"x0vncserver");
@@ -307,13 +310,18 @@ int main(int argc, char** argv)
QueryConnHandler qcHandler(dpy, &server);
server.setQueryConnectionHandler(&qcHandler);

createTcpListeners(&listeners, 0, (int)rfbport);
vlog.info("Listening on port %d", (int)rfbport);
if (rfbunixpath.getValueStr()[0] != '\0') {
listeners.push_back(new network::UnixListener(rfbunixpath, rfbunixmode));
vlog.info("Listening on %s (mode %04o)", (const char*)rfbunixpath, (int)rfbunixmode);
} else {
createTcpListeners(&listeners, 0, (int)rfbport);
vlog.info("Listening on port %d", (int)rfbport);
}

const char *hostsData = hostsFile.getData();
FileTcpFilter fileTcpFilter(hostsData);
if (strlen(hostsData) != 0)
for (std::list<TcpListener*>::iterator i = listeners.begin();
for (std::list<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
(*i)->setFilter(&fileTcpFilter);
@@ -335,7 +343,7 @@ int main(int argc, char** argv)
FD_ZERO(&wfds);

FD_SET(ConnectionNumber(dpy), &rfds);
for (std::list<TcpListener*>::iterator i = listeners.begin();
for (std::list<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
FD_SET((*i)->getFd(), &rfds);
@@ -387,7 +395,7 @@ int main(int argc, char** argv)
}

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

+ 9
- 0
unix/x0vncserver/x0vncserver.man View File

@@ -66,6 +66,15 @@ Use IPv4 for incoming and outgoing connections. Default is on.
Use IPv6 for incoming and outgoing connections. Default is on.
.
.TP
.B \-rfbunixpath \fIpath\fP
Specifies the path of a Unix domain socket on which x0vncserver listens for
connections from viewers, instead of listening on a TCP port.
.
.TP
.B \-rfbunixmode \fImode\fP
Specifies the mode of the Unix domain socket. The default is 0600.
.
.TP
.B \-Log \fIlogname\fP:\fIdest\fP:\fIlevel\fP
Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP,
\fBstdout\fP or \fBsyslog\fP, and \fIlevel\fP is between 0 and 100, 100 meaning

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

@@ -192,14 +192,14 @@ void vncListParams(int width, int nameWidth)

int vncGetSocketPort(int fd)
{
return network::TcpSocket::getSockPort(fd);
return network::getSockPort(fd);
}

int vncIsTCPPortUsed(int port)
{
try {
// Attempt to create TCPListeners on that port.
std::list<network::TcpListener*> dummy;
std::list<network::SocketListener*> dummy;
network::createTcpListeners (&dummy, 0, port);
while (!dummy.empty()) {
delete dummy.back();

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

@@ -32,7 +32,7 @@
#include <fcntl.h>
#include <sys/utsname.h>

#include <network/TcpSocket.h>
#include <network/Socket.h>
#include <rfb/Exception.h>
#include <rfb/VNCServerST.h>
#include <rfb/HTTPServer.h>
@@ -107,8 +107,8 @@ public:


XserverDesktop::XserverDesktop(int screenIndex_,
std::list<network::TcpListener*> listeners_,
std::list<network::TcpListener*> httpListeners_,
std::list<network::SocketListener*> listeners_,
std::list<network::SocketListener*> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
int width, int height,
void* fbptr, int stride)
@@ -127,13 +127,13 @@ XserverDesktop::XserverDesktop(int screenIndex_,
if (!httpListeners.empty ())
httpServer = new FileHTTPServer(this);

for (std::list<TcpListener*>::iterator i = listeners.begin();
for (std::list<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
i++) {
vncSetNotifyFd((*i)->getFd(), screenIndex, true, false);
}

for (std::list<TcpListener*>::iterator i = httpListeners.begin();
for (std::list<SocketListener*>::iterator i = httpListeners.begin();
i != httpListeners.end();
i++) {
vncSetNotifyFd((*i)->getFd(), screenIndex, true, false);
@@ -386,10 +386,10 @@ void XserverDesktop::handleSocketEvent(int fd, bool read, bool write)
}

bool XserverDesktop::handleListenerEvent(int fd,
std::list<TcpListener*>* sockets,
std::list<SocketListener*>* sockets,
SocketServer* sockserv)
{
std::list<TcpListener*>::iterator i;
std::list<SocketListener*>::iterator i;

for (i = sockets->begin(); i != sockets->end(); i++) {
if ((*i)->getFd() == fd)

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

@@ -44,7 +44,7 @@ namespace rfb {
class VNCServerST;
}

namespace network { class TcpListener; class Socket; class SocketServer; }
namespace network { class SocketListener; class Socket; class SocketServer; }

class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
public rdr::Substitutor,
@@ -53,8 +53,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::SocketListener*> listeners_,
std::list<network::SocketListener*> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
int width, int height, void* fbptr, int stride);
virtual ~XserverDesktop();
@@ -109,7 +109,7 @@ public:

protected:
bool handleListenerEvent(int fd,
std::list<network::TcpListener*>* sockets,
std::list<network::SocketListener*>* sockets,
network::SocketServer* sockserv);
bool handleSocketEvent(int fd,
network::SocketServer* sockserv,
@@ -122,8 +122,8 @@ private:
int screenIndex;
rfb::VNCServerST* server;
rfb::HTTPServer* httpServer;
std::list<network::TcpListener*> listeners;
std::list<network::TcpListener*> httpListeners;
std::list<network::SocketListener*> listeners;
std::list<network::SocketListener*> httpListeners;
bool directFbptr;

uint32_t queryConnectId;

+ 9
- 0
unix/xserver/hw/vnc/Xvnc.man View File

@@ -91,6 +91,15 @@ Use IPv4 for incoming and outgoing connections. Default is on.
Use IPv6 for incoming and outgoing connections. Default is on.
.
.TP
.B \-rfbunixpath \fIpath\fP
Specifies the path of a Unix domain socket on which Xvnc listens for
connections from viewers, instead of listening on a TCP port.
.
.TP
.B \-rfbunixmode \fImode\fP
Specifies the mode of the Unix domain socket. The default is 0600.
.
.TP
.B \-rfbwait \fItime\fP, \-ClientWaitTimeMillis \fItime\fP
Time in milliseconds to wait for a viewer which is blocking the server. This is
necessary because the server is single-threaded and sometimes blocks until the

+ 1
- 0
unix/xserver/hw/vnc/vncExt.c View File

@@ -585,6 +585,7 @@ static int SProcVncExtDispatch(ClientPtr client)

static void vncResetProc(ExtensionEntry* extEntry)
{
vncExtensionClose();
}

static void vncClientStateChange(CallbackListPtr * l, void * d, void * p)

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

@@ -34,6 +34,7 @@
#include <rfb/Region.h>
#include <rfb/ledStates.h>
#include <network/TcpSocket.h>
#include <network/UnixSocket.h>

#include "XserverDesktop.h"
#include "vncExtInit.h"
@@ -79,6 +80,8 @@ rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0);
rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis",
&rfb::Server::clientWaitTimeMillis);
rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0);
rfb::StringParameter rfbunixpath("rfbunixpath", "Unix socket to listen for RFB protocol", "");
rfb::IntParameter rfbunixmode("rfbunixmode", "Unix socket access mode", 0600);
rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11");
rfb::BoolParameter localhostOnly("localhost",
"Only allow connections from localhost",
@@ -173,14 +176,29 @@ 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::SocketListener*> listeners;
std::list<network::SocketListener*> httpListeners;
if (scr == 0 && vncInetdSock != -1) {
if (network::TcpSocket::isListening(vncInetdSock))
if (network::isSocketListening(vncInetdSock))
{
listeners.push_back(new network::TcpListener(vncInetdSock));
vlog.info("inetd wait");
}
} else if (rfbunixpath.getValueStr()[0] != '\0') {
char path[PATH_MAX];
int mode = (int)rfbunixmode;

if (scr == 0)
strncpy(path, rfbunixpath, sizeof(path));
else
snprintf(path, sizeof(path), "%s.%d",
rfbunixpath.getValueStr(), scr);
path[sizeof(path)-1] = '\0';

listeners.push_back(new network::UnixListener(path, mode));

vlog.info("Listening for VNC connections on %s (mode %04o)",
path, mode);
} else {
const char *addr = interface;
int port = rfbport;
@@ -244,6 +262,18 @@ void vncExtensionInit(void)
vncRegisterBlockHandlers();
}

void vncExtensionClose(void)
{
try {
for (int scr = 0; scr < vncGetScreenCount(); scr++) {
delete desktop[scr];
desktop[scr] = NULL;
}
} catch (rdr::Exception& e) {
vncFatalError("vncExtInit: %s",e.str());
}
}

void vncHandleSocketEvent(int fd, int scrIdx, int read, int write)
{
desktop[scrIdx]->handleSocketEvent(fd, read, write);

+ 1
- 0
unix/xserver/hw/vnc/vncExtInit.h View File

@@ -48,6 +48,7 @@ extern int vncFbstride[];
extern int vncInetdSock;

void vncExtensionInit(void);
void vncExtensionClose(void);

void vncHandleSocketEvent(int fd, int scrIdx, int read, int write);
void vncCallBlockHandlers(int* timeout);

+ 15
- 3
vncviewer/CConn.cxx View File

@@ -39,6 +39,9 @@
#include <rdr/MemInStream.h>
#include <rdr/MemOutStream.h>
#include <network/TcpSocket.h>
#ifndef WIN32
#include <network/UnixSocket.h>
#endif

#include <FL/Fl.H>
#include <FL/fl_ask.H>
@@ -106,10 +109,19 @@ CConn::CConn(const char* vncServerName, network::Socket* socket=NULL)

if(sock == NULL) {
try {
getHostAndPort(vncServerName, &serverHost, &serverPort);
#ifndef WIN32
if (strchr(vncServerName, '/') != NULL) {
sock = new network::UnixSocket(vncServerName);
serverHost = sock->getPeerAddress();
vlog.info(_("connected to socket %s"), serverHost);
} else
#endif
{
getHostAndPort(vncServerName, &serverHost, &serverPort);

sock = new network::TcpSocket(serverHost, serverPort);
vlog.info(_("connected to host %s port %d"), serverHost, serverPort);
sock = new network::TcpSocket(serverHost, serverPort);
vlog.info(_("connected to host %s port %d"), serverHost, serverPort);
}
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
if (alertOnFatalError)

+ 15
- 3
vncviewer/vncviewer.cxx View File

@@ -376,6 +376,18 @@ potentiallyLoadConfigurationFile(char *vncServerName)
(strchr(vncServerName, '\\')) != NULL);

if (hasPathSeparator) {
#ifndef WIN32
struct stat sb;

// This might be a UNIX socket, we need to check
if (stat(vncServerName, &sb) == -1) {
// Some access problem; let loadViewerParameters() deal with it...
} else {
if ((sb.st_mode & S_IFMT) == S_IFSOCK)
return;
}
#endif

try {
const char* newServerName;
newServerName = loadViewerParameters(vncServerName);
@@ -573,7 +585,7 @@ int main(int argc, char** argv)
#endif

if (listenMode) {
std::list<TcpListener*> listeners;
std::list<SocketListener*> listeners;
try {
int port = 5500;
if (isdigit(vncServerName[0]))
@@ -587,7 +599,7 @@ 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<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
FD_SET((*i)->getFd(), &rfds);
@@ -602,7 +614,7 @@ int main(int argc, char** argv)
}
}

for (std::list<TcpListener*>::iterator i = listeners.begin ();
for (std::list<SocketListener*>::iterator i = listeners.begin ();
i != listeners.end();
i++)
if (FD_ISSET((*i)->getFd(), &rfds)) {

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

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

ManagedListener::~ManagedListener() {
if (!sockets.empty()) {
std::list<network::TcpListener*>::iterator iter;
std::list<network::SocketListener*>::iterator iter;
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
manager->remListener(*iter);
sockets.clear();
@@ -62,7 +62,7 @@ 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::SocketListener*>::iterator iter;
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
(*iter)->setFilter(filter);
}
@@ -80,7 +80,7 @@ bool ManagedListener::isListening() {
}

void ManagedListener::refresh() {
std::list<network::TcpListener*>::iterator iter;
std::list<network::SocketListener*>::iterator iter;
if (!sockets.empty()) {
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
manager->remListener(*iter);
@@ -107,7 +107,7 @@ void ManagedListener::refresh() {
for (iter = sockets.begin(); iter != sockets.end(); ++iter)
manager->addListener(*iter, server, addrChangeNotifier);
} catch (...) {
std::list<network::TcpListener*>::iterator iter2;
std::list<network::SocketListener*>::iterator iter2;
for (iter2 = sockets.begin(); iter2 != iter; ++iter2)
manager->remListener(*iter2);
for (; iter2 != sockets.end(); ++iter2)

+ 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::SocketListener*> sockets;
network::TcpFilter* filter;
rfb::win32::SocketManager* manager;
rfb::win32::SocketManager::AddressChangeNotifier* addrChangeNotifier;

Loading…
Cancel
Save