Skip to content

Conversation

@mathieucarbou
Copy link
Member

No description provided.

@mathieucarbou
Copy link
Member Author

This PR adds a LargeResponse example that we did not have in the project to show the usage of a custom response and the AwsResponseFiller callback.

This example was also built in order to serve as a MRE for these 2 issues:

Endpoint using AwsResponseFiller

curl -v http://192.168.4.1/1 | grep -o '.' | sort | uniq -c

5652 A
4308 B
5760 C
 280 D

ESP32:

Filling 'A' @ index: 0, maxLen: 5652, toSend: 5652
Filling 'B' @ index: 5652, maxLen: 4308, toSend: 4308
Filling 'C' @ index: 9960, maxLen: 5760, toSend: 5760
Filling 'D' @ index: 15720, maxLen: 280, toSend: 280

Endpoint with a custom response:

curl -v http://192.168.4.1/2 | grep -o '.' | sort | uniq -c

5675 A
4308 B
2888 C
3129 D

ESP32:

Filling 'A' @ sent: 0, buflen: 5675
Filling 'B' @ sent: 5675, buflen: 4308
Filling 'C' @ sent: 9983, buflen: 2888
Filling 'D' @ sent: 12871, buflen: 3129

So everything works fine in the example.
I am sending 16K, I receive 16K and I also receive the right number of characters.

@mathieucarbou
Copy link
Member Author

@ESP32Async/devs : build pass. I am going to merge in main do that we can rebase and use these examples as a base to work on for the prs / fixes. Let me know if something is off otherwise i will merge. Thank you!

@vortigont
Copy link

looks OK to me, but with a quick test on my side it also does not reproduce the issue - strange. Will play with it more tomorrow

@mathieucarbou mathieucarbou merged commit b67f0e9 into main Oct 19, 2025
31 checks passed
@mathieucarbou
Copy link
Member Author

For now i will merge - these are good examples we do not have. And besides they will be helpful for your tests ;-)

@mathieucarbou mathieucarbou deleted the examples/LargeResponse branch October 20, 2025 08:09
@vortigont
Copy link

I cracked it.

So this is how it works:
That space that _tcp is writing to identified by CONFIG_TCP_SND_BUF_DEFAULT (and is value-matching with default TCP windows size which is very confusing itself).
The space returned by client()->write() and client->space() somehow might not be atomically/thread synced (had not dived that deep yet). So if first call to _fillBuffer is done via user-code thread and ended up with some small amount of data consumed and second one is done by _poll or _ack? returns full size again! This is where old code fails.

If you change your class this way it will fail 100%.

class CustomResponse : public AsyncAbstractResponse {
public:
  explicit CustomResponse() {
    _code = 200;
    _contentType = "text/plain";
    _sendContentLength = false;
    // add some useless headers
    addHeader("Clear-Site-Data", "Clears browsing data (e.g., cookies, storage, cache) associated with the requesting website.");
    addHeader("No-Vary-Search", "Specifies a set of rules that define how a URL's query parameters will affect cache matching. These rules dictate whether the same URL with different URL parameters should be saved as separate browser cache entries");
  }

  bool _sourceValid() const override {
    return true;
  }

  size_t _fillBuffer(uint8_t *buf, size_t buflen) override {
    if (fillChar == NULL){
      fillChar = 'A';
      return RESPONSE_TRY_AGAIN;
    }
    if (_sent == RESPONSE_TRY_AGAIN) {
      Serial.println("Simulating temporary unavailability of data...");
      _sent = 0;
      return RESPONSE_TRY_AGAIN;
    }
    size_t remaining = totalResponseSize - _sent;
    if (remaining == 0) {
      return 0;
    }
    if (buflen > remaining) {
      buflen = remaining;
    }
    Serial.printf("Filling '%c' @ sent: %u, buflen: %u\n", fillChar, _sent, buflen);
    std::fill_n(buf, buflen, static_cast<uint8_t>(fillChar));
    _sent += buflen;
    fillChar = (fillChar == 'Z') ? 'A' : fillChar + 1;
    return buflen;
  }

private:
  char fillChar = NULL; //'A';
  size_t _sent = 0;
};

@mathieucarbou
Copy link
Member Author

@vortigont : thanks ! I will push an update to the example in the working branch of your PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants