@@ -98,7 +98,113 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() {
98
98
}
99
99
100
100
OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetchChunk () {
101
- return OtaDownloadFail;
101
+ OTACloudProcessInterface::State res = Fetch;
102
+ int http_res = 0 ;
103
+ uint32_t start = millis ();
104
+ char range[128 ] = {0 };
105
+
106
+ /* stop connected client */
107
+ http_client->stop ();
108
+
109
+ /* request chunk */
110
+ http_client->beginRequest ();
111
+ http_res = http_client->get (context->parsed_url .path ());
112
+
113
+ if (username != nullptr && password != nullptr ) {
114
+ http_client->sendBasicAuth (username, password);
115
+ }
116
+
117
+ size_t rangeSize = context->downloadedSize + context->maxChunkSize > context->contentLength ? context->contentLength - context->downloadedSize : context->maxChunkSize ;
118
+ sprintf (range, " bytes=%d-%d" , context->downloadedSize , context->downloadedSize + rangeSize);
119
+ DEBUG_VERBOSE (" OTA downloading range: %s" , range);
120
+ http_client->sendHeader (" Range" , range);
121
+ http_client->endRequest ();
122
+
123
+ if (http_res == HTTP_ERROR_CONNECTION_FAILED) {
124
+ DEBUG_VERBOSE (" OTA ERROR: http client error connecting to server \" %s:%d\" " ,
125
+ context->parsed_url .host (), context->parsed_url .port ());
126
+ return ServerConnectErrorFail;
127
+ } else if (http_res == HTTP_ERROR_TIMED_OUT) {
128
+ DEBUG_VERBOSE (" OTA ERROR: http client timeout \" %s\" " , OTACloudProcessInterface::context->url );
129
+ return OtaHeaderTimeoutFail;
130
+ } else if (http_res != HTTP_SUCCESS) {
131
+ DEBUG_VERBOSE (" OTA ERROR: http client returned %d on get \" %s\" " , res, OTACloudProcessInterface::context->url );
132
+ return OtaDownloadFail;
133
+ }
134
+
135
+ int statusCode = http_client->responseStatusCode ();
136
+
137
+ if (statusCode != 206 ) {
138
+ DEBUG_VERBOSE (" OTA ERROR: get response on \" %s\" returned status %d" , OTACloudProcessInterface::context->url , statusCode);
139
+ return HttpResponseFail;
140
+ }
141
+
142
+ http_client->skipResponseHeaders ();
143
+
144
+ /* download chunk */
145
+ context->downloadedChunkSize = 0 ;
146
+ do {
147
+ if (!http_client->connected ()) {
148
+ res = OtaDownloadFail;
149
+ goto exit;
150
+ }
151
+
152
+ if (http_client->available () == 0 ) {
153
+ /* Avoid tight loop and allow yield */
154
+ delay (1 );
155
+ continue ;
156
+ }
157
+
158
+ http_res = http_client->read (context->buffer , context->bufLen );
159
+
160
+ if (http_res < 0 ) {
161
+ DEBUG_VERBOSE (" OTA ERROR: Download read error %d" , http_res);
162
+ res = OtaDownloadFail;
163
+ goto exit;
164
+ }
165
+
166
+ parseOta (context->buffer , http_res);
167
+
168
+ if (context->writeError ) {
169
+ DEBUG_VERBOSE (" OTA ERROR: File write error" );
170
+ res = ErrorWriteUpdateFileFail;
171
+ goto exit;
172
+ }
173
+
174
+ context->downloadedChunkSize += http_res;
175
+
176
+ } while ((context->downloadState == OtaDownloadFile || context->downloadState == OtaDownloadHeader) &&
177
+ (context->downloadedChunkSize < rangeSize));
178
+
179
+ // TODO verify that the information present in the ota header match the info in context
180
+ if (context->downloadState == OtaDownloadCompleted) {
181
+ // Verify that the downloaded file size is matching the expected size ??
182
+ // this could distinguish between consistency of the downloaded bytes and filesize
183
+
184
+ // validate CRC
185
+ context->calculatedCrc32 ^= 0xFFFFFFFF ; // finalize CRC
186
+ if (context->header .header .crc32 == context->calculatedCrc32 ) {
187
+ DEBUG_VERBOSE (" Ota download completed successfully" );
188
+ res = FlashOTA;
189
+ } else {
190
+ res = OtaHeaderCrcFail;
191
+ }
192
+ } else if (context->downloadState == OtaDownloadError) {
193
+ DEBUG_VERBOSE (" OTA ERROR: OtaDownloadError" );
194
+
195
+ res = OtaDownloadFail;
196
+ } else if (context->downloadState == OtaDownloadMagicNumberMismatch) {
197
+ DEBUG_VERBOSE (" OTA ERROR: Magic number mismatch" );
198
+ res = OtaHeaderMagicNumberFail;
199
+ }
200
+
201
+ exit:
202
+ if (res != Fetch) {
203
+ http_client->stop (); // close the connection
204
+ delete http_client;
205
+ http_client = nullptr ;
206
+ }
207
+ return res;
102
208
}
103
209
104
210
OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetchTime () {
@@ -265,6 +371,7 @@ OTADefaultCloudProcessInterface::Context::Context(
265
371
, lastReportTime(0 )
266
372
, contentLength(0 )
267
373
, writeError(false )
374
+ , downloadedChunkSize(0 )
268
375
, decoder(putc) { }
269
376
270
377
static const uint32_t crc_table[256 ] = {
0 commit comments