// OpenVPN -- An application to securely tunnel IP networks // over a single port, with support for SSL/TLS-based // session authentication and key exchange, // packet encryption, packet authentication, and // packet compression. // // Copyright (C) 2012-2022 OpenVPN Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License Version 3 // as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program in the COPYING file. // If not, see . // These classes define function objects to be used as asynchronous callbacks // for Asio methods. Think of these as optimized special cases of function // objects that could be more generally (but perhaps less optimally) defined // with lambdas. #ifndef OPENVPN_COMMON_ASIODISPATCH_H #define OPENVPN_COMMON_ASIODISPATCH_H #include #include #include namespace openvpn { // Dispatcher for asio async_write template class AsioDispatchWrite { public: AsioDispatchWrite(Handler handle_write, C* obj) : handle_write_(handle_write), obj_(obj) {} void operator()(const asio::error_code& error, const size_t bytes_sent) { (obj_.get()->*handle_write_)(error, bytes_sent); } private: Handler handle_write_; RCPtr obj_; }; template AsioDispatchWrite asio_dispatch_write(Handler handle_write, C* obj) { return AsioDispatchWrite(handle_write, obj); } // Dispatcher for asio async_read with argument template class AsioDispatchRead { public: AsioDispatchRead(Handler handle_read, C* obj, Data data) : handle_read_(handle_read), obj_(obj), data_(data) {} void operator()(const asio::error_code& error, const size_t bytes_recvd) { (obj_.get()->*handle_read_)(data_, error, bytes_recvd); } private: Handler handle_read_; RCPtr obj_; Data data_; }; template AsioDispatchRead asio_dispatch_read(Handler handle_read, C* obj, Data data) { return AsioDispatchRead(handle_read, obj, data); } // Dispatcher for asio async_read without argument template class AsioDispatchReadNoArg { public: AsioDispatchReadNoArg(Handler handle_read, C* obj) : handle_read_(handle_read), obj_(obj) {} void operator()(const asio::error_code& error, const size_t bytes_recvd) { (obj_.get()->*handle_read_)(error, bytes_recvd); } private: Handler handle_read_; RCPtr obj_; }; template AsioDispatchReadNoArg asio_dispatch_read_noarg(Handler handle_read, C* obj) { return AsioDispatchReadNoArg(handle_read, obj); } // Dispatcher for asio async_wait with argument template class AsioDispatchTimerArg { public: AsioDispatchTimerArg(Handler handler, C* obj, Data data) : handler_(handler), obj_(obj), data_(data) {} void operator()(const asio::error_code& error) { (obj_.get()->*handler_)(data_, error); } private: Handler handler_; RCPtr obj_; Data data_; }; template AsioDispatchTimerArg asio_dispatch_timer_arg(Handler handler, C* obj, Data data) { return AsioDispatchTimerArg(handler, obj, data); } // Dispatcher for asio async_wait without argument template class AsioDispatchTimer { public: AsioDispatchTimer(Handler handler, C* obj) : handler_(handler), obj_(obj) {} void operator()(const asio::error_code& error) { (obj_.get()->*handler_)(error); } private: Handler handler_; RCPtr obj_; }; template AsioDispatchTimer asio_dispatch_timer(Handler handler, C* obj) { return AsioDispatchTimer(handler, obj); } // Dispatcher for asio async_connect with argument template class AsioDispatchConnectArg { public: AsioDispatchConnectArg(Handler handler, C* obj, Data data) : handler_(handler), obj_(obj), data_(data) {} void operator()(const asio::error_code& error) { (obj_.get()->*handler_)(data_, error); } private: Handler handler_; RCPtr obj_; Data data_; }; template AsioDispatchConnectArg asio_dispatch_connect_arg(Handler handler, C* obj, Data data) { return AsioDispatchConnectArg(handler, obj, data); } // Dispatcher for asio async_connect without argument template class AsioDispatchConnect { public: AsioDispatchConnect(Handler handler, C* obj) : handler_(handler), obj_(obj) {} void operator()(const asio::error_code& error) { (obj_.get()->*handler_)(error); } private: Handler handler_; RCPtr obj_; }; template AsioDispatchConnect asio_dispatch_connect(Handler handler, C* obj) { return AsioDispatchConnect(handler, obj); } // Dispatcher for asio async_connect (ComposedConnectHandler) without argument template class AsioDispatchComposedConnect { public: AsioDispatchComposedConnect(Handler handler, C* obj) : handler_(handler), obj_(obj) {} void operator()(const asio::error_code& error, asio::ip::tcp::resolver::iterator endpoint_iterator) { (obj_.get()->*handler_)(error, endpoint_iterator); } private: Handler handler_; RCPtr obj_; }; template AsioDispatchComposedConnect asio_dispatch_composed_connect(Handler handler, C* obj) { return AsioDispatchComposedConnect(handler, obj); } // Dispatcher for asio async_accept with argument template class AsioDispatchAcceptArg { public: AsioDispatchAcceptArg(Handler handler, C* obj, Data data) : handler_(handler), obj_(obj), data_(data) {} void operator()(const asio::error_code& error) { (obj_.get()->*handler_)(data_, error); } private: Handler handler_; RCPtr obj_; Data data_; }; template AsioDispatchAcceptArg asio_dispatch_accept_arg(Handler handler, C* obj, Data data) { return AsioDispatchAcceptArg(handler, obj, data); } // Dispatcher for asio post with argument template class AsioDispatchPostArg { public: AsioDispatchPostArg(Handler handler, C* obj, Data data) : handler_(handler), obj_(obj), data_(data) {} void operator()() { (obj_.get()->*handler_)(data_); } private: Handler handler_; RCPtr obj_; Data data_; }; template AsioDispatchPostArg asio_dispatch_post_arg(Handler handler, C* obj, Data data) { return AsioDispatchPostArg(handler, obj, data); } // Dispatcher for asio post without argument template class AsioDispatchPost { public: AsioDispatchPost(Handler handler, C* obj) : handler_(handler), obj_(obj) {} void operator()() { (obj_.get()->*handler_)(); } private: Handler handler_; RCPtr obj_; }; template AsioDispatchPost asio_dispatch_post(Handler handler, C* obj) { return AsioDispatchPost(handler, obj); } // Dispatcher for asynchronous resolver without argument template class AsioDispatchResolve { public: AsioDispatchResolve(Handler handler, C* obj) : handler_(handler), obj_(obj) {} void operator()(const asio::error_code& error, EndpointIterator iter) { (obj_.get()->*handler_)(error, iter); } private: Handler handler_; RCPtr obj_; }; // Dispatcher for asynchronous resolver with argument template class AsioDispatchResolveArg { public: AsioDispatchResolveArg(Handler handler, C* obj, Data data) : handler_(handler), obj_(obj), data_(data) {} void operator()(const asio::error_code& error, EndpointIterator iter) { (obj_.get()->*handler_)(error, iter, data_); } private: Handler handler_; RCPtr obj_; Data data_; }; // Dispatcher for asio signal template class AsioDispatchSignal { public: AsioDispatchSignal(Handler handler, C* obj) : handler_(handler), obj_(obj) {} void operator()(const asio::error_code& error, int signal_number) { (obj_.get()->*handler_)(error, signal_number); } private: Handler handler_; RCPtr obj_; }; template AsioDispatchSignal asio_dispatch_signal(Handler handler, C* obj) { return AsioDispatchSignal(handler, obj); } // General purpose dispatcher with data template class SimpleDispatch { public: SimpleDispatch(Handler handler, C* obj) : handler_(handler), obj_(obj) {} void operator()(Data data) { (obj_->*handler_)(data); } private: Handler handler_; C* obj_; }; } // namespace openvpn #endif // OPENVPN_COMMON_ASIODISPATCH_H