@@ -26,6 +26,7 @@ extern "C"
26
26
{
27
27
#include " osapi.h"
28
28
#include " ets_sys.h"
29
+ #include " queue.h"
29
30
}
30
31
#include < errno.h>
31
32
#include " debug.h"
@@ -50,6 +51,28 @@ extern "C"
50
51
#define SSL_DEBUG_OPTS 0
51
52
#endif
52
53
54
+
55
+ typedef struct BufferItem
56
+ {
57
+ size_t size;
58
+ STAILQ_ENTRY (BufferItem) next;
59
+ uint8_t data[0 ];
60
+
61
+ static BufferItem* Create (const uint8_t * data, size_t size)
62
+ {
63
+ BufferItem* newItem = (BufferItem*) calloc (1 , sizeof (BufferItem) + size);
64
+ if (newItem == nullptr ) {
65
+ return nullptr ;
66
+ }
67
+ newItem->size = size;
68
+ memcpy (newItem->data , data, size);
69
+ return newItem;
70
+ }
71
+
72
+ } BufferItem;
73
+
74
+ typedef STAILQ_HEAD (BufferList, BufferItem) BufferList;
75
+
53
76
class SSLContext
54
77
{
55
78
public:
@@ -59,6 +82,7 @@ class SSLContext
59
82
_ssl_ctx = ssl_ctx_new (SSL_SERVER_VERIFY_LATER | SSL_DEBUG_OPTS | SSL_CONNECT_IN_PARTS | SSL_READ_BLOCKING | SSL_NO_DEFAULT_KEY, 0 );
60
83
}
61
84
++_ssl_ctx_refcnt;
85
+ STAILQ_INIT (&_writeBuffers);
62
86
}
63
87
64
88
~SSLContext ()
@@ -139,6 +163,10 @@ class SSLContext
139
163
_available -= will_copy;
140
164
if (_available == 0 ) {
141
165
_read_ptr = nullptr ;
166
+ /* Send pending outgoing data, if any */
167
+ if (_hasWriteBuffers ()) {
168
+ _writeBuffersSend ();
169
+ }
142
170
}
143
171
return will_copy;
144
172
}
@@ -155,10 +183,34 @@ class SSLContext
155
183
--_available;
156
184
if (_available == 0 ) {
157
185
_read_ptr = nullptr ;
186
+ /* Send pending outgoing data, if any */
187
+ if (_hasWriteBuffers ()) {
188
+ _writeBuffersSend ();
189
+ }
158
190
}
159
191
return result;
160
192
}
161
193
194
+ int write (const uint8_t * src, size_t size)
195
+ {
196
+ if (!_available) {
197
+ if (_hasWriteBuffers ()) {
198
+ int rc = _writeBuffersSend ();
199
+ if (rc < 0 ) {
200
+ return rc;
201
+ }
202
+ }
203
+ return _write (src, size);
204
+ }
205
+ /* Some received data is still present in the axtls fragment buffer.
206
+ We can't call ssl_write now, as that will overwrite the contents of
207
+ the fragment buffer, corrupting the received data.
208
+ Save a copy of the outgoing data, and call ssl_write when all
209
+ recevied data has been consumed by the application.
210
+ */
211
+ return _writeBufferAdd (src, size);
212
+ }
213
+
162
214
int peek ()
163
215
{
164
216
if (!_available) {
@@ -282,12 +334,71 @@ class SSLContext
282
334
return _available;
283
335
}
284
336
337
+ int _write (const uint8_t * src, size_t size)
338
+ {
339
+ if (!_ssl) {
340
+ return 0 ;
341
+ }
342
+
343
+ int rc = ssl_write (_ssl, src, size);
344
+ if (rc >= 0 ) {
345
+ return rc;
346
+ }
347
+ return rc;
348
+ }
349
+
350
+ int _writeBufferAdd (const uint8_t * data, size_t size)
351
+ {
352
+ if (!_ssl) {
353
+ return 0 ;
354
+ }
355
+
356
+ BufferItem* newItem = BufferItem::Create (data, size);
357
+ if (newItem == nullptr ) {
358
+ return SSL_NOT_OK;
359
+ }
360
+ STAILQ_INSERT_TAIL (&_writeBuffers, newItem, next);
361
+ return size;
362
+ }
363
+
364
+ int _writeBuffersSend ()
365
+ {
366
+ BufferItem* it;
367
+ BufferItem* tmp;
368
+ STAILQ_FOREACH_SAFE (it, &_writeBuffers, next, tmp) {
369
+ STAILQ_REMOVE_HEAD (&_writeBuffers, next);
370
+ int rc = _write (it->data , it->size );
371
+ free (it);
372
+ if (rc < 0 ) {
373
+ _writeBuffersDiscard ();
374
+ return rc;
375
+ }
376
+ }
377
+ return 0 ;
378
+ }
379
+
380
+ void _writeBuffersDiscard ()
381
+ {
382
+ BufferItem* it;
383
+ BufferItem* tmp;
384
+ STAILQ_FOREACH_SAFE (it, &_writeBuffers, next, tmp) {
385
+ STAILQ_REMOVE_HEAD (&_writeBuffers, next);
386
+ free (it);
387
+ }
388
+ }
389
+
390
+ bool _hasWriteBuffers ()
391
+ {
392
+ return !STAILQ_EMPTY (&_writeBuffers);
393
+ }
394
+
285
395
static SSL_CTX* _ssl_ctx;
286
396
static int _ssl_ctx_refcnt;
287
397
SSL* _ssl = nullptr ;
288
398
int _refcnt = 0 ;
289
399
const uint8_t * _read_ptr = nullptr ;
290
400
size_t _available = 0 ;
401
+ BufferList _writeBuffers;
291
402
bool _allowSelfSignedCerts = false ;
292
403
static ClientContext* s_io_ctx;
293
404
};
@@ -371,7 +482,7 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
371
482
return 0 ;
372
483
}
373
484
374
- int rc = ssl_write (* _ssl, buf, size);
485
+ int rc = _ssl-> write ( buf, size);
375
486
if (rc >= 0 ) {
376
487
return rc;
377
488
}
0 commit comments