1 #include "Connection.hpp"
7 Connection::Connection(socket_or_port_t socket_or_port
) {
8 if (holds_alternative
<string
>(socket_or_port
)) {
9 const auto path
= get
<string
>(socket_or_port
);
10 const auto safe
= path
.c_str();
11 const auto zlen
= path
.length() + 1;
12 const auto ulen
= sizeof(sockaddr_un
) - sizeof(sa_family_t
);
15 throw invalid_argument(error({"socket(): path too long '", path
, "'"}));
18 if (0 > (sock
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_NONBLOCK
|SOCK_CLOEXEC
, 0))) {
19 throw runtime_error(error({"socket(): ", strerror(errno
)}));
22 auto sa
= reinterpret_cast<sockaddr_un
*>(&addr
);
23 sa
->sun_family
= AF_UNIX
;
24 copy(safe
, safe
+ zlen
, sa
->sun_path
);
29 if (0 > (sock
= socket(AF_INET6
, SOCK_STREAM
|SOCK_NONBLOCK
|SOCK_CLOEXEC
, 0))) {
30 throw runtime_error(error({"socket(): ", strerror(errno
)}));
33 const auto port
= get
<int>(socket_or_port
);
34 auto sa
= reinterpret_cast<struct sockaddr_in6
*>(&addr
);
35 sa
->sin6_family
= AF_INET6
;
36 sa
->sin6_port
= htons(static_cast<unsigned short>(port
));
37 sa
->sin6_addr
= IN6ADDR_LOOPBACK_INIT
;
43 Connection::~Connection() {
47 void swap(Connection
&a
, Connection
&b
) {
51 void Connection::swap(Connection
&conn
) {
52 Connection
copy(conn
);
56 conn
.last_err
= last_err
;
57 sock
= exchange(copy
.sock
, -1);
60 last_err
= copy
.last_err
;
63 Connection::Connection(const Connection
&conn
) {
65 sock
= dup(conn
.sock
);
69 last_err
= conn
.last_err
;
72 Connection
&Connection::operator=(const Connection
&conn
) {
73 Connection
copy(conn
);
78 Connection::Connection(Connection
&&conn
) noexcept
{
83 Connection
&Connection::operator=(Connection
&&conn
) noexcept
{
84 Connection
copy(move(conn
));
89 void Connection::close() {
97 int Connection::getError() {
99 socklen_t len
= sizeof(int);
102 if (0 > getsockopt(sock
, SOL_SOCKET
, SO_ERROR
, &err
, &len
)) {
110 int Connection::getLastError() {
111 if (last_err
== -1) {
117 bool Connection::isWritable() {
118 pollfd fd
{sock
, POLLOUT
, 0};
119 if (1 > poll(&fd
, 1, 0)) {
122 if (fd
.revents
& (POLLNVAL
|POLLERR
|POLLHUP
)) {
125 return fd
.revents
& POLLOUT
;
128 bool Connection::isOpen() {
131 return getError() == 0;
134 return getError() == 0;
141 bool Connection::open() {
147 if (0 == ::connect(sock
, reinterpret_cast<sockaddr
*>(&addr
), size
)) {
168 string
Connection::error(const initializer_list
<string
> &args
) {
171 for (auto &arg
: args
) {
175 cerr
<< ss
.str() << endl
;