Skip to content

Commit e1c5931

Browse files
committed
Update to the latest oatpp API.
1 parent f4db488 commit e1c5931

File tree

8 files changed

+206
-154
lines changed

8 files changed

+206
-154
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
55
## use these variables to configure module installation
66

77
set(OATPP_THIS_MODULE_NAME oatpp-mbedtls) ## name of the module (also name of folders in installation dirs)
8-
set(OATPP_THIS_MODULE_VERSION "0.19.11") ## version of the module (also sufix of folders in installation dirs)
8+
set(OATPP_THIS_MODULE_VERSION "0.19.12") ## version of the module (also sufix of folders in installation dirs)
99
set(OATPP_THIS_MODULE_LIBRARIES oatpp-mbedtls) ## list of libraries to find when find_package is called
1010
set(OATPP_THIS_MODULE_TARGETS oatpp-mbedtls) ## list of targets to install
1111
set(OATPP_THIS_MODULE_DIRECTORIES oatpp-mbedtls) ## list of directories to install

src/oatpp-mbedtls/Connection.cpp

+152-75
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ void Connection::ConnectionContext::init() {
5353
auto inIOMode = m_connection->getInputStreamIOMode();
5454
auto outIOMode = m_connection->getOutputStreamIOMode();
5555

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);
5858

5959
int res = -1;
6060
while(true) {
@@ -63,8 +63,36 @@ void Connection::ConnectionContext::init() {
6363

6464
std::lock_guard<std::mutex> lock(HANDSHAKE_MUTEX);
6565

66+
async::Action action;
67+
68+
IOLockGuard ioGuard(m_connection, &action);
69+
6670
res = mbedtls_ssl_handshake(m_connection->m_tlsHandle);
6771

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+
6896
if(res == 0) {
6997
break;
7098
} else if (res != MBEDTLS_ERR_SSL_WANT_READ && res != MBEDTLS_ERR_SSL_WANT_WRITE) {
@@ -104,24 +132,40 @@ async::CoroutineStarter Connection::ConnectionContext::initAsync() {
104132
return finish();
105133
}
106134

135+
m_connection->m_initialized = true;
136+
return yieldTo(&HandshakeCoroutine::doInit);
137+
138+
}
139+
140+
Action doInit() {
141+
107142
std::lock_guard<std::mutex> lock(HANDSHAKE_MUTEX);
108143

144+
async::Action action;
145+
IOLockGuard ioGuard(m_connection, &action);
146+
109147
/* handshake iteration */
110148
auto res = mbedtls_ssl_handshake(m_connection->m_tlsHandle);
111149

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+
112159
switch(res) {
113160

114161
case MBEDTLS_ERR_SSL_WANT_READ:
115-
/* reschedule to EventIOWorker */
116-
return m_connection->suggestInputStreamAction(oatpp::data::IOError::WAIT_RETRY_READ);
162+
return repeat();
117163

118164
case MBEDTLS_ERR_SSL_WANT_WRITE:
119-
/* reschedule to EventIOWorker */
120-
return m_connection->suggestOutputStreamAction(oatpp::data::IOError::WAIT_RETRY_WRITE);
165+
return repeat();
121166

122167
case 0:
123168
/* Handshake successful */
124-
m_connection->m_initialized = true;
125169
return finish();
126170

127171
}
@@ -132,6 +176,7 @@ async::CoroutineStarter Connection::ConnectionContext::initAsync() {
132176

133177
return error<Error>("[oatpp::mbedtls::Connection::ConnectionContext::initAsync()]: Error. Handshake failed.");
134178

179+
135180
}
136181

137182
};
@@ -152,48 +197,92 @@ data::stream::StreamType Connection::ConnectionContext::getStreamType() const {
152197
return m_streamType;
153198
}
154199

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+
155224
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156225
// Connection
157226

158227
int Connection::writeCallback(void *ctx, const unsigned char *buf, size_t len) {
159228

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();
163231

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;
167242
}
168243

244+
connection->packIOAction(ioAction);
245+
169246
return (int)res;
247+
170248
}
171249

172250
int Connection::readCallback(void *ctx, unsigned char *buf, size_t len) {
173251

174-
auto stream = static_cast<IOStream*>(ctx);
175252

176-
auto res = stream->read(buf, len);
253+
auto connection = static_cast<Connection*>(ctx);
254+
async::Action* ioAction = connection->unpackIOAction();
177255

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;
181264
}
182265

266+
connection->packIOAction(ioAction);
267+
183268
return (int)res;
184269

270+
185271
}
186272

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);
189275
}
190276

191277
Connection::Connection(mbedtls_ssl_context* tlsHandle, const std::shared_ptr<oatpp::data::stream::IOStream>& stream, bool initialized)
192278
: m_tlsHandle(tlsHandle)
193279
, m_stream(stream)
194280
, m_initialized(initialized)
281+
, m_ioAction(nullptr)
195282
{
196283

284+
setTLSStreamBIOCallbacks(m_tlsHandle, this);
285+
197286
auto& streamInContext = stream->getInputStreamContext();
198287

199288
data::stream::Context::Properties inProperties(streamInContext.getProperties());
@@ -231,80 +320,68 @@ Connection::~Connection(){
231320
delete m_tlsHandle;
232321
}
233322

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+
}
237327

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+
}
241334

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){
245336

246-
case MBEDTLS_ERR_SSL_WANT_WRITE:
247-
return oatpp::data::IOError::WAIT_RETRY_WRITE;
337+
IOLockGuard ioGuard(this, &action);
248338

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);
251340

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+
}
254345

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+
}
255355
}
256356

257-
return data::IOError::BROKEN_PIPE;
357+
return result;
258358

259359
}
260360

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);
262364

263365
auto result = mbedtls_ssl_read(m_tlsHandle, (unsigned char *) buff, (size_t)count);
264366

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;
267370
}
268371

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+
}
282381
}
283382

284-
return data::IOError::BROKEN_PIPE;
285-
286-
}
383+
return result;
287384

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-
}
308385
}
309386

310387
void Connection::setOutputStreamIOMode(oatpp::data::stream::IOMode ioMode) {

0 commit comments

Comments
 (0)