// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PLATFORM_IMPL_UDP_SOCKET_POSIX_H_ #define PLATFORM_IMPL_UDP_SOCKET_POSIX_H_ #include "absl/types/optional.h" #include "platform/api/udp_socket.h" #include "platform/base/macros.h" #include "platform/impl/platform_client_posix.h" #include "platform/impl/socket_handle_posix.h" #include "util/weak_ptr.h" namespace openscreen { class UdpSocketReaderPosix; // Threading: All public methods must be called on the same thread--the one // executing the TaskRunner. All non-public methods, except ReceiveMessage(), // are also assumed to be called on that thread. class UdpSocketPosix : public UdpSocket { public: // Creates a new UdpSocketPosix. The provided client and task_runner must // exist for the duration of this socket's lifetime. UdpSocketPosix(TaskRunner* task_runner, Client* client, SocketHandle handle, const IPEndpoint& local_endpoint, PlatformClientPosix* platform_client = PlatformClientPosix::GetInstance()); ~UdpSocketPosix() override; // Implementations of UdpSocket methods. bool IsIPv4() const override; bool IsIPv6() const override; IPEndpoint GetLocalEndpoint() const override; void Bind() override; void SetMulticastOutboundInterface(NetworkInterfaceIndex ifindex) override; void JoinMulticastGroup(const IPAddress& address, NetworkInterfaceIndex ifindex) override; void SendMessage(const void* data, size_t length, const IPEndpoint& dest) override; void SetDscp(DscpMode state) override; const SocketHandle& GetHandle() const; protected: friend class UdpSocketReaderPosix; // Called by UdpSocketReaderPosix to perform a non-blocking read on the socket // and then dispatch the packet to this socket's Client. This method is the // only one in this class possibly being called from another thread. void ReceiveMessage(); private: // Helper to close the socket if |error| is fatal, in addition to dispatching // an Error to the |client_|. void OnError(Error::Code error); bool is_closed() const { return handle_.fd < 0; } void Close(); // Task runner to use for queuing |client_| callbacks. TaskRunner* const task_runner_; // Client to use for callbacks. This can be nullptr if the user does not want // any callbacks (for example, in the send-only case). Client* const client_; // Holds the POSIX file descriptor, or -1 if the socket is closed. SocketHandle handle_; // Cached value of current local endpoint. This can change (e.g., when the // operating system auto-assigns a free local port when Bind() is called). If // the port is zero, getsockname() is called to try to resolve it. Once the // port is non-zero, it is assumed never to change again. mutable IPEndpoint local_endpoint_; WeakPtrFactory weak_factory_{this}; PlatformClientPosix* const platform_client_; OSP_DISALLOW_COPY_AND_ASSIGN(UdpSocketPosix); }; } // namespace openscreen #endif // PLATFORM_IMPL_UDP_SOCKET_POSIX_H_