8#include "uringpp/event_loop.h"
9#include "uringpp/ip_address.h"
10#include "uringpp/socket.h"
14static inline std::string get_in_addr_string(
struct addrinfo *ai) {
15 char s[INET6_ADDRSTRLEN];
16 inet_ntop(ai->ai_family, get_in_addr(ai->ai_addr), s,
sizeof(s));
25 std::shared_ptr<event_loop> loop_;
28 : loop_(loop), fd_(
fd) {}
36 int fd()
const {
return fd_; }
48 std::string
const &hostname,
49 std::string
const &port,
int backlog = 128) {
50 struct addrinfo hints, *servinfo, *p;
51 ::bzero(&hints,
sizeof(hints));
52 hints.ai_family = AF_UNSPEC;
53 hints.ai_socktype = SOCK_STREAM;
54 hints.ai_flags = AI_PASSIVE;
56 if (
auto rc = getaddrinfo(hostname.empty() ?
nullptr : hostname.c_str(),
57 port.c_str(), &hints, &servinfo);
59 throw_with(
"getaddrinfo: %s", gai_strerror(rc));
61 for (p = servinfo; p !=
nullptr; p = p->ai_next) {
63 int fd = ::socket(p->ai_family, p->ai_flags, p->ai_protocol);
64 check_errno(
fd,
"failed to create socket");
68 ::setsockopt(
fd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(yes)),
69 "failed to set reuse address");
71 auto const &ip = get_in_addr_string(p);
72 check_errno(::bind(
fd, p->ai_addr, p->ai_addrlen),
"failed to bind");
73 check_errno(
::listen(
fd, backlog),
"failed to listen");
74 URINGPP_LOG_DEBUG(
"binding %s:%s", ip.c_str(), port.c_str());
75 ::freeaddrinfo(servinfo);
77 }
catch (std::runtime_error &e) {
78 URINGPP_LOG_ERROR(
"%s", e.what());
83 throw std::runtime_error(
"try all addresses, failed to listen");
92 : loop_(std::move(other.loop_)), fd_(std::exchange(other.fd_, -1)) {}
102 auto fd =
co_await loop_->accept(
103 fd_,
reinterpret_cast<struct sockaddr *
>(&addr.ss_), &addr.len_);
104 check_nerrno(
fd,
"failed to accept connection");
105 co_return std::make_pair(addr,
socket(loop_,
fd));
116 auto fd =
co_await loop_->accept(
117 fd_,
reinterpret_cast<struct sockaddr *
>(&addr.ss_), &addr.len_);
118 check_nerrno(
fd,
"failed to accept connection");
119 co_return std::make_pair(addr,
socket(loop,
fd));
129 co_await loop_->close(fd_);
141 loop_->close_detach(fd_);
Definition: ip_address.h:28
Definition: noncopyable.h:5
Listen for incoming TCP connections on a socket.
Definition: tcp_listener.h:24
static tcp_listener listen(std::shared_ptr< event_loop > loop, std::string const &hostname, std::string const &port, int backlog=128)
Listen for incoming TCP connections on the given address. It will create a socket and bind it to the ...
Definition: tcp_listener.h:47
task< void > close()
Close the listener.
Definition: tcp_listener.h:127
task< std::pair< ip_address, socket > > accept(std::shared_ptr< event_loop > loop)
Accept an incoming connection and attach it with the specified loop.
Definition: tcp_listener.h:114
tcp_listener(tcp_listener &&other) noexcept
Move construct a new listener object.
Definition: tcp_listener.h:91
~tcp_listener()
Destroy the listener object. If the socket is still open, it will be closed.
Definition: tcp_listener.h:139
task< std::pair< ip_address, socket > > accept()
Accept an incoming connection.
Definition: tcp_listener.h:100
int fd() const
Get the file descriptor of the listener.
Definition: tcp_listener.h:36