From e3de59c08cb3bd8e77d9935948c452919fcb1764 Mon Sep 17 00:00:00 2001 From: David Brodsky Date: Fri, 15 Jun 2007 21:37:49 +0200 Subject: [PATCH] Add support for unix sockets to Tairon::Net::Socket. This change breaks compatibility with older code, because constructor of Tairon::Net::Socket now takes one extra argument for family type. It means that if the code using previous version isn't changed then the other constructor is used. --- src/net-core/socket.cpp | 31 ++++++++++++++++++++++++++++--- src/net-core/socket.h | 30 ++++++++++++++++++++++++++---- src/net-http/httpclient.cpp | 2 +- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/net-core/socket.cpp b/src/net-core/socket.cpp index 70d5d5c..9b76638 100644 --- a/src/net-core/socket.cpp +++ b/src/net-core/socket.cpp @@ -14,6 +14,7 @@ * * ***************************************************************************/ +#include #include #include #include @@ -34,10 +35,10 @@ namespace Net const size_t Socket::bufLength = 65536; -/* {{{ Socket::Socket(Type) */ -Socket::Socket(Type type) +/* {{{ Socket::Socket(Family, Type) */ +Socket::Socket(Family family, Type type) { - fd = socket(PF_INET, type, 0); + fd = socket(family, type, 0); if (fd == -1) throw SocketException("Cannot create socket", errno); @@ -103,6 +104,30 @@ void Socket::connected() } /* }}} */ +/* {{{ Socket::connect(const String &) */ +void Socket::connect(const String &path) +{ + if (path.length() >= 108) // length of struct socaddr_un.sun_path field + throw SocketException("Path for unix socket is too long", 0); + + if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) == -1) + throw SocketException("Cannot set nonblocking socket", errno); + + sockaddr_un addr; + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, path.data(), path.length()); + addr.sun_path[path.length()] = 0; + + int ret = ::connect(fd, (sockaddr *) &addr, sizeof(addr)); + if ((ret == -1) && (errno != EINPROGRESS)) + throw SocketException("Error while connecting", errno); + + notifier->setReadyWriteFunctor(Tairon::Core::methodFunctor(this, &Socket::connected)); + + Poll::self()->registerSocketToWrite(fd, notifier); +} +/* }}} */ + /* {{{ Socket::connect(const String &, uint16_t) */ void Socket::connect(const String &address, uint16_t port) { diff --git a/src/net-core/socket.h b/src/net-core/socket.h index 68def3e..a9e294d 100644 --- a/src/net-core/socket.h +++ b/src/net-core/socket.h @@ -34,8 +34,12 @@ class SocketNotifier; /** \brief This class provides non-blocking network connection. * - * Socket type can be either a stream (TCP) or a datagram (UDP). When new data - * is incoming readyRead signal is emitted and the data can be read with + * Socket's family can be Unix for local communication through unix sockets or + * IPv4 for communication using protocol with the same name. + * + * Socket type can be either a stream (for reliable connection-based byte + * streams) or a datagram (for connectionless, unreliable messages). When new + * data is incoming readyRead signal is emitted and the data can be read with * readAll() method which reads all the data from socket. In some cases better * performance can be achieved with readTo() method which reads not more than * given amount of data into specified location in memory (this can be a mmaped @@ -48,6 +52,18 @@ class SocketNotifier; class Socket { public: + /** Family of the socket. + */ + enum Family { + /** Unix socket (only local connections). + */ + Unix = PF_UNIX, + + /** IPv4 socket. + */ + IPv4 = PF_INET + }; + /** Type of the socket. */ enum Type { @@ -64,7 +80,7 @@ class Socket /** Creates new socket of given type. */ - Socket(Type type); + Socket(Family family, Type type); /** Creates new socket object associated with given descriptor. */ @@ -78,7 +94,13 @@ class Socket */ void close(); - /** Connects this socket to a host. + /** Connects this socket to a unix socket. + * + * \param path Path to the unix socket. + */ + void connect(const String &path); + + /** Connects this socket (with IPv4 family) to a host. * * \param address Host to which this socket should be connected. * \param port Target port of the connection in host byte order. diff --git a/src/net-http/httpclient.cpp b/src/net-http/httpclient.cpp index 14e33aa..d3ee42b 100644 --- a/src/net-http/httpclient.cpp +++ b/src/net-http/httpclient.cpp @@ -132,7 +132,7 @@ void HTTPClient::get(const String &what) Tairon::Core::Thread *current = Tairon::Core::Thread::current(); - socket = new Socket(Socket::Stream); + socket = new Socket(Socket::IPv4, Socket::Stream); socket->connectedSignal.connect(Tairon::Core::threadMethodDFunctor(current, this, &HTTPClient::connected)); socket->errorSignal.connect(Tairon::Core::threadMethodDFunctor(current, this, &HTTPClient::error)); socket->readyReadSignal.connect(Tairon::Core::threadMethodDFunctor(current, this, &HTTPClient::readyRead)); -- 2.11.4.GIT