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)); }
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(); } } }
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; } } }
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(); }