You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rm...@apache.org on 2022/08/14 03:11:10 UTC

[logging-log4cxx] 01/04: LOGCXX-549 Turned the Socket and SocketServer classes into non APR-specific classes

This is an automated email from the ASF dual-hosted git repository.

rmiddleton pushed a commit to branch LOGCXX-549
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git

commit f503f453cad66c8bc23ceccdf44b49527de47867
Author: Robert Middleton <ro...@rm5248.com>
AuthorDate: Sat Aug 13 15:14:01 2022 -0400

    LOGCXX-549 Turned the Socket and SocketServer classes into non APR-specific classes
---
 CMakeLists.txt                                     |   1 +
 src/main/cpp/CMakeLists.txt                        |   6 +-
 .../cpp/{serversocket.cpp => aprserversocket.cpp}  |  80 ++++++------
 src/main/cpp/{socket.cpp => aprsocket.cpp}         |  82 ++++++-------
 src/main/cpp/serversocket.cpp                      | 135 ++-------------------
 src/main/cpp/socket.cpp                            | 129 ++------------------
 src/main/cpp/socketappenderskeleton.cpp            |   4 +-
 src/main/cpp/sockethubappender.cpp                 |   7 +-
 src/main/cpp/telnetappender.cpp                    |   2 +-
 src/main/include/CMakeLists.txt                    |   6 +
 src/main/include/log4cxx/helpers/serversocket.h    |  27 +++--
 src/main/include/log4cxx/helpers/socket.h          |  44 +++----
 src/main/include/log4cxx/log4cxx.h.in              |   3 +-
 .../serversocket.h => private/aprserversocket.h}   |  51 +++-----
 .../serversocket.h => private/aprsocket.h}         |  49 +++-----
 .../serversocket.h => private/serversocket_priv.h} |  48 ++------
 .../serversocket.h => private/socket_priv.h}       |  48 ++------
 17 files changed, 204 insertions(+), 518 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a4b96376..2e95bdcd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -242,6 +242,7 @@ message(STATUS "  charset ......................... : ${LOG4CXX_CHARSET}")
 message(STATUS "  Using libESMTP .................. : ${HAS_LIBESMTP}")
 message(STATUS "  ODBC library .................... : ${HAS_ODBC}")
 message(STATUS "  syslog .......................... : ${HAS_SYSLOG}")
+message(STATUS "  Networking support .............. : ${NETWORKING_SUPPORT}")
 message(STATUS "  Qt support ...................... : ${LOG4CXX_QT_SUPPORT}")
 message(STATUS "C++ version and Boost settings:")
 message(STATUS "  Prefer boost: ................... : ${PREFER_BOOST}")
diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index 8f9c16d5..0f71bf66 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -139,13 +139,15 @@ target_sources(log4cxx
   rollingpolicybase.cpp
   rolloverdescription.cpp
   rootlogger.cpp
-  serversocket.cpp
+  $<IF:$<BOOL:NETWORKING_SUPPORT>,serversocket.cpp,>
+  $<IF:$<BOOL:NETWORKING_SUPPORT>,aprserversocket.cpp,>
   shortfilelocationpatternconverter.cpp
   simpledateformat.cpp
   simplelayout.cpp
   sizebasedtriggeringpolicy.cpp
   smtpappender.cpp
-  socket.cpp
+  $<IF:$<BOOL:NETWORKING_SUPPORT>,socket.cpp,>
+  $<IF:$<BOOL:NETWORKING_SUPPORT>,aprsocket.cpp,>
   socketappenderskeleton.cpp
   sockethubappender.cpp
   socketoutputstream.cpp
diff --git a/src/main/cpp/serversocket.cpp b/src/main/cpp/aprserversocket.cpp
similarity index 64%
copy from src/main/cpp/serversocket.cpp
copy to src/main/cpp/aprserversocket.cpp
index 1cc9a3b9..797b5a1b 100644
--- a/src/main/cpp/serversocket.cpp
+++ b/src/main/cpp/aprserversocket.cpp
@@ -15,28 +15,35 @@
  * limitations under the License.
  */
 
-#include <log4cxx/helpers/serversocket.h>
-#include <mutex>
+#include <log4cxx/private/aprserversocket.h>
+#include <log4cxx/private/serversocket_priv.h>
+#include <log4cxx/private/aprsocket.h>
 #include "apr_network_io.h"
 #include "apr_pools.h"
 #include "apr_poll.h"
 
-using namespace log4cxx::helpers;
+using log4cxx::helpers::APRServerSocket;
 
-/**  Creates a server socket on a specified port.
-*/
-ServerSocket::ServerSocket(int port) : pool(), socket(0), timeout(0)
-{
+#define _priv static_cast<APRServerSocketPriv*>(m_priv.get())
+
+struct APRServerSocket::APRServerSocketPriv : public ServerSocketPrivate {
+	Pool pool;
+	std::mutex mutex;
+	apr_socket_t* socket;
+};
+
+APRServerSocket::APRServerSocket(int port) :
+	ServerSocket(std::make_unique<APRServerSocketPriv>()){
 	apr_status_t status =
-		apr_socket_create(&socket, APR_INET, SOCK_STREAM,
-			APR_PROTO_TCP, pool.getAPRPool());
+		apr_socket_create(&_priv->socket, APR_INET, SOCK_STREAM,
+			APR_PROTO_TCP, _priv->pool.getAPRPool());
 
 	if (status != APR_SUCCESS)
 	{
 		throw SocketException(status);
 	}
 
-	status = apr_socket_opt_set(socket, APR_SO_NONBLOCK, 1);
+	status = apr_socket_opt_set(_priv->socket, APR_SO_NONBLOCK, 1);
 
 	if (status != APR_SUCCESS)
 	{
@@ -47,7 +54,7 @@ ServerSocket::ServerSocket(int port) : pool(), socket(0), timeout(0)
 	apr_sockaddr_t* server_addr;
 	status =
 		apr_sockaddr_info_get(&server_addr, NULL, APR_INET,
-			port, 0, pool.getAPRPool());
+			port, 0, _priv->pool.getAPRPool());
 
 	if (status != APR_SUCCESS)
 	{
@@ -55,7 +62,7 @@ ServerSocket::ServerSocket(int port) : pool(), socket(0), timeout(0)
 	}
 
 	// bind the socket to the address
-	status = apr_socket_bind(socket, server_addr);
+	status = apr_socket_bind(_priv->socket, server_addr);
 
 	if (status != APR_SUCCESS)
 	{
@@ -63,7 +70,7 @@ ServerSocket::ServerSocket(int port) : pool(), socket(0), timeout(0)
 	}
 
 
-	status = apr_socket_listen(socket, 50);
+	status = apr_socket_listen(_priv->socket, 50);
 
 	if (status != APR_SUCCESS)
 	{
@@ -71,50 +78,45 @@ ServerSocket::ServerSocket(int port) : pool(), socket(0), timeout(0)
 	}
 }
 
+void APRServerSocket::close(){
+	std::unique_lock<std::mutex> lock(_priv->mutex);
 
-ServerSocket::~ServerSocket()
-{
-}
-
-void ServerSocket::close()
-{
-	std::unique_lock<std::mutex> lock(mutex);
-
-	if (socket != 0)
+	if (_priv->socket != 0)
 	{
-		apr_status_t status = apr_socket_close(socket);
+		apr_status_t status = apr_socket_close(_priv->socket);
 
 		if (status != APR_SUCCESS)
 		{
 			throw SocketException(status);
 		}
 
-		socket = 0;
+		_priv->socket = 0;
 	}
 }
 
+
 /** Listens for a connection to be made to this socket and
 accepts it
 */
-SocketPtr ServerSocket::accept()
+log4cxx::helpers::SocketPtr APRServerSocket::accept()
 {
-	std::unique_lock<std::mutex> lock(mutex);
+	std::unique_lock<std::mutex> lock(_priv->mutex);
 
-	if (socket == 0)
+	if (_priv->socket == 0)
 	{
 		throw IOException();
 	}
 
 	apr_pollfd_t poll;
-	poll.p = pool.getAPRPool();
+	poll.p = _priv->pool.getAPRPool();
 	poll.desc_type = APR_POLL_SOCKET;
 	poll.reqevents = APR_POLLIN;
 	poll.rtnevents = 0;
-	poll.desc.s = socket;
+	poll.desc.s = _priv->socket;
 	poll.client_data = NULL;
 
 	apr_int32_t signaled;
-	apr_interval_time_t to = timeout * 1000;
+	apr_interval_time_t to = _priv->timeout * 1000;
 	apr_status_t status = apr_poll(&poll, 1, &signaled, to);
 
 	if (APR_STATUS_IS_TIMEUP(status))
@@ -135,7 +137,7 @@ SocketPtr ServerSocket::accept()
 	}
 
 	apr_socket_t* newSocket;
-	status = apr_socket_accept(&newSocket, socket, newPool);
+	status = apr_socket_accept(&newSocket, _priv->socket, newPool);
 
 	if (status != APR_SUCCESS)
 	{
@@ -151,19 +153,5 @@ SocketPtr ServerSocket::accept()
 		throw SocketException(status);
 	}
 
-	return SocketPtr(new Socket(newSocket, newPool));
-}
-
-/** Retrive setting for SO_TIMEOUT.
-*/
-int ServerSocket::getSoTimeout() const
-{
-	return timeout;
-}
-
-/** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
-*/
-void ServerSocket::setSoTimeout(int newVal)
-{
-	timeout = newVal;
+	return std::make_shared<APRSocket>(newSocket, newPool);
 }
diff --git a/src/main/cpp/socket.cpp b/src/main/cpp/aprsocket.cpp
similarity index 64%
copy from src/main/cpp/socket.cpp
copy to src/main/cpp/aprsocket.cpp
index cdd8724f..fa56fe91 100644
--- a/src/main/cpp/socket.cpp
+++ b/src/main/cpp/aprsocket.cpp
@@ -14,39 +14,50 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <log4cxx/helpers/socket.h>
+
+#include <log4cxx/private/aprsocket.h>
+#include <log4cxx/private/socket_priv.h>
 #include <log4cxx/helpers/bytebuffer.h>
-#include <log4cxx/helpers/transcoder.h>
+
 #include "apr_network_io.h"
 #include "apr_signal.h"
 
+using log4cxx::helpers::APRSocket;
 
-using namespace log4cxx;
-using namespace log4cxx::helpers;
+struct APRSocket::APRSocketPriv : public log4cxx::helpers::Socket::SocketPrivate {
+	APRSocketPriv() :
+		socket(nullptr)
+	{}
 
-IMPLEMENT_LOG4CXX_OBJECT(Socket)
+	APRSocketPriv(apr_socket_t* sock, apr_pool_t* p) :
+		pool(p, true),
+		socket(sock)
+	{}
 
-/** Creates a stream socket and connects it to the specified port
-number at the specified IP address.
-*/
-Socket::Socket(InetAddressPtr& addr, int prt) : pool(), socket(0), address(addr), port(prt)
-{
+	Pool pool;
+	apr_socket_t* socket;
+};
+
+#define _priv static_cast<APRSocketPriv*>(m_priv.get())
+
+APRSocket::APRSocket(InetAddressPtr& address, int port) :
+	Socket(std::make_unique<APRSocketPriv>()){
 	apr_status_t status =
-		apr_socket_create(&socket, APR_INET, SOCK_STREAM,
-			APR_PROTO_TCP, pool.getAPRPool());
+		apr_socket_create(&_priv->socket, APR_INET, SOCK_STREAM,
+			APR_PROTO_TCP, _priv->pool.getAPRPool());
 
 	if (status != APR_SUCCESS)
 	{
 		throw SocketException(status);
 	}
 
-	LOG4CXX_ENCODE_CHAR(host, addr->getHostAddress());
+	LOG4CXX_ENCODE_CHAR(host, address->getHostAddress());
 
 	// create socket address (including port)
 	apr_sockaddr_t* client_addr;
 	status =
 		apr_sockaddr_info_get(&client_addr, host.c_str(), APR_INET,
-			prt, 0, pool.getAPRPool());
+			port, 0, _priv->pool.getAPRPool());
 
 	if (status != APR_SUCCESS)
 	{
@@ -54,7 +65,7 @@ Socket::Socket(InetAddressPtr& addr, int prt) : pool(), socket(0), address(addr)
 	}
 
 	// connect the socket
-	status =  apr_socket_connect(socket, client_addr);
+	status =  apr_socket_connect(_priv->socket, client_addr);
 
 	if (status != APR_SUCCESS)
 	{
@@ -62,15 +73,14 @@ Socket::Socket(InetAddressPtr& addr, int prt) : pool(), socket(0), address(addr)
 	}
 }
 
-Socket::Socket(apr_socket_t* s, apr_pool_t* p) :
-	pool(p, true), socket(s)
-{
+APRSocket::APRSocket(apr_socket_t* s, apr_pool_t* pool) :
+	Socket(std::make_unique<APRSocketPriv>(s, pool)){
 	apr_sockaddr_t* sa;
 	apr_status_t status = apr_socket_addr_get(&sa, APR_REMOTE, s);
 
 	if (status == APR_SUCCESS)
 	{
-		port = sa->port;
+		_priv->port = sa->port;
 		LogString remotename;
 		LogString remoteip;
 
@@ -87,17 +97,13 @@ Socket::Socket(apr_socket_t* s, apr_pool_t* p) :
 			Transcoder::decode(buf, remoteip);
 		}
 
-		address = InetAddressPtr(new InetAddress(remotename, remoteip));
+		_priv->address = InetAddressPtr(new InetAddress(remotename, remoteip));
 	}
 }
 
-Socket::~Socket()
-{
-}
-
-size_t Socket::write(ByteBuffer& buf)
+size_t APRSocket::write(ByteBuffer& buf)
 {
-	if (socket == 0)
+	if (_priv->socket == 0)
 	{
 		throw ClosedChannelException();
 	}
@@ -114,10 +120,10 @@ size_t Socket::write(ByteBuffer& buf)
 		// SIGPIPE handler.
 #if APR_HAVE_SIGACTION
 		apr_sigfunc_t* old = apr_signal(SIGPIPE, SIG_IGN);
-		apr_status_t status = apr_socket_send(socket, buf.current(), &written);
+		apr_status_t status = apr_socket_send(_priv->socket, buf.current(), &written);
 		apr_signal(SIGPIPE, old);
 #else
-		apr_status_t status = apr_socket_send(socket, buf.current(), &written);
+		apr_status_t status = apr_socket_send(_priv->socket, buf.current(), &written);
 #endif
 
 		buf.position(buf.position() + written);
@@ -133,29 +139,17 @@ size_t Socket::write(ByteBuffer& buf)
 }
 
 
-void Socket::close()
+void APRSocket::close()
 {
-	if (socket != 0)
+	if (_priv->socket != 0)
 	{
-		apr_status_t status = apr_socket_close(socket);
+		apr_status_t status = apr_socket_close(_priv->socket);
 
 		if (status != APR_SUCCESS)
 		{
 			throw SocketException(status);
 		}
 
-		socket = 0;
+		_priv->socket = 0;
 	}
 }
-
-InetAddressPtr Socket::getInetAddress() const
-{
-	return address;
-}
-
-int Socket::getPort() const
-{
-	return port;
-}
-
-
diff --git a/src/main/cpp/serversocket.cpp b/src/main/cpp/serversocket.cpp
index 1cc9a3b9..cb81a141 100644
--- a/src/main/cpp/serversocket.cpp
+++ b/src/main/cpp/serversocket.cpp
@@ -16,154 +16,41 @@
  */
 
 #include <log4cxx/helpers/serversocket.h>
-#include <mutex>
-#include "apr_network_io.h"
-#include "apr_pools.h"
-#include "apr_poll.h"
+#include <log4cxx/private/serversocket_priv.h>
+#include <log4cxx/private/aprserversocket.h>
 
 using namespace log4cxx::helpers;
 
 /**  Creates a server socket on a specified port.
 */
-ServerSocket::ServerSocket(int port) : pool(), socket(0), timeout(0)
+ServerSocket::ServerSocket(std::unique_ptr<ServerSocketPrivate> priv) :
+	m_priv(std::move(priv))
 {
-	apr_status_t status =
-		apr_socket_create(&socket, APR_INET, SOCK_STREAM,
-			APR_PROTO_TCP, pool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
-
-	status = apr_socket_opt_set(socket, APR_SO_NONBLOCK, 1);
-
-	if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
-
-	// Create server socket address (including port number)
-	apr_sockaddr_t* server_addr;
-	status =
-		apr_sockaddr_info_get(&server_addr, NULL, APR_INET,
-			port, 0, pool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw ConnectException(status);
-	}
-
-	// bind the socket to the address
-	status = apr_socket_bind(socket, server_addr);
-
-	if (status != APR_SUCCESS)
-	{
-		throw BindException(status);
-	}
-
-
-	status = apr_socket_listen(socket, 50);
-
-	if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
 }
 
-
 ServerSocket::~ServerSocket()
 {
+	close();
 }
 
 void ServerSocket::close()
 {
-	std::unique_lock<std::mutex> lock(mutex);
-
-	if (socket != 0)
-	{
-		apr_status_t status = apr_socket_close(socket);
-
-		if (status != APR_SUCCESS)
-		{
-			throw SocketException(status);
-		}
-
-		socket = 0;
-	}
-}
-
-/** Listens for a connection to be made to this socket and
-accepts it
-*/
-SocketPtr ServerSocket::accept()
-{
-	std::unique_lock<std::mutex> lock(mutex);
-
-	if (socket == 0)
-	{
-		throw IOException();
-	}
-
-	apr_pollfd_t poll;
-	poll.p = pool.getAPRPool();
-	poll.desc_type = APR_POLL_SOCKET;
-	poll.reqevents = APR_POLLIN;
-	poll.rtnevents = 0;
-	poll.desc.s = socket;
-	poll.client_data = NULL;
-
-	apr_int32_t signaled;
-	apr_interval_time_t to = timeout * 1000;
-	apr_status_t status = apr_poll(&poll, 1, &signaled, to);
-
-	if (APR_STATUS_IS_TIMEUP(status))
-	{
-		throw SocketTimeoutException();
-	}
-	else if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
-
-	apr_pool_t* newPool;
-	status = apr_pool_create(&newPool, 0);
-
-	if (status != APR_SUCCESS)
-	{
-		throw PoolException(status);
-	}
-
-	apr_socket_t* newSocket;
-	status = apr_socket_accept(&newSocket, socket, newPool);
-
-	if (status != APR_SUCCESS)
-	{
-		apr_pool_destroy(newPool);
-		throw SocketException(status);
-	}
-
-	status = apr_socket_opt_set(newSocket, APR_SO_NONBLOCK, 0);
-
-	if (status != APR_SUCCESS)
-	{
-		apr_pool_destroy(newPool);
-		throw SocketException(status);
-	}
-
-	return SocketPtr(new Socket(newSocket, newPool));
 }
 
 /** Retrive setting for SO_TIMEOUT.
 */
 int ServerSocket::getSoTimeout() const
 {
-	return timeout;
+	return m_priv->timeout;
 }
 
 /** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
 */
 void ServerSocket::setSoTimeout(int newVal)
 {
-	timeout = newVal;
+	m_priv->timeout = newVal;
+}
+
+ServerSocketUniquePtr ServerSocket::create(int port){
+	return std::make_unique<APRServerSocket>(port);
 }
diff --git a/src/main/cpp/socket.cpp b/src/main/cpp/socket.cpp
index cdd8724f..d27e4924 100644
--- a/src/main/cpp/socket.cpp
+++ b/src/main/cpp/socket.cpp
@@ -17,145 +17,36 @@
 #include <log4cxx/helpers/socket.h>
 #include <log4cxx/helpers/bytebuffer.h>
 #include <log4cxx/helpers/transcoder.h>
-#include "apr_network_io.h"
-#include "apr_signal.h"
 
+#include <log4cxx/private/socket_priv.h>
+#include <log4cxx/private/aprsocket.h>
 
 using namespace log4cxx;
 using namespace log4cxx::helpers;
 
 IMPLEMENT_LOG4CXX_OBJECT(Socket)
 
-/** Creates a stream socket and connects it to the specified port
-number at the specified IP address.
-*/
-Socket::Socket(InetAddressPtr& addr, int prt) : pool(), socket(0), address(addr), port(prt)
-{
-	apr_status_t status =
-		apr_socket_create(&socket, APR_INET, SOCK_STREAM,
-			APR_PROTO_TCP, pool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
-
-	LOG4CXX_ENCODE_CHAR(host, addr->getHostAddress());
-
-	// create socket address (including port)
-	apr_sockaddr_t* client_addr;
-	status =
-		apr_sockaddr_info_get(&client_addr, host.c_str(), APR_INET,
-			prt, 0, pool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw ConnectException(status);
-	}
-
-	// connect the socket
-	status =  apr_socket_connect(socket, client_addr);
-
-	if (status != APR_SUCCESS)
-	{
-		throw ConnectException(status);
-	}
-}
+Socket::Socket(std::unique_ptr<Socket::SocketPrivate> priv) :
+	m_priv(std::move(priv)){
 
-Socket::Socket(apr_socket_t* s, apr_pool_t* p) :
-	pool(p, true), socket(s)
-{
-	apr_sockaddr_t* sa;
-	apr_status_t status = apr_socket_addr_get(&sa, APR_REMOTE, s);
-
-	if (status == APR_SUCCESS)
-	{
-		port = sa->port;
-		LogString remotename;
-		LogString remoteip;
-
-		if (sa->hostname != NULL)
-		{
-			Transcoder::decode(sa->hostname, remotename);
-		}
-
-		char* buf = 0;
-		status = apr_sockaddr_ip_get(&buf, sa);
-
-		if (status == APR_SUCCESS)
-		{
-			Transcoder::decode(buf, remoteip);
-		}
-
-		address = InetAddressPtr(new InetAddress(remotename, remoteip));
-	}
 }
 
 Socket::~Socket()
 {
 }
 
-size_t Socket::write(ByteBuffer& buf)
-{
-	if (socket == 0)
-	{
-		throw ClosedChannelException();
-	}
-
-	int totalWritten = 0;
-
-	while (buf.remaining() > 0)
-	{
-		apr_size_t written = buf.remaining();
-
-		// while writing to the socket, we need to ignore the SIGPIPE
-		// signal. Otherwise, when the client has closed the connection,
-		// the send() function would not return an error but call the
-		// SIGPIPE handler.
-#if APR_HAVE_SIGACTION
-		apr_sigfunc_t* old = apr_signal(SIGPIPE, SIG_IGN);
-		apr_status_t status = apr_socket_send(socket, buf.current(), &written);
-		apr_signal(SIGPIPE, old);
-#else
-		apr_status_t status = apr_socket_send(socket, buf.current(), &written);
-#endif
-
-		buf.position(buf.position() + written);
-		totalWritten += written;
-
-		if (status != APR_SUCCESS)
-		{
-			throw SocketException(status);
-		}
-	}
-
-	return totalWritten;
-}
-
-
-void Socket::close()
-{
-	if (socket != 0)
-	{
-		apr_status_t status = apr_socket_close(socket);
-
-		if (status != APR_SUCCESS)
-		{
-			throw SocketException(status);
-		}
-
-		socket = 0;
-	}
-}
-
 InetAddressPtr Socket::getInetAddress() const
 {
-	return address;
+	return m_priv->address;
 }
 
 int Socket::getPort() const
 {
-	return port;
+	return m_priv->port;
+}
+
+SocketUniquePtr Socket::create(InetAddressPtr& address, int port){
+	return std::make_unique<APRSocket>(address, port);
 }
 
 
diff --git a/src/main/cpp/socketappenderskeleton.cpp b/src/main/cpp/socketappenderskeleton.cpp
index de79bd8a..03d87cc1 100644
--- a/src/main/cpp/socketappenderskeleton.cpp
+++ b/src/main/cpp/socketappenderskeleton.cpp
@@ -89,7 +89,7 @@ void SocketAppenderSkeleton::connect(Pool& p)
 
 		try
 		{
-			SocketPtr socket(new Socket(_priv->address, _priv->port));
+			SocketPtr socket = Socket::create(_priv->address, _priv->port);
 			setSocket(socket, p);
 		}
 		catch (SocketException& e)
@@ -157,7 +157,7 @@ void SocketAppenderSkeleton::monitor()
 			{
 				LogLog::debug(LogString(LOG4CXX_STR("Attempting connection to "))
 					+ _priv->address->getHostName());
-				socket = SocketPtr(new Socket(_priv->address, _priv->port));
+				socket = Socket::create(_priv->address, _priv->port);
 				Pool p;
 				setSocket(socket, p);
 				LogLog::debug(LOG4CXX_STR("Connection established. Exiting connector thread."));
diff --git a/src/main/cpp/sockethubappender.cpp b/src/main/cpp/sockethubappender.cpp
index 86613bbe..ca84f168 100644
--- a/src/main/cpp/sockethubappender.cpp
+++ b/src/main/cpp/sockethubappender.cpp
@@ -201,17 +201,16 @@ void SocketHubAppender::startServer()
 
 void SocketHubAppender::monitor()
 {
-	ServerSocket* serverSocket = 0;
+	ServerSocketUniquePtr serverSocket = 0;
 
 	try
 	{
-		serverSocket = new ServerSocket(_priv->port);
+		serverSocket = ServerSocket::create(_priv->port);
 		serverSocket->setSoTimeout(1000);
 	}
 	catch (SocketException& e)
 	{
 		LogLog::error(LOG4CXX_STR("exception setting timeout, shutting down server socket."), e);
-		delete serverSocket;
 		return;
 	}
 
@@ -266,8 +265,6 @@ void SocketHubAppender::monitor()
 
 		stopRunning = (stopRunning || _priv->closed);
 	}
-
-	delete serverSocket;
 }
 
 void SocketHubAppender::setPort(int port1)
diff --git a/src/main/cpp/telnetappender.cpp b/src/main/cpp/telnetappender.cpp
index 9a2e8ee5..0c72a809 100644
--- a/src/main/cpp/telnetappender.cpp
+++ b/src/main/cpp/telnetappender.cpp
@@ -75,7 +75,7 @@ void TelnetAppender::activateOptions(Pool& /* p */)
 {
 	if (_priv->serverSocket == NULL)
 	{
-		_priv->serverSocket = std::make_unique<ServerSocket>(_priv->port);
+		_priv->serverSocket = ServerSocket::create(_priv->port);
 		_priv->serverSocket->setSoTimeout(1000);
 	}
 
diff --git a/src/main/include/CMakeLists.txt b/src/main/include/CMakeLists.txt
index e31443fb..576701f7 100644
--- a/src/main/include/CMakeLists.txt
+++ b/src/main/include/CMakeLists.txt
@@ -58,6 +58,12 @@ foreach(varName WCHAR_T  UNICHAR  CFSTRING )
   endif()
 endforeach()
 
+option(NETWORKING_SUPPORT "Support logging over a network socket" ON)
+if(NETWORKING_SUPPORT)
+    set(NETWORKING_SUPPORT 1)
+else()
+    set(NETWORKING_SUPPORT 0)
+endif()
 
 # Configure log4cxx_private.h
 set(LOG4CXX_CHARSET "locale" CACHE STRING "LogString characters, choice of locale (default), utf-8, ISO-8859-1, US-ASCII, EBCDIC")
diff --git a/src/main/include/log4cxx/helpers/serversocket.h b/src/main/include/log4cxx/helpers/serversocket.h
index 7da75b96..b6cc51d7 100644
--- a/src/main/include/log4cxx/helpers/serversocket.h
+++ b/src/main/include/log4cxx/helpers/serversocket.h
@@ -21,27 +21,35 @@
 #include <log4cxx/helpers/socket.h>
 #include <mutex>
 
+struct apr_socket_t;
+
 namespace log4cxx
 {
 namespace helpers
 {
+
+class ServerSocket;
+LOG4CXX_PTR_DEF(ServerSocket);
+LOG4CXX_UNIQUE_PTR_DEF(ServerSocket);
+
 class LOG4CXX_EXPORT ServerSocket
 {
+	protected:
+		struct ServerSocketPrivate;
+		ServerSocket(std::unique_ptr<ServerSocketPrivate> priv);
+
 	public:
-		/**  Creates a server socket on a specified port.
-		*/
-		ServerSocket(int port);
 
 		virtual ~ServerSocket();
 
 		/** Listens for a connection to be made to this socket and
 		accepts it
 		*/
-		SocketPtr accept();
+		virtual SocketPtr accept() = 0;
 
 		/** Closes this socket.
 		*/
-		void close();
+		virtual void close();
 
 		/** Retrive setting for SO_TIMEOUT.
 		*/
@@ -51,11 +59,10 @@ class LOG4CXX_EXPORT ServerSocket
 		*/
 		void setSoTimeout(int timeout);
 
-	private:
-		Pool pool;
-		std::mutex mutex;
-		apr_socket_t* socket;
-		int timeout;
+		static ServerSocketUniquePtr create(int port);
+
+	protected:
+		std::unique_ptr<ServerSocketPrivate> m_priv;
 
 };
 }  // namespace helpers
diff --git a/src/main/include/log4cxx/helpers/socket.h b/src/main/include/log4cxx/helpers/socket.h
index 9284490b..fd7cadd4 100644
--- a/src/main/include/log4cxx/helpers/socket.h
+++ b/src/main/include/log4cxx/helpers/socket.h
@@ -18,11 +18,6 @@
 #ifndef _LOG4CXX_HELPERS_SOCKET_H
 #define _LOG4CXX_HELPERS_SOCKET_H
 
-extern "C" {
-	struct apr_socket_t;
-}
-
-
 #include <log4cxx/helpers/inetaddress.h>
 #include <log4cxx/helpers/pool.h>
 
@@ -32,6 +27,11 @@ namespace log4cxx
 namespace helpers
 {
 class ByteBuffer;
+
+class Socket;
+LOG4CXX_PTR_DEF(Socket);
+LOG4CXX_UNIQUE_PTR_DEF(Socket);
+
 /**
 <p>This class implements client sockets (also called just "sockets"). A socket
 is an endpoint for communication between two machines.
@@ -42,48 +42,40 @@ local firewall.
 */
 class LOG4CXX_EXPORT Socket : public helpers::Object
 {
+	protected:
+		struct SocketPrivate;
+
+		Socket(std::unique_ptr<SocketPrivate>);
+
 	public:
 		DECLARE_ABSTRACT_LOG4CXX_OBJECT(Socket)
 		BEGIN_LOG4CXX_CAST_MAP()
 		LOG4CXX_CAST_ENTRY(Socket)
 		END_LOG4CXX_CAST_MAP()
 
-		/** Creates a stream socket and connects it to the specified port
-		number at the specified IP address.
-		*/
-		Socket(InetAddressPtr& address, int port);
-		Socket(apr_socket_t* socket, apr_pool_t* pool);
-		~Socket();
+		virtual ~Socket();
 
-		size_t write(ByteBuffer&);
+		virtual size_t write(ByteBuffer&) = 0;
 
 		/** Closes this socket. */
-		void close();
+		virtual void close() = 0;
 
 		/** Returns the value of this socket's address field. */
 		InetAddressPtr getInetAddress() const;
 
 		/** Returns the value of this socket's port field. */
 		int getPort() const;
+
+		static SocketUniquePtr create(InetAddressPtr& address, int port);
+
 	private:
 		Socket(const Socket&);
 		Socket& operator=(const Socket&);
 
-		Pool pool;
-
-		apr_socket_t* socket;
-
-
-		/** The IP address of the remote end of this socket. */
-		InetAddressPtr address;
-
-		/** The port number on the remote host to which
-		this socket is connected. */
-		int port;
+	protected:
+		std::unique_ptr<SocketPrivate> m_priv;
 };
 
-LOG4CXX_PTR_DEF(Socket);
-
 } // namespace helpers
 } // namespace log4cxx
 
diff --git a/src/main/include/log4cxx/log4cxx.h.in b/src/main/include/log4cxx/log4cxx.h.in
index c97869cc..e350d831 100644
--- a/src/main/include/log4cxx/log4cxx.h.in
+++ b/src/main/include/log4cxx/log4cxx.h.in
@@ -48,7 +48,7 @@
 #define LOG4CXX_WCHAR_T_API @WCHAR_T_API@
 #define LOG4CXX_UNICHAR_API @UNICHAR_API@
 #define LOG4CXX_CFSTRING_API @CFSTRING_API@
-
+#define LOG4CXX_HAS_NETWORKING @NETWORKING_SUPPORT@
 
 typedef long long log4cxx_int64_t;
 #define LOG4CXX_USE_GLOBAL_SCOPE_TEMPLATE 0
@@ -62,6 +62,7 @@ typedef unsigned int log4cxx_uint32_t;
 
 #define LOG4CXX_PTR_DEF(T) typedef std::shared_ptr<T> T##Ptr;\
 	typedef std::weak_ptr<T> T##WeakPtr
+#define LOG4CXX_UNIQUE_PTR_DEF(T) typedef std::unique_ptr<T> T##UniquePtr;
 #define LOG4CXX_LIST_DEF(N, T) typedef std::vector<T> N
 
 #if _WIN32
diff --git a/src/main/include/log4cxx/helpers/serversocket.h b/src/main/include/log4cxx/private/aprserversocket.h
similarity index 52%
copy from src/main/include/log4cxx/helpers/serversocket.h
copy to src/main/include/log4cxx/private/aprserversocket.h
index 7da75b96..b05aba91 100644
--- a/src/main/include/log4cxx/helpers/serversocket.h
+++ b/src/main/include/log4cxx/private/aprserversocket.h
@@ -15,50 +15,33 @@
  * limitations under the License.
  */
 
-#ifndef _LOG4CXX_HELPERS_SERVER_SOCKET_H
-#define _LOG4CXX_HELPERS_SERVER_SOCKET_H
+#ifndef LOG4CXX_HELPERS_APRSERVERSOCKET_H
+#define LOG4CXX_HELPERS_APRSERVERSOCKET_H
 
-#include <log4cxx/helpers/socket.h>
-#include <mutex>
+#include <log4cxx/helpers/serversocket.h>
 
 namespace log4cxx
 {
 namespace helpers
 {
-class LOG4CXX_EXPORT ServerSocket
-{
-	public:
-		/**  Creates a server socket on a specified port.
-		*/
-		ServerSocket(int port);
-
-		virtual ~ServerSocket();
 
-		/** Listens for a connection to be made to this socket and
-		accepts it
-		*/
-		SocketPtr accept();
-
-		/** Closes this socket.
-		*/
-		void close();
+/**
+ * A ServerSocket that uses APR as the network implementation
+ */
+class LOG4CXX_EXPORT APRServerSocket : public helpers::ServerSocket
+{
+        public:
+            APRServerSocket(int port);
 
-		/** Retrive setting for SO_TIMEOUT.
-		*/
-		int getSoTimeout() const;
+	    void close();
 
-		/** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
-		*/
-		void setSoTimeout(int timeout);
+	    SocketPtr accept();
 
 	private:
-		Pool pool;
-		std::mutex mutex;
-		apr_socket_t* socket;
-		int timeout;
-
+		struct APRServerSocketPriv;
 };
-}  // namespace helpers
-} // namespace log4cxx
 
-#endif //_LOG4CXX_HELPERS_SERVER_SOCKET_H
+}
+}
+
+#endif /* LOG4CXX_HELPERS_APRSERVERSOCKET_H */
diff --git a/src/main/include/log4cxx/helpers/serversocket.h b/src/main/include/log4cxx/private/aprsocket.h
similarity index 55%
copy from src/main/include/log4cxx/helpers/serversocket.h
copy to src/main/include/log4cxx/private/aprsocket.h
index 7da75b96..5869a756 100644
--- a/src/main/include/log4cxx/helpers/serversocket.h
+++ b/src/main/include/log4cxx/private/aprsocket.h
@@ -15,50 +15,37 @@
  * limitations under the License.
  */
 
-#ifndef _LOG4CXX_HELPERS_SERVER_SOCKET_H
-#define _LOG4CXX_HELPERS_SERVER_SOCKET_H
+#ifndef LOG4CXX_HELPERS_APRSOCKET_H
+#define LOG4CXX_HELPERS_APRSOCKET_H
 
 #include <log4cxx/helpers/socket.h>
-#include <mutex>
+
+struct apr_socket_t;
 
 namespace log4cxx
 {
 namespace helpers
 {
-class LOG4CXX_EXPORT ServerSocket
+
+class LOG4CXX_EXPORT APRSocket : public helpers::Socket
 {
 	public:
-		/**  Creates a server socket on a specified port.
+		/** Creates a stream socket and connects it to the specified port
+		number at the specified IP address.
 		*/
-		ServerSocket(int port);
-
-		virtual ~ServerSocket();
+		APRSocket(InetAddressPtr& address, int port);
+		APRSocket(apr_socket_t*, apr_pool_t* pool);
 
-		/** Listens for a connection to be made to this socket and
-		accepts it
-		*/
-		SocketPtr accept();
+		virtual size_t write(ByteBuffer&);
 
-		/** Closes this socket.
-		*/
-		void close();
-
-		/** Retrive setting for SO_TIMEOUT.
-		*/
-		int getSoTimeout() const;
-
-		/** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
-		*/
-		void setSoTimeout(int timeout);
+		/** Closes this socket. */
+		virtual void close();
 
 	private:
-		Pool pool;
-		std::mutex mutex;
-		apr_socket_t* socket;
-		int timeout;
-
+		struct APRSocketPriv;
 };
-}  // namespace helpers
-} // namespace log4cxx
 
-#endif //_LOG4CXX_HELPERS_SERVER_SOCKET_H
+}
+}
+
+#endif /* LOG4CXX_HELPERS_APRSOCKET_H */
diff --git a/src/main/include/log4cxx/helpers/serversocket.h b/src/main/include/log4cxx/private/serversocket_priv.h
similarity index 51%
copy from src/main/include/log4cxx/helpers/serversocket.h
copy to src/main/include/log4cxx/private/serversocket_priv.h
index 7da75b96..0d3b021d 100644
--- a/src/main/include/log4cxx/helpers/serversocket.h
+++ b/src/main/include/log4cxx/private/serversocket_priv.h
@@ -15,50 +15,24 @@
  * limitations under the License.
  */
 
-#ifndef _LOG4CXX_HELPERS_SERVER_SOCKET_H
-#define _LOG4CXX_HELPERS_SERVER_SOCKET_H
+#ifndef LOG4CXX_HELPERS_SERVERSOCKET_PRIV_H
+#define LOG4CXX_HELPERS_SERVERSOCKET_PRIV_H
 
-#include <log4cxx/helpers/socket.h>
-#include <mutex>
+#include <log4cxx/helpers/serversocket.h>
 
 namespace log4cxx
 {
 namespace helpers
 {
-class LOG4CXX_EXPORT ServerSocket
-{
-	public:
-		/**  Creates a server socket on a specified port.
-		*/
-		ServerSocket(int port);
-
-		virtual ~ServerSocket();
-
-		/** Listens for a connection to be made to this socket and
-		accepts it
-		*/
-		SocketPtr accept();
-
-		/** Closes this socket.
-		*/
-		void close();
 
-		/** Retrive setting for SO_TIMEOUT.
-		*/
-		int getSoTimeout() const;
-
-		/** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
-		*/
-		void setSoTimeout(int timeout);
-
-	private:
-		Pool pool;
-		std::mutex mutex;
-		apr_socket_t* socket;
-		int timeout;
+struct ServerSocket::ServerSocketPrivate{
+    ServerSocketPrivate() :
+        timeout(0){}
 
+    int timeout;
 };
-}  // namespace helpers
-} // namespace log4cxx
 
-#endif //_LOG4CXX_HELPERS_SERVER_SOCKET_H
+}
+}
+
+#endif /* LOG4CXX_HELPERS_SERVERSOCKET_PRIV_H */
diff --git a/src/main/include/log4cxx/helpers/serversocket.h b/src/main/include/log4cxx/private/socket_priv.h
similarity index 53%
copy from src/main/include/log4cxx/helpers/serversocket.h
copy to src/main/include/log4cxx/private/socket_priv.h
index 7da75b96..fcc09bf7 100644
--- a/src/main/include/log4cxx/helpers/serversocket.h
+++ b/src/main/include/log4cxx/private/socket_priv.h
@@ -15,50 +15,26 @@
  * limitations under the License.
  */
 
-#ifndef _LOG4CXX_HELPERS_SERVER_SOCKET_H
-#define _LOG4CXX_HELPERS_SERVER_SOCKET_H
+#ifndef LOG4CXX_HELPERS_SOCKET_PRIV_H
+#define LOG4CXX_HELPERS_SOCKET_PRIV_H
 
 #include <log4cxx/helpers/socket.h>
-#include <mutex>
 
 namespace log4cxx
 {
 namespace helpers
 {
-class LOG4CXX_EXPORT ServerSocket
-{
-	public:
-		/**  Creates a server socket on a specified port.
-		*/
-		ServerSocket(int port);
-
-		virtual ~ServerSocket();
-
-		/** Listens for a connection to be made to this socket and
-		accepts it
-		*/
-		SocketPtr accept();
-
-		/** Closes this socket.
-		*/
-		void close();
 
-		/** Retrive setting for SO_TIMEOUT.
-		*/
-		int getSoTimeout() const;
-
-		/** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
-		*/
-		void setSoTimeout(int timeout);
-
-	private:
-		Pool pool;
-		std::mutex mutex;
-		apr_socket_t* socket;
-		int timeout;
+struct Socket::SocketPrivate{
+    /** The IP address of the remote end of this socket. */
+    InetAddressPtr address;
 
+    /** The port number on the remote host to which
+    this socket is connected. */
+    int port;
 };
-}  // namespace helpers
-} // namespace log4cxx
 
-#endif //_LOG4CXX_HELPERS_SERVER_SOCKET_H
+}
+}
+
+#endif /* LOG4CXX_HELPERS_SOCKET_PRIV_H */