Discussion:
[asio-users] SSL: only first async_write data goes to channel, subsequent goes nowhere.
Andrey Kulikov
2015-04-27 17:42:22 UTC
Permalink
Hello,

While developing a simple program, what send series of messages via SSL
over network using boost::asio, I faced a problem:
Only first message goes to channel, and others stays somewhere, while
async_write() handler was called.

There is a small programm in attachment, illustrates the issue.
In order to use, first start opnessl s_server, allowing NULL
encryption:

openssl s_server -WWW -tls1 -accept 443 -state -cert server.crt
-key server.key -cipher "eNULL"

Then compile the porgramm like that:
c++ -pedantic -ansi -std=c++11 -Wall -Werror ggdb3 -O0 -DDEBUG -o
aio_ssl aio_ssl.cpp -L/usr/lib -lstdc++ -lpthread -lboost_thread
-lboost_system -lcrypto -lssl
and run, pointing to listening OpenSSL s_server:
./aio_ssl 127.0.0.1 443

Issue reproduceы on Debian and on Windows x86. With boost 1.49, 1.57
and 1.58 everyting looks the same.

Programm establish communication with SSL server, and send series of
messages (sime pieces of text) here.
All messages reported to be sent sucessfully (async_write handlers
where called).
But, Wireshark reports that only first string goes to channel (here
NULL encryption can serve us - we may see what really goes inside SSL).

Could anyone enlighten me, ignoramus, what I'm doing wrong?

Diging little bit deeper, I found where it probably goes wrong:

/usr/include/boost/asio/ssl/detail/io.hpp:179

case engine::want_output_and_retry:
case engine::want_output:

// The engine wants some data to be written to the output.
However, we
// cannot allow more than one write operation at a time on
the
// underlying transport. The pending_write_ timer's expiry is
set to
// pos_infin if a write is in progress, and neg_infin
otherwise.
if (core_.pending_write_.expires_at() ==
boost::posix_time::neg_infin)
{
// Prevent other write operations from being started.

core_.pending_write_.expires_at(boost::posix_time::pos_infin);

// Start writing all the data to the underlying transport.
boost::asio::async_write(next_layer_,
core_.engine_.get_output(core_.output_buffer_),
BOOST_ASIO_MOVE_CAST(io_op)(*this));
}
else
{
// Wait until the current write operation completes.

core_.pending_write_.async_wait(BOOST_ASIO_MOVE_CAST(io_op)(*this));
}

First message goes to if{}, and all subsequens messages goes to else{}.
One write operation still active, and other postponed till... some
event.
But it never happens, and data not being send at all.

Does anone have any idea how to fix this situation?

Best wishes,
Andrey



------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
asio-users mailing list
asio-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsin
Andrey Kulikov
2015-04-27 17:52:34 UTC
Permalink
And here is a programm attached.
Post by Andrey Kulikov
Hello,
While developing a simple program, what send series of messages via
Only first message goes to channel, and others stays somewhere, while
async_write() handler was called.
There is a small programm in attachment, illustrates the issue.
In order to use, first start opnessl s_server, allowing NULL
openssl s_server -WWW -tls1 -accept 443 -state -cert server.crt
-key server.key -cipher "eNULL"
c++ -pedantic -ansi -std=c++11 -Wall -Werror ggdb3 -O0 -DDEBUG -o
aio_ssl aio_ssl.cpp -L/usr/lib -lstdc++ -lpthread -lboost_thread
-lboost_system -lcrypto -lssl
./aio_ssl 127.0.0.1 443
Issue reproduceы on Debian and on Windows x86. With boost 1.49, 1.57
and 1.58 everyting looks the same.
Programm establish communication with SSL server, and send series of
messages (sime pieces of text) here.
All messages reported to be sent sucessfully (async_write handlers
where called).
But, Wireshark reports that only first string goes to channel (here
NULL encryption can serve us - we may see what really goes inside SSL).
Could anyone enlighten me, ignoramus, what I'm doing wrong?
/usr/include/boost/asio/ssl/detail/io.hpp:179
// The engine wants some data to be written to the output.
However, we
// cannot allow more than one write operation at a time on
the
// underlying transport. The pending_write_ timer's expiry
is set to
// pos_infin if a write is in progress, and neg_infin
otherwise.
if (core_.pending_write_.expires_at() ==
boost::posix_time::neg_infin)
{
// Prevent other write operations from being started.
core_.pending_write_.expires_at(boost::posix_time::pos_infin);
// Start writing all the data to the underlying transport.
boost::asio::async_write(next_layer_,
core_.engine_.get_output(core_.output_buffer_),
BOOST_ASIO_MOVE_CAST(io_op)(*this));
}
else
{
// Wait until the current write operation completes.
core_.pending_write_.async_wait(BOOST_ASIO_MOVE_CAST(io_op)(*this));
}
First message goes to if{}, and all subsequens messages goes to else{}.
One write operation still active, and other postponed till... some
event.
But it never happens, and data not being send at all.
Does anone have any idea how to fix this situation?
Best wishes,
Andrey
Igor R
2015-04-27 18:43:54 UTC
Permalink
Post by Andrey Kulikov
And here is a programm attached.
You call async_write (which is a composed operation) on the same
socket several times, without waiting for the completion handlers.
This causes the data to get messed, as the order of the actual writes
is undefined. If it were a plain socket, your data would get to the
other side, but in an "interleaved" form. However, since SSL is
"record-oriented", such a mess probably causes more severe issues...
The correct flow is as follows:
async_write --> handle_upstream_write --> async_write -->
handle_upstream_write --> ...etc...

(BTW, note that no one calls async_read_some/handle_upstream_read in
your program.)

------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
asio-users mailing list
asio-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio

Igor R
2015-04-27 18:00:36 UTC
Permalink
Post by Andrey Kulikov
While developing a simple program, what send series of messages via SSL
Only first message goes to channel, and others stays somewhere, while
async_write() handler was called.
There is a small programm in attachment, illustrates the issue.
Looks like you forgot to attach it.

------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
asio-users mailing list
asio-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/asio-users
_______________________________________________
Using Asio? List your project at
http://think-async.com/Asio/WhoIsUsingAsio
Loading...