Refactor UDP Socket to allow for Mocks
- Change platform/api/udp_socket to an abstract class
- Change platform/posix/udp_socket to an implementation of the abstract class
- Add platform/test/fake_udp_socket for testing
This fake_udp_socket class is needed for my upcoming Networking Pt 2 change
This change includes udp_socket changes from Networking Changes Pt 1 ongoing CL
to make merging the two easier, since this part of that CL seems to have
reached consensus.
Change-Id: Ia18671756d7457594b4fdceffef6c33e5fd4771a
Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/1680971
Commit-Queue: Ryan Keane <rwkeane@google.com>
Reviewed-by: mark a. foltz <mfoltz@chromium.org>
Reviewed-by: Max Yakimakha <yakimakha@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
diff --git a/platform/api/udp_socket.h b/platform/api/udp_socket.h
index 7c999c2..e648124 100644
--- a/platform/api/udp_socket.h
+++ b/platform/api/udp_socket.h
@@ -6,6 +6,7 @@
#define PLATFORM_API_UDP_SOCKET_H_
#include <cstdint>
+#include <functional>
#include <memory>
#include "osp_base/error.h"
@@ -18,13 +19,7 @@
class UdpSocket;
-// Platform-specific deleter of a UdpSocket instance returned by
-// UdpSocket::Create().
-struct UdpSocketDeleter {
- void operator()(UdpSocket* socket) const;
-};
-
-using UdpSocketUniquePtr = std::unique_ptr<UdpSocket, UdpSocketDeleter>;
+using UdpSocketUniquePtr = std::unique_ptr<UdpSocket>;
// An open UDP socket for sending/receiving datagrams to/from either specific
// endpoints or over IP multicast.
@@ -41,6 +36,8 @@
// reference implementation.
class UdpSocket {
public:
+ virtual ~UdpSocket();
+
// Constants used to specify how we want packets sent from this socket.
enum class DscpMode : uint8_t {
// Default value set by the system on creation of a new socket.
@@ -58,23 +55,25 @@
using Version = IPAddress::Version;
- // Creates a new, scoped UdpSocket within the IPv4 or IPv6 family.
+ // Creates a new, scoped UdpSocket within the IPv4 or IPv6 family. This method
+ // must be defined in the platform-level implementation.
static ErrorOr<UdpSocketUniquePtr> Create(Version version);
// Returns true if |socket| belongs to the IPv4/IPv6 address family.
- bool IsIPv4() const;
- bool IsIPv6() const;
+ virtual bool IsIPv4() const = 0;
+ virtual bool IsIPv6() const = 0;
// Sets the socket for address reuse, binds to the address/port.
- Error Bind(const IPEndpoint& local_endpoint);
+ virtual Error Bind(const IPEndpoint& local_endpoint) = 0;
// Sets the device to use for outgoing multicast packets on the socket.
- Error SetMulticastOutboundInterface(NetworkInterfaceIndex ifindex);
+ virtual Error SetMulticastOutboundInterface(
+ NetworkInterfaceIndex ifindex) = 0;
// Joins to the multicast group at the given address, using the specified
// interface.
- Error JoinMulticastGroup(const IPAddress& address,
- NetworkInterfaceIndex ifindex);
+ virtual Error JoinMulticastGroup(const IPAddress& address,
+ NetworkInterfaceIndex ifindex) = 0;
// Performs a non-blocking read on the socket, returning the number of bytes
// received. Note that a non-Error return value of 0 is a valid result,
@@ -83,24 +82,34 @@
// ready for receive, which can be expected during normal operation. |src| and
// |original_destination| are optional output arguments that provide the
// source of the message and its intended destination, respectively.
- ErrorOr<size_t> ReceiveMessage(void* data,
- size_t length,
- IPEndpoint* src,
- IPEndpoint* original_destination);
+ virtual ErrorOr<size_t> ReceiveMessage(void* data,
+ size_t length,
+ IPEndpoint* src,
+ IPEndpoint* original_destination) = 0;
// Sends a message and returns the number of bytes sent, on success.
// Error::Code::kAgain might be returned to indicate the operation would
// block, which can be expected during normal operation.
- Error SendMessage(const void* data, size_t length, const IPEndpoint& dest);
+ virtual Error SendMessage(const void* data,
+ size_t length,
+ const IPEndpoint& dest) = 0;
// Sets the DSCP value to use for all messages sent from this socket.
- Error SetDscp(DscpMode state);
+ virtual Error SetDscp(DscpMode state) = 0;
+
+ // Sets the callback that should be called upon deletion of this socket. This
+ // allows other objects to observe the socket's destructor and act when it is
+ // called.
+ void SetDeletionCallback(std::function<void(UdpSocket*)> callback);
protected:
UdpSocket();
- ~UdpSocket();
private:
+ // This callback allows other objects to observe the socket's destructor and
+ // act when it is called.
+ std::function<void(UdpSocket*)> deletion_callback_;
+
OSP_DISALLOW_COPY_AND_ASSIGN(UdpSocket);
};