3#include "AudioToolsConfig.h"
6# include "WiFiInclude.h"
9#include "AudioTools/CoreAudio/AudioBasic/Str.h"
10#include "AudioTools/Communication/HTTP/AbstractURLStream.h"
11#include "AudioTools/Communication/HTTP/HttpRequest.h"
12#include "AudioTools/Communication/HTTP/URLStreamBufferedT.h"
28 URLStream(
int readBufferSize = DEFAULT_BUFFER_SIZE) {
33 URLStream(
Client& clientPar,
int readBufferSize = DEFAULT_BUFFER_SIZE) {
39 URLStream(
const char* network,
const char* password,
40 int readBufferSize = DEFAULT_BUFFER_SIZE) {
52 if (clientSecure !=
nullptr) {
54 clientSecure =
nullptr;
56 if (clientInsecure !=
nullptr) {
57 delete clientInsecure;
58 clientInsecure =
nullptr;
66 void setSSID(
const char* ssid)
override { this->network = ssid; }
69 void setPassword(
const char* password)
override { this->password = password; }
73 read_buffer_size = readBufferSize;
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);
81 if (!preProcess(
urlStr, acceptMime)) {
82 LOGE(
"preProcess failed");
85 int result = process<const char*>(action, url, reqMime, reqData);
87 size = request.contentLength();
88 LOGI(
"contentLength: %d", (
int)size);
89 if (size >= 0 && wait_for_data) {
94 active = result == 200;
95 LOGI(
"==> http status: %d", result);
101 MethodID action,
const char* reqMime,
Stream& reqData,
103 LOGI(
"%s: %s", LOG_METHOD,
urlStr);
104 if (!preProcess(
urlStr, acceptMime)) {
105 LOGE(
"preProcess failed");
108 int result = process<Stream&>(action, url, reqMime, reqData, len);
110 size = request.contentLength();
111 LOGI(
"size: %d", (
int)size);
112 if (size >= 0 && wait_for_data) {
117 active = result == 200;
118 LOGI(
"==> http status: %d", result);
122 virtual void end()
override {
123 if (active) request.stop();
128 virtual int available()
override {
129 if (!active)
return 0;
131 int result = request.available();
132 LOGD(
"available: %d", result);
136 virtual size_t readBytes(uint8_t* data,
size_t len)
override {
137 if (!active)
return 0;
139 int read = request.read((uint8_t*)&data[0], len);
144 LOGD(
"readBytes %d -> %d", (
int)len, read);
148 virtual int read()
override {
149 if (!active)
return -1;
151 read_buffer.resize(read_buffer_size);
155 return isEOS() ? -1 : read_buffer[read_pos++];
158 virtual int peek()
override {
159 if (!active)
return -1;
161 read_buffer.resize(read_buffer_size);
164 return isEOS() ? -1 : read_buffer[read_pos];
167 virtual void flush()
override {}
169 virtual size_t write(uint8_t)
override {
return not_supported(0); }
171 virtual size_t write(
const uint8_t*,
size_t len)
override {
172 return not_supported(0);
178 operator bool()
override {
return active && request.
isReady(); }
194 httpRequest().setConnection(close ? CON_CLOSE : CON_KEEP_ALIVE);
201 read_buffer.resize(0);
208 request.
header().put(key, value);
212 return request.reply().get(key);
221 void setWaitForData(
bool flag) { wait_for_data = flag; }
229 uint32_t end =
millis() + timeout;
230 if (request.available() == 0) {
231 LOGI(
"Request written ... waiting for reply");
232 while (request.available() == 0) {
233 if (
millis() > end)
break;
235 if (request.reply().statusCode() >= 300) {
236 LOGE(
"Error code recieved ... stop waiting for reply");
242 int avail = request.available();
243 LOGD(
"available: %d", avail);
252 if (clientSecure!=
nullptr) clientSecure->setCACert(cert);
263 uint16_t read_buffer_size = DEFAULT_BUFFER_SIZE;
267 bool wait_for_data =
true;
269 const char* network =
nullptr;
270 const char* password =
nullptr;
271 Client* client =
nullptr;
272 WiFiClient* clientInsecure =
nullptr;
273 WiFiClientSecure* clientSecure =
nullptr;
274 int clientTimeout = URL_CLIENT_TIMEOUT;
275 unsigned long handshakeTimeout = URL_HANDSHAKE_TIMEOUT;
276 bool is_power_save =
false;
278 bool preProcess(
const char*
urlStr,
const char* acceptMime) {
281 url.setUrl(url_str.
c_str());
288 if (client ==
nullptr){
290 LOGE(
"Not connected");
296 if (acceptMime !=
nullptr) {
297 request.setAcceptMime(acceptMime);
301 Client& client =
getClient(url.isSecure());
302 request.setClient(client);
305 client.setTimeout(clientTimeout / 1000);
310 if (clientSecure !=
nullptr) {
311 clientSecure->setHandshakeTimeout(handshakeTimeout);
315 if (!is_power_save) {
316 esp_wifi_set_ps(WIFI_PS_NONE);
324 template <
typename T>
325 int process(MethodID action,
Url& url,
const char* reqMime, T reqData,
329 const char* icy = request.
header().get(
"Icy-MetaData");
331 int status_code = request.process(action, url, reqMime, reqData, len);
334 const char* redirect_url = request.reply().get(LOCATION);
335 if (redirect_url !=
nullptr) {
336 LOGW(
"Redirected to: %s", redirect_url);
337 url.setUrl(redirect_url);
340 request.setClient(*p_client);
342 request.
header().put(
"Icy-MetaData", icy);
344 status_code = request.process(action, url, reqMime, reqData, len);
346 LOGE(
"Location is null");
356 if (clientSecure ==
nullptr) {
357 clientSecure =
new WiFiClientSecure();
358 clientSecure->setInsecure();
360 LOGI(
"WiFiClientSecure");
361 return *clientSecure;
363 if (clientInsecure ==
nullptr) {
364 clientInsecure =
new WiFiClient();
367 return *clientInsecure;
370 inline void fillBuffer() {
373 read_size = readBytes(&read_buffer[0], read_buffer_size);
378 inline bool isEOS() {
return read_pos >= read_size; }
381 if (network !=
nullptr && password !=
nullptr &&
382 WiFi.status() != WL_CONNECTED) {
384 WiFi.begin(network, password);
385 while (WiFi.status() != WL_CONNECTED) {
391 return WiFi.status() == WL_CONNECTED;
393 return WiFi.status() == WL_CONNECTED;
398#if defined(USE_CONCURRENCY)