REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
native_ethernet_udp.cpp
Go to the documentation of this file.
1
2#include <net/ethernet_udp.h>
3#include <IPAddress.h>
5
6namespace net {
7
8EthernetUDP::EthernetUDP() : hal_(std::make_unique<NativeEthernetUDP>()) {
9
10}
11
13 _socket(INVALID_SOCKET),
14 _localPort(0),
15 _sendBuffer(nullptr),
16 _sendBufferSize(1024),
17 _sendBufferPos(0),
18 _recvBuffer(nullptr),
19 _recvBufferSize(1024),
20 _recvBufferPos(0),
21 _recvDataSize(0),
22 _hasData(false)
23{
24#ifdef _WIN32
25 if (!_wsaInitialized) {
26 WSADATA wsaData;
27 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
28 std::cerr << "WSAStartup failed" << std::endl;
29 return;
30 }
31 _wsaInitialized = true;
32 }
33#endif
34 _sendBuffer = new uint8_t[_sendBufferSize];
35 _recvBuffer = new uint8_t[_recvBufferSize];
36 memset(&_localAddr, 0, sizeof(_localAddr));
37 memset(&_remoteAddr, 0, sizeof(_remoteAddr));
38}
39
41 stop();
42 delete[] _sendBuffer;
43 delete[] _recvBuffer;
44}
45
46uint8_t NativeEthernetUDP::begin(uint16_t port) {
47 if (_socket != INVALID_SOCKET) {
48 closesocket(_socket);
49 }
50
51 _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
52 if (_socket == INVALID_SOCKET) {
53 return 0;
54 }
55
56 // Set socket to non-blocking mode
57#ifdef _WIN32
58 u_long mode = 1;
59 if (ioctlsocket(_socket, FIONBIO, &mode) != 0) {
60 closesocket(_socket);
61 _socket = INVALID_SOCKET;
62 return 0;
63 }
64#else
65 int flags = fcntl(_socket, F_GETFL, 0);
66 if (flags == -1 || fcntl(_socket, F_SETFL, flags | O_NONBLOCK) == -1) {
67 closesocket(_socket);
68 _socket = INVALID_SOCKET;
69 return 0;
70 }
71#endif
72
73 _localAddr.sin_family = AF_INET;
74 _localAddr.sin_addr.s_addr = INADDR_ANY;
75 _localAddr.sin_port = htons(port);
76
77 if (bind(_socket, (struct sockaddr*)&_localAddr, sizeof(_localAddr)) == SOCKET_ERROR) {
78 closesocket(_socket);
79 _socket = INVALID_SOCKET;
80 return 0;
81 }
82
83 _localPort = port;
84 return 1;
85}
86
87uint8_t NativeEthernetUDP::beginMulticast(IPAddress ip, uint16_t port) {
88 if (!begin(port)) {
89 return 0;
90 }
91
92 // Join multicast group
93 struct ip_mreq mreq;
94 mreq.imr_multiaddr.s_addr = ip;
95 mreq.imr_interface.s_addr = INADDR_ANY;
96
97 if (setsockopt(_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
98 (const char*)&mreq, sizeof(mreq)) == SOCKET_ERROR) {
99 stop();
100 return 0;
101 }
102
103 return 1;
104}
105
107 if (_socket != INVALID_SOCKET) {
108 closesocket(_socket);
109 _socket = INVALID_SOCKET;
110 }
111 _hasData = false;
112 _recvDataSize = 0;
113 _recvBufferPos = 0;
114 _sendBufferPos = 0;
115}
116
117int NativeEthernetUDP::beginPacket(IPAddress ip, uint16_t port) {
118 _remoteAddr.sin_family = AF_INET;
119 _remoteAddr.sin_addr.s_addr = ip;
120 _remoteAddr.sin_port = htons(port);
121 _sendBufferPos = 0;
122 return 1;
123}
124
125int NativeEthernetUDP::beginPacket(const char* host, uint16_t port) {
126 struct hostent* he = gethostbyname(host);
127 if (he == nullptr) {
128 return 0;
129 }
130
131 IPAddress ip = *((uint32_t*)he->h_addr_list[0]);
132 return beginPacket(ip, port);
133}
134
136 if (_socket == INVALID_SOCKET || _sendBufferPos == 0) {
137 return 0;
138 }
139
140 int result = sendto(_socket, (const char*)_sendBuffer, _sendBufferPos,
141 0, (struct sockaddr*)&_remoteAddr, sizeof(_remoteAddr));
142
143 _sendBufferPos = 0;
144 return (result == SOCKET_ERROR) ? 0 : 1;
145}
146
147size_t NativeEthernetUDP::write(uint8_t byte) {
148 return write(&byte, 1);
149}
150
151size_t NativeEthernetUDP::write(const uint8_t* buffer, size_t size) {
152 if (_sendBufferPos + size > _sendBufferSize) {
153 // Resize buffer if needed
154 size_t newSize = _sendBufferSize * 2;
155 while (newSize < _sendBufferPos + size) {
156 newSize *= 2;
157 }
158 uint8_t* newBuffer = new uint8_t[newSize];
159 memcpy(newBuffer, _sendBuffer, _sendBufferPos);
160 delete[] _sendBuffer;
161 _sendBuffer = newBuffer;
162 _sendBufferSize = newSize;
163 }
164
165 memcpy(_sendBuffer + _sendBufferPos, buffer, size);
166 _sendBufferPos += size;
167 return size;
168}
169
171 if (_socket == INVALID_SOCKET) {
172 return 0;
173 }
174
175 socklen_t addrLen = sizeof(_remoteAddr);
176 int result = recvfrom(_socket, (char*)_recvBuffer, _recvBufferSize,
177 0, (struct sockaddr*)&_remoteAddr, &addrLen);
178
179 if (result == SOCKET_ERROR) {
180#ifdef _WIN32
181 int error = WSAGetLastError();
182 if (error == WSAEWOULDBLOCK) {
183 return 0; // No data available
184 }
185#else
186 if (errno == EAGAIN || errno == EWOULDBLOCK) {
187 return 0; // No data available
188 }
189#endif
190 return 0; // Error
191 }
192
193 _recvDataSize = result;
194 _recvBufferPos = 0;
195 _hasData = true;
196 return result;
197}
198
200 if (!_hasData) {
201 return 0;
202 }
203 return _recvDataSize - _recvBufferPos;
204}
205
207 if (!_hasData || _recvBufferPos >= _recvDataSize) {
208 return -1;
209 }
210 return _recvBuffer[_recvBufferPos++];
211}
212
213int NativeEthernetUDP::read(unsigned char* buffer, size_t len) {
214 return read((char*)buffer, len);
215}
216
217int NativeEthernetUDP::read(char* buffer, size_t len) {
218 if (!_hasData) {
219 return 0;
220 }
221
222 size_t available_bytes = _recvDataSize - _recvBufferPos;
223 size_t bytes_to_read = (len < available_bytes) ? len : available_bytes;
224
225 memcpy(buffer, _recvBuffer + _recvBufferPos, bytes_to_read);
226 _recvBufferPos += bytes_to_read;
227
228 return bytes_to_read;
229}
230
232 if (!_hasData || _recvBufferPos >= _recvDataSize) {
233 return -1;
234 }
235 return _recvBuffer[_recvBufferPos];
236}
237
239 _hasData = false;
240 _recvDataSize = 0;
241 _recvBufferPos = 0;
242}
243
245 return _remoteAddr.sin_addr.s_addr;
246}
247
249 return ntohs(_remoteAddr.sin_port);
250}
251
252}
IPAddress remoteIP() override
size_t write(uint8_t) override
int beginPacket(IPAddress ip, uint16_t port) override
uint8_t begin(uint16_t) override
uint16_t remotePort() override
uint8_t beginMulticast(IPAddress, uint16_t) override
uint32_t
Definition flasher.cpp:195
uint32_t uint32_t size
Definition flasher.cpp:63
Definition mode.h:14
#define INVALID_SOCKET
#define SOCKET_ERROR
#define closesocket