14 #ifndef THRILL_NET_TCP_SOCKET_HEADER 15 #define THRILL_NET_TCP_SOCKET_HEADER 25 #include <netinet/in.h> 26 #include <sys/socket.h> 52 static constexpr
bool debug =
false;
60 explicit Socket(
int fd,
bool loopback_socket =
false)
63 if (!loopback_socket) {
81 if (
this == &s)
return *
this;
95 int fd = ::socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
97 int fd = ::socket(PF_INET, SOCK_STREAM, 0);
100 LOG <<
"Socket::Create()" 102 <<
" error=" << strerror(errno);
106 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
108 "Error setting FD_CLOEXEC on network socket");
120 int r = ::socketpair(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
122 int r = ::socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
125 LOG1 <<
"Socket::CreatePair()" 126 <<
" error=" << strerror(errno);
131 if (fcntl(fds[0], F_SETFD, FD_CLOEXEC) != 0) {
133 "Error setting FD_CLOEXEC on network socket");
135 if (fcntl(fds[1], F_SETFD, FD_CLOEXEC) != 0) {
137 "Error setting FD_CLOEXEC on network socket");
140 return std::make_pair(
Socket(fds[0],
true),
158 int socket_error = -1;
159 socklen_t len =
sizeof(socket_error);
160 getsockopt(SOL_SOCKET, SO_ERROR, &socket_error, &len);
167 int old_opts = fcntl(fd, F_GETFL);
169 int new_opts = non_blocking
170 ? (old_opts | O_NONBLOCK) : (old_opts & ~O_NONBLOCK);
172 if (fcntl(fd, F_SETFL, new_opts) != 0)
174 LOG <<
"Socket::SetNonBlocking()" 176 <<
" non_blocking=" << non_blocking
177 <<
" error=" << strerror(errno);
201 struct sockaddr_in6 sa;
202 socklen_t salen =
sizeof(sa);
205 fd_, reinterpret_cast<struct sockaddr*>(&sa), &salen) != 0)
207 LOG <<
"Socket::GetLocalAddress()" 209 <<
" error=" << strerror(errno);
213 return SocketAddress(reinterpret_cast<struct sockaddr*>(&sa), salen);
220 struct sockaddr_in6 sa;
221 socklen_t salen =
sizeof(sa);
224 fd_, reinterpret_cast<struct sockaddr*>(&sa), &salen) != 0)
226 LOG <<
"Socket::GetPeerAddress()" 228 <<
" error=" << strerror(errno);
232 return SocketAddress(reinterpret_cast<struct sockaddr*>(&sa), salen);
246 LOG <<
"Socket::close()" 248 <<
" error=" << strerror(errno);
252 LOG <<
"Socket::close()" 274 LOG <<
"Socket::bind()" 278 <<
" error=" << strerror(errno);
294 LOG <<
"Socket::connect()" 298 <<
" error=" << strerror(errno);
307 if (backlog == 0) backlog = SOMAXCONN;
312 LOG <<
"Socket::listen()" 316 LOG <<
"Socket::listen()" 318 <<
" error=" << strerror(errno);
327 struct sockaddr_in6 sa;
328 socklen_t salen =
sizeof(sa);
331 reinterpret_cast<struct sockaddr*>(&sa), &salen);
333 LOG <<
"Socket::accept()" 335 <<
" error=" << strerror(errno);
339 LOG <<
"Socket::accept()" 341 <<
" newfd=" << newfd;
354 ssize_t
send_one(
const void* data,
size_t size,
int flags = 0) {
358 LOG <<
"Socket::send_one()" 362 <<
" flags=" << flags;
365 ssize_t r =
::send(
fd_, data, size, flags);
367 LOG <<
"done Socket::send_one()" 375 ssize_t
send(
const void* data,
size_t size,
int flags = 0) {
379 LOG <<
"Socket::send()" 383 <<
" flags=" << flags;
386 const char* cdata =
static_cast<const char*
>(data);
391 ssize_t r =
::send(
fd_, cdata + wb, size - wb, flags);
395 if (errno == EAGAIN)
continue;
397 LOG <<
"done Socket::send()" 400 <<
" errno=" << strerror(errno);
408 LOG <<
"done Socket::send()" 416 ssize_t
sendto(
const void* data,
size_t size,
int flags,
421 LOG <<
"Socket::sendto()" 425 <<
" flags=" << flags
432 LOG <<
"done Socket::sendto()" 440 ssize_t
recv_one(
void* out_data,
size_t max_size,
int flags = 0) {
447 LOG <<
"Socket::recv_one()" 449 <<
" max_size=" << max_size
450 <<
" flags=" << flags
451 <<
" errno=" << errno;
453 ssize_t r =
::recv(
fd_, out_data, max_size, flags);
456 LOG <<
"done Socket::recv_one()" 459 <<
" errno=" << errno
460 <<
" data=" << (r >= 0 ?
MaybeHexdump(out_data, r) :
"<error>");
467 ssize_t
recv(
void* out_data,
size_t size,
int flags = 0) {
470 LOG <<
"Socket::recv()" 473 <<
" flags=" << flags;
475 char* cdata =
static_cast<char*
>(out_data);
480 ssize_t r =
::recv(
fd_, cdata + rb, size - rb, flags);
484 if (errno == EAGAIN)
continue;
486 LOG <<
"done Socket::recv()" 490 <<
" errno=" << strerror(errno);
499 LOG <<
"done Socket::recv()" 510 ssize_t
recvfrom(
void* out_data,
size_t max_size,
int flags = 0,
514 LOG <<
"Socket::recvfrom()" 516 <<
" max_size=" << max_size
517 <<
" flags=" << flags
518 <<
" out_socklen=" << (out_source ? out_source->socklen() : 0);
520 socklen_t out_socklen = out_source ? out_source->socklen() : 0;
523 out_source ? out_source->sockaddr() :
nullptr,
527 LOG <<
"done Socket::recvfrom()" 533 << (out_source ? out_source->ToStringHostPort() :
"<null>");
546 void* optval, socklen_t* optlen)
const {
552 LOG <<
"Socket::getsockopt()" 554 <<
" level=" << level
555 <<
" optname=" << optname
556 <<
" optval=" << optval
557 <<
" optlen=" << optlen
558 <<
" error=" << strerror(errno);
565 const void* optval, socklen_t optlen) {
571 LOG <<
"Socket::setsockopt()" 573 <<
" level=" << level
574 <<
" optname=" << optname
575 <<
" optval=" << optval
576 <<
" optlen=" << optlen
577 <<
" error=" << strerror(errno);
623 #endif // !THRILL_NET_TCP_SOCKET_HEADER
ssize_t recvfrom(void *out_data, size_t max_size, int flags=0, SocketAddress *out_source=nullptr)
void SetRcvBuf(size_t size)
Set SO_RCVBUF socket option.
int getsockopt(int level, int optname, void *optval, socklen_t *optlen) const
Perform raw getsockopt() operation on socket.
bool close()
Close socket.
bool listen(int backlog=0)
Turn socket into listener state to accept incoming connections.
static std::string MaybeHexdump(const void *data, size_t size)
return hexdump or just [data] if not debugging
int fd_
the file descriptor of the socket.
SocketAddress is a super class used to unify the two different IPv4 and IPv6 socket address represent...
An Exception which is thrown on system errors and contains errno information.
static std::pair< Socket, Socket > CreatePair()
Socket()
default constructor: invalid socket.
void SetKeepAlive(bool activate=true)
Enable sending of keep-alive messages on connection-oriented sockets.
int connect(const SocketAddress &sa)
Initial socket connection to address.
ssize_t recv_one(void *out_data, size_t max_size, int flags=0)
Recv (out_data,max_size) from socket (BSD socket API function wrapper)
bool SetNonBlocking(bool non_blocking)
Turn socket into non-blocking state.
ssize_t send_one(const void *data, size_t size, int flags=0)
bool bind(const SocketAddress &sa)
Bind socket to given SocketAddress for listening or connecting.
SocketAddress GetLocalAddress() const
Return the current local socket address.
bool non_blocking_
flag whether the socket is set to non-blocking
ssize_t sendto(const void *data, size_t size, int flags, const SocketAddress &dest)
Send (data,size) to destination.
Socket accept() const
Wait on socket until a new connection comes in.
Socket is a light-weight wrapper around the BSD socket API.
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
socklen_t socklen() const
Return total length of enclosed sockaddr structure.
void SetReuseAddr(bool activate=true)
Socket & operator=(const Socket &)=delete
non-copyable: delete assignment operator
ssize_t recv(void *out_data, size_t size, int flags=0)
Receive (data,size) from socket, retry recvs if short-reads occur.
static Socket Create()
Create a new stream socket.
Socket(int fd, bool loopback_socket=false)
construct new Socket object from existing file descriptor.
int GetError() const
Query socket for its current error state.
static bool SetNonBlocking(int fd, bool non_blocking)
Turn socket into non-blocking state.
struct sockaddr * sockaddr()
Return pointer to enclosed address as a generic sockattr struct.
std::string hexdump(const void *const data, size_t size)
Dump a (binary) string as a sequence of uppercase hexadecimal pairs.
Socket(Socket &&s) noexcept
move-constructor: move file descriptor
static constexpr bool debug
int fd() const
Return the associated file descriptor.
void SetSndBuf(size_t size)
Set SO_SNDBUF socket option.
void SetNoDelay(bool activate=true)
SocketAddress GetPeerAddress() const
Return the current peer socket address.
#define LOG
Default logging method: output if the local debug variable is true.
ssize_t send(const void *data, size_t size, int flags=0)
Send (data,size) to socket, retry sends if short-sends occur.
int setsockopt(int level, int optname, const void *optval, socklen_t optlen)
Perform raw setsockopt() operation on socket.
bool IsValid() const
Check whether the contained file descriptor is valid.
static constexpr bool debug_data