예제 #1
0
	/// Connection base state machine
	void nextOperation()
	{
		NetworkOperation netOp = m_connHandler->nextOperation();
		switch ( netOp.operation() )	{
			case NetworkOperation::READ:	{
				LOG_TRACE << "Next operation: READ " << netOp.size() << " bytes from " << identifier();
				if ( netOp.buffer() == NULL )	{
					LOG_FATAL << "Attempt to READ from " << identifier() << " to a NULL data block";
					abort();		// here should be a system exception
				}
				if ( netOp.size() == 0 )	{
					LOG_FATAL << "Attempt to READ 0 bytes data block from " << identifier();
					abort();		// here should be a system exception
				}
				if ( netOp.timeout() > 0 )
					setTimeout( netOp.timeout());
				m_readBuffer = netOp.buffer();
				socket().async_read_some( boost::asio::buffer( m_readBuffer, netOp.size() ),
							  m_strand.wrap( boost::bind( &ConnectionBase::handleRead,
										      this->shared_from_this(),
										      boost::asio::placeholders::error,
										      boost::asio::placeholders::bytes_transferred )));
				break;
			}

			case NetworkOperation::WRITE:	{
				LOG_TRACE << "Next operation: WRITE " << netOp.size() << " bytes to " << identifier();
				if ( netOp.data() == NULL )	{
					LOG_FATAL << "Attempt to WRITE a NULL data block to " << identifier();
					abort();		// here should be a system exception
				}
				if ( netOp.size() == 0 )	{
					LOG_FATAL << "Attempt to WRITE a 0 bytes data block to " << identifier();
					abort();		// here should be a system exception
				}
				if ( netOp.timeout() > 0 )
					setTimeout( netOp.timeout());
				boost::asio::async_write( socket(),
							  boost::asio::buffer( netOp.data(), netOp.size() ),
							  m_strand.wrap( boost::bind( &ConnectionBase::handleWrite,
										      this->shared_from_this(),
										      boost::asio::placeholders::error )));
				break;
			}

			case NetworkOperation::CLOSE:	{
				LOG_TRACE << "Next operation: CLOSE connection to " << identifier();
				// Initiate graceful connection closure.
				setTimeout( 0 );
				unregister();
				m_strand.post( boost::bind( &ConnectionBase::handleShutdown,
							    this->shared_from_this() ));
				break;
			}

			case NetworkOperation::NOOP:
				LOG_TRACE << "Next operation: NOOP on connection to " << identifier();
				break;
		}
	}
예제 #2
0
 void justdoit()
 {
     rc_->get(strand_.wrap(
         boost::bind(&tormoz_get::handle_done, shared_from_this(), _1, _2))
              );
     timer_.expires_from_now(boost::posix_time::milliseconds(100));
     timer_.async_wait(strand_.wrap(boost::bind(&tormoz_get::handle_timeout, shared_from_this(), _1)));
 }
예제 #3
0
    void do_resolve (std::vector <std::string> const& names,
        HandlerType const& handler, CompletionCounter)
    {
        check_precondition (! names.empty());

        if (m_called_stop.load () == 0)
        {
            // TODO NIKB use emplace_back once we move to C++11
            m_work.push_back(Work(names, handler));

            m_journal.debug <<
                "Queued new job with " << names.size() <<
                " tasks. " << m_work.size() << " jobs outstanding.";

            if (m_work.size() == 1)
            {
                check_precondition (m_idle);

                m_journal.trace << "Waking up";
                m_idle = false;

                m_io_service.post (m_strand.wrap (boost::bind (
                    &NameResolverImpl::do_work, this,
                    CompletionCounter(this))));
            }
        }
    }
