--- /dev/null
+Boost Software License - Version 1.0 - August 17th, 2003\r
+\r
+Permission is hereby granted, free of charge, to any person or organization\r
+obtaining a copy of the software and accompanying documentation covered by\r
+this license (the "Software") to use, reproduce, display, distribute,\r
+execute, and transmit the Software, and to prepare derivative works of the\r
+Software, and to permit third-parties to whom the Software is furnished to\r
+do so, all subject to the following:\r
+\r
+The copyright notices in the Software and this entire statement, including\r
+the above license grant, this restriction and the following disclaimer,\r
+must be included in all copies of the Software, in whole or in part, and\r
+all derivative works of the Software, unless such copies or derivative\r
+works are solely in the form of machine-executable object code generated by\r
+a source language processor.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\r
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\r
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\r
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+DEALINGS IN THE SOFTWARE.\r
--- /dev/null
+// \r
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
+// \r
+// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
+// \r
+\r
+#ifndef BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_HPP \r
+#define BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_HPP \r
+\r
+#include <boost/asio.hpp> \r
+#include <signal.h> \r
+\r
+namespace boost { \r
+namespace asio { \r
+namespace posix { \r
+\r
+template <typename Service> \r
+class basic_signal_handler \r
+ : public boost::asio::basic_io_object<Service> \r
+{ \r
+public: \r
+ explicit basic_signal_handler(boost::asio::io_service &io_service) \r
+ : boost::asio::basic_io_object<Service>(io_service) \r
+ { \r
+ } \r
+\r
+ void add_signal(int signal, int flags = 0, sigset_t *mask = 0) \r
+ { \r
+ this->service.add_signal(this->implementation, signal, flags, mask); \r
+ } \r
+\r
+ void remove_signal(int signal) \r
+ { \r
+ this->service.remove_signal(this->implementation, signal); \r
+ } \r
+\r
+ int wait() \r
+ { \r
+ boost::system::error_code ec; \r
+ int signal = this->service.wait(this->implementation, ec); \r
+ boost::asio::detail::throw_error(ec); \r
+ return signal; \r
+ } \r
+\r
+ int wait(boost::system::error_code &ec) \r
+ { \r
+ return this->service.wait(this->implementation, ec); \r
+ } \r
+\r
+ template <typename Handler> \r
+ void async_wait(Handler handler) \r
+ { \r
+ this->service.async_wait(this->implementation, handler); \r
+ } \r
+}; \r
+\r
+} \r
+} \r
+} \r
+\r
+#endif \r
--- /dev/null
+// \r
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
+// \r
+// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
+// \r
+\r
+#ifndef BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_SERVICE_HPP \r
+#define BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_SERVICE_HPP \r
+\r
+#include "signal_handler_impl.hpp" \r
+#include <boost/asio.hpp> \r
+#include <boost/thread.hpp> \r
+#include <boost/bind.hpp> \r
+#include <boost/shared_ptr.hpp> \r
+#include <boost/weak_ptr.hpp> \r
+#include <boost/scoped_ptr.hpp> \r
+#include <boost/system/error_code.hpp> \r
+#include <boost/system/system_error.hpp> \r
+#include <cstring> \r
+#include <signal.h> \r
+#include <unistd.h> \r
+\r
+namespace boost { \r
+namespace asio { \r
+namespace posix { \r
+\r
+template <typename SignalHandlerImplementation = signal_handler_impl> \r
+class basic_signal_handler_service \r
+ : public boost::asio::io_service::service \r
+{ \r
+public: \r
+ static boost::asio::io_service::id id; \r
+\r
+ explicit basic_signal_handler_service(boost::asio::io_service &io_service) \r
+ : boost::asio::io_service::service(io_service), \r
+ async_wait_work_(new boost::asio::io_service::work(async_wait_io_service_)), \r
+ async_wait_thread_(boost::bind(&boost::asio::io_service::run, &async_wait_io_service_)) \r
+ { \r
+ } \r
+\r
+ virtual ~basic_signal_handler_service()\r
+ { \r
+ // The async_wait thread will finish when async_wait_work_ is reset as all asynchronous \r
+ // operations have been aborted and were discarded before (in destroy). \r
+ async_wait_work_.reset(); \r
+\r
+ // Event processing is stopped to discard queued operations. \r
+ async_wait_io_service_.stop(); \r
+\r
+ // The async_wait thread is joined to make sure the signal handler service is \r
+ // destroyed _after_ the thread is finished (not that the thread tries to access \r
+ // instance properties which don't exist anymore). \r
+ async_wait_thread_.join(); \r
+ } \r
+\r
+ typedef boost::shared_ptr<SignalHandlerImplementation> implementation_type; \r
+\r
+ void construct(implementation_type &impl) \r
+ { \r
+ // We must count the I/O objects and can't rely on the shared pointer impl_ \r
+ // as an asynchronous call can hold a shared pointer at any time, too, thus \r
+ // preventing the implementation to be destroyed in destroy(). \r
+ ++count_; \r
+\r
+ implementation_type shared_impl = impl_.lock(); \r
+ if (shared_impl) \r
+ { \r
+ impl = shared_impl; \r
+ } \r
+ else \r
+ { \r
+ impl.reset(new SignalHandlerImplementation()); \r
+ impl_ = impl; \r
+ fd_ = impl->write_end(); \r
+ } \r
+ } \r
+\r
+ void destroy(implementation_type &impl) \r
+ { \r
+ // If an asynchronous call is currently waiting for a signal \r
+ // we must interrupt the blocked call to make sure it returns. \r
+ if (!--count_) \r
+ impl->destroy(); \r
+\r
+ impl.reset(); \r
+ } \r
+\r
+ void add_signal(implementation_type &impl, int signal, int flags, sigset_t *mask) \r
+ { \r
+ struct sigaction act, oldact; \r
+\r
+ std::memset(&act, 0, sizeof(struct sigaction)); \r
+ act.sa_handler = basic_signal_handler_service<SignalHandlerImplementation>::signal_handler; \r
+ act.sa_flags = flags; \r
+ if (mask) \r
+ act.sa_mask = *mask; \r
+\r
+ int res = sigaction(signal, &act, &oldact); \r
+ if (res == -1) \r
+ { \r
+ boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::asio::posix::basic_signal_handler_service::add_signal: sigaction failed"); \r
+ boost::throw_exception(e); \r
+ } \r
+\r
+ impl->add_signal(signal, oldact); \r
+ } \r
+\r
+ void remove_signal(implementation_type &impl, int signal) \r
+ { \r
+ impl->remove_signal(signal); \r
+ } \r
+\r
+ int wait(implementation_type &impl, boost::system::error_code &ec) \r
+ { \r
+ return impl->wait(ec); \r
+ } \r
+\r
+ template <typename Handler> \r
+ class wait_operation \r
+ { \r
+ public: \r
+ wait_operation(implementation_type &impl, boost::asio::io_service &io_service, Handler handler) \r
+ : impl_(impl), \r
+ io_service_(io_service), \r
+ work_(io_service), \r
+ handler_(handler) \r
+ { \r
+ } \r
+\r
+ void operator()() const \r
+ { \r
+ implementation_type impl = impl_.lock(); \r
+ if (impl) \r
+ { \r
+ boost::system::error_code ec; \r
+ int signal = impl->wait(ec); \r
+ this->io_service_.post(boost::asio::detail::bind_handler(handler_, ec, signal)); \r
+ } \r
+ else \r
+ { \r
+ this->io_service_.post(boost::asio::detail::bind_handler(handler_, boost::asio::error::operation_aborted, 0)); \r
+ } \r
+ } \r
+\r
+ private: \r
+ boost::weak_ptr<SignalHandlerImplementation> impl_; \r
+ boost::asio::io_service &io_service_; \r
+ boost::asio::io_service::work work_; \r
+ Handler handler_; \r
+ }; \r
+\r
+ template <typename Handler> \r
+ void async_wait(implementation_type &impl, Handler handler) \r
+ { \r
+ this->async_wait_io_service_.post(wait_operation<Handler>(impl, this->get_io_service(), handler)); \r
+ } \r
+\r
+private: \r
+ void shutdown_service() \r
+ { \r
+ } \r
+\r
+ static void signal_handler(int signal) \r
+ { \r
+ while (::write(fd_, &signal, sizeof(signal)) == -1 && errno == EINTR); \r
+ } \r
+\r
+ static int count_; \r
+ static boost::weak_ptr<SignalHandlerImplementation> impl_; \r
+ static int fd_; \r
+ boost::asio::io_service async_wait_io_service_; \r
+ boost::scoped_ptr<boost::asio::io_service::work> async_wait_work_; \r
+ boost::thread async_wait_thread_; \r
+}; \r
+\r
+template <typename SignalHandlerImplementation> \r
+boost::asio::io_service::id basic_signal_handler_service<SignalHandlerImplementation>::id; \r
+\r
+template <typename SignalHandlerImplementation> \r
+int basic_signal_handler_service<SignalHandlerImplementation>::count_ = 0; \r
+\r
+template <typename SignalHandlerImplementation> \r
+boost::weak_ptr<SignalHandlerImplementation> basic_signal_handler_service<SignalHandlerImplementation>::impl_; \r
+\r
+template <typename SignalHandlerImplementation> \r
+int basic_signal_handler_service<SignalHandlerImplementation>::fd_; \r
+\r
+} \r
+} \r
+} \r
+\r
+#endif \r
--- /dev/null
+// \r
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
+// \r
+// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
+// \r
+\r
+#ifndef BOOST_ASIO_POSIX_SIGNAL_HANDLER_HPP \r
+#define BOOST_ASIO_POSIX_SIGNAL_HANDLER_HPP \r
+\r
+#include "basic_signal_handler.hpp" \r
+#include "basic_signal_handler_service.hpp" \r
+\r
+namespace boost { \r
+namespace asio { \r
+namespace posix { \r
+\r
+typedef basic_signal_handler<basic_signal_handler_service<> > signal_handler; \r
+\r
+} \r
+} \r
+} \r
+\r
+#endif \r
--- /dev/null
+// \r
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
+// \r
+// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
+// \r
+\r
+#ifndef BOOST_ASIO_POSIX_SIGNAL_HANDLER_IMPL_HPP \r
+#define BOOST_ASIO_POSIX_SIGNAL_HANDLER_IMPL_HPP \r
+\r
+#include <boost/asio.hpp> \r
+#include <boost/thread.hpp> \r
+#include <boost/bind.hpp> \r
+#include <boost/system/error_code.hpp> \r
+#include <boost/system/system_error.hpp> \r
+#include <map> \r
+#include <deque> \r
+#include <signal.h> \r
+#include <unistd.h> \r
+\r
+namespace boost { \r
+namespace asio { \r
+namespace posix { \r
+\r
+class signal_handler_impl \r
+{ \r
+public: \r
+ signal_handler_impl() \r
+ : sd_(signal_handler_io_service_), \r
+ run_(true) \r
+ { \r
+ int res = pipe(fds_); \r
+ if (res == -1) \r
+ { \r
+ boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::asio::posix::signal_handler_impl::signal_handler_impl: pipe failed"); \r
+ boost::throw_exception(e); \r
+ } \r
+\r
+ sd_.assign(fds_[0]); \r
+ begin_read(); \r
+ signal_handler_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &signal_handler_io_service_)); \r
+ } \r
+\r
+ ~signal_handler_impl() \r
+ { \r
+ for (sigactions_t::iterator it = sigactions_.begin(); it != sigactions_.end(); ++it) \r
+ sigaction(it->first, &it->second, 0); \r
+\r
+ close(fds_[1]); \r
+ sd_.close(); \r
+\r
+ signal_handler_io_service_.stop(); \r
+ signal_handler_thread_.join(); \r
+ } \r
+\r
+ int write_end() const \r
+ { \r
+ return fds_[1]; \r
+ } \r
+\r
+ void add_signal(int signal, struct sigaction oldact) \r
+ { \r
+ sigactions_.insert(sigactions_t::value_type(signal, oldact)); \r
+ } \r
+\r
+ void remove_signal(int signal) \r
+ { \r
+ sigactions_t::iterator it = sigactions_.find(signal); \r
+ if (it != sigactions_.end()) \r
+ { \r
+ sigaction(signal, &it->second, 0); \r
+ sigactions_.erase(it); \r
+ } \r
+ } \r
+\r
+ void destroy() \r
+ { \r
+ boost::unique_lock<boost::mutex> lock(pending_signals_mutex_); \r
+ run_ = false; \r
+ pending_signals_cond_.notify_all(); \r
+ } \r
+\r
+ int wait(boost::system::error_code &ec) \r
+ { \r
+ boost::unique_lock<boost::mutex> lock(pending_signals_mutex_); \r
+ while (run_ && pending_signals_.empty()) \r
+ pending_signals_cond_.wait(lock); \r
+ int signal = 0; \r
+ if (!pending_signals_.empty()) \r
+ { \r
+ signal = pending_signals_.front(); \r
+ pending_signals_.pop_front(); \r
+ } \r
+ else \r
+ ec = boost::asio::error::operation_aborted; \r
+ return signal; \r
+ } \r
+\r
+private: \r
+ void begin_read() \r
+ { \r
+ boost::asio::async_read(sd_, boost::asio::buffer(signal_buffer_), \r
+ boost::bind(&signal_handler_impl::end_read, this, \r
+ boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); \r
+ } \r
+\r
+ void end_read(const boost::system::error_code &ec, std::size_t bytes_transferred) \r
+ { \r
+ if (!ec) \r
+ { \r
+ boost::unique_lock<boost::mutex> lock(pending_signals_mutex_); \r
+ pending_signals_.push_back(signal_buffer_[0]); \r
+ pending_signals_cond_.notify_all(); \r
+ begin_read(); \r
+ } \r
+ } \r
+\r
+ int fds_[2]; \r
+ boost::asio::io_service signal_handler_io_service_; \r
+ boost::thread signal_handler_thread_; \r
+ boost::asio::posix::stream_descriptor sd_; \r
+ int signal_buffer_[1]; \r
+ typedef std::map<int, struct sigaction> sigactions_t; \r
+ sigactions_t sigactions_; \r
+ boost::mutex pending_signals_mutex_; \r
+ boost::condition_variable_any pending_signals_cond_; \r
+ bool run_; \r
+ std::deque<int> pending_signals_; \r
+}; \r
+\r
+} \r
+} \r
+} \r
+\r
+#endif \r
# package: boost-net-dns
include_directories(${CMAKE_SOURCE_DIR}/lib/boost-net-dns)
+# package: boost-signal_handler
+include_directories(${CMAKE_SOURCE_DIR}/lib/boost-signal_handler)
+
# package: libi2ncommon
pkg_check_modules(I2NCOMMON REQUIRED libi2ncommon)
include_directories(${I2NCOMMON_INCLUDE_DIRS})
Thread.join();
}
+/**
+ * @brief Stops pinging the host. Request the thread to finish, which makes the
+ * any blocking wait (join) on this object to return.
+ */
+void PingScheduler::stop_pinging_thread()
+{
+ stop_pinging();
+}
+
bool PingScheduler::start_pinging()
{
bool address_resolved = resolve_ping_address();
bool start_pinging_thread();
void wait_pinging_thread();
+ void stop_pinging_thread();
+
+private:
bool start_pinging();
void stop_pinging();
-private:
bool resolve_ping_address();
bool ping( const std::string &destination_ip ) const;
void setup_next_ping();
void schedule_next_ping();
+
void update_ping_statistics( const bool ping_success );
void update_ping_interval();
void update_ping_elapsed_time();
+#include <signal.h>
+
#include <vector>
#include <iostream>
#include <boost/asio.hpp>
+#include <boost/asio/posix/signal_handler.hpp>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
return link_analyzer;
}
-void init_log()
+void init_logger()
{
I2n::Logger::enable_syslog( I2n::Logger::Facility::User );
// TODO: Change back to Notice log level
I2n::Logger::set_log_level( I2n::Logger::LogLevel::Info );
}
+void init_signal_handler()
+{
+ // TODO
+}
+
void init_pingers(
const ConfigurationItem &configuration,
const LinkStatusAnalyzerItem &status_notifier,
const PingSchedulerList &scheduler_list
)
{
- // start each scheduler
+ // start each ping scheduler
BOOST_FOREACH( PingSchedulerItem scheduler, scheduler_list )
{
bool started = scheduler->start_pinging_thread();
}
}
+#if 0
// Main loop to handle scheduled ping requests
BOOST_FOREACH( PingSchedulerItem scheduler, scheduler_list )
{
scheduler->wait_pinging_thread();
}
+#endif
+}
+
+void stop_pingers(
+ const PingSchedulerList &scheduler_list
+)
+{
+ // stop each ping scheduler
+ BOOST_FOREACH( PingSchedulerItem scheduler, scheduler_list )
+ {
+ scheduler->stop_pinging_thread();
+ }
+}
+
+void handle_SIGINT(
+ const boost::system::error_code &ec,
+ int signal
+)
+{
+// cerr << "handle_SIGINT" << endl;
+ // TODO may I call stop_pingers() them from here?
+// stop_pingers();
}
int main( int argc, char *argv[] )
{
- init_log();
+ init_logger();
ConfigurationItem configuration = get_configuration( argc, argv );
if ( configuration.get() != NULL )
init_pingers( configuration, status_notifier, &scheduler_list );
start_pingers( scheduler_list );
+
+ // TODO signal stuff to method
+ io_service io_serv;
+ boost::asio::posix::signal_handler sh( io_serv );
+ sh.add_signal( SIGINT );
+ sh.async_wait( handle_SIGINT );
+ io_serv.run();
}
return 0;