34 #include <arpa/inet.h>
38 #include <sys/socket.h>
39 #include <sys/types.h>
49 using namespace std::string_literals;
53 uint32_t constexpr invalid_socket{std::numeric_limits<uint32_t>::max()};
57 tcp_socket::~tcp_socket()
61 }
catch (std::runtime_error
const &ex) {
62 DOCA_LOG_ERR(
"Failed to close socket during destruction: %s", ex.what());
66 tcp_socket::tcp_socket() : m_fd{invalid_socket}
68 auto ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
74 m_fd =
static_cast<uint32_t
>(ret);
80 if (fd != invalid_socket) {
88 other.m_fd = invalid_socket;
93 if (std::addressof(other) ==
this)
97 other.m_fd = invalid_socket;
104 auto flags = fcntl(
static_cast<int>(m_fd), F_GETFL);
111 flags &= ~O_NONBLOCK;
115 auto ret = fcntl(
static_cast<int>(m_fd), F_SETFL, flags);
125 if (m_fd == invalid_socket)
129 auto const ret =
::close(
static_cast<int>(m_fd));
135 m_fd = invalid_socket;
141 sa.sin_family = AF_INET;
142 sa.sin_port = htons(address.
get_port());
144 if (::inet_pton(AF_INET, address.
get_address().c_str(), &sa.sin_addr) < 0) {
146 "Failed to parse address: \"" + address.
get_address() +
151 if (::
connect(
static_cast<int>(m_fd),
reinterpret_cast<sockaddr *
>(&sa),
sizeof(sa)) != 0) {
153 auto const err = errno;
165 "Failed to connect to: \"" + address.
get_address() +
175 ::memset(&sa, 0,
sizeof(sa));
176 sa.sin_family = AF_INET;
177 sa.sin_addr.s_addr = htonl(INADDR_ANY);
178 sa.sin_port = htons(port);
182 if (::bind(
static_cast<int>(m_fd),
reinterpret_cast<sockaddr *
>(&sa),
sizeof(sa)) != 0) {
188 if (::
listen(
static_cast<int>(m_fd), 1) != 0) {
199 pfd.fd =
static_cast<int>(m_fd);
200 pfd.events = POLLOUT;
203 auto ret = poll(&pfd, 1, 0);
212 if (pfd.revents & POLLOUT) {
213 socklen_t ret_size =
sizeof(ret);
214 if (::getsockopt(
static_cast<int>(m_fd), SOL_SOCKET, SO_ERROR, &ret, &ret_size) != 0) {
218 if (ret == ECONNABORTED || ret == ECONNREFUSED || ret == ECONNRESET || ret == ENOTCONN) {
223 struct sockaddr_in peeraddr {};
224 socklen_t peeraddrlen{};
225 ret = getpeername(
static_cast<int>(m_fd), (
struct sockaddr *)&peeraddr, &peeraddrlen);
229 inet_ntoa(peeraddr.sin_addr),
230 ntohs(peeraddr.sin_port));
234 auto const err = errno;
247 sockaddr_storage ss{};
248 socklen_t peer_addr_len =
sizeof(ss);
249 auto const client_fd =
250 ::accept4(
static_cast<int>(m_fd),
reinterpret_cast<sockaddr *
>(&ss), &peer_addr_len, SOCK_NONBLOCK);
254 auto const err = errno;
257 #if EWOULDBLOCK != EAGAIN
271 return tcp_socket{
static_cast<uint32_t
>(client_fd)};
276 auto const ret =
::write(
static_cast<int>(m_fd), buffer, byte_count);
278 auto const err = errno;
283 #if EWOULDBLOCK != EAGAIN
302 return static_cast<size_t>(ret);
307 auto const ret =
::read(
static_cast<int>(m_fd), buffer, buffer_capacity);
309 auto const err = errno;
314 #if EWOULDBLOCK != EAGAIN
333 return static_cast<size_t>(ret);
338 return m_fd != invalid_socket;
341 void tcp_socket::set_socket_options(
void)
346 linger linger_options{
351 ret = ::setsockopt(
static_cast<int>(m_fd),
355 sizeof(linger_options));
358 "Failed to set socket option SO_LINGER. Error: \""s +
359 ::gai_strerror(errno) +
"\""};
363 int const reuse_addr{1};
365 ret = ::setsockopt(
static_cast<int>(m_fd), SOL_SOCKET, SO_REUSEADDR, &reuse_addr,
sizeof(reuse_addr));
368 "Failed to set socket option SO_REUSEADDR. Error: \""s +
369 ::gai_strerror(errno) +
"\""};
uint16_t get_port() const noexcept
std::string const & get_address() const noexcept
size_t read(char *buffer, size_t buffer_capacity)
void set_blocking(bool blocking)
void listen(uint16_t port)
tcp_socket & operator=(tcp_socket const &)=delete
bool is_valid(void) const noexcept
size_t write(char const *buffer, size_t byte_count)
void connect(storage::ip_address const &address)
connection_status poll_is_connected(void)
@ DOCA_ERROR_OPERATING_SYSTEM
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
std::string to_string(storage::control::message_type type)
std::string strerror_r(int err) noexcept
DOCA_LOG_REGISTER(TCP_SOCKET)