예제 #4
0
        // Called when the timer expires.
        // We operate the timer continuously this simplifies the code.
        //
        void on_timer(error_code ec)
        {
            if(ec && ec != boost::asio::error::operation_aborted)
                return fail("timer", ec);

            // Verify that the timer really expired
            // since the deadline may have moved.
            //
            if(timer_.expires_at() <= clock_type::now())
            {
                // Closing the socket cancels all outstanding
                // operations. They will complete with
                // boost::asio::error::operation_aborted
                //
                ws_.next_layer().close(ec);
                return;
            }

            // Wait on the timer
            timer_.async_wait(
                strand_.wrap(std::bind(
                    &connection::on_timer,
                    shared_from_this(),
                    std::placeholders::_1)));
        }
예제 #5
0
    void do_finish (
        std::string name,
        boost::system::error_code const& ec,
        HandlerType handler,
        boost::asio::ip::tcp::resolver::iterator iter,
        CompletionCounter)
    {
        if (ec == boost::asio::error::operation_aborted)
            return;

        std::vector <beast::IP::Endpoint> addresses;

        // If we get an error message back, we don't return any
        // results that we may have gotten.
        if (!ec)
        {
            while (iter != boost::asio::ip::tcp::resolver::iterator())
            {
                addresses.push_back (beast::IPAddressConversion::from_asio (*iter));
                ++iter;
            }
        }

        handler (name, addresses);

        m_io_service.post (m_strand.wrap (std::bind (
            &ResolverAsioImpl::do_work, this,
                CompletionCounter (this))));
    }
예제 #6
0
    void stop_async () override
    {
        if (m_stop_called.exchange (true) == false)
        {
            m_io_service.dispatch (m_strand.wrap (std::bind (
                &ResolverAsioImpl::do_stop,
                    this, CompletionCounter (this))));

            JLOG(m_journal.debug()) << "Queued a stop request";
        }
    }
예제 #7
0
    void stop_async ()
    {
        if (m_called_stop.exchange (1) == 0)
        {
            m_io_service.dispatch (m_strand.wrap (boost::bind (
                &NameResolverImpl::do_stop, 
                    this, CompletionCounter (this))));

            m_journal.debug << "Stopping";
        }
    }
예제 #8
0
        // Read a message from the websocket stream
        void do_read()
        {
            // Put the read on the timer
            timer_.expires_from_now(std::chrono::seconds(15));

            // Read a message
            ws_.async_read(buffer_,
                strand_.wrap(std::bind(
                    &connection::on_read,
                    shared_from_this(),
                    std::placeholders::_1)));
        }
예제 #9
0
    void resolve (
        std::vector <std::string> const& names,
        HandlerType const& handler)
    {
        check_precondition (m_called_stop.load () == 0);
        check_precondition (!names.empty());

        // TODO NIKB use rvalue references to construct and move
        //           reducing cost.
        m_io_service.dispatch (m_strand.wrap (boost::bind (
            &NameResolverImpl::do_resolve, this,
            names, handler, CompletionCounter(this))));
    }
예제 #10
0
	inline void connection::handle_read(const boost::system::error_code& e,
					    std::size_t bytes_transferred) {
	    if (!e) {
		boost::tribool result;
		boost::tie(result, boost::tuples::ignore) = request_parser_.parse(
		  *request_, buffer_.data(), buffer_.data() + bytes_transferred);

		if (result) {
		    try {
			request_handler_.handle_request(*request_, reply_);
		    } catch (webserver::reply rep) {
			reply_ = rep;
		    }
		    std::cerr << reply_.content << std::endl;
		    boost::asio::async_write(socket_, reply_.to_buffers(),
		     strand_.wrap(
			  boost::bind(&connection::handle_write, shared_from_this(),
				      boost::asio::placeholders::error)));
		} else if (!result) {
		    reply_ = reply::stock_reply(reply::bad_request);
		    boost::asio::async_write(socket_, reply_.to_buffers(),
		     strand_.wrap(
			  boost::bind(&connection::handle_write, shared_from_this(),
				      boost::asio::placeholders::error)));
		} else {
		    socket_.async_read_some(boost::asio::buffer(buffer_),
			    strand_.wrap(
				 boost::bind(&connection::handle_read, shared_from_this(),
					     boost::asio::placeholders::error,
					     boost::asio::placeholders::bytes_transferred)));
		}
	    }

	    // If an error occurs then no new asynchronous operations are started. This
	    // means that all shared_ptr references to the connection object will
	    // disappear and the object will be destroyed automatically after this
	    // handler returns. The connection class's destructor closes the socket.
	}
