arduino-audio-tools
Loading...
Searching...
No Matches
URLStream.h
Go to the documentation of this file.
1#pragma once
2
3#include "AudioToolsConfig.h"
4
5#if defined(USE_WIFI)
6# include "WiFiInclude.h"
7#endif
8
13
14namespace audio_tools {
15
27 public:
32
38
46
47 URLStream(const URLStream&) = delete;
48
50 TRACED();
51 end();
52 if (client_secure != nullptr) {
53 delete client_secure;
54 client_secure = nullptr;
55 }
56 if (client_insecure != nullptr) {
57 delete client_insecure;
58 client_insecure = nullptr;
59 }
60 }
61
63 void setClient(Client& clientPar) override { client = &clientPar; }
64
66 void setSSID(const char* ssid) override { this->network = ssid; }
67
69 void setPassword(const char* password) override { this->password = password; }
70
75
77 virtual bool begin(const char* urlStr, const char* acceptMime = nullptr,
78 MethodID action = GET, const char* reqMime = "",
79 const char* reqData = "") override {
80 LOGI("%s: %s", LOG_METHOD, urlStr);
82 LOGE("preProcess failed");
83 return false;
84 }
86 if (result > 0) {
88 LOGI("contentLength: %d", (int)content_length);
89 if (content_length >= 0 && wait_for_data) {
91 }
92 }
93 total_read = 0;
94 active = result == 200;
95 LOGI("==> http status: %d", result);
96 return active;
97 }
98
100 virtual bool begin(const char* urlStr, const char* acceptMime,
101 MethodID action, const char* reqMime, Stream& reqData,
102 int len = -1) {
103 LOGI("%s: %s", LOG_METHOD, urlStr);
105 LOGE("preProcess failed");
106 return false;
107 }
108 int result = process<Stream&>(action, url, reqMime, reqData, len);
109 if (result > 0) {
111 LOGI("size: %d", (int)content_length);
112 if (content_length >= 0 && wait_for_data) {
114 }
115 }
116 total_read = 0;
117 active = result == 200;
118 LOGI("==> http status: %d", result);
119 return active;
120 }
121
123 virtual void end() override {
124 if (active) request.stop();
125 active = false;
126 clear();
127 }
128
129 virtual int available() override {
130 if (!active) return 0;
131
132 int result = request.available();
133 LOGD("available: %d", result);
134 return result;
135 }
136
137 virtual size_t readBytes(uint8_t* data, size_t len) override {
138 if (!active) return 0;
139
140 int read = request.read(data, len);
141 if (read < 0) {
142 read = 0;
143 }
144 total_read += read;
145 LOGD("readBytes %d -> %d", (int)len, read);
146 return read;
147 }
148
149 virtual int read() override {
150 if (!active) return -1;
151 // lazy allocation since this is rarely used
153
154 fillBuffer();
155 total_read++;
156 return isEOS() ? -1 : read_buffer[read_pos++];
157 }
158
159 virtual int peek() override {
160 if (!active) return -1;
161 // lazy allocation since this is rarely used
163
164 fillBuffer();
165 return isEOS() ? -1 : read_buffer[read_pos];
166 }
167
168 virtual void flush() override {}
169
170 virtual size_t write(uint8_t) override { return not_supported(0); }
171
172 virtual size_t write(const uint8_t*, size_t len) override {
173 return not_supported(0);
174 }
175
177 virtual HttpRequest& httpRequest() override { return request; }
178
179 operator bool() override { return active && request.isReady(); }
180
182 virtual void setTimeout(int ms) { client_timeout = ms; }
183
186 void setPowerSave(bool ps) override { is_power_save = ps; }
187
192
194 void setConnectionClose(bool close) override {
196 }
197
199 void clear() {
200 httpRequest().reply().clear();
203 read_pos = 0;
204 read_size = 0;
205 }
206
208 void addRequestHeader(const char* key, const char* value) override {
209 request.header().put(key, value);
210 }
211
213 const char* getReplyHeader(const char* key) override {
214 return request.reply().get(key);
215 }
216
218 void setOnConnectCallback(void (*callback)(
219 HttpRequest& request, Url& url, HttpRequestHeader& request_header)) {
221 }
222
225
227 int contentLength() override { return content_length; }
228
230 size_t totalRead() override { return total_read; }
231
233 bool waitForData (int timeout) override{
234 TRACED();
235 uint32_t end = millis() + timeout;
236 if (request.available() == 0) {
237 LOGI("Request written ... waiting for reply");
238 while (request.available() == 0) {
239 if (millis() > end) break;
240 // stop waiting if we got an error
241 if (request.reply().statusCode() >= 300) {
242 LOGE("Error code recieved ... stop waiting for reply");
243 break;
244 }
245 delay(500);
246 }
247 }
248 int avail = request.available();
249 LOGD("available: %d", avail);
250 return avail > 0;
251 }
252
254 const char* urlStr() override { return url_str.c_str(); }
255
257 void setCACert(const char* cert) override{
258 if (client_secure!=nullptr) client_secure->setCACert(cert);
259 }
260
262 size_t size() { return content_length; }
263
264 protected:
269 long total_read = 0;
270 // buffered single byte read
275 bool active = false;
276 bool wait_for_data = true;
277 Client* client = nullptr; // client defined via setClient
278 WiFiClient* client_insecure = nullptr; // wifi client for http
279 WiFiClientSecure* client_secure = nullptr; // wifi client for https
281 unsigned long handshake_timeout = URL_HANDSHAKE_TIMEOUT; // 120000
282 bool is_power_save = false;
283 // optional
284 const char* network = nullptr;
285 const char* password = nullptr;
286
287 bool preProcess(const char* urlStr, const char* acceptMime) {
288 TRACED();
289 url_str = urlStr;
291 int result = -1;
292
293 // close it - if we have an active connection
294 if (active) end();
295
296 // optional: login if necessary if no external client is defined
297 if (client == nullptr){
298 if (!login()){
299 LOGE("Not connected");
300 return false;
301 }
302 }
303
304 // request.reply().setAutoCreateLines(false);
305 if (acceptMime != nullptr) {
307 }
308
309 // setup client
313
314#if defined(ESP32)
315 // Performance optimization for ESP32
316 if (!is_power_save) {
318 }
319#endif
320
321 return true;
322 }
323
325 template <typename T>
327 int len = -1) {
328 TRACED();
329 // keep icy across redirect requests ?
330 const char* icy = request.header().get("Icy-MetaData");
331
332 int status_code = request.process(action, url, reqMime, reqData, len);
333 // redirect
334 while (request.reply().isRedirectStatus()) {
335 const char* redirect_url = request.reply().get(LOCATION);
336 if (redirect_url != nullptr) {
337 LOGW("Redirected to: %s", redirect_url);
339 Client* p_client = &getClient(url.isSecure());
340 p_client->stop();
341 request.setClient(*p_client);
342 if (icy) {
343 request.header().put("Icy-MetaData", icy);
344 }
345 status_code = request.process(action, url, reqMime, reqData, len);
346 } else {
347 LOGE("Location is null");
348 break;
349 }
350 }
351 return status_code;
352 }
353
355 Client& getClient(bool isSecure) {
356 if (isSecure) {
357 if (client_secure == nullptr) {
359 client_secure->setInsecure();
360 client_secure->setTimeout(client_timeout);
361#ifdef ESP32
362 client_secure->setConnectionTimeout(client_timeout);
363 client_secure->setHandshakeTimeout(handshake_timeout);
364#endif
365#ifdef RP2040_HOWER
366 client_secure->setTLSConnectTimeout(client_timeout);
367#endif
368 }
369 LOGI("WiFiClientSecure");
370 return *client_secure;
371 }
372 if (client_insecure == nullptr) {
374 client_insecure->setTimeout(client_timeout);
375#ifdef ESP32
376 client_insecure->setConnectionTimeout(client_timeout);
377#endif
378 LOGI("WiFiClient");
379 }
380 return *client_insecure;
381 }
382
383 inline void fillBuffer() {
384 if (isEOS()) {
385 // if we consumed all bytes we refill the buffer
387 read_pos = 0;
388 }
389 }
390
391 inline bool isEOS() { return read_pos >= read_size; }
392
393 bool login() {
394 if (network != nullptr && password != nullptr &&
395 WiFi.status() != WL_CONNECTED) {
396 TRACEI();
397 WiFi.begin(network, password);
398 while (WiFi.status() != WL_CONNECTED) {
399 Serial.print(".");
400 delay(500);
401 }
402 Serial.println();
403 delay(10);
404 return WiFi.status() == WL_CONNECTED;
405 }
406 return WiFi.status() == WL_CONNECTED;
407 }
408};
409
410
411#if defined(USE_CONCURRENCY)
414
415#endif
416
417} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define LOG_METHOD
Definition AudioToolsConfig.h:64
MethodID
supported http methods
Definition HttpTypes.h:3
@ GET
Definition HttpTypes.h:5
WiFiClient WiFiClientSecure
Definition desktop.h:39
#define DEFAULT_BUFFER_SIZE
Definition avr.h:20
Abstract Base class for all URLStream implementations.
Definition AbstractURLStream.h:17
virtual int not_supported(int out, const char *msg="")
Definition BaseStream.h:176
Definition NoArduino.h:169
void stop()
Definition NoArduino.h:171
HttpHeader & clear()
clears the data
Definition HttpHeader.h:74
int statusCode()
Definition HttpHeader.h:206
HttpHeader & put(const char *key, const char *value)
Definition HttpHeader.h:86
bool isRedirectStatus()
returns true if the status code is >=300 and < 400
Definition HttpHeader.h:297
void setAutoCreateLines(bool is_auto_line)
automatically create new lines
Definition HttpHeader.h:289
const char * get(const char *key)
Definition HttpHeader.h:151
Reading and writing of Http Requests.
Definition HttpHeader.h:394
Simple API to process get, put, post, del http requests I tried to use Arduino HttpClient,...
Definition HttpRequest.h:25
void setTimeout(size_t timeoutMs)
Defines the client timeout in ms.
Definition HttpRequest.h:349
virtual HttpReplyHeader & reply()
Definition HttpRequest.h:165
virtual int process(MethodID action, Url &url, const char *mime, const char *data, int lenData=-1)
Definition HttpRequest.h:209
size_t contentLength()
Definition HttpRequest.h:183
int available() override
Definition HttpRequest.h:56
virtual void setConnection(const char *connection)
Definition HttpRequest.h:173
void setClient(Client &client)
Definition HttpRequest.h:37
void setOnConnectCallback(void(*callback)(HttpRequest &request, Url &url, HttpRequestHeader &request_header))
Callback which allows you to add additional paramters dynamically.
Definition HttpRequest.h:343
virtual int read(uint8_t *str, int len)
Definition HttpRequest.h:130
bool isReady()
Definition HttpRequest.h:196
virtual void stop()
Definition HttpRequest.h:78
virtual HttpRequestHeader & header()
provides access to the request header
Definition HttpRequest.h:168
virtual void setAcceptMime(const char *mime)
Definition HttpRequest.h:181
Str which keeps the data on the heap. We grow the allocated memory only if the copy source is not fit...
Definition Str.h:24
virtual const char * c_str()
provides the string value as const char*
Definition StrView.h:379
Definition NoArduino.h:142
URLStream implementation for the ESP32 based on a separate FreeRTOS task: the.
Definition URLStreamBufferedT.h:162
Represents the content of a URL as Stream. We use the WiFi.h API. If you run into performance issues,...
Definition URLStream.h:26
Client * client
Definition URLStream.h:277
bool active
Definition URLStream.h:275
size_t size()
Returns the content length of the request.
Definition URLStream.h:262
size_t totalRead() override
returns the total number of bytes read from the stream
Definition URLStream.h:230
WiFiClient * client_insecure
Definition URLStream.h:278
void fillBuffer()
Definition URLStream.h:383
bool preProcess(const char *urlStr, const char *acceptMime)
Definition URLStream.h:287
bool wait_for_data
Definition URLStream.h:276
virtual int read() override
Definition URLStream.h:149
long total_read
Definition URLStream.h:269
HttpRequest request
Definition URLStream.h:265
bool login()
Definition URLStream.h:393
virtual bool begin(const char *urlStr, const char *acceptMime=nullptr, MethodID action=GET, const char *reqMime="", const char *reqData="") override
Execute http request: by default we use a GET request.
Definition URLStream.h:77
const char * network
Definition URLStream.h:284
uint16_t read_size
Definition URLStream.h:274
virtual void setTimeout(int ms)
Defines the client timeout in ms.
Definition URLStream.h:182
bool waitForData(int timeout) override
Waits for some data - returns false if the request has failed.
Definition URLStream.h:233
void setConnectionClose(bool close) override
Sets if the connection should be close automatically.
Definition URLStream.h:194
~URLStream()
Definition URLStream.h:49
virtual size_t readBytes(uint8_t *data, size_t len) override
Definition URLStream.h:137
uint16_t read_buffer_size
Definition URLStream.h:272
void setReadBufferSize(int readBufferSize)
Defines the buffer that is used by individual read() or peek() calls.
Definition URLStream.h:72
WiFiClientSecure * client_secure
Definition URLStream.h:279
void setPowerSave(bool ps) override
Definition URLStream.h:186
Client & getClient(bool isSecure)
Determines the client.
Definition URLStream.h:355
int client_timeout
Definition URLStream.h:280
void setWaitForData(bool flag)
Defines if the stream should wait for data after the request has been sent.
Definition URLStream.h:224
virtual size_t write(uint8_t) override
Definition URLStream.h:170
int process(MethodID action, Url &url, const char *reqMime, T reqData, int len=-1)
Process the Http request and handle redirects.
Definition URLStream.h:326
Url url
Definition URLStream.h:267
Str url_str
Definition URLStream.h:266
void addRequestHeader(const char *key, const char *value) override
Adds/Updates a request header.
Definition URLStream.h:208
virtual int peek() override
Definition URLStream.h:159
URLStream(int readBufferSize=DEFAULT_BUFFER_SIZE)
Definition URLStream.h:28
URLStream(const URLStream &)=delete
const char * password
Definition URLStream.h:285
void setSSID(const char *ssid) override
Sets the ssid that will be used for logging in (when calling begin)
Definition URLStream.h:66
URLStream(const char *network, const char *password, int readBufferSize=DEFAULT_BUFFER_SIZE)
Definition URLStream.h:39
virtual size_t write(const uint8_t *, size_t len) override
Definition URLStream.h:172
virtual bool begin(const char *urlStr, const char *acceptMime, MethodID action, const char *reqMime, Stream &reqData, int len=-1)
Execute e.g. http POST request which submits the content as a stream.
Definition URLStream.h:100
const char * urlStr() override
returns the url as string
Definition URLStream.h:254
bool isEOS()
Definition URLStream.h:391
void setClient(Client &clientPar) override
(Re-)defines the client
Definition URLStream.h:63
Vector< uint8_t > read_buffer
Definition URLStream.h:271
void setCACert(const char *cert) override
Define the Root PEM Certificate for SSL.
Definition URLStream.h:257
void setOnConnectCallback(void(*callback)(HttpRequest &request, Url &url, HttpRequestHeader &request_header))
Callback which allows you to add additional paramters dynamically.
Definition URLStream.h:218
URLStream(Client &clientPar, int readBufferSize=DEFAULT_BUFFER_SIZE)
Definition URLStream.h:33
void clear()
Releases the memory from the request and reply.
Definition URLStream.h:199
uint16_t read_pos
Definition URLStream.h:273
int contentLength() override
returns the content length
Definition URLStream.h:227
void setAutoCreateLines(bool flag)
If set to true, new undefined reply parameters will be stored.
Definition URLStream.h:189
unsigned long handshake_timeout
Definition URLStream.h:281
void setPassword(const char *password) override
Sets the password that will be used for logging in (when calling begin)
Definition URLStream.h:69
virtual void end() override
Ends the request and releases the memory.
Definition URLStream.h:123
long content_length
Definition URLStream.h:268
virtual HttpRequest & httpRequest() override
provides access to the HttpRequest
Definition URLStream.h:177
bool is_power_save
Definition URLStream.h:282
virtual void flush() override
Definition URLStream.h:168
virtual int available() override
Definition URLStream.h:129
const char * getReplyHeader(const char *key) override
Provides the value of the reply header for the given key.
Definition URLStream.h:213
URL parser which breaks a full url string up into its individual parts.
Definition Url.h:22
bool isSecure()
Definition Url.h:42
void setUrl(const char *url)
Definition Url.h:44
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(int newSize, T value)
Definition Vector.h:266
#define URL_CLIENT_TIMEOUT
Definition esp8266.h:23
#define URL_HANDSHAKE_TIMEOUT
Definition esp8266.h:24
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
void delay(unsigned long ms)
Definition Time.h:23
static HardwareSerial Serial
Definition NoArduino.h:186
static const char * LOCATION
Definition HttpHeader.h:32
static const char * CON_KEEP_ALIVE
Definition HttpHeader.h:20
static const char * CON_CLOSE
Definition HttpHeader.h:19
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512