| 1 | #include "connection.hpp"
|
|---|
| 2 | #include "tcp_connection.hpp"
|
|---|
| 3 | #include "ssl_connection.hpp"
|
|---|
| 4 | #include <vector>
|
|---|
| 5 | #include <boost/bind.hpp>
|
|---|
| 6 | #include <boost/logic/tribool.hpp>
|
|---|
| 7 | #include <boost/utility.hpp>
|
|---|
| 8 | #include <boost/tuple/tuple.hpp>
|
|---|
| 9 | #include <boost/asio/ssl.hpp>
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 | namespace nrpe {
|
|---|
| 13 | namespace server {
|
|---|
| 14 |
|
|---|
| 15 | connection::connection(boost::asio::io_service& io_service, boost::shared_ptr<nrpe::server::handler> handler)
|
|---|
| 16 | : strand_(io_service)
|
|---|
| 17 | , handler_(handler)
|
|---|
| 18 | , parser_(handler)
|
|---|
| 19 | , timer_(io_service)
|
|---|
| 20 | {}
|
|---|
| 21 |
|
|---|
| 22 | connection::~connection() {}
|
|---|
| 23 |
|
|---|
| 24 | connection* factories::create(boost::asio::io_service& io_service, boost::asio::ssl::context &context, boost::shared_ptr<nrpe::server::handler> handler, bool use_ssl) {
|
|---|
| 25 | if (use_ssl)
|
|---|
| 26 | return create_ssl(io_service, context, handler);
|
|---|
| 27 | return create_tcp(io_service, handler);
|
|---|
| 28 | }
|
|---|
| 29 | connection* factories::create_tcp(boost::asio::io_service& io_service, boost::shared_ptr<nrpe::server::handler> handler) {
|
|---|
| 30 | return new tcp_connection(io_service, handler);
|
|---|
| 31 | }
|
|---|
| 32 | connection* factories::create_ssl(boost::asio::io_service& io_service, boost::asio::ssl::context &context, boost::shared_ptr<nrpe::server::handler> handler) {
|
|---|
| 33 | return new ssl_connection(io_service, context, handler);
|
|---|
| 34 | }
|
|---|
| 35 |
|
|---|
| 36 | void connection::start() {
|
|---|
| 37 | handler_->log_debug(__FILE__, __LINE__, _T("starting data connection"));
|
|---|
| 38 | start_read_request(buffer_, 30);
|
|---|
| 39 | }
|
|---|
| 40 |
|
|---|
| 41 | void connection::set_timeout(int seconds) {
|
|---|
| 42 | timer_.expires_from_now(boost::posix_time::seconds(seconds));
|
|---|
| 43 | timer_.async_wait(boost::bind(&connection::timeout, shared_from_this(), boost::asio::placeholders::error));
|
|---|
| 44 | }
|
|---|
| 45 |
|
|---|
| 46 | void connection::cancel_timer() {
|
|---|
| 47 | timer_.cancel();
|
|---|
| 48 | }
|
|---|
| 49 |
|
|---|
| 50 | void connection::timeout(const boost::system::error_code& e) {
|
|---|
| 51 | handler_->log_debug(__FILE__, __LINE__, _T("Timeout"));
|
|---|
| 52 | if (e != boost::asio::error::operation_aborted) {
|
|---|
| 53 | handler_->log_debug(__FILE__, __LINE__, _T("Timeout <<<-"));
|
|---|
| 54 | boost::system::error_code ignored_ec;
|
|---|
| 55 | socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
|---|
| 56 | }
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 |
|
|---|
| 60 | void connection::handle_read_request(const boost::system::error_code& e, std::size_t bytes_transferred) {
|
|---|
| 61 | if (!e) {
|
|---|
| 62 | bool result;
|
|---|
| 63 | buffer_type::iterator begin = buffer_.begin();
|
|---|
| 64 | buffer_type::iterator end = buffer_.begin() + bytes_transferred;
|
|---|
| 65 | while (begin != end) {
|
|---|
| 66 | buffer_type::iterator old_begin = begin;
|
|---|
| 67 | boost::tie(result, begin) = parser_.digest(begin, end);
|
|---|
| 68 | if (begin == old_begin) {
|
|---|
| 69 | handler_->create_error(_T("Something strange happened..."));
|
|---|
| 70 | return;
|
|---|
| 71 | }
|
|---|
| 72 | if (result) {
|
|---|
| 73 | nrpe::packet response;
|
|---|
| 74 | try {
|
|---|
| 75 | nrpe::packet request = parser_.parse();
|
|---|
| 76 | response = handler_->handle(request);
|
|---|
| 77 | } catch (nrpe::nrpe_packet_exception &e) {
|
|---|
| 78 | response = handler_->create_error(e.getMessage());
|
|---|
| 79 | } catch (...) {
|
|---|
| 80 | response = handler_->create_error(_T("Unknown error handling packet"));
|
|---|
| 81 | }
|
|---|
| 82 |
|
|---|
| 83 | std::vector<boost::asio::const_buffer> buffers;
|
|---|
| 84 | buffers.push_back(buf(response.get_buffer()));
|
|---|
| 85 | start_write_request(buffers);
|
|---|
| 86 | cancel_timer();
|
|---|
| 87 | }
|
|---|
| 88 | }
|
|---|
| 89 | } else {
|
|---|
| 90 | handler_->log_debug(__FILE__, __LINE__, _T("Failed to read request"));
|
|---|
| 91 | }
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 | boost::asio::const_buffer connection::buf(const std::vector<char> s) {
|
|---|
| 95 | buffers_.push_back(s);
|
|---|
| 96 | return boost::asio::buffer(buffers_.back());
|
|---|
| 97 | }
|
|---|
| 98 |
|
|---|
| 99 | void connection::handle_write_response(const boost::system::error_code& e) {
|
|---|
| 100 | if (!e) {
|
|---|
| 101 | // Initiate graceful connection closure.
|
|---|
| 102 | boost::system::error_code ignored_ec;
|
|---|
| 103 | socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
|---|
| 104 | }
|
|---|
| 105 | }
|
|---|
| 106 | } // namespace server
|
|---|
| 107 | } // namespace nrpe
|
|---|