boost::asio::io_service &io();
uint32_t read_forwarded_port(yield_ctx yield);
void setup_port_socket(int port, yield_ctx yield);
+ /* This might be scheduled after ProxySession is destroyed, so let's keep it static */
+ static void stop_port_listening_at_timeout(
+ std::shared_ptr<boost::asio::deadline_timer> timeout,
+ std::shared_ptr<ip::tcp::acceptor> port_acceptor,
+ yield_ctx yield);
std::shared_ptr<AsyncEvent> start_forwarding();
template<typename T>
void close_socket(std::shared_ptr<boost::asio::basic_stream_socket<T>> sock);
return target_port[0];
}
+void ProxySession::stop_port_listening_at_timeout(
+ std::shared_ptr<boost::asio::deadline_timer> timeout,
+ std::shared_ptr<ip::tcp::acceptor> port_acceptor,
+ yield_ctx yield)
+{
+ timeout->expires_from_now(ProxySession::PORT_TIMEOUT);
+ try {
+ timeout->async_wait(yield);
+ } catch (boost::system::system_error &e) {
+ /* We were canceled, just continue */
+ };
+ port_acceptor->cancel();
+}
+
void ProxySession::setup_port_socket(int port, yield_ctx yield)
{
ip::tcp::endpoint port_ep(ip::address::from_string("127.0.0.1"), port);
auto port_acceptor = std::make_shared<ip::tcp::acceptor>(this->io(), port_ep);
-
/* FIXME: We don't want to read data from local socket before
* forwarding it, so checking if it closed while we're listening on the
* port is difficult. Let's just timeout instead.
*/
- auto stop_at_timeout =
- [this, &io = this->io(), acceptor_ptr = std::weak_ptr<ip::tcp::acceptor>(port_acceptor)]
- (yield_ctx yield) {
- boost::asio::deadline_timer timeout(this->io());
- timeout.expires_from_now(ProxySession::PORT_TIMEOUT);
- timeout.async_wait(yield);
- auto acceptor = acceptor_ptr.lock();
- if (!acceptor)
- return;
- acceptor->cancel();
+ auto timeout = std::make_shared<boost::asio::deadline_timer>(this->io());
+ boost::asio::spawn(this->io(), boost::bind(
+ &ProxySession::stop_port_listening_at_timeout,
+ timeout, port_acceptor, _1));
+ try {
+ port_acceptor->async_accept(*this->port_socket, yield);
+ } catch (boost::system::system_error &e) {
+ if (e.code() == boost::asio::error::operation_aborted)
LOGI(MODULE_DEBUGPROXY, "(%p) Timed out waiting for a port connection", this);
- };
- boost::asio::spawn(this->io(), stop_at_timeout);
- port_acceptor->async_accept(*this->port_socket, yield);
+ throw;
+ }
+ timeout->cancel();
}
std::shared_ptr<AsyncEvent> ProxySession::start_forwarding()