瀏覽代碼

Merge common socket code

tags/v1.8.90
Pierre Ossman 6 年之前
父節點
當前提交
559e8b8854

+ 1
- 0
common/network/CMakeLists.txt 查看文件

@@ -1,6 +1,7 @@
include_directories(${CMAKE_SOURCE_DIR}/common)

set(NETWORK_SOURCES
Socket.cxx
TcpSocket.cxx)

if(NOT WIN32)

+ 183
- 0
common/network/Socket.cxx 查看文件

@@ -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;
}

+ 31
- 23
common/network/Socket.h 查看文件

@@ -30,24 +30,22 @@

namespace network {

void initSockets();

bool isSocketListening(int sock);

class Socket {
public:
Socket(int fd)
: instream(new rdr::FdInStream(fd)),
outstream(new rdr::FdOutStream(fd)),
isShutdown_(false),
queryConnection(false) {}
virtual ~Socket() {
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_;}
void shutdown();
bool isShutdown() const;
virtual bool cork(bool enable) = 0;

// information about the remote end of the socket
@@ -55,15 +53,15 @@ namespace network {
virtual char* getPeerEndpoint() = 0; // <address>::<port>

// 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),
isShutdown_(false), queryConnection(false) {}
Socket(rdr::FdInStream* i, rdr::FdOutStream* o)
: instream(i), outstream(o),
isShutdown_(false), queryConnection(false) {}
Socket();
void setFd(int fd);
private:
rdr::FdInStream* instream;
rdr::FdOutStream* outstream;
bool isShutdown_;
@@ -78,22 +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;

+ 25
- 117
common/network/TcpSocket.cxx 查看文件

@@ -33,8 +33,6 @@
#include <netinet/tcp.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#endif

#include <stdlib.h>
@@ -97,30 +95,27 @@ 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)
: Socket(new FdInStream(sock), new FdOutStream(sock))
TcpSocket::TcpSocket(int sock) : Socket(sock)
{
// Disable Nagle's algorithm, to reduce latency
enableNagles(false);
}

TcpSocket::TcpSocket(const char *host, int port)
@@ -129,7 +124,6 @@ TcpSocket::TcpSocket(const char *host, int port)
struct addrinfo *ai, *current, hints;

// - Create a socket
initSockets();

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
@@ -211,21 +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);
}

TcpSocket::~TcpSocket() {
closesocket(getFd());
enableNagles(false);
}

char* TcpSocket::getPeerAddress() {
@@ -293,15 +277,9 @@ char* TcpSocket::getPeerEndpoint() {
return buffer;
}

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);
@@ -321,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,
@@ -358,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);

@@ -397,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;
}

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

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) {
@@ -489,7 +397,7 @@ void TcpListener::getMyAddresses(std::list<char*>* result) {
}

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



+ 7
- 9
common/network/TcpSocket.h 查看文件

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

int getSockPort(int sock);

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

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

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);
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);

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

void createLocalTcpListeners(std::list<SocketListener*> *listeners,

+ 5
- 62
common/network/UnixSocket.cxx 查看文件

@@ -26,8 +26,6 @@
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stddef.h>

@@ -39,20 +37,9 @@ using namespace rdr;

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

// -=- Socket initialisation
static bool socketsInitialised = false;
static void initSockets() {
if (socketsInitialised)
return;
signal(SIGPIPE, SIG_IGN);
socketsInitialised = true;
}


// -=- UnixSocket

UnixSocket::UnixSocket(int sock)
: Socket(new FdInStream(sock), new FdOutStream(sock))
UnixSocket::UnixSocket(int sock) : Socket(sock)
{
}

@@ -66,7 +53,6 @@ UnixSocket::UnixSocket(const char *path)
throw SocketException("socket path is too long", ENAMETOOLONG);

// - Create a socket
initSockets();
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1)
throw SocketException("unable to create socket", errno);
@@ -85,16 +71,7 @@ UnixSocket::UnixSocket(const char *path)
if (result == -1)
throw SocketException("unable connect to socket", err);

// - By default, close the socket on exec()
fcntl(sock, F_SETFD, FD_CLOEXEC);

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

UnixSocket::~UnixSocket() {
close(getFd());
setFd(sock);
}

char* UnixSocket::getPeerAddress() {
@@ -132,12 +109,6 @@ char* UnixSocket::getPeerEndpoint() {
return getPeerAddress();
}

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

bool UnixSocket::cork(bool enable)
{
return true;
@@ -153,13 +124,9 @@ UnixListener::UnixListener(const char *path, int mode)
throw SocketException("socket path is too long", ENAMETOOLONG);

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

// - By default, close the socket on exec()
fcntl(fd, F_SETFD, FD_CLOEXEC);

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

@@ -183,12 +150,7 @@ UnixListener::UnixListener(const char *path, int mode)
throw SocketException("unable to set socket mode", err);
}

// - Set it to be a listening socket
if (listen(fd, 5) < 0) {
err = errno;
close(fd);
throw SocketException("unable to set socket to listening mode", err);
}
listen(fd);
}

UnixListener::~UnixListener()
@@ -196,31 +158,12 @@ UnixListener::~UnixListener()
struct sockaddr_un addr;
socklen_t salen = sizeof(addr);

close(fd);

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

void UnixListener::shutdown()
{
::shutdown(getFd(), 2);
}


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

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

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

// - Create the socket object
return new UnixSocket(new_sock);
Socket* UnixListener::createSocket(int fd) {
return new UnixSocket(fd);
}

int UnixListener::getMyPort() {

+ 3
- 5
common/network/UnixSocket.h 查看文件

@@ -37,12 +37,10 @@ namespace network {
public:
UnixSocket(int sock);
UnixSocket(const char *name);
virtual ~UnixSocket();

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

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

@@ -51,10 +49,10 @@ namespace network {
UnixListener(const char *listenaddr, int mode);
virtual ~UnixListener();

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

int getMyPort();

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

}

+ 1
- 1
unix/xserver/hw/vnc/RFBGlue.cc 查看文件

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

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

int vncIsTCPPortUsed(int port)

+ 1
- 1
unix/xserver/hw/vnc/vncExtInit.cc 查看文件

@@ -179,7 +179,7 @@ void vncExtensionInit(void)
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");

Loading…
取消
儲存