// std:string _sql_statement;
// char _client_data[max_data_length];
// size_t bytes_transferred;
void tcp_proxy::Bridge::handle_read_fclient(const error_code& error, const size_t & bytes_transferred)
{
if (!error) {
asio::async_write(*_upstream_socket.get(),
asio::buffer(_client_data, bytes_transferred),
boost::bind(&Bridge::handle_write_tserver,
shared_from_this(),
asio::placeholders::error)
);
_sql_statement.append(_client_data, bytes_transferred);
std::cout << _sql_statement << "\n";
}
else {
stop();
}
}
When i run mysql-client and send sql query, i get this output:
����=9漢 �\�gOx� �u%e��A ��
��jxt�6���� �bc ���z�
�-x��w<�0NH�+�,�/�#�'�0�$�(��g@�kj��� ��
23895�A��<=/��
*(
+-3GEA1�����Ȩf� ��b�_�Epx����D�47�~�;%/x��C)�Q���D3 ���n�]�B�brU�N�ݘ%_\�
7F�e����
u��ED�Ϳ�T�Q����XyȀt�xb8��� ����������'�Zm�V엇DT��!»
����@��2�� Nd۠;��̭�1�t5QtU�M�`�B�<�վmwX[�
�0�5���]��yM!��}/E��|g$�&���8�&~�a?C��_���z��տ�ɝN�D�LJ0�z����|�v,�r�$]���*HJ�$'��xGQ)P�4��TI�=8qc?���)`��N?_U率`���K��U4��8f��� &�
I tried using printf, but it didn't work. I will be glad of any hint, a link to the literature.
It is working. Mysql protocol isn't text-based. Printing it as-if it were text is inappropriate. Instead, consider hex-dumping like e.g.:
_sql_statement.assign(_client_data, bytes_transferred);
std::cout << "Received " << bytes_transferred << " bytes: ";
{
std::ostream hex(std::cout.rdbuf());
hex << std::hex << std::showbase << std::setfill('0');
for (auto i = 0; i < bytes_transferred; ++i) {
uint8_t octet = _client_data[i];
hex << " " << std::setw(4) << static_cast<int>(octet);
}
}
std::cout << std::endl;
Note I also changed
append
intoassign
to avoid infinite growth. Also consider renaming_sql_statemtent
into_data
to avoid misleading names.
A few things:
the mutex is useless if only one spot ever locks it
to avoid issues, don't close()
during potential async operations. Instead cancel()
them and let the error handling clean up via shared_from_this()
same for the acceptor, just setting _stopped = true
doesn't force the pending accept to complete. Instead, cancel() the _acceptor
.
Don't abuse shared_ptr::get()
, atomic<T>::load()
and atomic<T>::store()
for no reason
avoid the code duplication around async read:
void tcp_proxy::Bridge::handle_connection(error_code const& error) {
if (!error) {
do_read_fserver();
do_read_fclient();
} else {
std::cerr << "Connect Error! Error code = " << error.value() << ". Message : " << error.message() << "\n";
stop();
}
}
and re-use the same do_read_fXXX()
function in the write completions.
handle EOF properly. It's possible to have received data when EOF is encountered. So, write the data to the other end destroying the connection:
if (!error || error == asio::error::eof) {
I'll leave it as an exercise to the reader to optionally keep track of shutdown states (see e.g. boost::asio cleanly disconnecting)
you call proxy.stop_proxy()
after ... ios.run()
completed. That's useless by definition. Consider just omitting it, or put it in a more useful spot (e.g. in a signal_set::async_wait
handler?)
I also created a branch with these review comments on Gitlab: https://gitlab.com/v-danis/tcp-proxy/-/merge_requests/1 (branch https://gitlab.com/bitbucket54/tcp-proxy/-/tree/sehe-review?ref_type=heads).