예제 #11
0
    void resolve (
        std::vector <std::string> const& names,
        HandlerType const& handler) override
    {
        assert (m_stop_called == false);
        assert (m_stopped == true);
        assert (!names.empty());

        // TODO NIKB use rvalue references to construct and move
        //           reducing cost.
        m_io_service.dispatch (m_strand.wrap (std::bind (
            &ResolverAsioImpl::do_resolve, this,
                names, handler, CompletionCounter (this))));
    }
예제 #12
0
	/// Set / reset the timeout timer
	void setTimeout( unsigned timeout )
	{
		if ( timeout == 0 )	{
			LOG_TRACE << "Timeout for connection to " << identifier() << " reset";
			m_timer.cancel();
		}
		else	{
			m_timer.cancel();
			m_timer.expires_from_now( boost::posix_time::seconds( timeout ));
			m_timer.async_wait( m_strand.wrap( boost::bind( &ConnectionBase::handleTimeout,
									this->shared_from_this(),
									boost::asio::placeholders::error )));
			LOG_TRACE << "Timeout for connection to " << identifier() << " set to " << timeout << "s";
		}
	}
예제 #13
0
 WSClientImpl(Config const& cfg, bool v2)
     : work_(ios_)
     , strand_(ios_)
     , thread_([&] {
     ios_.run();
 })
 , stream_(ios_)
 , ws_(stream_)
 {
     auto const ep = getEndpoint(cfg, v2);
     stream_.connect(ep);
     ws_.handshake(ep.address().to_string() +
                   ":" + std::to_string(ep.port()), "/");
     ws_.async_read(op_, rb_,
                    strand_.wrap(std::bind(&WSClientImpl::on_read_msg,
                                           this, beast::asio::placeholders::error)));
 }
예제 #14
0
    void handle_timeout(const boost::system::error_code& ec)
    {
        if (--count_ > 0)
        {
            rc_->stop();
            rc_.reset( new rc_check(timer_.io_service(), std::string(p_.pp.login).append("@").append(p_.pp.domain),
                            p_.pp.ukey, p_.l, 1) );

            timer_.expires_from_now(boost::posix_time::milliseconds(rand_r(&seed_) % 500));
            timer_.async_wait(strand_.wrap(boost::bind(&tormoz_get::handle_timeout, shared_from_this(), _1)));
        }
        else if (rc_)
        {
            rc_->stop();
            rc_.reset();
        }
    }
예제 #15
0
    void
    onTimer (boost::system::error_code ec)
    {
        if (ec)
        {
            if (ec != boost::asio::error::operation_aborted)
                journal_.error <<
                    "onTimer: " << ec.message();
            return;
        }

        logic_.onTimer();

        timer_.expires_from_now(std::chrono::seconds(1), ec);
        timer_.async_wait(strand_.wrap(exec_.wrap(
            std::bind(&ManagerImp::onTimer, this,
                beast::asio::placeholders::error))));
    }
예제 #16
0
    void do_work (CompletionCounter)
    {
        if (m_called_stop.load () == 1)
            return;

        // We don't have any work to do at this time
        if (m_work.empty())
        {
            m_idle = true;
            m_journal.trace << "Sleeping";
            return;
        }

        if (m_work.front().names.empty())
            m_work.pop_front();

        std::string const name (m_work.front().names.back());
        HandlerType handler (m_work.front().handler);

        m_work.front().names.pop_back();

        HostAndPort const hp (parseName(name));

        if (hp.first.empty())
        {
            m_journal.error <<
                "Unable to parse '" << name << "'";

            m_io_service.post (m_strand.wrap (boost::bind (
                &NameResolverImpl::do_work, this,
                CompletionCounter(this))));

            return;
        }

        boost::asio::ip::tcp::resolver::query query (
            hp.first, hp.second);

        m_resolver.async_resolve (query, boost::bind (
            &NameResolverImpl::do_finish, this, name,
            boost::asio::placeholders::error, handler,
            boost::asio::placeholders::iterator,
            CompletionCounter(this)));
    }
