@@ -27,6 +27,7 @@ extern "C"
27
27
#include " osapi.h"
28
28
#include " ets_sys.h"
29
29
}
30
+ #include < list>
30
31
#include < errno.h>
31
32
#include " debug.h"
32
33
#include " ESP8266WiFi.h"
@@ -50,6 +51,26 @@ extern "C"
50
51
#define SSL_DEBUG_OPTS 0
51
52
#endif
52
53
54
+
55
+ typedef struct BufferItem
56
+ {
57
+ BufferItem (const uint8_t * data_, size_t size_)
58
+ : size(size_), data(new uint8_t [size])
59
+ {
60
+ if (data.get () != nullptr ) {
61
+ memcpy (data.get (), data_, size);
62
+ } else {
63
+ DEBUGV (" :wcs alloc %d failed\r\n " , size_);
64
+ size = 0 ;
65
+ }
66
+ }
67
+
68
+ size_t size;
69
+ std::unique_ptr<uint8_t []> data;
70
+ } BufferItem;
71
+
72
+ typedef std::list<BufferItem> BufferList;
73
+
53
74
class SSLContext
54
75
{
55
76
public:
@@ -139,6 +160,10 @@ class SSLContext
139
160
_available -= will_copy;
140
161
if (_available == 0 ) {
141
162
_read_ptr = nullptr ;
163
+ /* Send pending outgoing data, if any */
164
+ if (_hasWriteBuffers ()) {
165
+ _writeBuffersSend ();
166
+ }
142
167
}
143
168
return will_copy;
144
169
}
@@ -155,10 +180,34 @@ class SSLContext
155
180
--_available;
156
181
if (_available == 0 ) {
157
182
_read_ptr = nullptr ;
183
+ /* Send pending outgoing data, if any */
184
+ if (_hasWriteBuffers ()) {
185
+ _writeBuffersSend ();
186
+ }
158
187
}
159
188
return result;
160
189
}
161
190
191
+ int write (const uint8_t * src, size_t size)
192
+ {
193
+ if (!_available) {
194
+ if (_hasWriteBuffers ()) {
195
+ int rc = _writeBuffersSend ();
196
+ if (rc < 0 ) {
197
+ return rc;
198
+ }
199
+ }
200
+ return _write (src, size);
201
+ }
202
+ /* Some received data is still present in the axtls fragment buffer.
203
+ We can't call ssl_write now, as that will overwrite the contents of
204
+ the fragment buffer, corrupting the received data.
205
+ Save a copy of the outgoing data, and call ssl_write when all
206
+ recevied data has been consumed by the application.
207
+ */
208
+ return _writeBufferAdd (src, size);
209
+ }
210
+
162
211
int peek ()
163
212
{
164
213
if (!_available) {
@@ -288,12 +337,63 @@ class SSLContext
288
337
return _available;
289
338
}
290
339
340
+ int _write (const uint8_t * src, size_t size)
341
+ {
342
+ if (!_ssl) {
343
+ return 0 ;
344
+ }
345
+
346
+ int rc = ssl_write (_ssl, src, size);
347
+ if (rc >= 0 ) {
348
+ return rc;
349
+ }
350
+ DEBUGV (" :wcs write rc=%d\r\n " , rc);
351
+ return rc;
352
+ }
353
+
354
+ int _writeBufferAdd (const uint8_t * data, size_t size)
355
+ {
356
+ if (!_ssl) {
357
+ return 0 ;
358
+ }
359
+
360
+ _writeBuffers.emplace_back (data, size);
361
+ if (_writeBuffers.back ().data .get () == nullptr ) {
362
+ _writeBuffers.pop_back ();
363
+ return 0 ;
364
+ }
365
+ return size;
366
+ }
367
+
368
+ int _writeBuffersSend ()
369
+ {
370
+ while (!_writeBuffers.empty ()) {
371
+ auto & first = _writeBuffers.front ();
372
+ int rc = _write (first.data .get (), first.size );
373
+ _writeBuffers.pop_front ();
374
+ if (rc < 0 ) {
375
+ if (_hasWriteBuffers ()) {
376
+ DEBUGV (" :wcs _writeBuffersSend dropping unsent data\r\n " );
377
+ _writeBuffers.clear ();
378
+ }
379
+ return rc;
380
+ }
381
+ }
382
+ return 0 ;
383
+ }
384
+
385
+ bool _hasWriteBuffers ()
386
+ {
387
+ return !_writeBuffers.empty ();
388
+ }
389
+
291
390
static SSL_CTX* _ssl_ctx;
292
391
static int _ssl_ctx_refcnt;
293
392
SSL* _ssl = nullptr ;
294
393
int _refcnt = 0 ;
295
394
const uint8_t * _read_ptr = nullptr ;
296
395
size_t _available = 0 ;
396
+ BufferList _writeBuffers;
297
397
bool _allowSelfSignedCerts = false ;
298
398
static ClientContext* s_io_ctx;
299
399
};
@@ -377,7 +477,7 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
377
477
return 0 ;
378
478
}
379
479
380
- int rc = ssl_write (* _ssl, buf, size);
480
+ int rc = _ssl-> write ( buf, size);
381
481
if (rc >= 0 ) {
382
482
return rc;
383
483
}
0 commit comments