zaphoyd/websocketpp — Issue #59: Policy Refactor: Server does not work on system having only IPv4
Author: megabyte1024
Created: 2012-02-01 18:43:33+00:00
State: open

Issue Description: Server does not work on system having only IPv4 (for instance WinXP without installed IPv6) and there is no possibility to use custom endpoint to use IPv4.
Cause: endpoint of io_service constructed with IPv6 protocol family.
File: server.hpp
Fix description: It's not necessary to have the boost::asio::ip::tcp::endpoint m_endpoint member. it's enough to to use a local endpoint. Additionally added a few new listen methods.
Fix:

diff --git a/src/roles/server.hpp b/src/roles/server.hpp
---------------------------------------------- cut here ----------------------------------------------
server(boost::asio::io_service& m)
: m_ws_endpoint(static_cast< endpoint_type& >(*this)),
m_io_service(m),
- // the only way to set an endpoint address family appears to be using
- // this constructor, which also requires a port. This port number can be
- // ignored, as it is always overwriten later by the listen() member func
- m_endpoint(boost::asio::ip::tcp::v6(),9000),
m_acceptor(m),
m_timer(m,boost::posix_time::seconds(0)) {}
-
- void listen(uint16_t port);
+ void listen(uint16_t port); // compatibility
+	void listen(const boost::asio::ip::tcp::endpoint &ep); // universal. Possible to suer external resolver
+	void listen(const std::string &host, const std::string &service); // uses internal resolver
+	template void listen(const InternetProtocol &internet_protocol, uint16_t port) {
+	m_ws_endpoint.alog().at(log::alevel::DEVEL) << "role::server listening on port " << port << log::endl;
+	boost::asio::ip::tcp::endpoint endpoint(internet_protocol, port);
+	listen(endpoint);
+	}
protected:
bool is_server() {
return true;
---------------------------------------------- cut here ----------------------------------------------
endpoint_type& m_ws_endpoint;
boost::asio::io_service& m_io_service;
- boost::asio::ip::tcp::endpoint m_endpoint;
boost::asio::ip::tcp::acceptor m_acceptor;

boost::asio::deadline_timer m_timer;
};

+template
+void server::listen(const boost::asio::ip::tcp::endpoint &ep) {
+	m_acceptor.open(ep.protocol());
+	m_acceptor.set_option(boost::asio::socket_base::reuse_address(true));
+	m_acceptor.bind(ep);
+	m_acceptor.listen();
+
+	this->start_accept();
+	m_ws_endpoint.run_internal();
+}
+
// server Implimentation
// TODO: protect listen from being called twice or in the wrong state.
// TODO: provide a way to stop/reset the server endpoint
template
void server::listen(uint16_t port) {
- m_endpoint.port(port);
- m_acceptor.open(m_endpoint.protocol());
- m_acceptor.set_option(boost::asio::socket_base::reuse_address(true));
- m_acceptor.bind(m_endpoint);
- m_acceptor.listen();
-
- this->start_accept();
-
- m_ws_endpoint.alog().at(log::alevel::DEVEL) << "role::server listening on port " << port << log::endl;
-
- m_ws_endpoint.run_internal();
+	listen(boost::asio::ip::tcp::v6(), port);
+}
+
+template
+void server::listen(const std::string &host, const std::string &service) {
+	boost::asio::ip::tcp::resolver resolver(m_io_service);
+	boost::asio::ip::tcp::resolver::query query(host, service);
+	boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
+	boost::asio::ip::tcp::resolver::iterator end;
+	if (endpoint_iterator == end) {
+	throw std::invalid_argument("Can't resolve host/service to listen");
+	}
+	listen(*endpoint_iterator);
}

template
---------------------------------------------- cut here ----------------------------------------------