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:12 UTC

[logging-log4cxx] 03/04: Make the datagram socket abstract

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 a845d5101c74fa28e37f12b6b4b0aabd6751652b
Author: Robert Middleton <ro...@rm5248.com>
AuthorDate: Sat Aug 13 16:01:16 2022 -0400

    Make the datagram socket abstract
---
 src/main/cpp/CMakeLists.txt                        |   5 +-
 .../{datagramsocket.cpp => aprdatagramsocket.cpp}  | 265 ++++++++-------------
 src/main/cpp/datagramsocket.cpp                    | 224 ++---------------
 src/main/cpp/syslogwriter.cpp                      |   2 +-
 src/main/include/log4cxx/helpers/datagramsocket.h  |  57 +++--
 .../include/log4cxx/private/aprdatagramsocket.h    |  59 +++++
 .../include/log4cxx/private/datagramsocket_priv.h  |  58 +++++
 7 files changed, 275 insertions(+), 395 deletions(-)

diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index 0f71bf66..e8f8d905 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -51,8 +51,9 @@ target_sources(log4cxx
   configurator.cpp
   consoleappender.cpp
   cyclicbuffer.cpp
-  datagrampacket.cpp
-  datagramsocket.cpp
+  $<IF:$<BOOL:NETWORKING_SUPPORT>,datagrampacket.cpp,>
+  $<IF:$<BOOL:NETWORKING_SUPPORT>,datagramsocket.cpp,>
+  $<IF:$<BOOL:NETWORKING_SUPPORT>,aprdatagramsocket.cpp,>
   date.cpp
   dateformat.cpp
   datepatternconverter.cpp
diff --git a/src/main/cpp/datagramsocket.cpp b/src/main/cpp/aprdatagramsocket.cpp
similarity index 53%
copy from src/main/cpp/datagramsocket.cpp
copy to src/main/cpp/aprdatagramsocket.cpp
index 0aa46ff9..3ace8528 100644
--- a/src/main/cpp/datagramsocket.cpp
+++ b/src/main/cpp/aprdatagramsocket.cpp
@@ -14,168 +14,60 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <log4cxx/logstring.h>
-#include <log4cxx/helpers/datagramsocket.h>
-#include <log4cxx/helpers/datagrampacket.h>
-#include <log4cxx/helpers/loglog.h>
-#include <log4cxx/helpers/transcoder.h>
 
-#include "apr_network_io.h"
-#include "apr_lib.h"
+#include <log4cxx/private/aprdatagramsocket.h>
+#include <log4cxx/private/datagramsocket_priv.h>
+#include <apr_network_io.h>
 
-using namespace log4cxx::helpers;
+using log4cxx::helpers::APRDatagramSocket;
 
-struct DatagramSocket::DatagramSocketPriv
-{
-	DatagramSocketPriv()
-		: socket(0), address(), localAddress(), port(0), localPort(0)
-	{
-	}
+#define _priv static_cast<APRDatagramSocketPriv*>(m_priv.get())
 
-	DatagramSocketPriv(int localPort1)
-		: socket(0), address(), localAddress(), port(0), localPort(0)
-	{
-	}
+struct APRDatagramSocket::APRDatagramSocketPriv : public DatagramSocketPriv {
+	APRDatagramSocketPriv() :
+		DatagramSocketPriv(),
+		socket(nullptr)
+	{}
 
-	DatagramSocketPriv(int localPort1, InetAddressPtr localAddress1)
-		: socket(0), address(), localAddress(), port(0), localPort(0)
-	{
-	}
+	APRDatagramSocketPriv(int port) :
+		DatagramSocketPriv(port),
+		socket(nullptr)
+	{}
+
+	APRDatagramSocketPriv(int port, InetAddressPtr localAddress) :
+		DatagramSocketPriv(port, localAddress),
+		socket(nullptr)
+	{}
 
 	/** The APR socket */
 	apr_socket_t* socket;
 
 	/** The memory pool for the socket */
 	Pool socketPool;
-
-	InetAddressPtr address;
-
-	InetAddressPtr localAddress;
-
-	int port;
-
-	/** The local port number to which this socket is connected. */
-	int localPort;
 };
 
-IMPLEMENT_LOG4CXX_OBJECT(DatagramSocket)
-
-DatagramSocket::DatagramSocket()
-	: m_priv(std::make_unique<DatagramSocketPriv>())
-{
-	create();
-}
-
-DatagramSocket::DatagramSocket(int localPort1)
-	: m_priv(std::make_unique<DatagramSocketPriv>(localPort1))
-{
-	InetAddressPtr bindAddr = InetAddress::anyAddress();
-
-	create();
-	bind(localPort1, bindAddr);
-}
-
-DatagramSocket::DatagramSocket(int localPort1, InetAddressPtr localAddress1)
-	: m_priv(std::make_unique<DatagramSocketPriv>(localPort1, localAddress1))
-{
-	create();
-	bind(localPort1, localAddress1);
-}
-
-DatagramSocket::~DatagramSocket()
-{
-	try
-	{
-		close();
-	}
-	catch (SocketException&)
-	{
-	}
-}
-
-/**  Binds a datagram socket to a local port and address.*/
-void DatagramSocket::bind(int localPort1, InetAddressPtr localAddress1)
-{
-	Pool addrPool;
-
-	// Create server socket address (including port number)
-	LOG4CXX_ENCODE_CHAR(hostAddr, localAddress1->getHostAddress());
-	apr_sockaddr_t* server_addr;
-	apr_status_t status =
-		apr_sockaddr_info_get(&server_addr, hostAddr.c_str(), APR_INET,
-			localPort1, 0, addrPool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw BindException(status);
-	}
-
-	// bind the socket to the address
-	status = apr_socket_bind(m_priv->socket, server_addr);
-
-	if (status != APR_SUCCESS)
-	{
-		throw BindException(status);
-	}
-
-	m_priv->localPort = localPort1;
-	m_priv->localAddress = localAddress1;
+APRDatagramSocket::APRDatagramSocket() :
+	DatagramSocket(std::make_unique<APRDatagramSocketPriv>()){
+	init();
 }
 
-/** Close the socket.*/
-void DatagramSocket::close()
-{
-	if (m_priv->socket != 0)
-	{
-		apr_status_t status = apr_socket_close(m_priv->socket);
-
-		if (status != APR_SUCCESS)
-		{
-			throw SocketException(status);
-		}
-
-		m_priv->socket = 0;
-		m_priv->localPort = 0;
-	}
+APRDatagramSocket::APRDatagramSocket(int port) :
+	DatagramSocket(std::make_unique<APRDatagramSocketPriv>(port)){
+	init();
 }
 
-void DatagramSocket::connect(InetAddressPtr address1, int port1)
-{
-
-	m_priv->address = address1;
-	m_priv->port = port1;
-
-	Pool addrPool;
-
-	// create socket address
-	LOG4CXX_ENCODE_CHAR(hostAddr, address1->getHostAddress());
-	apr_sockaddr_t* client_addr;
-	apr_status_t status =
-		apr_sockaddr_info_get(&client_addr, hostAddr.c_str(), APR_INET,
-			m_priv->port, 0, addrPool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw ConnectException(status);
-	}
-
-	// connect the socket
-	status = apr_socket_connect(m_priv->socket, client_addr);
-
-	if (status != APR_SUCCESS)
-	{
-		throw ConnectException(status);
-	}
+APRDatagramSocket::APRDatagramSocket(int port, InetAddressPtr laddr) :
+	DatagramSocket(std::make_unique<APRDatagramSocketPriv>(port, laddr)){
+	init();
 }
 
-/** Creates a datagram socket.*/
-void DatagramSocket::create()
+void APRDatagramSocket::init()
 {
 	apr_socket_t* newSocket;
 	apr_status_t status =
 		apr_socket_create(&newSocket, APR_INET, SOCK_DGRAM,
-			APR_PROTO_UDP, m_priv->socketPool.getAPRPool());
-	m_priv->socket = newSocket;
+			APR_PROTO_UDP, _priv->socketPool.getAPRPool());
+	_priv->socket = newSocket;
 
 	if (status != APR_SUCCESS)
 	{
@@ -183,8 +75,7 @@ void DatagramSocket::create()
 	}
 }
 
-/** Receive the datagram packet.*/
-void DatagramSocket::receive(DatagramPacketPtr& p)
+void APRDatagramSocket::receive(DatagramPacketPtr& p)
 {
 	Pool addrPool;
 
@@ -202,7 +93,7 @@ void DatagramSocket::receive(DatagramPacketPtr& p)
 
 	// receive the datagram packet
 	apr_size_t len = p->getLength();
-	status = apr_socket_recvfrom(addr, m_priv->socket, 0,
+	status = apr_socket_recvfrom(addr, _priv->socket, 0,
 			(char*)p->getData(), &len);
 
 	if (status != APR_SUCCESS)
@@ -211,8 +102,7 @@ void DatagramSocket::receive(DatagramPacketPtr& p)
 	}
 }
 
-/**  Sends a datagram packet.*/
-void DatagramSocket::send(DatagramPacketPtr& p)
+void APRDatagramSocket::send(DatagramPacketPtr& p)
 {
 	Pool addrPool;
 
@@ -230,7 +120,7 @@ void DatagramSocket::send(DatagramPacketPtr& p)
 
 	// send the datagram packet
 	apr_size_t len = p->getLength();
-	status = apr_socket_sendto(m_priv->socket, addr, 0,
+	status = apr_socket_sendto(_priv->socket, addr, 0,
 			(char*)p->getData(), &len);
 
 	if (status != APR_SUCCESS)
@@ -239,37 +129,80 @@ void DatagramSocket::send(DatagramPacketPtr& p)
 	}
 }
 
-InetAddressPtr DatagramSocket::getInetAddress() const
-{
-	return m_priv->address;
-}
+void APRDatagramSocket::close(){
+	if (_priv->socket != 0)
+	{
+		apr_status_t status = apr_socket_close(_priv->socket);
 
-InetAddressPtr DatagramSocket::getLocalAddress() const
-{
-	return m_priv->localAddress;
-}
+		if (status != APR_SUCCESS)
+		{
+			throw SocketException(status);
+		}
 
-int DatagramSocket::getLocalPort() const
-{
-	return m_priv->localPort;
+		_priv->socket = 0;
+		_priv->localPort = 0;
+	}
 }
 
-int DatagramSocket::getPort() const
+void APRDatagramSocket::bind(int localPort1, InetAddressPtr localAddress1)
 {
-	return m_priv->port;
-}
+	Pool addrPool;
 
-bool DatagramSocket::isBound() const
-{
-	return m_priv->localPort != 0;
+	// Create server socket address (including port number)
+	LOG4CXX_ENCODE_CHAR(hostAddr, localAddress1->getHostAddress());
+	apr_sockaddr_t* server_addr;
+	apr_status_t status =
+		apr_sockaddr_info_get(&server_addr, hostAddr.c_str(), APR_INET,
+			localPort1, 0, addrPool.getAPRPool());
+
+	if (status != APR_SUCCESS)
+	{
+		throw BindException(status);
+	}
+
+	// bind the socket to the address
+	status = apr_socket_bind(_priv->socket, server_addr);
+
+	if (status != APR_SUCCESS)
+	{
+		throw BindException(status);
+	}
+
+	m_priv->localPort = localPort1;
+	m_priv->localAddress = localAddress1;
 }
 
-bool DatagramSocket::isClosed() const
+
+void APRDatagramSocket::connect(InetAddressPtr address1, int port1)
 {
-	return m_priv->socket != 0;
+	m_priv->address = address1;
+	m_priv->port = port1;
+
+	Pool addrPool;
+
+	// create socket address
+	LOG4CXX_ENCODE_CHAR(hostAddr, address1->getHostAddress());
+	apr_sockaddr_t* client_addr;
+	apr_status_t status =
+		apr_sockaddr_info_get(&client_addr, hostAddr.c_str(), APR_INET,
+			m_priv->port, 0, addrPool.getAPRPool());
+
+	if (status != APR_SUCCESS)
+	{
+		throw ConnectException(status);
+	}
+
+	// connect the socket
+	status = apr_socket_connect(_priv->socket, client_addr);
+
+	if (status != APR_SUCCESS)
+	{
+		throw ConnectException(status);
+	}
 }
 
-bool DatagramSocket::isConnected() const
+
+bool APRDatagramSocket::isClosed() const
 {
-	return m_priv->port != 0;
+	return _priv->socket != nullptr;
 }
diff --git a/src/main/cpp/datagramsocket.cpp b/src/main/cpp/datagramsocket.cpp
index 0aa46ff9..ac71ecbe 100644
--- a/src/main/cpp/datagramsocket.cpp
+++ b/src/main/cpp/datagramsocket.cpp
@@ -19,68 +19,19 @@
 #include <log4cxx/helpers/datagrampacket.h>
 #include <log4cxx/helpers/loglog.h>
 #include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/private/datagramsocket_priv.h>
+#include <log4cxx/private/aprdatagramsocket.h>
 
 #include "apr_network_io.h"
 #include "apr_lib.h"
 
 using namespace log4cxx::helpers;
 
-struct DatagramSocket::DatagramSocketPriv
-{
-	DatagramSocketPriv()
-		: socket(0), address(), localAddress(), port(0), localPort(0)
-	{
-	}
-
-	DatagramSocketPriv(int localPort1)
-		: socket(0), address(), localAddress(), port(0), localPort(0)
-	{
-	}
-
-	DatagramSocketPriv(int localPort1, InetAddressPtr localAddress1)
-		: socket(0), address(), localAddress(), port(0), localPort(0)
-	{
-	}
-
-	/** The APR socket */
-	apr_socket_t* socket;
-
-	/** The memory pool for the socket */
-	Pool socketPool;
-
-	InetAddressPtr address;
-
-	InetAddressPtr localAddress;
-
-	int port;
-
-	/** The local port number to which this socket is connected. */
-	int localPort;
-};
-
 IMPLEMENT_LOG4CXX_OBJECT(DatagramSocket)
 
-DatagramSocket::DatagramSocket()
-	: m_priv(std::make_unique<DatagramSocketPriv>())
-{
-	create();
-}
-
-DatagramSocket::DatagramSocket(int localPort1)
-	: m_priv(std::make_unique<DatagramSocketPriv>(localPort1))
-{
-	InetAddressPtr bindAddr = InetAddress::anyAddress();
-
-	create();
-	bind(localPort1, bindAddr);
-}
-
-DatagramSocket::DatagramSocket(int localPort1, InetAddressPtr localAddress1)
-	: m_priv(std::make_unique<DatagramSocketPriv>(localPort1, localAddress1))
-{
-	create();
-	bind(localPort1, localAddress1);
-}
+DatagramSocket::DatagramSocket(std::unique_ptr<DatagramSocketPriv> priv) :
+	m_priv(std::move(priv))
+{}
 
 DatagramSocket::~DatagramSocket()
 {
@@ -93,150 +44,9 @@ DatagramSocket::~DatagramSocket()
 	}
 }
 
-/**  Binds a datagram socket to a local port and address.*/
-void DatagramSocket::bind(int localPort1, InetAddressPtr localAddress1)
-{
-	Pool addrPool;
-
-	// Create server socket address (including port number)
-	LOG4CXX_ENCODE_CHAR(hostAddr, localAddress1->getHostAddress());
-	apr_sockaddr_t* server_addr;
-	apr_status_t status =
-		apr_sockaddr_info_get(&server_addr, hostAddr.c_str(), APR_INET,
-			localPort1, 0, addrPool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw BindException(status);
-	}
-
-	// bind the socket to the address
-	status = apr_socket_bind(m_priv->socket, server_addr);
-
-	if (status != APR_SUCCESS)
-	{
-		throw BindException(status);
-	}
-
-	m_priv->localPort = localPort1;
-	m_priv->localAddress = localAddress1;
-}
-
 /** Close the socket.*/
 void DatagramSocket::close()
 {
-	if (m_priv->socket != 0)
-	{
-		apr_status_t status = apr_socket_close(m_priv->socket);
-
-		if (status != APR_SUCCESS)
-		{
-			throw SocketException(status);
-		}
-
-		m_priv->socket = 0;
-		m_priv->localPort = 0;
-	}
-}
-
-void DatagramSocket::connect(InetAddressPtr address1, int port1)
-{
-
-	m_priv->address = address1;
-	m_priv->port = port1;
-
-	Pool addrPool;
-
-	// create socket address
-	LOG4CXX_ENCODE_CHAR(hostAddr, address1->getHostAddress());
-	apr_sockaddr_t* client_addr;
-	apr_status_t status =
-		apr_sockaddr_info_get(&client_addr, hostAddr.c_str(), APR_INET,
-			m_priv->port, 0, addrPool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw ConnectException(status);
-	}
-
-	// connect the socket
-	status = apr_socket_connect(m_priv->socket, client_addr);
-
-	if (status != APR_SUCCESS)
-	{
-		throw ConnectException(status);
-	}
-}
-
-/** Creates a datagram socket.*/
-void DatagramSocket::create()
-{
-	apr_socket_t* newSocket;
-	apr_status_t status =
-		apr_socket_create(&newSocket, APR_INET, SOCK_DGRAM,
-			APR_PROTO_UDP, m_priv->socketPool.getAPRPool());
-	m_priv->socket = newSocket;
-
-	if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
-}
-
-/** Receive the datagram packet.*/
-void DatagramSocket::receive(DatagramPacketPtr& p)
-{
-	Pool addrPool;
-
-	// Create the address from which to receive the datagram packet
-	LOG4CXX_ENCODE_CHAR(hostAddr, p->getAddress()->getHostAddress());
-	apr_sockaddr_t* addr;
-	apr_status_t status =
-		apr_sockaddr_info_get(&addr, hostAddr.c_str(), APR_INET,
-			p->getPort(), 0, addrPool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
-
-	// receive the datagram packet
-	apr_size_t len = p->getLength();
-	status = apr_socket_recvfrom(addr, m_priv->socket, 0,
-			(char*)p->getData(), &len);
-
-	if (status != APR_SUCCESS)
-	{
-		throw IOException(status);
-	}
-}
-
-/**  Sends a datagram packet.*/
-void DatagramSocket::send(DatagramPacketPtr& p)
-{
-	Pool addrPool;
-
-	// create the adress to which to send the datagram packet
-	LOG4CXX_ENCODE_CHAR(hostAddr, p->getAddress()->getHostAddress());
-	apr_sockaddr_t* addr;
-	apr_status_t status =
-		apr_sockaddr_info_get(&addr, hostAddr.c_str(), APR_INET, p->getPort(),
-			0, addrPool.getAPRPool());
-
-	if (status != APR_SUCCESS)
-	{
-		throw SocketException(status);
-	}
-
-	// send the datagram packet
-	apr_size_t len = p->getLength();
-	status = apr_socket_sendto(m_priv->socket, addr, 0,
-			(char*)p->getData(), &len);
-
-	if (status != APR_SUCCESS)
-	{
-		throw IOException(status);
-	}
 }
 
 InetAddressPtr DatagramSocket::getInetAddress() const
@@ -264,12 +74,26 @@ bool DatagramSocket::isBound() const
 	return m_priv->localPort != 0;
 }
 
-bool DatagramSocket::isClosed() const
-{
-	return m_priv->socket != 0;
-}
-
 bool DatagramSocket::isConnected() const
 {
 	return m_priv->port != 0;
 }
+
+DatagramSocketUniquePtr DatagramSocket::create(){
+	return std::make_unique<APRDatagramSocket>();
+}
+
+DatagramSocketUniquePtr DatagramSocket::create(int localPort1){
+	std::unique_ptr<APRDatagramSocket> sock = std::make_unique<APRDatagramSocket>();
+	InetAddressPtr bindAddr = InetAddress::anyAddress();
+
+	sock->bind(localPort1, bindAddr);
+	return sock;
+}
+
+DatagramSocketUniquePtr DatagramSocket::create(int localPort1, InetAddressPtr localAddress1){
+	std::unique_ptr<APRDatagramSocket> sock = std::make_unique<APRDatagramSocket>();
+
+	sock->bind(localPort1, localAddress1);
+	return sock;
+}
diff --git a/src/main/cpp/syslogwriter.cpp b/src/main/cpp/syslogwriter.cpp
index ad8c92e8..dde4ffa8 100644
--- a/src/main/cpp/syslogwriter.cpp
+++ b/src/main/cpp/syslogwriter.cpp
@@ -54,7 +54,7 @@ SyslogWriter::SyslogWriter(const LogString& syslogHost1, int syslogHostPort1)
 
 	try
 	{
-		m_priv->ds = DatagramSocketPtr(new DatagramSocket());
+		m_priv->ds = DatagramSocket::create();
 	}
 	catch (SocketException& e)
 	{
diff --git a/src/main/include/log4cxx/helpers/datagramsocket.h b/src/main/include/log4cxx/helpers/datagramsocket.h
index 04df8edb..cbfd29d2 100644
--- a/src/main/include/log4cxx/helpers/datagramsocket.h
+++ b/src/main/include/log4cxx/helpers/datagramsocket.h
@@ -27,42 +27,38 @@ namespace log4cxx
 {
 namespace helpers
 {
+
+class DatagramSocket;
+LOG4CXX_PTR_DEF(DatagramSocket);
+LOG4CXX_UNIQUE_PTR_DEF(DatagramSocket);
+
 /** This class represents a socket for sending and receiving
 datagram packets.*/
 class LOG4CXX_EXPORT DatagramSocket : public helpers::Object
 {
+	protected:
+		struct DatagramSocketPriv;
+		std::unique_ptr<DatagramSocketPriv> m_priv;
+
+		DatagramSocket(std::unique_ptr<DatagramSocketPriv> priv);
+
 	public:
 		DECLARE_ABSTRACT_LOG4CXX_OBJECT(DatagramSocket)
 		BEGIN_LOG4CXX_CAST_MAP()
 		LOG4CXX_CAST_ENTRY(DatagramSocket)
 		END_LOG4CXX_CAST_MAP()
 
-		/** Constructs a datagram socket and binds it to any available port
-		on the local host machine.*/
-		DatagramSocket();
-
-		/** Constructs a datagram socket and binds it to the specified
-		port on the local host machine. */
-		DatagramSocket(int port);
-
-		/**  Creates a datagram socket, bound to the specified local
-		address. */
-		DatagramSocket(int port, InetAddressPtr laddr);
-
 		/** ensure the socket is closed. */
-		~DatagramSocket();
+		virtual ~DatagramSocket();
 
 		/**  Binds a datagram socket to a local port and address.*/
-		void bind(int lport, InetAddressPtr laddress);
-
-		/** Creates a datagram socket.*/
-		void create();
+		virtual void bind(int lport, InetAddressPtr laddress) = 0;
 
 		/** Closes this datagram socket */
-		void close();
+		virtual void close();
 
 		/** Connects the socket to a remote address for this socket. */
-		void connect(InetAddressPtr address, int port);
+		virtual void connect(InetAddressPtr address, int port) = 0;
 
 		/** Returns the address to which this socket is connected. */
 		InetAddressPtr getInetAddress() const;
@@ -81,26 +77,35 @@ class LOG4CXX_EXPORT DatagramSocket : public helpers::Object
 		bool isBound() const;
 
 		/** Returns wether the socket is closed or not. */
-		bool isClosed() const;
+		virtual bool isClosed() const = 0;
 
 		/** Returns the connection state of the socket. */
 		bool isConnected() const;
 
 		/**  Receives a datagram packet from this socket. */
-		void receive(DatagramPacketPtr& p);
+		virtual void receive(DatagramPacketPtr& p) = 0;
 
 		/** Sends a datagram packet from this socket. */
-		void  send(DatagramPacketPtr& p);
+		virtual void  send(DatagramPacketPtr& p) = 0;
+
+		/** Constructs a datagram socket and binds it to any available port
+		on the local host machine.*/
+		static DatagramSocketUniquePtr create();
+
+		/** Constructs a datagram socket and binds it to the specified
+		port on the local host machine. */
+		static DatagramSocketUniquePtr create(int port);
+
+		/**  Creates a datagram socket, bound to the specified local
+		address. */
+		static DatagramSocketUniquePtr create(int port, InetAddressPtr laddr);
 
 	private:
 		DatagramSocket(const DatagramSocket&);
 		DatagramSocket& operator=(const DatagramSocket&);
 
-		struct DatagramSocketPriv;
-		std::unique_ptr<DatagramSocketPriv> m_priv;
-
 };
-LOG4CXX_PTR_DEF(DatagramSocket);
+
 }  // namespace helpers
 } // namespace log4cxx
 
diff --git a/src/main/include/log4cxx/private/aprdatagramsocket.h b/src/main/include/log4cxx/private/aprdatagramsocket.h
new file mode 100644
index 00000000..0f75cd0a
--- /dev/null
+++ b/src/main/include/log4cxx/private/aprdatagramsocket.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef LOG4CXX_HELPERS_APRDATAGRAM_SOCKET_H
+#define LOG4CXX_HELPERS_APRDATAGRAM_SOCKET_H
+
+#include <log4cxx/helpers/datagramsocket.h>
+
+namespace log4cxx
+{
+namespace helpers
+{
+
+class APRDatagramSocket : public DatagramSocket {
+    private:
+        struct APRDatagramSocketPriv;
+
+    public:
+	APRDatagramSocket();
+
+	APRDatagramSocket(int port);
+
+	APRDatagramSocket(int port, InetAddressPtr laddr);
+
+	virtual void bind(int lport, InetAddressPtr laddress);
+
+	virtual void close();
+
+	virtual bool isClosed() const;
+
+	/**  Receives a datagram packet from this socket. */
+	virtual void receive(DatagramPacketPtr& p);
+
+	/** Sends a datagram packet from this socket. */
+	virtual void  send(DatagramPacketPtr& p);
+
+	virtual void connect(InetAddressPtr address, int port);
+
+    private:
+	void init();
+};
+
+}
+}
+
+#endif /* LOG4CXX_HELPERS_APRDATAGRAM_SOCKET_H */
diff --git a/src/main/include/log4cxx/private/datagramsocket_priv.h b/src/main/include/log4cxx/private/datagramsocket_priv.h
new file mode 100644
index 00000000..1b4b4bb9
--- /dev/null
+++ b/src/main/include/log4cxx/private/datagramsocket_priv.h
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LOG4CXX_HELPERS_SOCKET_PRIV_H
+#define LOG4CXX_HELPERS_SOCKET_PRIV_H
+
+#include <log4cxx/helpers/datagramsocket.h>
+
+namespace log4cxx
+{
+namespace helpers
+{
+
+struct DatagramSocket::DatagramSocketPriv
+{
+        DatagramSocketPriv()
+	        : address(), localAddress(), port(0), localPort(0)
+	{
+	}
+
+	DatagramSocketPriv(int localPort1)
+	        : address(), localAddress(), port(0), localPort(0)
+	{
+	}
+
+	DatagramSocketPriv(int localPort1, InetAddressPtr localAddress1)
+	        : address(), localAddress(), port(0), localPort(0)
+	{
+	}
+
+	InetAddressPtr address;
+
+	InetAddressPtr localAddress;
+
+	int port;
+
+	/** The local port number to which this socket is connected. */
+	int localPort;
+};
+
+}
+}
+
+#endif /* LOG4CXX_HELPERS_SOCKET_PRIV_H */