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)