예제 #17
0
        // Called immediately after the connection is created.
        // We keep this separate from the constructor because
        // shared_from_this may not be called from constructors.
        void run()
        {
            // Run the timer
            on_timer({});

            // Put the handshake on the timer
            timer_.expires_from_now(std::chrono::seconds(15));

            // Read the websocket handshake and send the response
            ws_.async_accept_ex(
                [](websocket::response_type& res)
                {
                    res.insert(http::field::server, "websocket-server-async");
                },
                strand_.wrap(std::bind(
                    &connection::on_accept,
                    shared_from_this(),
                    std::placeholders::_1)));
        }
예제 #18
0
 void
 on_read_msg(error_code const& ec)
 {
     if(ec)
         return;
     Json::Value jv;
     Json::Reader jr;
     jr.parse(buffer_string(rb_.data()), jv);
     rb_.consume(rb_.size());
     auto m = std::make_shared<msg>(
                  std::move(jv));
     {
         std::lock_guard<std::mutex> lock(m_);
         msgs_.push_front(m);
         cv_.notify_all();
     }
     ws_.async_read(op_, rb_, strand_.wrap(
                        std::bind(&WSClientImpl::on_read_msg,
                                  this, beast::asio::placeholders::error)));
 }
예제 #19
0
        // Called after the message read completes
        void on_read(error_code ec)
        {
            // This error means the other side
            // closed the websocket stream.
            if(ec == websocket::error::closed)
                return;

            if(ec)
                return fail("read", ec);

            // Put the write on the timer
            timer_.expires_from_now(std::chrono::seconds(15));

            // Write the received message back
            ws_.binary(ws_.got_binary());
            ws_.async_write(buffer_.data(),
                strand_.wrap(std::bind(
                    &connection::on_write,
                    shared_from_this(),
                    std::placeholders::_1)));
        }
예제 #20
0
    void do_resolve (std::vector <std::string> const& names,
        HandlerType const& handler, CompletionCounter)
    {
        assert (! names.empty());

        if (m_stop_called == false)
        {
            m_work.emplace_back (names, handler);

            JLOG(m_journal.debug()) <<
                "Queued new job with " << names.size() <<
                " tasks. " << m_work.size() << " jobs outstanding.";

            if (m_work.size() > 0)
            {
                m_io_service.post (m_strand.wrap (std::bind (
                    &ResolverAsioImpl::do_work, this,
                        CompletionCounter (this))));
            }
        }
    }
예제 #21
0
    void do_work (CompletionCounter)
    {
        if (m_stop_called == true)
            return;

        // We don't have any work to do at this time
        if (m_work.empty ())
            return;

        std::string const name (m_work.front ().names.back());
        HandlerType handler (m_work.front ().handler);

        m_work.front ().names.pop_back ();

        if (m_work.front ().names.empty ())
            m_work.pop_front();

        HostAndPort const hp (parseName (name));

        if (hp.first.empty ())
        {
            JLOG(m_journal.error()) <<
                "Unable to parse '" << name << "'";

            m_io_service.post (m_strand.wrap (std::bind (
                &ResolverAsioImpl::do_work, this,
                CompletionCounter (this))));

            return;
        }

        boost::asio::ip::tcp::resolver::query query (
            hp.first, hp.second);

        m_resolver.async_resolve (query, std::bind (
            &ResolverAsioImpl::do_finish, this, name,
                std::placeholders::_1, handler,
                    std::placeholders::_2,
                        CompletionCounter (this)));
    }
예제 #22
-1
	inline void connection::start() {
	    socket_.async_read_some(boost::asio::buffer(buffer_),
		    strand_.wrap(
			 boost::bind(&connection::handle_read, shared_from_this(),
				     boost::asio::placeholders::error,
				     boost::asio::placeholders::bytes_transferred)));
	}