6#include "dawn/proto/udp/simple.hxx"
8#include "dawn/common/poll_loop.hxx"
11#include <netinet/in.h>
13#include <sys/socket.h>
20int CProtoUdp::sendFrame(uint8_t cmd,
const uint8_t *payload,
size_t len)
22 uint8_t frame[FRAME_MAX_PAYLOAD + FRAME_MIN_LEN];
27 if (len > FRAME_MAX_PAYLOAD || fd < 0)
29 DAWNERR(
"UDP sendFrame invalid state cmd=0x%02x len=%zu fd=%d\n", cmd, len, fd);
33 tosend = FRAME_MIN_LEN + len;
36 frame[1] = (uint8_t)(len & 0xFF);
37 frame[2] = (uint8_t)((len >> 8) & 0xFF);
42 std::memcpy(&frame[4], payload, len);
46 frame[4 + len] = (uint8_t)(crc & 0xFF);
47 frame[5 + len] = (uint8_t)((crc >> 8) & 0xFF);
50 std::lock_guard<std::mutex> lock(senderMutex);
51 if (sender.sin_port == 0)
53 DAWNERR(
"UDP sendFrame no sender cmd=0x%02x len=%zu\n", cmd, len);
57 DAWNINFO(
"UDP sendFrame cmd=0x%02x len=%zu to port=%u ip=0x%08" PRIx32
"\n",
60 ntohs(sender.sin_port),
61 ntohl(sender.sin_addr.s_addr));
64 sendto(fd, frame, tosend, 0,
reinterpret_cast<struct sockaddr *
>(&sender),
sizeof(sender));
67 if (ret < 0 ||
static_cast<size_t>(ret) != tosend)
69 DAWNERR(
"UDP sendto failed cmd=0x%02x ret=%zd exp=%zu errno=%d\n", cmd, ret, tosend, errno);
70 return ret < 0 ? static_cast<int>(ret) : -EIO;
76void CProtoUdp::thread()
81 std::memset(fds, 0,
sizeof(fds));
84 fds[0].events = POLLIN;
86 callbacks.
beforePoll = CProtoUdp::cbPollBefore;
87 callbacks.
afterPoll = CProtoUdp::cbPollAfter;
93int CProtoUdp::pollBefore(
struct pollfd *pfds, nfds_t nfds)
95 if (pfds ==
nullptr || nfds == 0)
104void CProtoUdp::pollAfter(
int ret)
108 DAWNERR(
"UDP poll failed %d\n", -errno);
112int CProtoUdp::pollOnReady(
struct pollfd *pfds, nfds_t nfds,
int pollRet)
117 if (pfds ==
nullptr || nfds == 0 || pollRet <= 0)
122 if ((pfds[0].revents & POLLIN) == 0)
127 fromlen =
sizeof(sender);
129 std::lock_guard<std::mutex> lock(senderMutex);
131 fd, rxbuffer,
sizeof(rxbuffer), 0,
reinterpret_cast<struct sockaddr *
>(&sender), &fromlen);
136 DAWNERR(
"UDP recvfrom ret=%zd errno=%d\n", ret, errno);
138 return static_cast<int>(ret);
141 int frameRet =
handleFrame(rxbuffer,
static_cast<size_t>(ret));
144 DAWNERR(
"UDP handleFrame failed ret=%d\n", frameRet);
151int CProtoUdp::cbPollBefore(
void *priv,
struct pollfd *pfds, nfds_t nfds)
161 return self->pollBefore(pfds, nfds);
164void CProtoUdp::cbPollAfter(
void *priv,
struct pollfd *pfds, nfds_t nfds,
int ret)
177 self->pollAfter(ret);
180int CProtoUdp::cbPollOnReady(
void *priv,
struct pollfd *pfds, nfds_t nfds,
int pollRet)
190 return self->pollOnReady(pfds, nfds, pollRet);
193int CProtoUdp::configureDesc(
const CDescObject &desc)
200 for (
size_t i = 0; i < desc.
getSize(); i++)
206 DAWNERR(
"Unsupported UDP config 0x%08" PRIx32
"\n", item->
cfgid.
v);
212 case PROTO_UDP_CFG_IOBIND:
216 SProtoUdpIOBind *tmp;
218 tmp =
reinterpret_cast<SProtoUdpIOBind *
>(item->
data + j);
221 j +=
sizeof(SProtoUdpIOBind) / 4;
227 case PROTO_UDP_CFG_PORT:
229 port =
static_cast<uint16_t
>(item->
data[0]);
235 DAWNERR(
"Unsupported UDP config 0x%08" PRIx32
"\n", item->
cfgid.
v);
244int CProtoUdp::udpInit()
246 struct sockaddr_in addr;
249 fd = socket(AF_INET, SOCK_DGRAM, 0);
252 DAWNERR(
"Failed to create UDP socket: %d\n", -errno);
256 std::memset(&addr, 0,
sizeof(addr));
257 addr.sin_family = AF_INET;
258 addr.sin_addr.s_addr = INADDR_ANY;
259 addr.sin_port = htons(port);
261 ret = bind(fd,
reinterpret_cast<struct sockaddr *
>(&addr),
sizeof(addr));
264 DAWNERR(
"Failed to bind UDP socket to port %u: %d\n", port, -errno);
270 DAWNINFO(
"UDP protocol initialized on port %u\n", port);
275CProtoUdp::~CProtoUdp()
284 ret = configureDesc(
getDesc());
287 DAWNERR(
"UDP configure failed (error %d)\n", ret);
307 DAWNERR(
"failed to create data %d\n", ret);
311#ifdef CONFIG_DAWN_IO_NOTIFY
312 ret = setupNotifications();
315 DAWNERR(
"failed to setup notifications %d\n", ret);
324#ifdef CONFIG_DAWN_IO_NOTIFY
325 destroyNotifications();
346 DAWNERR(
"failed to start thread %d\n", ret);
350 DAWNINFO(
"UDP protocol started\n");
357#ifdef CONFIG_DAWN_IO_NOTIFY
358 cleanupNotifications();
363 DAWNINFO(
"UDP protocol stopped\n");
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemNext(size_t &offset) const
Get config item at current offset and advance past it.
CDescObject & getDesc()
Get descriptor object for this object.
static int run(CThreadedObject &threadCtl, struct pollfd *pfds, nfds_t nfds, int timeoutMs, const SPollLoopCallbacks &callbacks, void *priv)
Run poll loop until quit is requested.
@ PROTO_CLASS_UDP
UDP-based protocol.
static uint8_t FRAME_SYNC
Frame structure constants.
void allocObject(SProtoSimpleIOBind *cfg)
Store an allocated IO binding.
uint16_t calculateCrc(const uint8_t *data, size_t len)
Calculate 16-bit CRC checksum.
int handleFrame(const uint8_t *frame, size_t len)
Process a received frame.
int createBuffers()
Allocate shared per-IO data buffers.
int destroyBuffers()
Destroy shared per-IO data buffers.
Simple binary UDP protocol for device communication.
bool hasThread() const
Check if a background thread is active.
int deinit()
De-initialize object.
int init()
One-time initialize object after bindings are resolved.
int configure()
Configure object from descriptor data.
int doStart()
Start implementation hook.
int doStop()
Stop implementation hook.
bool workerThreadRunning() const
Check if the worker thread is running.
int stopWorkerThread()
Stop the worker thread.
int startWorkerThread(Func &&func)
Start the worker thread with a given function.
CThreadedObject & workerThread()
Get a reference to this thread controller.
Out-of-tree user-extension hooks for Dawn.
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
Callback set for poll-based worker loops.
void(* afterPoll)(void *priv, struct pollfd *pfds, nfds_t nfds, int ret)
Optional hook called after each poll() return.
int(* onPollReady)(void *priv, struct pollfd *pfds, nfds_t nfds, int pollRet)
Optional hook called when poll() reports ready descriptors.
int(* beforePoll)(void *priv, struct pollfd *pfds, nfds_t nfds)
Optional hook called before each poll() call.
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.