arduino-audio-tools
Loading...
Searching...
No Matches
WiFiClientZephyr.h
Go to the documentation of this file.
1#pragma once
2
3#include <errno.h>
4#include <stddef.h>
5#include <stdint.h>
6#include <stdio.h>
7#include <string.h>
8#include <zephyr/kernel.h>
9#include <zephyr/net/net_ip.h>
10#include <zephyr/net/socket.h>
11#include <zephyr/sys/util.h> // for BUILD_ASSERT
13
14// Fail fast at compile time if required Kconfig symbols are missing.
15BUILD_ASSERT(IS_ENABLED(CONFIG_NETWORKING),
16 "WiFiClientZephyr requires CONFIG_NETWORKING=y");
17
18BUILD_ASSERT(IS_ENABLED(CONFIG_NET_TCP),
19 "WiFiClientZephyr requires CONFIG_NET_TCP=y");
20
21BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS),
22 "WiFiClientZephyr requires CONFIG_NET_SOCKETS=y");
23
24BUILD_ASSERT(IS_ENABLED(CONFIG_DNS_RESOLVER),
25 "WiFiClientZephyr requires CONFIG_DNS_RESOLVER=y");
26
27
28namespace audio_tools {
29
44class WiFiClientZephyr : public Client {
45 public:
47 WiFiClientZephyr() = default;
50
51 virtual ~WiFiClientZephyr() { stop(); }
52
53 // ----------------------------------------------------------------
54 // Connection management
55 // ----------------------------------------------------------------
56
63 virtual int connect(const char* host, uint16_t port) {
64 stop();
65
66 struct sockaddr_storage addr = {};
67 socklen_t addrlen = sizeof(addr);
68
69 if (_resolve(host, port, (struct sockaddr*)&addr, &addrlen) < 0) {
70 return 0;
71 }
72
74 if (_sock < 0) {
75 return 0;
76 }
77
79
80 if (zsock_connect(_sock, (struct sockaddr*)&addr, addrlen) < 0) {
82 _sock = -1;
83 return 0;
84 }
85
86 return 1;
87 }
88
95 virtual int connect(uint32_t ip, uint16_t port) {
96 char host[INET_ADDRSTRLEN];
97 struct in_addr addr_in;
98 addr_in.s_addr = ip;
99 zsock_inet_ntop(AF_INET, &addr_in, host, sizeof(host));
100 return connect(host, port);
101 }
102
104 void stop() {
105 if (_sock >= 0) {
107 _sock = -1;
108 _has_peek = false;
109 }
110 }
111
113 int connected() {
114 if (_sock < 0) return 0;
115
116 // Zero-byte peek detects a graceful remote close without consuming data.
119 if (rc == 0) return 0;
120 if (rc < 0 && errno != EAGAIN && errno != EWOULDBLOCK) return 0;
121 return 1;
122 }
123
124 // ----------------------------------------------------------------
125 // Write
126 // ----------------------------------------------------------------
127
129 size_t write(uint8_t b) { return write(&b, 1); }
130
132 size_t write(const uint8_t* buf, size_t size) {
133 if (_sock < 0 || !buf || size == 0) return 0;
134
135 size_t sent = 0;
136 while (sent < size) {
137 ssize_t rc = zsock_send(_sock, buf + sent, size - sent, 0);
138 if (rc < 0) {
139 stop();
140 break;
141 }
142 sent += (size_t)rc;
143 }
144 return sent;
145 }
146
147 size_t print(const char* str) {
148 if (!str) return 0;
149 return write((const uint8_t*)str, strlen(str));
150 }
151
152 size_t println(const char* str) {
153 return print(str) + write((const uint8_t*)"\r\n", 2);
154 }
155
156 size_t print(int value) {
157 char buf[16];
158 snprintf(buf, sizeof(buf), "%d", value);
159 return print(buf);
160 }
161
162 size_t println(int value) {
163 char buf[16];
164 snprintf(buf, sizeof(buf), "%d", value);
165 return println(buf);
166 }
167
168 // ----------------------------------------------------------------
169 // Read
170 // ----------------------------------------------------------------
171
175 int available() {
176 if (_sock < 0) return -1;
177 if (_has_peek) return 1;
178
179 // Fast path: FIONREAD
180 int bytes = 0;
181 if (zsock_ioctl(_sock, ZFD_IOCTL_FIONREAD, &bytes) == 0) {
182 return bytes;
183 }
184
185 // Fallback: non-blocking peek
186 uint8_t b;
188 if (rc > 0) return 1;
189 if (rc == 0) {
190 stop();
191 return 0;
192 }
193 return (errno == EAGAIN || errno == EWOULDBLOCK) ? 0 : -1;
194 }
195
200 int read() {
201 if (_sock < 0) return -1;
202
203 if (_has_peek) {
204 _has_peek = false;
205 return _peek_byte;
206 }
207
208 uint8_t b;
209 ssize_t rc = zsock_recv(_sock, &b, 1, 0);
210 if (rc == 1) return b;
211 if (rc == 0) stop();
212 return -1;
213 }
214
219 int read(uint8_t* buf, size_t size) {
220 if (_sock < 0 || !buf || size == 0) return -1;
221
222 size_t offset = 0;
223
224 if (_has_peek && size > 0) {
225 buf[0] = _peek_byte;
226 _has_peek = false;
227 offset = 1;
228 size -= 1;
229 }
230
231 if (size == 0) return (int)offset;
232
233 ssize_t rc = zsock_recv(_sock, buf + offset, size, 0);
234 if (rc < 0) {
235 if (errno == EAGAIN || errno == EWOULDBLOCK) return (int)offset;
236 return offset > 0 ? (int)offset : -1;
237 }
238 if (rc == 0) stop();
239 return (int)(offset + (size_t)rc);
240 }
241
246 int peek() {
247 if (_sock < 0) return -1;
248 if (_has_peek) return _peek_byte;
249
250 uint8_t b;
252 if (rc == 1) {
253 _peek_byte = b;
254 _has_peek = true;
255 return b;
256 }
257 if (rc == 0) stop();
258 return -1;
259 }
260
261 // ----------------------------------------------------------------
262 // Socket options
263 // ----------------------------------------------------------------
264
269 void setTimeout(uint32_t timeout_ms) {
270 _timeout_ms = timeout_ms;
272 }
273
275 int fd() const { return _sock; }
276
277 protected:
278 int _sock = -1;
281 bool _has_peek = false;
282
284 if (_sock < 0) return;
285 struct timeval tv = {};
286 tv.tv_sec = _timeout_ms / 1000;
287 tv.tv_usec = (_timeout_ms % 1000) * 1000;
289 }
290
291 int _resolve(const char* host, uint16_t port, struct sockaddr* out,
292 socklen_t* outlen) {
293 struct zsock_addrinfo hints = {};
294 struct zsock_addrinfo* res = nullptr;
295 char port_str[8];
296 snprintf(port_str, sizeof(port_str), "%u", port);
297
298 hints.ai_family = AF_UNSPEC;
299 hints.ai_socktype = SOCK_STREAM;
300
301 int rc = zsock_getaddrinfo(host, port_str, &hints, &res);
302 if (rc != 0 || !res) return -1;
303
304 memcpy(out, res->ai_addr, res->ai_addrlen);
305 *outlen = res->ai_addrlen;
307 return 0;
308 }
309};
310
312
313} // namespace audio_tools
BUILD_ASSERT(IS_ENABLED(CONFIG_NETWORKING), "WiFiClientZephyr requires CONFIG_NETWORKING=y")
Definition Arduino.h:162
Definition WiFiClientZephyr.h:44
void setTimeout(uint32_t timeout_ms)
Definition WiFiClientZephyr.h:269
WiFiClientZephyr(int socket)
Constructor providing a socket (e.g. used by server)
Definition WiFiClientZephyr.h:49
size_t print(int value)
Definition WiFiClientZephyr.h:156
bool _has_peek
Definition WiFiClientZephyr.h:281
virtual ~WiFiClientZephyr()
Definition WiFiClientZephyr.h:51
int _sock
Definition WiFiClientZephyr.h:278
WiFiClientZephyr()=default
Default constructor.
size_t println(const char *str)
Definition WiFiClientZephyr.h:152
int available()
Definition WiFiClientZephyr.h:175
int _resolve(const char *host, uint16_t port, struct sockaddr *out, socklen_t *outlen)
Definition WiFiClientZephyr.h:291
virtual int connect(const char *host, uint16_t port)
Definition WiFiClientZephyr.h:63
uint8_t _peek_byte
Definition WiFiClientZephyr.h:280
void stop()
Definition WiFiClientZephyr.h:104
int peek()
Definition WiFiClientZephyr.h:246
int read()
Definition WiFiClientZephyr.h:200
int read(uint8_t *buf, size_t size)
Definition WiFiClientZephyr.h:219
size_t write(uint8_t b)
Definition WiFiClientZephyr.h:129
virtual int connect(uint32_t ip, uint16_t port)
Definition WiFiClientZephyr.h:95
int fd() const
Definition WiFiClientZephyr.h:275
size_t println(int value)
Definition WiFiClientZephyr.h:162
uint32_t _timeout_ms
Definition WiFiClientZephyr.h:279
void _applyTimeout()
Definition WiFiClientZephyr.h:283
int connected()
Definition WiFiClientZephyr.h:113
size_t write(const uint8_t *buf, size_t size)
Definition WiFiClientZephyr.h:132
size_t print(const char *str)
Definition WiFiClientZephyr.h:147
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508