1 #include "Connection.hpp"
8 static inline int socket_ex(int af
, int so
, int pf
, int fl
) {
9 #if HAVE_SOCK_NONBLOCK && HAVE_SOCK_CLOEXEC
10 return socket(af
, so
| fl
, pf
);
12 # define SOCK_NONBLOCK O_NONBLOCK
13 # define SOCK_CLOEXEC O_CLOEXEC
14 auto sock
= socket(af
, so
, pf
);
16 if (0 > fcntl(sock
, F_SETFL
, fl
| fcntl(sock
, F_GETFL
))) {
25 Connection::Connection(socket_or_port_t socket_or_port
) {
26 if (holds_alternative
<string
>(socket_or_port
)) {
27 const auto path
= get
<string
>(socket_or_port
);
28 const auto safe
= path
.c_str();
29 const auto zlen
= path
.length() + 1;
30 const auto ulen
= sizeof(sockaddr_un
) - sizeof(sa_family_t
);
33 throw invalid_argument(error({"socket(): path too long '", path
, "'"}));
36 if (0 > (sock
= socket_ex(AF_UNIX
, SOCK_STREAM
, 0, SOCK_NONBLOCK
|SOCK_CLOEXEC
))) {
37 throw runtime_error(error({"socket(): ", strerror(errno
)}));
40 auto sa
= reinterpret_cast<sockaddr_un
*>(&addr
);
41 sa
->sun_family
= AF_UNIX
;
42 copy(safe
, safe
+ zlen
, sa
->sun_path
);
47 if (0 > (sock
= socket_ex(AF_INET6
, SOCK_STREAM
, 0, SOCK_NONBLOCK
|SOCK_CLOEXEC
))) {
48 throw runtime_error(error({"socket(): ", strerror(errno
)}));
51 const auto port
= get
<int>(socket_or_port
);
52 auto sa
= reinterpret_cast<struct sockaddr_in6
*>(&addr
);
53 sa
->sin6_family
= AF_INET6
;
54 sa
->sin6_port
= htons(static_cast<unsigned short>(port
));
55 sa
->sin6_addr
= IN6ADDR_LOOPBACK_INIT
;
61 Connection::~Connection() {
65 void swap(Connection
&a
, Connection
&b
) {
69 void Connection::swap(Connection
&conn
) {
70 Connection
copy(conn
);
74 conn
.last_err
= last_err
;
75 sock
= exchange(copy
.sock
, -1);
78 last_err
= copy
.last_err
;
81 Connection::Connection(const Connection
&conn
) {
83 sock
= dup(conn
.sock
);
87 last_err
= conn
.last_err
;
90 Connection
&Connection::operator=(const Connection
&conn
) {
91 Connection
copy(conn
);
96 Connection::Connection(Connection
&&conn
) noexcept
{
101 Connection
&Connection::operator=(Connection
&&conn
) noexcept
{
102 Connection
copy(move(conn
));
107 void Connection::close() {
115 int Connection::getError() {
117 socklen_t len
= sizeof(int);
120 if (0 > getsockopt(sock
, SOL_SOCKET
, SO_ERROR
, &err
, &len
)) {
128 int Connection::getLastError() {
129 if (last_err
== -1) {
135 bool Connection::isWritable() {
136 pollfd fd
{sock
, POLLOUT
, 0};
137 if (1 > poll(&fd
, 1, 0)) {
140 if (fd
.revents
& (POLLNVAL
|POLLERR
|POLLHUP
)) {
143 return fd
.revents
& POLLOUT
;
146 bool Connection::isOpen() {
149 return getError() == 0;
152 return getError() == 0;
159 bool Connection::open() {
165 if (0 == ::connect(sock
, reinterpret_cast<sockaddr
*>(&addr
), size
)) {
186 string
Connection::error(const initializer_list
<string
> &args
) {
189 for (auto &arg
: args
) {
193 cerr
<< ss
.str() << endl
;