FC Updates from BitShares and myself #21
3 changed files with 65 additions and 9 deletions
|
|
@ -50,8 +50,13 @@ namespace fc { namespace http {
|
||||||
void on_connection( const on_connection_handler& handler);
|
void on_connection( const on_connection_handler& handler);
|
||||||
void listen( uint16_t port );
|
void listen( uint16_t port );
|
||||||
void listen( const fc::ip::endpoint& ep );
|
void listen( const fc::ip::endpoint& ep );
|
||||||
|
uint16_t get_listening_port();
|
||||||
void start_accept();
|
void start_accept();
|
||||||
|
|
||||||
|
void stop_listening();
|
||||||
|
void close();
|
||||||
|
void synchronous_close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class detail::websocket_server_impl;
|
friend class detail::websocket_server_impl;
|
||||||
std::unique_ptr<detail::websocket_server_impl> my;
|
std::unique_ptr<detail::websocket_server_impl> my;
|
||||||
|
|
@ -83,6 +88,9 @@ namespace fc { namespace http {
|
||||||
|
|
||||||
websocket_connection_ptr connect( const std::string& uri );
|
websocket_connection_ptr connect( const std::string& uri );
|
||||||
websocket_connection_ptr secure_connect( const std::string& uri );
|
websocket_connection_ptr secure_connect( const std::string& uri );
|
||||||
|
|
||||||
|
void close();
|
||||||
|
void synchronous_close();
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<detail::websocket_client_impl> my;
|
std::unique_ptr<detail::websocket_client_impl> my;
|
||||||
std::unique_ptr<detail::websocket_tls_client_impl> smy;
|
std::unique_ptr<detail::websocket_tls_client_impl> smy;
|
||||||
|
|
|
||||||
|
|
@ -431,6 +431,7 @@ namespace fc { namespace http {
|
||||||
|
|
||||||
typedef websocket_client_type::connection_ptr websocket_client_connection_type;
|
typedef websocket_client_type::connection_ptr websocket_client_connection_type;
|
||||||
typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type;
|
typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type;
|
||||||
|
using websocketpp::connection_hdl;
|
||||||
|
|
||||||
class websocket_client_impl
|
class websocket_client_impl
|
||||||
{
|
{
|
||||||
|
|
@ -484,6 +485,7 @@ namespace fc { namespace http {
|
||||||
websocket_client_type _client;
|
websocket_client_type _client;
|
||||||
websocket_connection_ptr _connection;
|
websocket_connection_ptr _connection;
|
||||||
std::string _uri;
|
std::string _uri;
|
||||||
|
fc::optional<connection_hdl> _hdl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -625,11 +627,35 @@ namespace fc { namespace http {
|
||||||
}
|
}
|
||||||
void websocket_server::listen( const fc::ip::endpoint& ep )
|
void websocket_server::listen( const fc::ip::endpoint& ep )
|
||||||
{
|
{
|
||||||
my->_server.listen( boost::asio::ip::tcp::endpoint( boost::asio::ip::address_v4(uint32_t(ep.get_address())),ep.port()) );
|
my->_server.listen( boost::asio::ip::tcp::endpoint( boost::asio::ip::address_v4(uint32_t(ep.get_address())),ep.port()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t websocket_server::get_listening_port()
|
||||||
|
{
|
||||||
|
websocketpp::lib::asio::error_code ec;
|
||||||
|
return my->_server.get_local_endpoint(ec).port();
|
||||||
}
|
}
|
||||||
|
|
||||||
void websocket_server::start_accept() {
|
void websocket_server::start_accept() {
|
||||||
my->_server.start_accept();
|
my->_server.start_accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void websocket_server::stop_listening()
|
||||||
|
{
|
||||||
|
my->_server.stop_listening();
|
||||||
|
}
|
||||||
|
|
||||||
|
void websocket_server::close()
|
||||||
|
{
|
||||||
|
for (auto& connection : my->_connections)
|
||||||
|
my->_server.close(connection.first, websocketpp::close::status::normal, "Goodbye");
|
||||||
|
}
|
||||||
|
|
||||||
|
void websocket_server::synchronous_close()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
while (!my->_connections.empty())
|
||||||
|
fc::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -678,6 +704,7 @@ namespace fc { namespace http {
|
||||||
my->_connected = fc::promise<void>::ptr( new fc::promise<void>("websocket::connect") );
|
my->_connected = fc::promise<void>::ptr( new fc::promise<void>("websocket::connect") );
|
||||||
|
|
||||||
my->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){
|
my->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){
|
||||||
|
my->_hdl = hdl;
|
||||||
auto con = my->_client.get_con_from_hdl(hdl);
|
auto con = my->_client.get_con_from_hdl(hdl);
|
||||||
my->_connection = std::make_shared<detail::websocket_connection_impl<detail::websocket_client_connection_type>>( con );
|
my->_connection = std::make_shared<detail::websocket_connection_impl<detail::websocket_client_connection_type>>( con );
|
||||||
my->_closed = fc::promise<void>::ptr( new fc::promise<void>("websocket::closed") );
|
my->_closed = fc::promise<void>::ptr( new fc::promise<void>("websocket::closed") );
|
||||||
|
|
@ -717,7 +744,20 @@ namespace fc { namespace http {
|
||||||
smy->_client.connect(con);
|
smy->_client.connect(con);
|
||||||
smy->_connected->wait();
|
smy->_connected->wait();
|
||||||
return smy->_connection;
|
return smy->_connection;
|
||||||
} FC_CAPTURE_AND_RETHROW( (uri) ) }
|
} FC_CAPTURE_AND_RETHROW( (uri) ) }
|
||||||
|
|
||||||
|
void websocket_client::close()
|
||||||
|
{
|
||||||
|
if (my->_hdl)
|
||||||
|
my->_client.close(*my->_hdl, websocketpp::close::status::normal, "Goodbye");
|
||||||
|
}
|
||||||
|
|
||||||
|
void websocket_client::synchronous_close()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
if (my->_closed)
|
||||||
|
my->_closed->wait();
|
||||||
|
}
|
||||||
|
|
||||||
websocket_connection_ptr websocket_tls_client::connect( const std::string& uri )
|
websocket_connection_ptr websocket_tls_client::connect( const std::string& uri )
|
||||||
{ try {
|
{ try {
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,14 @@ BOOST_AUTO_TEST_CASE(login_test) {
|
||||||
c->set_session_data( wsc );
|
c->set_session_data( wsc );
|
||||||
});
|
});
|
||||||
|
|
||||||
server->listen( 8090 );
|
server->listen( 0 );
|
||||||
|
auto listen_port = server->get_listening_port();
|
||||||
server->start_accept();
|
server->start_accept();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto client = std::make_shared<fc::http::websocket_client>();
|
auto client = std::make_shared<fc::http::websocket_client>();
|
||||||
auto con = client->connect( "ws://localhost:8090" );
|
auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||||
|
server->stop_listening();
|
||||||
auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
|
auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
|
||||||
auto remote_login_api = apic->get_remote_api<login_api>();
|
auto remote_login_api = apic->get_remote_api<login_api>();
|
||||||
auto remote_calc = remote_login_api->get_calc();
|
auto remote_calc = remote_login_api->get_calc();
|
||||||
|
|
@ -87,8 +89,10 @@ BOOST_AUTO_TEST_CASE(login_test) {
|
||||||
BOOST_CHECK_EQUAL(remote_calc->add( 4, 5 ), 9);
|
BOOST_CHECK_EQUAL(remote_calc->add( 4, 5 ), 9);
|
||||||
BOOST_CHECK(remote_triggered);
|
BOOST_CHECK(remote_triggered);
|
||||||
|
|
||||||
|
client->synchronous_close();
|
||||||
|
server->synchronous_close();
|
||||||
|
fc::usleep(fc::milliseconds(50));
|
||||||
client.reset();
|
client.reset();
|
||||||
fc::usleep(fc::milliseconds(100));
|
|
||||||
server.reset();
|
server.reset();
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
|
|
@ -110,12 +114,14 @@ BOOST_AUTO_TEST_CASE(optionals_test) {
|
||||||
c->set_session_data( wsc );
|
c->set_session_data( wsc );
|
||||||
});
|
});
|
||||||
|
|
||||||
server->listen( 8090 );
|
server->listen( 0 );
|
||||||
|
auto listen_port = server->get_listening_port();
|
||||||
server->start_accept();
|
server->start_accept();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto client = std::make_shared<fc::http::websocket_client>();
|
auto client = std::make_shared<fc::http::websocket_client>();
|
||||||
auto con = client->connect( "ws://localhost:8090" );
|
auto con = client->connect( "ws://localhost:" + std::to_string(listen_port) );
|
||||||
|
server->stop_listening();
|
||||||
auto apic = std::make_shared<websocket_api_connection>(*con, MAX_DEPTH);
|
auto apic = std::make_shared<websocket_api_connection>(*con, MAX_DEPTH);
|
||||||
auto remote_optionals = apic->get_remote_api<optionals_api>();
|
auto remote_optionals = apic->get_remote_api<optionals_api>();
|
||||||
|
|
||||||
|
|
@ -124,8 +130,10 @@ BOOST_AUTO_TEST_CASE(optionals_test) {
|
||||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
|
BOOST_CHECK_EQUAL(remote_optionals->foo("a", "b", "c"), "[\"a\",\"b\",\"c\"]");
|
||||||
BOOST_CHECK_EQUAL(remote_optionals->foo("a", {}, "c"), "[\"a\",null,\"c\"]");
|
BOOST_CHECK_EQUAL(remote_optionals->foo("a", {}, "c"), "[\"a\",null,\"c\"]");
|
||||||
|
|
||||||
|
client->synchronous_close();
|
||||||
|
server->synchronous_close();
|
||||||
|
fc::usleep(fc::milliseconds(50));
|
||||||
client.reset();
|
client.reset();
|
||||||
fc::usleep(fc::milliseconds(100));
|
|
||||||
server.reset();
|
server.reset();
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue