Skip to content

Commit 5b0dc29

Browse files
committed
refactoring
1 parent 73af7f0 commit 5b0dc29

File tree

3 files changed

+227
-205
lines changed

3 files changed

+227
-205
lines changed

src/core/AsyncClient/AsyncClient.h

Lines changed: 31 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* 2025-01-25
2+
* 2025-01-26
33
*
44
* For MCU build target (CORE_ARDUINO_XXXX), see Options.h.
55
*
@@ -218,6 +218,8 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
218218

219219
void newCon(async_data *sData, const char *host, uint16_t port)
220220
{
221+
sData->request.setClient(client_type, client, async_tcp_config);
222+
sData->response.setClient(client_type, client, async_tcp_config);
221223

222224
if ((!sData->sse && session_timeout_sec >= FIREBASE_SESSION_TIMEOUT_SEC && session_timer.remaining() == 0) || (sse && !sData->sse) || (!sse && sData->sse) || (sData->auth_used && sData->state == astate_undefined) ||
223225
strcmp(this->host.c_str(), host) != 0 || this->port != port)
@@ -403,7 +405,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
403405
{
404406
uint16_t toSend = len - sData->request.dataIndex > FIREBASE_CHUNK_SIZE ? FIREBASE_CHUNK_SIZE : len - sData->request.dataIndex;
405407

406-
size_t sent = sData->request.tcpWrite(client_type, client, async_tcp_config, data + sData->request.dataIndex, toSend);
408+
size_t sent = sData->request.tcpWrite(data + sData->request.dataIndex, toSend);
407409
sys_idle();
408410

409411
if (sent == toSend)
@@ -716,7 +718,6 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
716718

717719
void returnResult(async_data *sData, bool setData)
718720
{
719-
720721
bool error_notify_timeout = false;
721722
if (sData->err_timer.remaining() == 0)
722723
{
@@ -800,52 +801,14 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
800801
}
801802
}
802803

803-
int readLine(async_data *sData, String &buf)
804-
{
805-
int p = 0;
806-
807-
while (sData->response.tcpAvailable(client_type, client, async_tcp_config))
808-
{
809-
int res = sData->response.tcpRead(client_type, client, async_tcp_config);
810-
if (res > -1)
811-
{
812-
buf += (char)res;
813-
p++;
814-
if (res == '\n')
815-
return p;
816-
}
817-
}
818-
return p;
819-
}
820-
821-
uint32_t hex2int(const char *hex)
822-
{
823-
uint32_t val = 0;
824-
while (*hex)
825-
{
826-
// get current character then increment
827-
uint8_t byte = *hex++;
828-
// transform hex character to the 4bit equivalent number, using the ascii table indexes
829-
if (byte >= '0' && byte <= '9')
830-
byte = byte - '0';
831-
else if (byte >= 'a' && byte <= 'f')
832-
byte = byte - 'a' + 10;
833-
else if (byte >= 'A' && byte <= 'F')
834-
byte = byte - 'A' + 10;
835-
// shift 4 to make space for new digit, and add the 4 bits of the new digit
836-
val = (val << 4) | (byte & 0xF);
837-
}
838-
return val;
839-
}
840-
841804
void clear(String &str) { sut.clear(str); }
842805

843806
bool readResponse(async_data *sData)
844807
{
845808
if (!client || !sData)
846809
return false;
847810

848-
if (sData->response.tcpAvailable(client_type, client, async_tcp_config) > 0)
811+
if (sData->response.tcpAvailable() > 0)
849812
{
850813
// status line or data?
851814
if (!readStatusLine(sData))
@@ -885,7 +848,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
885848
// Prevent sse timeout due to large sse Stream playload
886849
feedSSETimer(&sData->aResult.rtdbResult);
887850

888-
if ((*payload)[payload->length() - 1] == '\n' && sData->response.tcpAvailable(client_type, client, async_tcp_config) == 0)
851+
if ((*payload)[payload->length() - 1] == '\n' && sData->response.tcpAvailable() == 0)
889852
{
890853
setRefPayload(&sData->aResult.rtdbResult, payload);
891854
parseSSE(&sData->aResult.rtdbResult);
@@ -925,28 +888,16 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
925888
return true;
926889
}
927890

928-
int getStatusCode(const String &header)
929-
{
930-
String out;
931-
int p1 = header.indexOf("HTTP/1.");
932-
if (p1 > -1)
933-
{
934-
out = header.substring(p1 + 9, header.indexOf(' ', p1 + 9));
935-
return atoi(out.c_str());
936-
}
937-
return 0;
938-
}
939-
940891
bool readStatusLine(async_data *sData)
941892
{
942893
if (sData->response.httpCode > 0)
943894
return false;
944895

945896
sData->response.val[resns::header].reserve(1024);
946897

947-
// the first chunk (line) can be http response status or already connected stream payload
948-
readLine(sData, sData->response.val[resns::header]);
949-
int status = getStatusCode(sData->response.val[resns::header]);
898+
// The first chunk (line) can be http response status or already connected stream payload
899+
sData->response.readLine();
900+
int status = sData->response.getStatusCode();
950901
if (status > 0)
951902
{
952903
// http response status
@@ -960,56 +911,53 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
960911
{
961912
if (sData->response.flags.header_remaining)
962913
{
963-
int read = readLine(sData, sData->response.val[resns::header]);
914+
int read = sData->response.readLine();
964915
if ((read == 1 && sData->response.val[resns::header][sData->response.val[resns::header].length() - 1] == '\n') ||
965916
(read == 2 && sData->response.val[resns::header][sData->response.val[resns::header].length() - 2] == '\r' && sData->response.val[resns::header][sData->response.val[resns::header].length() - 1] == '\n'))
966917
{
967918
sData->response.flags.http_response = true;
968919
clear(sData->response.val[resns::etag]);
969-
String temp[5];
920+
String temp;
970921
#if defined(ENABLE_CLOUD_STORAGE)
971922
if (sData->upload)
972-
parseRespHeader(sData, sData->response.val[resns::header], sData->request.file_data.resumable.getLocationRef(), "Location");
923+
sData->response.parseRespHeader(sData->request.file_data.resumable.getLocationRef(), "Location");
973924
#else
974-
parseRespHeader(sData, sData->response.val[resns::header], sData->response.val[resns::location], "Location");
925+
sData->response.parseRespHeader(sData->response.val[resns::location], "Location");
975926

976927
#endif
977-
parseRespHeader(sData, sData->response.val[resns::header], sData->response.val[resns::etag], "ETag");
928+
sData->response.parseRespHeader(sData->response.val[resns::etag], "ETag");
978929
resETag = sData->response.val[resns::etag];
979930
sData->aResult.val[ares_ns::res_etag] = sData->response.val[resns::etag];
980931
sData->aResult.val[ares_ns::data_path] = sData->request.val[reqns::path];
981932
#if defined(ENABLE_DATABASE)
982933
setNullETagOption(&sData->aResult.rtdbResult, sData->response.val[resns::etag].indexOf("null_etag") > -1);
983934
#endif
984935

985-
parseRespHeader(sData, sData->response.val[resns::header], temp[0], "Content-Length");
936+
sData->response.parseRespHeader(temp, "Content-Length");
937+
sData->response.payloadLen = atoi(temp.c_str());
986938

987-
sData->response.payloadLen = atoi(temp[0].c_str());
939+
sData->response.parseRespHeader(temp, "Connection");
940+
sData->response.flags.keep_alive = temp.length() && temp.indexOf("keep-alive") > -1;
988941

989-
parseRespHeader(sData, sData->response.val[resns::header], temp[1], "Connection");
990-
sData->response.flags.keep_alive = temp[1].length() && temp[1].indexOf("keep-alive") > -1;
942+
sData->response.parseRespHeader(temp, "Transfer-Encoding");
943+
sData->response.flags.chunks = temp.length() && temp.indexOf("chunked") > -1;
991944

992-
parseRespHeader(sData, sData->response.val[resns::header], temp[2], "Transfer-Encoding");
993-
sData->response.flags.chunks = temp[2].length() && temp[2].indexOf("chunked") > -1;
994-
995-
parseRespHeader(sData, sData->response.val[resns::header], temp[3], "Content-Type");
996-
sData->response.flags.sse = temp[3].length() && temp[3].indexOf("text/event-stream") > -1;
945+
sData->response.parseRespHeader(temp, "Content-Type");
946+
sData->response.flags.sse = temp.length() && temp.indexOf("text/event-stream") > -1;
997947

998948
if (sData->upload)
999-
parseRespHeader(sData, sData->response.val[resns::header], temp[4], "Range");
949+
sData->response.parseRespHeader(temp, "Range");
1000950

1001951
clear(sData);
1002952

1003953
#if defined(ENABLE_CLOUD_STORAGE)
1004954
if (sData->upload && sData->request.file_data.resumable.isEnabled())
1005955
{
1006956
sData->request.file_data.resumable.setHeaderState();
1007-
if (sData->response.httpCode == FIREBASE_ERROR_HTTP_CODE_PERMANENT_REDIRECT && temp[4].indexOf("bytes=") > -1)
957+
if (sData->response.httpCode == FIREBASE_ERROR_HTTP_CODE_PERMANENT_REDIRECT && temp.indexOf("bytes=") > -1)
1008958
sData->request.file_data.resumable.updateRange();
1009959
}
1010960
#endif
1011-
for (size_t i = 0; i < 5; i++)
1012-
sut.clear(temp[i]);
1013961

1014962
if (sData->response.httpCode > 0 && sData->response.httpCode != FIREBASE_ERROR_HTTP_CODE_NO_CONTENT)
1015963
sData->response.flags.payload_remaining = true;
@@ -1023,121 +971,6 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
1023971
}
1024972
}
1025973

1026-
void parseRespHeader(async_data *sData, const String &src, String &out, const char *header)
1027-
{
1028-
if (sData->response.httpCode > 0)
1029-
{
1030-
int p1 = -1, p2 = -1, p3 = -1;
1031-
p1 = src.indexOf(header);
1032-
if (p1 > -1)
1033-
p2 = src.indexOf(':', p1);
1034-
1035-
if (p2 > -1)
1036-
p3 = src.indexOf("\r\n", p2);
1037-
1038-
if (p2 > -1 && p3 > -1)
1039-
out = src.substring(p2 + 1, p3);
1040-
1041-
out.trim();
1042-
}
1043-
}
1044-
1045-
int getChunkSize(async_data *sData, Client *client, String &line)
1046-
{
1047-
if (line.length() == 0)
1048-
readLine(sData, line);
1049-
1050-
int p = line.indexOf(";");
1051-
if (p == -1)
1052-
p = line.indexOf("\r\n");
1053-
if (p != -1)
1054-
sData->response.chunkInfo.chunkSize = hex2int(line.substring(0, p).c_str());
1055-
1056-
return sData->response.chunkInfo.chunkSize;
1057-
}
1058-
1059-
// Returns -1 when complete
1060-
int decodeChunks(async_data *sData, Client *client, String *out)
1061-
{
1062-
if (!client || !sData || !out)
1063-
return 0;
1064-
int res = 0, read = 0;
1065-
String line;
1066-
1067-
// because chunks might span multiple reads, we need to keep track of where we are in the chunk
1068-
// chunkInfo.dataLen is our current position in the chunk
1069-
// chunkInfo.chunkSize is the total size of the chunk
1070-
1071-
// readline() only reads while there is data available, so it might return early
1072-
// when available() is less than the remaining amount of data in the chunk
1073-
1074-
// read chunk-size, chunk-extension (if any) and CRLF
1075-
if (sData->response.chunkInfo.phase == res_handler::READ_CHUNK_SIZE)
1076-
{
1077-
sData->response.chunkInfo.phase = res_handler::READ_CHUNK_DATA;
1078-
sData->response.chunkInfo.chunkSize = -1;
1079-
sData->response.chunkInfo.dataLen = 0;
1080-
res = getChunkSize(sData, client, line);
1081-
sData->response.payloadLen += res > -1 ? res : 0;
1082-
}
1083-
// read chunk-data and CRLF
1084-
// append chunk-data to entity-body
1085-
else
1086-
{
1087-
// if chunk-size is 0, it's the last chunk, and can be skipped
1088-
if (sData->response.chunkInfo.chunkSize > 0)
1089-
{
1090-
read = readLine(sData, line);
1091-
1092-
// if we read till a CRLF, we have a chunk (or the rest of it)
1093-
// if the last two bytes are NOT CRLF, we have a partial chunk
1094-
// if we read 0 bytes, read next chunk size
1095-
1096-
// check for \n and \r, remove them if present (they're part of the protocol, not the data)
1097-
if (read >= 2 && line[read - 2] == '\r' && line[read - 1] == '\n')
1098-
{
1099-
// last chunk?
1100-
if (line[0] == '0')
1101-
return -1;
1102-
1103-
// remove the \r\n
1104-
line.remove(line.length() - 2);
1105-
read -= 2;
1106-
}
1107-
1108-
// if we still have data, append it and update the chunkInfo
1109-
if (read)
1110-
{
1111-
*out += line;
1112-
sData->response.chunkInfo.dataLen += read;
1113-
sData->response.payloadRead += read;
1114-
1115-
// check if we're done reading this chunk
1116-
if (sData->response.chunkInfo.dataLen == sData->response.chunkInfo.chunkSize)
1117-
sData->response.chunkInfo.phase = res_handler::READ_CHUNK_SIZE;
1118-
}
1119-
// if we read 0 bytes, read next chunk size
1120-
else
1121-
{
1122-
sData->response.chunkInfo.phase = res_handler::READ_CHUNK_SIZE;
1123-
}
1124-
}
1125-
else
1126-
{
1127-
1128-
read = readLine(sData, line);
1129-
1130-
// CRLF (end of chunked body)
1131-
if (read == 2 && line[0] == '\r' && line[1] == '\n')
1132-
res = -1;
1133-
else // another chunk?
1134-
getChunkSize(sData, client, line);
1135-
}
1136-
}
1137-
1138-
return res;
1139-
}
1140-
1141974
bool readPayload(async_data *sData)
1142975
{
1143976
uint8_t *buf = nullptr;
@@ -1154,7 +987,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
1154987
{
1155988
// Use temporary String buffer for decodeChunks
1156989
String temp;
1157-
int res = decodeChunks(sData, client, &temp);
990+
int res = sData->response.decodeChunks(&temp);
1158991
if (temp.length())
1159992
{
1160993
reserveString(sData);
@@ -1216,7 +1049,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
12161049
ofs = sData->request.base64 && sData->response.payloadRead == 0 ? 1 : 0;
12171050
toRead = (int)(sData->response.payloadLen - sData->response.payloadRead) > FIREBASE_CHUNK_SIZE + ofs ? FIREBASE_CHUNK_SIZE + ofs : sData->response.payloadLen - sData->response.payloadRead;
12181051
buf = reinterpret_cast<uint8_t *>(mem.alloc(toRead));
1219-
read = sData->response.tcpRead(client_type, client, async_tcp_config, buf, toRead);
1052+
read = sData->response.tcpRead(buf, toRead);
12201053
}
12211054

12221055
if (read > 0)
@@ -1316,7 +1149,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
13161149
{
13171150
// Use temporary String buffer for readLine
13181151
String temp;
1319-
size_t len = readLine(sData, temp);
1152+
size_t len = sData->response.readLine(&temp);
13201153
sData->response.payloadRead += len;
13211154
reserveString(sData);
13221155
sData->response.val[resns::payload] += temp;
@@ -1329,7 +1162,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
13291162
if (buf)
13301163
mem.release(&buf);
13311164

1332-
if (sData->response.payloadLen > 0 && sData->response.payloadRead >= sData->response.payloadLen && sData->response.tcpAvailable(client_type, client, async_tcp_config) == 0)
1165+
if (sData->response.payloadLen > 0 && sData->response.payloadRead >= sData->response.payloadLen && sData->response.tcpAvailable() == 0)
13331166
{
13341167

13351168
// Async payload and header data collision workaround from session reusage.
@@ -1400,7 +1233,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
14001233
{
14011234
if (sData->response.toFill && sData->response.toFillLen)
14021235
{
1403-
int currentRead = sData->response.tcpRead(client_type, client, async_tcp_config, sData->response.toFill + sData->response.toFillIndex, sData->response.toFillLen);
1236+
int currentRead = sData->response.tcpRead(sData->response.toFill + sData->response.toFillIndex, sData->response.toFillLen);
14041237
if (currentRead == sData->response.toFillLen)
14051238
{
14061239
buf = reinterpret_cast<uint8_t *>(mem.alloc(sData->response.toFillIndex + sData->response.toFillLen));
@@ -2374,7 +2207,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
23742207
if (sData->return_type == ret_complete)
23752208
sData->return_type = ret_continue;
23762209

2377-
if (sData->async && !sData->response.tcpAvailable(client_type, client, async_tcp_config))
2210+
if (sData->async && !sData->response.tcpAvailable())
23782211
{
23792212
if (sData->sse)
23802213
{
@@ -2388,7 +2221,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase
23882221
}
23892222
else if (!sData->async) // wait for non async
23902223
{
2391-
while (!sData->response.tcpAvailable(client_type, client, async_tcp_config) && networkConnect(sData) == ret_complete)
2224+
while (!sData->response.tcpAvailable() && networkConnect(sData) == ret_complete)
23922225
{
23932226
sys_idle();
23942227
if (handleReadTimeout(sData))

0 commit comments

Comments
 (0)