add support for IPv4v6 and IPv4 + IPv6

This commit is contained in:
badaix 2018-04-25 14:08:11 +02:00
parent 962ff983cb
commit 3ff49c81b2
4 changed files with 95 additions and 40 deletions

View file

@ -30,7 +30,12 @@ using namespace std;
using json = nlohmann::json;
ControlServer::ControlServer(asio::io_service* io_service, size_t port, ControlMessageReceiver* controlMessageReceiver) : io_service_(io_service), port_(port), controlMessageReceiver_(controlMessageReceiver)
ControlServer::ControlServer(asio::io_service* io_service, size_t port, ControlMessageReceiver* controlMessageReceiver) :
acceptor_v4_(nullptr),
acceptor_v6_(nullptr),
io_service_(io_service),
port_(port),
controlMessageReceiver_(controlMessageReceiver)
{
}
@ -102,8 +107,16 @@ void ControlServer::onMessageReceived(ControlSession* connection, const std::str
void ControlServer::startAccept()
{
socket_ptr socket = make_shared<tcp::socket>(*io_service_);
acceptor_->async_accept(*socket, bind(&ControlServer::handleAccept, this, socket));
if (acceptor_v4_)
{
socket_ptr socket_v4 = make_shared<tcp::socket>(*io_service_);
acceptor_v4_->async_accept(*socket_v4, bind(&ControlServer::handleAccept, this, socket_v4));
}
if (acceptor_v6_)
{
socket_ptr socket_v6 = make_shared<tcp::socket>(*io_service_);
acceptor_v6_->async_accept(*socket_v6, bind(&ControlServer::handleAccept, this, socket_v6));
}
}
@ -136,36 +149,52 @@ void ControlServer::handleAccept(socket_ptr socket)
void ControlServer::start()
{
asio::ip::address address = asio::ip::address::from_string("::");
tcp::endpoint endpoint(address, port_);
bool is_v6_only(true);
tcp::endpoint endpoint_v6(tcp::v6(), port_);
try
{
acceptor_ = make_shared<tcp::acceptor>(*io_service_, endpoint);
acceptor_v6_ = make_shared<tcp::acceptor>(*io_service_, endpoint_v6);
error_code ec;
acceptor_v6_->set_option(asio::ip::v6_only(false), ec);
asio::ip::v6_only option;
acceptor_v6_->get_option(option);
is_v6_only = option.value();
LOG(DEBUG) << "IPv6 only: " << is_v6_only << "\n";
}
catch (const asio::system_error& e)
{
LOG(ERROR) << "error creating TCP acceptor: " << e.what() << ", code: " << e.code() << "\n";
if (e.code().value() == asio::error::address_family_not_supported)
{
endpoint = tcp::endpoint(tcp::v4(), port_);
acceptor_ = make_shared<tcp::acceptor>(*io_service_, endpoint);
}
else
throw;
}
if (endpoint.protocol() == tcp::v6())
if (!acceptor_v6_ || is_v6_only)
{
error_code ec;
acceptor_->set_option(asio::ip::v6_only(false), ec);
tcp::endpoint endpoint_v4(tcp::v4(), port_);
try
{
acceptor_v4_ = make_shared<tcp::acceptor>(*io_service_, endpoint_v4);
}
catch (const asio::system_error& e)
{
LOG(ERROR) << "error creating TCP acceptor: " << e.what() << ", code: " << e.code() << "\n";
}
}
startAccept();
}
void ControlServer::stop()
{
if (acceptor_)
acceptor_->cancel();
if (acceptor_v4_)
{
acceptor_v4_->cancel();
acceptor_v4_ = nullptr;
}
if (acceptor_v6_)
{
acceptor_v6_->cancel();
acceptor_v6_ = nullptr;
}
std::lock_guard<std::recursive_mutex> mlock(mutex_);
for (auto s: sessions_)
s->stop();

View file

@ -65,7 +65,8 @@ private:
// void acceptor();
mutable std::recursive_mutex mutex_;
std::set<std::shared_ptr<ControlSession>> sessions_;
std::shared_ptr<tcp::acceptor> acceptor_;
std::shared_ptr<tcp::acceptor> acceptor_v4_;
std::shared_ptr<tcp::acceptor> acceptor_v6_;
Queue<std::shared_ptr<msg::BaseMessage>> messages_;
asio::io_service* io_service_;

View file

@ -29,7 +29,11 @@ using namespace std;
using json = nlohmann::json;
StreamServer::StreamServer(asio::io_service* io_service, const StreamServerSettings& streamServerSettings) : io_service_(io_service), settings_(streamServerSettings)
StreamServer::StreamServer(asio::io_service* io_service, const StreamServerSettings& streamServerSettings) :
io_service_(io_service),
acceptor_v4_(nullptr),
acceptor_v6_(nullptr),
settings_(streamServerSettings)
{
}
@ -385,7 +389,7 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
{
if (request->method.find("Stream.SetMeta") == 0)
{
/// Request: {"id":4,"jsonrpc":"2.0","method":"Stream.SetMeta","params":{"stream_id":"Spotify",
/// Request: {"id":4,"jsonrpc":"2.0","method":"Stream.SetMeta","params":{"id":"Spotify",
/// "meta": {"album": "some album", "artist": "some artist", "track": "some track"...}}}
///
/// Response: {"id":4,"jsonrpc":"2.0","result":{"stream_id":"Spotify"}}
@ -620,8 +624,16 @@ session_ptr StreamServer::getStreamSession(const std::string& clientId) const
void StreamServer::startAccept()
{
socket_ptr socket = make_shared<tcp::socket>(*io_service_);
acceptor_->async_accept(*socket, bind(&StreamServer::handleAccept, this, socket));
if (acceptor_v4_)
{
socket_ptr socket_v4 = make_shared<tcp::socket>(*io_service_);
acceptor_v4_->async_accept(*socket_v4, bind(&StreamServer::handleAccept, this, socket_v4));
}
if (acceptor_v6_)
{
socket_ptr socket_v6 = make_shared<tcp::socket>(*io_service_);
acceptor_v6_->async_accept(*socket_v6, bind(&StreamServer::handleAccept, this, socket_v6));
}
}
@ -672,29 +684,36 @@ void StreamServer::start()
}
streamManager_->start();
asio::ip::address address = asio::ip::address::from_string("::");
tcp::endpoint endpoint(address, settings_.port);
bool is_v6_only(true);
tcp::endpoint endpoint_v6(tcp::v6(), settings_.port);
try
{
acceptor_ = make_shared<tcp::acceptor>(*io_service_, endpoint);
acceptor_v6_ = make_shared<tcp::acceptor>(*io_service_, endpoint_v6);
error_code ec;
acceptor_v6_->set_option(asio::ip::v6_only(false), ec);
asio::ip::v6_only option;
acceptor_v6_->get_option(option);
is_v6_only = option.value();
LOG(DEBUG) << "IPv6 only: " << is_v6_only << "\n";
}
catch (const asio::system_error& e)
{
LOG(ERROR) << "error creating TCP acceptor: " << e.what() << ", code: " << e.code() << "\n";
if (e.code().value() == asio::error::address_family_not_supported)
{
endpoint = tcp::endpoint(tcp::v4(), settings_.port);
acceptor_ = make_shared<tcp::acceptor>(*io_service_, endpoint);
}
else
throw;
}
if (endpoint.protocol() == tcp::v6())
if (!acceptor_v6_ || is_v6_only)
{
error_code ec;
acceptor_->set_option(asio::ip::v6_only(false), ec);
tcp::endpoint endpoint_v4(tcp::v4(), settings_.port);
try
{
acceptor_v4_ = make_shared<tcp::acceptor>(*io_service_, endpoint_v4);
}
catch (const asio::system_error& e)
{
LOG(ERROR) << "error creating TCP acceptor: " << e.what() << ", code: " << e.code() << "\n";
}
}
startAccept();
}
catch (const std::exception& e)
@ -733,10 +752,15 @@ void StreamServer::stop()
controlServer_ = nullptr;
}
if (acceptor_)
if (acceptor_v4_)
{
acceptor_->cancel();
acceptor_ = nullptr;
acceptor_v4_->cancel();
acceptor_v4_ = nullptr;
}
if (acceptor_v6_)
{
acceptor_v6_->cancel();
acceptor_v6_ = nullptr;
}
}

View file

@ -106,7 +106,8 @@ private:
mutable std::recursive_mutex sessionsMutex_;
std::set<session_ptr> sessions_;
asio::io_service* io_service_;
std::shared_ptr<tcp::acceptor> acceptor_;
std::shared_ptr<tcp::acceptor> acceptor_v4_;
std::shared_ptr<tcp::acceptor> acceptor_v6_;
StreamServerSettings settings_;
Queue<std::shared_ptr<msg::BaseMessage>> messages_;