xdrpp
RFC4506 XDR compiler and message library
socket.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 #ifndef _XDRPP_SOCKET_H_HEADER_INCLUDED_
4 #define _XDRPP_SOCKET_H_HEADER_INCLUDED_ 1
5 
6 //! \file socket.h Simplified support for creating sockets.
7 
8 #include <memory>
9 #include <system_error>
10 #if MSVC
11 #include <WinSock2.h>
12 struct iovec {
13  void *iov_base;
14  size_t iov_len;
15 };
16 #else // !MSVC
17 #include <netdb.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/uio.h>
22 #include <netinet/in.h>
23 #endif // !MSVC
24 
25 namespace xdr {
26 
27 //! Abstract away the type of a socket (for windows).
28 struct sock_t {
29 #if MSVC
30  using type = SOCKET;
31  static constexpr type invalid = INVALID_SOCKET;
32 #else // !MSVC
33  using type = int;
34  static constexpr type invalid = -1;
35 #endif // !MSVC
36 
37  type fd_;
38  constexpr sock_t() : fd_(invalid) {}
39  constexpr sock_t(type fd) : fd_(fd) {}
40 
41  bool operator==(sock_t s) const { return fd_ == s.fd_; }
42  bool operator!=(sock_t s) const { return fd_ != s.fd_; }
43  bool operator<(sock_t s) const { return fd_ < s.fd_; }
44  explicit operator bool() const { return fd_ != invalid; }
45  type fd() const { return fd_; }
46 };
47 } namespace std {
48 template<> struct hash<xdr::sock_t> {
49  using argument_type = xdr::sock_t;
50  using result_type = size_t;
51  constexpr hash() {}
52  size_t operator()(const xdr::sock_t s) const { return s.fd(); }
53 };
54 } namespace xdr {
55 
56 constexpr sock_t invalid_sock{};
57 
58 //! Returns true if the most recent (socket) error is a temporary
59 //! error, such as EAGAIN, EWOULDBLOCK, or EINTR.
60 bool sock_eagain();
61 
62 //! Last socket error message (\c strerror(errno) on POSIX).
63 const char *sock_errmsg();
64 
65 //! Throw a \c system_error exception for the last socket error.
66 [[noreturn]] void throw_sockerr(const char *);
67 
68 ssize_t read(sock_t s, void *buf, std::size_t count);
69 ssize_t write(sock_t s, const void *buf, std::size_t count);
70 ssize_t readv(sock_t s, const struct iovec *iov, int iovcnt);
71 ssize_t writev(sock_t s, const struct iovec *iov, int iovcnt);
72 void close(sock_t s);
73 
74 //! Set the \c O_NONBLOCK flag on a socket. \throws std::system_error
75 //! on failure.
76 void set_nonblock(sock_t s);
77 
78 //! Set the close-on-exec flag of a file descriptor. \throws
79 //! std::system_error on failure.
80 void set_close_on_exec(sock_t s);
81 
82 //! Wrapper around accept for sock_t.
83 inline sock_t
84 accept(sock_t s, sockaddr *addr, socklen_t *addrlen)
85 {
86  return ::accept(s.fd(), addr, addrlen);
87 }
88 
89 //! Create a socket (or pipe on unix, where both are file descriptors)
90 //! that is connected to itself.
91 void create_selfpipe(sock_t ss[2]);
92 
93 // The remaining functions should be the same on Unix/Windows
94 
95 //! Category for system errors dealing with DNS (getaddrinfo, etc.).
96 const std::error_category &gai_category();
97 
98 //! A deleter to use \c std::unique_ptr with \c addrinfo structures
99 //! (which must be freed recursively).
101  constexpr delete_addrinfo() {}
102  void operator()(addrinfo *ai) const { freeaddrinfo(ai); }
103 };
104 //! Automatically garbage-collected addrinfo pointer.
105 using unique_addrinfo = std::unique_ptr<addrinfo, delete_addrinfo>;
106 
107 //! Wrapper around \c getaddrinfo that returns a garbage-collected
108 //! xdr::unique_addrinfo. \throws std::system_error with
109 //! xdr::gai_category on failure.
110 unique_addrinfo get_addrinfo(const char *host,
111  int socktype = SOCK_STREAM,
112  const char *service = nullptr,
113  int family = AF_UNSPEC);
114 
115 //! Return printable versions of numeric host and port number
116 void get_numinfo(const sockaddr *sa, socklen_t salen,
117  std::string *host, std::string *serv);
118 
119 //! Self-closing socket. Note that this socket will be closed as soon
120 //! as it goes out of scope, hence it is important to see whether
121 //! functions you pass it to take a "unique_sock &" or a "const
122 //! unique_sock &&". In the latter case, you are expected to keep the
123 //! file descriptor around.
124 class unique_sock {
125  sock_t s_;
126 public:
127  unique_sock() : s_(invalid_sock) {}
128  explicit unique_sock(sock_t s) : s_(s) {}
129  unique_sock(unique_sock &&uf) : s_(uf.release()) {}
130  ~unique_sock() { clear(); }
131  unique_sock &operator=(unique_sock &&uf) {
132  clear();
133  s_ = uf.release();
134  return *this;
135  }
136 
137  //! Return the file descriptor number, but maintain ownership.
138  sock_t get() const { return s_; }
139  //! True if the file descriptor is not -1.
140  explicit operator bool() const { return s_ != invalid_sock; }
141  //! Return the file descriptor number, relinquishing ownership of
142  //! it. The \c unique_sock will have file descriptor -1 after this
143  //! method returns.
145  sock_t ret = s_;
146  s_ = invalid_sock;
147  return ret;
148  }
149  void clear() {
150  if (s_ != invalid_sock) {
151  close(s_);
152  s_ = invalid_sock;
153  }
154  }
155  void reset(sock_t s) { clear(); s_ = s; }
156 };
157 
158 //! Try connecting to the first \b addrinfo in a linked list.
159 unique_sock tcp_connect1(const addrinfo *ai, bool ndelay = false);
160 
161 //! Try connecting to every \b addrinfo in a list until one succeeds.
162 unique_sock tcp_connect(const addrinfo *ai);
163 inline unique_sock
164 tcp_connect(const unique_addrinfo &ai)
165 {
166  return tcp_connect(ai.get());
167 }
168 unique_sock tcp_connect(const char *host, const char *service,
169  int family = AF_UNSPEC);
170 
171 //! Create bind a listening TCP socket.
172 unique_sock tcp_listen(const char *service = "0",
173  int family = AF_UNSPEC,
174  int backlog = 5);
175 
176 }
177 
178 #endif // !_XDRPP_SOCKET_H_HEADER_INCLUDED_
unique_sock tcp_connect(const addrinfo *ai)
Try connecting to every addrinfo in a list until one succeeds.
Definition: socket.cc:116
void get_numinfo(const sockaddr *sa, socklen_t salen, std::string *host, std::string *serv)
Return printable versions of numeric host and port number.
Definition: socket.cc:85
void throw_sockerr(const char *)
Throw a system_error exception for the last socket error.
Definition: socket_unix.cc:31
unique_sock tcp_connect1(const addrinfo *ai, bool ndelay)
Try connecting to the first addrinfo in a linked list.
Definition: socket.cc:102
Most of the xdrpp library is encapsulated in the xdr namespace.
Definition: arpc.cc:4
A deleter to use std::unique_ptr with addrinfo structures (which must be freed recursively).
Definition: socket.h:100
Definition: socket.h:47
std::enable_if< xdr_traits< T >::is_struct &&xdr_traits< T >::xdr_defined, bool >::type operator==(const T &a, const T &b)
Equality for XDR structures.
Definition: types.h:947
std::unique_ptr< addrinfo, delete_addrinfo > unique_addrinfo
Automatically garbage-collected addrinfo pointer.
Definition: socket.h:105
bool sock_eagain()
Returns true if the most recent (socket) error is a temporary error, such as EAGAIN, EWOULDBLOCK, or EINTR.
Definition: socket_unix.cc:18
void set_nonblock(sock_t s)
Set the O_NONBLOCK flag on a socket.
Definition: socket_unix.cc:70
sock_t release()
Return the file descriptor number, relinquishing ownership of it.
Definition: socket.h:144
std::enable_if< xdr_traits< T >::is_struct &&xdr_traits< T >::xdr_defined, bool >::type operator<(const T &a, const T &b)
Ordering of XDR structures. See note at xdr::operator==.
Definition: types.h:964
Self-closing socket.
Definition: socket.h:124
sock_t accept(sock_t s, sockaddr *addr, socklen_t *addrlen)
Wrapper around accept for sock_t.
Definition: socket.h:84
unique_addrinfo get_addrinfo(const char *host, int socktype, const char *service, int family)
Wrapper around getaddrinfo that returns a garbage-collected xdr::unique_addrinfo. ...
Definition: socket.cc:70
const std::error_category & gai_category()
Category for system errors dealing with DNS (getaddrinfo, etc.).
Definition: socket.cc:40
const char * sock_errmsg()
Last socket error message (strerror(errno) on POSIX).
Definition: socket_unix.cc:25
unique_sock tcp_listen(const char *service, int family, int backlog)
Create bind a listening TCP socket.
Definition: socket.cc:133
Abstract away the type of a socket (for windows).
Definition: socket.h:28
void create_selfpipe(sock_t ss[2])
Create a socket (or pipe on unix, where both are file descriptors) that is connected to itself...
Definition: socket_unix.cc:89
void set_close_on_exec(sock_t s)
Set the close-on-exec flag of a file descriptor.
Definition: socket_unix.cc:79