#ifndef UDP6_HPP_
#define UDP6_HPP_
#include "openthread-core-config.h"
#include <openthread/udp.h>
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "net/ip6_headers.hpp"
namespace ot {
namespace Ip6 {
class Udp;
class UdpReceiver : public otUdpReceiver, public LinkedListEntry<UdpReceiver>
{
friend class Udp;
public:
UdpReceiver(otUdpHandler aHandler, void *aContext)
{
mNext = NULL;
mHandler = aHandler;
mContext = aContext;
}
private:
bool HandleMessage(Message &aMessage, const MessageInfo &aMessageInfo)
{
return mHandler(mContext, &aMessage, &aMessageInfo);
}
};
class UdpSocket : public otUdpSocket, public InstanceLocator, public LinkedListEntry<UdpSocket>
{
friend class Udp;
public:
explicit UdpSocket(Udp &aUdp);
Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
otError Open(otUdpReceive aHandler, void *aContext);
otError Bind(const SockAddr &aSockAddr);
bool IsBound(void) const { return mSockName.mPort != 0; }
otError Connect(const SockAddr &aSockAddr);
otError Close(void);
otError SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
SockAddr &GetSockName(void) { return *static_cast<SockAddr *>(&mSockName); }
SockAddr &GetPeerName(void) { return *static_cast<SockAddr *>(&mPeerName); }
private:
void HandleUdpReceive(Message &aMessage, const MessageInfo &aMessageInfo)
{
mHandler(mContext, &aMessage, &aMessageInfo);
}
};
class Udp : public InstanceLocator
{
friend class UdpSocket;
public:
explicit Udp(Instance &aInstance);
otError AddReceiver(UdpReceiver &aReceiver);
otError RemoveReceiver(UdpReceiver &aReceiver);
void AddSocket(UdpSocket &aSocket);
void RemoveSocket(UdpSocket &aSocket);
uint16_t GetEphemeralPort(void);
Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
otError SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
otError HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
void HandlePayload(Message &aMessage, MessageInfo &aMessageInfo);
void UpdateChecksum(Message &aMessage, uint16_t aChecksum);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
otUdpSocket *GetUdpSockets(void) { return mSockets.GetHead(); }
#endif
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
void SetUdpForwarder(otUdpForwarder aForwarder, void *aContext)
{
mUdpForwarder = aForwarder;
mUdpForwarderContext = aContext;
}
#endif
private:
enum
{
kDynamicPortMin = 49152, kDynamicPortMax = 65535, };
uint16_t mEphemeralPort;
LinkedList<UdpReceiver> mReceivers;
LinkedList<UdpSocket> mSockets;
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
void * mUdpForwarderContext;
otUdpForwarder mUdpForwarder;
#endif
};
OT_TOOL_PACKED_BEGIN
struct UdpHeaderPoD
{
uint16_t mSource;
uint16_t mDestination;
uint16_t mLength;
uint16_t mChecksum;
} OT_TOOL_PACKED_END;
OT_TOOL_PACKED_BEGIN
class UdpHeader : private UdpHeaderPoD
{
public:
uint16_t GetSourcePort(void) const { return HostSwap16(mSource); }
void SetSourcePort(uint16_t aPort) { mSource = HostSwap16(aPort); }
uint16_t GetDestinationPort(void) const { return HostSwap16(mDestination); }
void SetDestinationPort(uint16_t aPort) { mDestination = HostSwap16(aPort); }
uint16_t GetLength(void) const { return HostSwap16(mLength); }
void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
static uint8_t GetLengthOffset(void) { return offsetof(UdpHeaderPoD, mLength); }
static uint8_t GetChecksumOffset(void) { return offsetof(UdpHeaderPoD, mChecksum); }
} OT_TOOL_PACKED_END;
} }
#endif