void take_fd(int fd)
	{
		ranger::util::scope_guard fd_guard([fd] { ranger::event::tcp_connection::file_descriptor_close(fd); });
		
		ranger::event::tcp_connection conn(m_disp, fd);
		conn.set_event_handler([this] (ranger::event::tcp_connection& conn, ranger::event::tcp_connection::event_code what)
				{
					switch (what)
					{
					case ranger::event::tcp_connection::event_code::read:
						handle_read(conn, conn.read_buffer());
						break;
					case ranger::event::tcp_connection::event_code::timeout:
						handle_timeout(conn);
						break;
					case ranger::event::tcp_connection::event_code::error:
						handle_error(conn);
						break;
					case ranger::event::tcp_connection::event_code::eof:
						handle_eof(conn);
						break;
					default:
						break;
					}
				});

		fd_guard.dismiss();

		auto remote_ep = conn.remote_endpoint();
		std::cout << "thread[" << std::this_thread::get_id() << "] " << "accept connection[" << remote_ep << "]." << std::endl;

		m_conn_set.emplace(std::move(conn));
	}
示例#2
0
void link_t::loop() {
	timeval_t last_conn = timeval_long_ago;

	while(true) {
		try {
			{
				timeval_t now = timeval_current();
				interval_t to_sleep = conn_timeout - (timeval_current() - last_conn);

				if(to_sleep > interval_zero && bq_sleep(&to_sleep) < 0)
					throw exception_sys_t(log::error, errno, "bq_sleep: %m");

			}

			last_conn = timeval_current();

			netaddr_t const &netaddr = remote_netaddr();

			int fd = socket(netaddr.sa->sa_family, SOCK_STREAM, 0);
			if(fd < 0)
				throw exception_sys_t(remote_errors, errno, "socket: %m");

			fd_guard_t fd_guard(fd);

			bq_fd_setup(fd);

			interval_t timeout = conn_timeout;

			if(bq_connect(fd, netaddr.sa, netaddr.sa_len, &timeout) < 0)
				throw exception_sys_t(remote_errors, errno, "connect: %m");

			log_debug("connected");

			bq_conn_fd_t conn(fd, ctl(), remote_errors, /* dup = */ true);

			proto_instance->proc(conn);
		}
		catch(exception_sys_t const &ex) {
			if(ex.errno_val == ECANCELED)
				throw;

			ex.log();
		}
		catch(exception_t const &ex) {
			ex.log();
		}
	}
}
示例#3
0
void io_stream_t::loop(int afd, bool conswitch) const {
	fd_guard_t fd_guard(afd);
	timeval_t last_poll = timeval::current();

	while(true) {
		bool poll_before = false;

		if(force_poll.is_real()) {
			timeval_t now = timeval::current();
			if(now - last_poll > force_poll) {
				poll_before = true;
				last_poll = now;
			}
		}

		netaddr_t *netaddr = new_netaddr();

		int nfd = bq_accept(afd, netaddr->sa, &netaddr->sa_len, NULL, poll_before);

		if(nfd < 0) {
			delete netaddr;
			throw exception_sys_t(log::error, errno, "accept: %m");
		}

		try {
			string_t _name = string_t::ctor_t(netaddr->print_len()).print(*netaddr);

			++stat.conns();

			bq_thr_t *thr = aux_scheduler
				? aux_scheduler->bq_thr()
				: (conswitch ? scheduler.bq_thr() : bq_thr_get())
			;
			log::handler_t handler(_name);
			bq_job(&io_stream_t::conn_proc)(*this, nfd, netaddr)->run(thr);
		}
		catch(exception_t const &ex) {
			::close(nfd);
			delete netaddr;
		}
		catch(...) {
			::close(nfd);
			delete netaddr;
			throw;
		}
	}
}
示例#4
0
void io_stream_t::conn_proc(int fd, netaddr_t *netaddr) const {
	fd_guard_t fd_guard(fd);

	class netaddr_guard_t {
		netaddr_t *netaddr;
	public:
		inline netaddr_guard_t(netaddr_t *_netaddr) throw() : netaddr(_netaddr) { }
		inline ~netaddr_guard_t() throw() { delete netaddr; }
	} netaddr_guard(netaddr);

	bq_fd_setup(fd);

	bq_conn_t *conn = transport.new_connect(fd, ctl(), remote_errors);

	class conn_guard_t {
		bq_conn_t *conn;
		io_stream::mmconns_t &mmconns;
	public:
		inline conn_guard_t(bq_conn_t *_conn, stat_t &stat) throw() :
			conn(_conn), mmconns(stat.mmconns()) {

			++mmconns;
		}

		inline ~conn_guard_t() throw() {
			--mmconns;

			delete conn;
		}
	} conn_guard(conn, stat);

	conn->setup_accept();

	netaddr_t const &local_addr = bind_addr();

	bq_in_t in(*conn, ibuf_size, &stat.icount());

	for(bool work = true; work;) {
		{
			char obuf[obuf_size];
			bq_out_t out(*conn, obuf, sizeof(obuf), &stat.ocount());

			in_t::ptr_t ptr(in);

			do {
				in.timeout_set(timeout);
				out.timeout_set(timeout);

				work = proto.request_proc(ptr, out, local_addr, *netaddr);
				++stat.reqs();

				if(!work)
					break;

			} while(in.truncate(ptr));
		}

		if(work) {
			short int events = POLLIN;
			interval_t _keepalive = keepalive;
			if(bq_poll(fd, events, &_keepalive) < 0)
				break;
		}
	}

	conn->shutdown();
}