@@ -36,26 +36,24 @@ const size_t LINE_LENGTH = 72;
3636const char CHARGEN_PATTERN_FULL[] = " !\" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~" ;
3737const size_t PATTERN_LENGTH_FULL = 95 ;
3838
39- #define WIFI_SSID " Your_SSID "
40- #define WIFI_PASSWORD " Your_PASSWORD "
39+ #define WIFI_SSID " WiFi_Pelicano "
40+ #define WIFI_PASSWORD " AcDhDdg7smBLgnUtfcV5t "
4141
42- // --- Global state for a SINGLE client ---
4342// This is the main asynchronous server object
4443AsyncServer* AsyncServerChargen = nullptr ;
4544// This is the pointer to the single connected client
4645AsyncClient* AsyncClientChargen= nullptr ;
4746// This is the pointer to the stream of data.
4847size_t startIndex = 0 ;
4948
50-
51- void makeAndSendLine (); // Forward declaration
49+ void makeAndSendLine (); // Forward declaration
5250
5351// --- Callback Functions ---
5452
5553// Called when the client acknowledges receiving data. We use this to send more.
5654void handleClientAck (void * arg, AsyncClient* client, size_t len, uint32_t time) {
57- if (!client->disconnected () && client->space () > (LINE_LENGTH + 2 )) {
58- makeAndSendLine (); // <--- ¡Aquí está la cadena!
55+ if (!client->disconnected () && client->space () >= (LINE_LENGTH + 2 )) {
56+ makeAndSendLine ();
5957 }
6058}
6159
@@ -64,14 +62,34 @@ void handleClientAck(void* arg, AsyncClient* client, size_t len, uint32_t time)
6462void handleClientPoll (void * arg, AsyncClient* client) {
6563 // We can reuse the same logic as the ACK handler.
6664 // Just try to send more data if there's space.
67- handleClientAck (arg, client, 0 , 0 );
65+ handleClientAck (arg, client, 0 , 0 ); // Original call
66+ }
67+
68+ // It handles errors that are not normal disconnections.
69+ void handleClientError (void * arg, AsyncClient* client, int error) {
70+ // The error codes are defined in esp_err.h
71+ Serial.printf (" Client error! Code: %d, Message: %s\n " , error, client->errorToString (error));
72+
73+ // If the client is the one we have stored, clean it up.
74+ if (AsyncClientChargen == client) {
75+ Serial.println (" Cleaning up global client pointer due to error." );
76+ AsyncClientChargen = nullptr ;
77+ }
78+ // We do not need to call "delete client" here because onDisconnect will do it
79+ // If the error is critical we will do it.
80+ if (client->connected ()) {
81+ client->close ();
82+ }
6883}
6984
7085// Called when the client disconnects.
7186void handleClientDisconnect (void * arg, AsyncClient* client) {
7287 Serial.println (" Client disconnected." );
7388 // Set the global client pointer to null to allow a new client to connect.
74- AsyncClientChargen = nullptr ;
89+ if (AsyncClientChargen == client) {
90+ AsyncClientChargen = nullptr ;
91+ }
92+ delete client;
7593}
7694
7795// Called when a new client tries to connect.
@@ -88,10 +106,20 @@ void handleClient(void* arg, AsyncClient* client) {
88106 AsyncClientChargen = client;
89107 startIndex = 0 ; // Reset pattern for the new client.
90108
91- // Set up callbacks for the new client.
109+ // Called when previously sent data is acknowledged by the client.
110+ // This is the core engine for continuous data transmission (Chargen).
92111 AsyncClientChargen->onAck (handleClientAck, nullptr );
93- // onPoll is a good backup to send data if the buffer was full.
112+
113+ // Called periodically by the AsyncTCP task.
114+ // Serves as a backup to resume transmission if the buffer was full and the ACK wasn't received.
94115 AsyncClientChargen->onPoll (handleClientPoll, nullptr );
116+
117+ // Called when a communication error (e.g., protocol failure or timeout) occurs.
118+ // Essential for cleaning up the global client pointer and preventing resource leaks.
119+ AsyncClientChargen->onError (handleClientError, nullptr );
120+
121+ // Called when the client actively closes the connection or if a fatal error occurs.
122+ // Responsible for resetting the global client pointer and freeing memory.
95123 AsyncClientChargen->onDisconnect (handleClientDisconnect, nullptr );
96124
97125 // Start sending data immediately.
0 commit comments