@@ -53,8 +53,8 @@ void Connection::ConnectionContext::init() {
53
53
auto inIOMode = m_connection->getInputStreamIOMode ();
54
54
auto outIOMode = m_connection->getOutputStreamIOMode ();
55
55
56
- m_connection->setInputStreamIOMode (data::stream::IOMode::NON_BLOCKING );
57
- m_connection->setOutputStreamIOMode (data::stream::IOMode::NON_BLOCKING );
56
+ m_connection->setInputStreamIOMode (data::stream::IOMode::ASYNCHRONOUS );
57
+ m_connection->setOutputStreamIOMode (data::stream::IOMode::ASYNCHRONOUS );
58
58
59
59
int res = -1 ;
60
60
while (true ) {
@@ -63,8 +63,36 @@ void Connection::ConnectionContext::init() {
63
63
64
64
std::lock_guard<std::mutex> lock (HANDSHAKE_MUTEX);
65
65
66
+ async::Action action;
67
+
68
+ IOLockGuard ioGuard (m_connection, &action);
69
+
66
70
res = mbedtls_ssl_handshake (m_connection->m_tlsHandle );
67
71
72
+ if (!ioGuard.unpackAndCheck ()) {
73
+ OATPP_LOGE (" [oatpp::mbedtls::Connection::ConnectionContext::init()]" , " Error. Packed action check failed!!!" );
74
+ return ;
75
+ }
76
+
77
+ // ////////////////////////////////////////////////
78
+ // **********************************************//
79
+ // ** NOTE: ASYNC ACTION IS INORED **//
80
+ // **********************************************//
81
+
82
+ // Ignoring an async action is NOT correct !!!
83
+ //
84
+ // The Reason:
85
+ // The connection is intentionally set to IOMode::ASYNCHRONOUS.
86
+ // This is a workaround for MbedTLS in order NOT to
87
+ // block accepting thread having HANDSHAKE_MUTEX locked.
88
+
89
+ // if(!action.isNone()) {
90
+ // OATPP_LOGE("[oatpp::mbedtls::Connection::ConnectionContext::init()]", "Error. Using Async stream as transport for blocking stream!!!");
91
+ // break;
92
+ // }
93
+
94
+ // ////////////////////////////////////////////////
95
+
68
96
if (res == 0 ) {
69
97
break ;
70
98
} else if (res != MBEDTLS_ERR_SSL_WANT_READ && res != MBEDTLS_ERR_SSL_WANT_WRITE) {
@@ -104,24 +132,40 @@ async::CoroutineStarter Connection::ConnectionContext::initAsync() {
104
132
return finish ();
105
133
}
106
134
135
+ m_connection->m_initialized = true ;
136
+ return yieldTo (&HandshakeCoroutine::doInit);
137
+
138
+ }
139
+
140
+ Action doInit () {
141
+
107
142
std::lock_guard<std::mutex> lock (HANDSHAKE_MUTEX);
108
143
144
+ async::Action action;
145
+ IOLockGuard ioGuard (m_connection, &action);
146
+
109
147
/* handshake iteration */
110
148
auto res = mbedtls_ssl_handshake (m_connection->m_tlsHandle );
111
149
150
+ if (!ioGuard.unpackAndCheck ()) {
151
+ OATPP_LOGE (" [oatpp::mbedtls::Connection::ConnectionContext::initAsync()]" , " Error. Packed action check failed!!!" );
152
+ return error<Error>(" [oatpp::mbedtls::Connection::ConnectionContext::initAsync()]: Error. Packed action check failed!!!" );
153
+ }
154
+
155
+ if (!action.isNone ()) {
156
+ return action;
157
+ }
158
+
112
159
switch (res) {
113
160
114
161
case MBEDTLS_ERR_SSL_WANT_READ:
115
- /* reschedule to EventIOWorker */
116
- return m_connection->suggestInputStreamAction (oatpp::data::IOError::WAIT_RETRY_READ);
162
+ return repeat ();
117
163
118
164
case MBEDTLS_ERR_SSL_WANT_WRITE:
119
- /* reschedule to EventIOWorker */
120
- return m_connection->suggestOutputStreamAction (oatpp::data::IOError::WAIT_RETRY_WRITE);
165
+ return repeat ();
121
166
122
167
case 0 :
123
168
/* Handshake successful */
124
- m_connection->m_initialized = true ;
125
169
return finish ();
126
170
127
171
}
@@ -132,6 +176,7 @@ async::CoroutineStarter Connection::ConnectionContext::initAsync() {
132
176
133
177
return error<Error>(" [oatpp::mbedtls::Connection::ConnectionContext::initAsync()]: Error. Handshake failed." );
134
178
179
+
135
180
}
136
181
137
182
};
@@ -152,48 +197,92 @@ data::stream::StreamType Connection::ConnectionContext::getStreamType() const {
152
197
return m_streamType;
153
198
}
154
199
200
+ // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
201
+ // IOLockGuard
202
+
203
+ Connection::IOLockGuard::IOLockGuard (Connection* connection, async::Action* checkAction)
204
+ : m_connection(connection)
205
+ , m_checkAction(checkAction)
206
+ {
207
+ m_connection->packIOAction (m_checkAction);
208
+ m_locked = true ;
209
+ }
210
+
211
+ Connection::IOLockGuard::~IOLockGuard () {
212
+ if (m_locked) {
213
+ m_connection->m_ioLock .unlock ();
214
+ }
215
+ }
216
+
217
+ bool Connection::IOLockGuard::unpackAndCheck () {
218
+ async::Action* check = m_connection->unpackIOAction ();
219
+ m_locked = false ;
220
+ return check == m_checkAction;
221
+ }
222
+
223
+
155
224
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156
225
// Connection
157
226
158
227
int Connection::writeCallback (void *ctx, const unsigned char *buf, size_t len) {
159
228
160
- auto stream = static_cast <IOStream*>(ctx);
161
-
162
- auto res = stream->write (buf, len);
229
+ auto connection = static_cast <Connection*>(ctx);
230
+ async::Action* ioAction = connection->unpackIOAction ();
163
231
164
- if (res == oatpp::data::IOError::RETRY_READ || res == oatpp::data::IOError::WAIT_RETRY_READ ||
165
- res == oatpp::data::IOError::RETRY_WRITE || res == oatpp::data::IOError::WAIT_RETRY_WRITE) {
166
- return MBEDTLS_ERR_SSL_WANT_WRITE;
232
+ v_io_size res;
233
+ if (ioAction && ioAction->isNone ()) {
234
+ res = connection->m_stream ->write (buf, len, *ioAction);
235
+ if (res == IOError::RETRY_READ || res == IOError::RETRY_WRITE) {
236
+ res = MBEDTLS_ERR_SSL_WANT_WRITE;
237
+ }
238
+ } else if (ioAction == nullptr ) {
239
+ res = len; // NOTE: Ignore client notification on connection close;
240
+ } else {
241
+ res = MBEDTLS_ERR_SSL_WANT_WRITE;
167
242
}
168
243
244
+ connection->packIOAction (ioAction);
245
+
169
246
return (int )res;
247
+
170
248
}
171
249
172
250
int Connection::readCallback (void *ctx, unsigned char *buf, size_t len) {
173
251
174
- auto stream = static_cast <IOStream*>(ctx);
175
252
176
- auto res = stream->read (buf, len);
253
+ auto connection = static_cast <Connection*>(ctx);
254
+ async::Action* ioAction = connection->unpackIOAction ();
177
255
178
- if (res == oatpp::data::IOError::RETRY_READ || res == oatpp::data::IOError::WAIT_RETRY_READ ||
179
- res == oatpp::data::IOError::RETRY_WRITE || res == oatpp::data::IOError::WAIT_RETRY_WRITE) {
180
- return MBEDTLS_ERR_SSL_WANT_READ;
256
+ v_io_size res;
257
+ if (ioAction && ioAction->isNone ()) {
258
+ res = connection->m_stream ->read (buf, len, *ioAction);
259
+ if (res == IOError::RETRY_READ || res == IOError::RETRY_WRITE) {
260
+ res = MBEDTLS_ERR_SSL_WANT_READ;
261
+ }
262
+ } else {
263
+ res = MBEDTLS_ERR_SSL_WANT_READ;
181
264
}
182
265
266
+ connection->packIOAction (ioAction);
267
+
183
268
return (int )res;
184
269
270
+
185
271
}
186
272
187
- void Connection::setTLSStreamBIOCallbacks (mbedtls_ssl_context* tlsHandle, oatpp::data::stream::IOStream* stream ) {
188
- mbedtls_ssl_set_bio (tlsHandle, stream , writeCallback, readCallback, NULL );
273
+ void Connection::setTLSStreamBIOCallbacks (mbedtls_ssl_context* tlsHandle, Connection* connection ) {
274
+ mbedtls_ssl_set_bio (tlsHandle, connection , writeCallback, readCallback, NULL );
189
275
}
190
276
191
277
Connection::Connection (mbedtls_ssl_context* tlsHandle, const std::shared_ptr<oatpp::data::stream::IOStream>& stream, bool initialized)
192
278
: m_tlsHandle(tlsHandle)
193
279
, m_stream(stream)
194
280
, m_initialized(initialized)
281
+ , m_ioAction(nullptr )
195
282
{
196
283
284
+ setTLSStreamBIOCallbacks (m_tlsHandle, this );
285
+
197
286
auto & streamInContext = stream->getInputStreamContext ();
198
287
199
288
data::stream::Context::Properties inProperties (streamInContext.getProperties ());
@@ -231,80 +320,68 @@ Connection::~Connection(){
231
320
delete m_tlsHandle;
232
321
}
233
322
234
- data::v_io_size Connection::write (const void *buff, v_buff_size count){
235
-
236
- auto result = mbedtls_ssl_write (m_tlsHandle, (const unsigned char *) buff, (size_t )count);
323
+ void Connection::packIOAction (async::Action* action) {
324
+ m_ioLock.lock ();
325
+ m_ioAction = action;
326
+ }
237
327
238
- if (result >= 0 ) {
239
- return result;
240
- }
328
+ async::Action* Connection::unpackIOAction () {
329
+ auto result = m_ioAction;
330
+ m_ioAction = nullptr ;
331
+ m_ioLock.unlock ();
332
+ return result;
333
+ }
241
334
242
- switch (result) {
243
- case MBEDTLS_ERR_SSL_WANT_READ:
244
- return oatpp::data::IOError::WAIT_RETRY_READ;
335
+ v_io_size Connection::write (const void *buff, v_buff_size count, async::Action& action){
245
336
246
- case MBEDTLS_ERR_SSL_WANT_WRITE:
247
- return oatpp::data::IOError::WAIT_RETRY_WRITE;
337
+ IOLockGuard ioGuard (this , &action);
248
338
249
- case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
250
- return oatpp::data::IOError::RETRY_WRITE;
339
+ auto result = mbedtls_ssl_write (m_tlsHandle, (const unsigned char *) buff, (size_t )count);
251
340
252
- case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
253
- return oatpp::data::IOError::RETRY_WRITE;
341
+ if (!ioGuard.unpackAndCheck ()) {
342
+ OATPP_LOGE (" [oatpp::mbedtls::Connection::write(...)]" , " Error. Packed action check failed!!!" );
343
+ return oatpp::IOError::BROKEN_PIPE;
344
+ }
254
345
346
+ if (result < 0 ) {
347
+ switch (result) {
348
+ case MBEDTLS_ERR_SSL_WANT_READ: return oatpp::IOError::RETRY_WRITE;
349
+ case MBEDTLS_ERR_SSL_WANT_WRITE: return oatpp::IOError::RETRY_WRITE;
350
+ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: return oatpp::IOError::RETRY_WRITE;
351
+ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: return oatpp::IOError::RETRY_WRITE;
352
+ default :
353
+ return oatpp::IOError::BROKEN_PIPE;
354
+ }
255
355
}
256
356
257
- return data::IOError::BROKEN_PIPE ;
357
+ return result ;
258
358
259
359
}
260
360
261
- data::v_io_size Connection::read (void *buff, v_buff_size count){
361
+ v_io_size Connection::read (void *buff, v_buff_size count, async::Action& action){
362
+
363
+ IOLockGuard ioGuard (this , &action);
262
364
263
365
auto result = mbedtls_ssl_read (m_tlsHandle, (unsigned char *) buff, (size_t )count);
264
366
265
- if (result >= 0 ) {
266
- return result;
367
+ if (!ioGuard.unpackAndCheck ()) {
368
+ OATPP_LOGE (" [oatpp::mbedtls::Connection::read(...)]" , " Error. Packed action check failed!!!" );
369
+ return oatpp::IOError::BROKEN_PIPE;
267
370
}
268
371
269
- switch (result) {
270
- case MBEDTLS_ERR_SSL_WANT_READ:
271
- return oatpp::data::IOError::WAIT_RETRY_READ;
272
-
273
- case MBEDTLS_ERR_SSL_WANT_WRITE:
274
- return oatpp::data::IOError::WAIT_RETRY_WRITE;
275
-
276
- case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
277
- return oatpp::data::IOError::RETRY_READ;
278
-
279
- case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
280
- return oatpp::data::IOError::RETRY_READ;
281
-
372
+ if (result < 0 ) {
373
+ switch (result) {
374
+ case MBEDTLS_ERR_SSL_WANT_READ: return oatpp::IOError::RETRY_READ;
375
+ case MBEDTLS_ERR_SSL_WANT_WRITE: return oatpp::IOError::RETRY_READ;
376
+ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: return oatpp::IOError::RETRY_READ;
377
+ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: return oatpp::IOError::RETRY_READ;
378
+ default :
379
+ return oatpp::IOError::BROKEN_PIPE;
380
+ }
282
381
}
283
382
284
- return data::IOError::BROKEN_PIPE;
285
-
286
- }
383
+ return result;
287
384
288
- oatpp::async::Action Connection::suggestOutputStreamAction (data::v_io_size ioResult) {
289
- switch (ioResult) {
290
- case oatpp::data::IOError::RETRY_READ:
291
- return m_stream->suggestInputStreamAction (ioResult);
292
- case oatpp::data::IOError::WAIT_RETRY_READ:
293
- return m_stream->suggestInputStreamAction (ioResult);
294
- default :
295
- return m_stream->suggestOutputStreamAction (ioResult);
296
- }
297
- }
298
-
299
- oatpp::async::Action Connection::suggestInputStreamAction (data::v_io_size ioResult) {
300
- switch (ioResult) {
301
- case oatpp::data::IOError::RETRY_WRITE:
302
- return m_stream->suggestOutputStreamAction (ioResult);
303
- case oatpp::data::IOError::WAIT_RETRY_WRITE:
304
- return m_stream->suggestOutputStreamAction (ioResult);
305
- default :
306
- return m_stream->suggestInputStreamAction (ioResult);
307
- }
308
385
}
309
386
310
387
void Connection::setOutputStreamIOMode (oatpp::data::stream::IOMode ioMode) {
0 commit comments