blob: 6dc7ae538ce285e44a6de65716c3b2872df7bb6f [file] [log] [blame]
// 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.
#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 {
// 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 =
~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;
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();
// 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<UdpSocketPosix> weak_factory_{this};
PlatformClientPosix* const platform_client_;
} // namespace openscreen