blob: 6471c4bdfb5bedf63262e03d4e4d930f29f7941f [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for UDP/IPv6 sockets.
*/
#ifndef UDP6_HPP_
#define UDP6_HPP_
#include "openthread-core-config.h"
#include <openthread/udp.h>
#include <openthread/platform/udp.h>
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "net/ip6_headers.hpp"
namespace ot {
namespace Ip6 {
class Udp;
/**
* @addtogroup core-udp
*
* @brief
* This module includes definitions for UDP/IPv6 sockets.
*
* @{
*
*/
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE && OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
#error "OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE and OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE must not both be set."
#endif
/**
* This class implements core UDP message handling.
*
*/
class Udp : public InstanceLocator, private NonCopyable
{
public:
/**
* This class implements a UDP/IPv6 socket.
*
*/
class SocketHandle : public otUdpSocket, public LinkedListEntry<SocketHandle>, public Clearable<SocketHandle>
{
friend class Udp;
friend class LinkedList<SocketHandle>;
public:
/**
* This method indicates whether or not the socket is bound.
*
* @retval TRUE if the socket is bound (i.e. source port is non-zero).
* @retval FALSE if the socket is not bound (source port is zero).
*
*/
bool IsBound(void) const { return mSockName.mPort != 0; }
/**
* This method returns the local socket address.
*
* @returns A reference to the local socket address.
*
*/
SockAddr &GetSockName(void) { return AsCoreType(&mSockName); }
/**
* This method returns the local socket address.
*
* @returns A reference to the local socket address.
*
*/
const SockAddr &GetSockName(void) const { return AsCoreType(&mSockName); }
/**
* This method returns the peer's socket address.
*
* @returns A reference to the peer's socket address.
*
*/
SockAddr &GetPeerName(void) { return AsCoreType(&mPeerName); }
/**
* This method returns the peer's socket address.
*
* @returns A reference to the peer's socket address.
*
*/
const SockAddr &GetPeerName(void) const { return AsCoreType(&mPeerName); }
private:
bool Matches(const MessageInfo &aMessageInfo) const;
void HandleUdpReceive(Message &aMessage, const MessageInfo &aMessageInfo)
{
mHandler(mContext, &aMessage, &aMessageInfo);
}
};
/**
* This class implements a UDP/IPv6 socket.
*
*/
class Socket : public InstanceLocator, public SocketHandle
{
friend class Udp;
public:
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to OpenThread instance.
*
*/
explicit Socket(Instance &aInstance);
/**
* This method returns a new UDP message with sufficient header space reserved.
*
* @param[in] aReserved The number of header bytes to reserve after the UDP header.
* @param[in] aSettings The message settings (default is used if not provided).
*
* @returns A pointer to the message or `nullptr` if no buffers are available.
*
*/
Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
/**
* This method opens the UDP socket.
*
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kErrorNone Successfully opened the socket.
* @retval kErrorFailed Failed to open the socket.
*
*/
Error Open(otUdpReceive aHandler, void *aContext);
/**
* This method returns if the UDP socket is open.
*
* @returns If the UDP socket is open.
*
*/
bool IsOpen(void) const;
/**
* This method binds the UDP socket.
*
* @param[in] aSockAddr A reference to the socket address.
* @param[in] aNetifIdentifier The network interface identifier.
*
* @retval kErrorNone Successfully bound the socket.
* @retval kErrorInvalidArgs Unable to bind to Thread network interface with the given address.
* @retval kErrorFailed Failed to bind UDP Socket.
*
*/
Error Bind(const SockAddr &aSockAddr, otNetifIdentifier aNetifIdentifier = OT_NETIF_THREAD);
/**
* This method binds the UDP socket.
*
* @param[in] aPort A port number.
* @param[in] aNetifIdentifier The network interface identifier.
*
* @retval kErrorNone Successfully bound the socket.
* @retval kErrorFailed Failed to bind UDP Socket.
*
*/
Error Bind(uint16_t aPort, otNetifIdentifier aNetifIdentifier = OT_NETIF_THREAD);
/**
* This method binds the UDP socket.
*
* @retval kErrorNone Successfully bound the socket.
* @retval kErrorFailed Failed to bind UDP Socket.
*
*/
Error Bind(void) { return Bind(0); }
/**
* This method connects the UDP socket.
*
* @param[in] aSockAddr A reference to the socket address.
*
* @retval kErrorNone Successfully connected the socket.
* @retval kErrorFailed Failed to connect UDP Socket.
*
*/
Error Connect(const SockAddr &aSockAddr);
/**
* This method connects the UDP socket.
*
* @param[in] aPort A port number.
*
* @retval kErrorNone Successfully connected the socket.
* @retval kErrorFailed Failed to connect UDP Socket.
*
*/
Error Connect(uint16_t aPort);
/**
* This method connects the UDP socket.
*
* @retval kErrorNone Successfully connected the socket.
* @retval kErrorFailed Failed to connect UDP Socket.
*
*/
Error Connect(void) { return Connect(0); }
/**
* This method closes the UDP socket.
*
* @retval kErrorNone Successfully closed the UDP socket.
* @retval kErrorFailed Failed to close UDP Socket.
*
*/
Error Close(void);
/**
* This method sends a UDP message.
*
* @param[in] aMessage The message to send.
* @param[in] aMessageInfo The message info associated with @p aMessage.
*
* @retval kErrorNone Successfully sent the UDP message.
* @retval kErrorInvalidArgs If no peer is specified in @p aMessageInfo or by Connect().
* @retval kErrorNoBufs Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
Error SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
/**
* This method configures the UDP socket to join a mutlicast group on a Host network interface.
*
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The multicast group address.
*
* @retval kErrorNone Successfully joined the multicast group.
* @retval kErrorFailed Failed to join the multicast group.
*
*/
Error JoinNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
/**
* This method configures the UDP socket to leave a multicast group on a Host network interface.
*
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The multicast group address.
*
* @retval kErrorNone Successfully left the multicast group.
* @retval kErrorFailed Failed to leave the multicast group.
*
*/
Error LeaveNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
#endif
};
/**
* This class implements a UDP receiver.
*
*/
class Receiver : public otUdpReceiver, public LinkedListEntry<Receiver>
{
friend class Udp;
public:
/**
* This constructor initializes the UDP receiver.
*
* @param[in] aHandler A pointer to the function to handle UDP message.
* @param[in] aContext A pointer to arbitrary context information.
*
*/
Receiver(otUdpHandler aHandler, void *aContext)
{
mNext = nullptr;
mHandler = aHandler;
mContext = aContext;
}
private:
bool HandleMessage(Message &aMessage, const MessageInfo &aMessageInfo)
{
return mHandler(mContext, &aMessage, &aMessageInfo);
}
};
/**
* This class implements UDP header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class Header : public Clearable<Header>
{
public:
static constexpr uint16_t kSourcePortFieldOffset = 0; ///< Byte offset of Source Port field in UDP header.
static constexpr uint16_t kDestPortFieldOffset = 2; ///< Byte offset of Destination Port field in UDP header.
static constexpr uint16_t kLengthFieldOffset = 4; ///< Byte offset of Length field in UDP header.
static constexpr uint16_t kChecksumFieldOffset = 6; ///< Byte offset of Checksum field in UDP header.
/**
* This method returns the UDP Source Port.
*
* @returns The UDP Source Port.
*
*/
uint16_t GetSourcePort(void) const { return HostSwap16(mSourcePort); }
/**
* This method sets the UDP Source Port.
*
* @param[in] aPort The UDP Source Port.
*
*/
void SetSourcePort(uint16_t aPort) { mSourcePort = HostSwap16(aPort); }
/**
* This method returns the UDP Destination Port.
*
* @returns The UDP Destination Port.
*
*/
uint16_t GetDestinationPort(void) const { return HostSwap16(mDestinationPort); }
/**
* This method sets the UDP Destination Port.
*
* @param[in] aPort The UDP Destination Port.
*
*/
void SetDestinationPort(uint16_t aPort) { mDestinationPort = HostSwap16(aPort); }
/**
* This method returns the UDP Length.
*
* @returns The UDP Length.
*
*/
uint16_t GetLength(void) const { return HostSwap16(mLength); }
/**
* This method sets the UDP Length.
*
* @param[in] aLength The UDP Length.
*
*/
void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
/**
* This method returns the UDP Checksum.
*
* @returns The UDP Checksum.
*
*/
uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
/**
* This method sets the UDP Checksum.
*
* @param[in] aChecksum The UDP Checksum.
*
*/
void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
private:
uint16_t mSourcePort;
uint16_t mDestinationPort;
uint16_t mLength;
uint16_t mChecksum;
} OT_TOOL_PACKED_END;
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to OpenThread instance.
*
*/
explicit Udp(Instance &aInstance);
/**
* This method adds a UDP receiver.
*
* @param[in] aReceiver A reference to the UDP receiver.
*
* @retval kErrorNone Successfully added the UDP receiver.
* @retval kErrorAlready The UDP receiver was already added.
*
*/
Error AddReceiver(Receiver &aReceiver);
/**
* This method removes a UDP receiver.
*
* @param[in] aReceiver A reference to the UDP receiver.
*
* @retval kErrorNone Successfully removed the UDP receiver.
* @retval kErrorNotFound The UDP receiver was not added.
*
*/
Error RemoveReceiver(Receiver &aReceiver);
/**
* This method opens a UDP socket.
*
* @param[in] aSocket A reference to the socket.
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kErrorNone Successfully opened the socket.
* @retval kErrorFailed Failed to open the socket.
*
*/
Error Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext);
/**
* This method returns if a UDP socket is open.
*
* @param[in] aSocket A reference to the socket.
*
* @returns If the UDP socket is open.
*
*/
bool IsOpen(const SocketHandle &aSocket) const { return mSockets.Contains(aSocket); }
/**
* This method binds a UDP socket.
*
* @param[in] aSocket A reference to the socket.
* @param[in] aSockAddr A reference to the socket address.
* @param[in] aNetifIdentifier The network interface identifier.
*
* @retval kErrorNone Successfully bound the socket.
* @retval kErrorInvalidArgs Unable to bind to Thread network interface with the given address.
* @retval kErrorFailed Failed to bind UDP Socket.
*
*/
Error Bind(SocketHandle &aSocket, const SockAddr &aSockAddr, otNetifIdentifier aNetifIdentifier);
/**
* This method connects a UDP socket.
*
* @param[in] aSocket A reference to the socket.
* @param[in] aSockAddr A reference to the socket address.
*
* @retval kErrorNone Successfully connected the socket.
* @retval kErrorFailed Failed to connect UDP Socket.
*
*/
Error Connect(SocketHandle &aSocket, const SockAddr &aSockAddr);
/**
* This method closes the UDP socket.
*
* @param[in] aSocket A reference to the socket.
*
* @retval kErrorNone Successfully closed the UDP socket.
* @retval kErrorFailed Failed to close UDP Socket.
*
*/
Error Close(SocketHandle &aSocket);
/**
* This method sends a UDP message using a socket.
*
* @param[in] aSocket A reference to the socket.
* @param[in] aMessage The message to send.
* @param[in] aMessageInfo The message info associated with @p aMessage.
*
* @retval kErrorNone Successfully sent the UDP message.
* @retval kErrorInvalidArgs If no peer is specified in @p aMessageInfo or by Connect().
* @retval kErrorNoBufs Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
Error SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo);
/**
* This method returns a new ephemeral port.
*
* @returns A new ephemeral port.
*
*/
uint16_t GetEphemeralPort(void);
/**
* This method returns a new UDP message with sufficient header space reserved.
*
* @param[in] aReserved The number of header bytes to reserve after the UDP header.
* @param[in] aSettings The message settings.
*
* @returns A pointer to the message or `nullptr` if no buffers are available.
*
*/
Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
/**
* This method sends an IPv6 datagram.
*
* @param[in] aMessage A reference to the message.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aIpProto The Internet Protocol value.
*
* @retval kErrorNone Successfully enqueued the message into an output interface.
* @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers.
*
*/
Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
/**
* This method handles a received UDP message.
*
* @param[in] aMessage A reference to the UDP message to process.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
* @retval kErrorNone Successfully processed the UDP message.
* @retval kErrorDrop Could not fully process the UDP message.
*
*/
Error HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
/**
* This method handles a received UDP message with offset set to the payload.
*
* @param[in] aMessage A reference to the UDP message to process.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
void HandlePayload(Message &aMessage, MessageInfo &aMessageInfo);
/**
* This method returns the head of UDP Sockets list.
*
* @returns A pointer to the head of UDP Socket linked list.
*
*/
SocketHandle *GetUdpSockets(void) { return mSockets.GetHead(); }
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
/**
* This method sets the forward sender.
*
* @param[in] aForwarder A function pointer to forward UDP packets.
* @param[in] aContext A pointer to arbitrary context information.
*
*/
void SetUdpForwarder(otUdpForwarder aForwarder, void *aContext)
{
mUdpForwarder = aForwarder;
mUdpForwarderContext = aContext;
}
#endif
/**
* This method returns whether a udp port is being used by OpenThread or any of it's optional
* features, e.g. CoAP API.
*
* @param[in] aPort The udp port
*
* @retval True when port is used by the OpenThread.
* @retval False when the port is not used by OpenThread.
*
*/
bool IsPortInUse(uint16_t aPort) const;
/**
* This method returns whether a udp port belongs to the platform or the stack.
*
* @param[in] aPort The udp port
*
* @retval True when the port belongs to the platform.
* @retval False when the port belongs to the stack.
*
*/
bool ShouldUsePlatformUdp(uint16_t aPort) const;
private:
static constexpr uint16_t kDynamicPortMin = 49152; // Service Name and Transport Protocol Port Number Registry
static constexpr uint16_t kDynamicPortMax = 65535; // Service Name and Transport Protocol Port Number Registry
// Reserved range for use by SRP server
static constexpr uint16_t kSrpServerPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN;
static constexpr uint16_t kSrpServerPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX;
static bool IsPortReserved(uint16_t aPort);
void AddSocket(SocketHandle &aSocket);
void RemoveSocket(SocketHandle &aSocket);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
bool ShouldUsePlatformUdp(const SocketHandle &aSocket) const;
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
void SetBackboneSocket(SocketHandle &aSocket);
const SocketHandle *GetBackboneSockets(void) const;
bool IsBackboneSocket(const SocketHandle &aSocket) const;
#endif
uint16_t mEphemeralPort;
LinkedList<Receiver> mReceivers;
LinkedList<SocketHandle> mSockets;
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
SocketHandle *mPrevBackboneSockets;
#endif
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
void * mUdpForwarderContext;
otUdpForwarder mUdpForwarder;
#endif
};
/**
* @}
*
*/
} // namespace Ip6
DefineCoreType(otUdpSocket, Ip6::Udp::SocketHandle);
DefineCoreType(otUdpReceiver, Ip6::Udp::Receiver);
} // namespace ot
#endif // UDP6_HPP_