annotate common/sockets.cpp @ 12:960e03040ddf

Docs: add missing highlight.js and make pre in white
author David Demelier <markand@malikania.fr>
date Wed, 10 Feb 2016 14:18:15 +0100
parents 1158cffe5a5e
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * sockets.cpp -- portable C++ socket wrappers
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
4 * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 *
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * Permission to use, copy, modify, and/or distribute this software for any
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 *
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
18
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 #define TIMEOUT_MSG "operation timeout"
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
20
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 #include <algorithm>
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 #include <atomic>
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 #include <cstring>
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 #include <mutex>
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
25
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 #include "sockets.h"
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
27
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 namespace irccd {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
29
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 namespace net {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
31
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 * Portable constants
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
34 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
36
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 /* {{{ Constants */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
38
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 #if defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
40
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 const Handle Invalid{INVALID_SOCKET};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
42 const int Failure{SOCKET_ERROR};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
43
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
44 #else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
45
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
46 const Handle Invalid{-1};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
47 const int Failure{-1};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
48
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
50
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
52
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
53 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
54 * Portable functions
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
56 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
57
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 /* {{{ Functions */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
59
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 #if defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
61
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 namespace {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
63
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 static std::mutex s_mutex;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 static std::atomic<bool> s_initialized{false};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
66
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 } // !namespace
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
68
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 #endif // !_WIN32
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
70
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
71 void init() noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 #if defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
74 std::lock_guard<std::mutex> lock(s_mutex);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
75
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
76 if (!s_initialized) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 s_initialized = true;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
78
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 WSADATA wsa;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 WSAStartup(MAKEWORD(2, 2), &wsa);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
81
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 * If SOCKET_WSA_NO_INIT is not set then the user
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 * must also call finish himself.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 #if !defined(SOCKET_NO_AUTO_INIT)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 atexit(finish);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
88 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
92
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 void finish() noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 #if defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 WSACleanup();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
98 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
99
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 std::string error(int errn)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 #if defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
103 LPSTR str = nullptr;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 std::string errmsg = "Unknown error";
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
105
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 FormatMessageA(
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 NULL,
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
109 errn,
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 (LPSTR)&str, 0, NULL);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
112
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
113
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
114 if (str) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 errmsg = std::string(str);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 LocalFree(str);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
117 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
118
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 return errmsg;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 #else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
121 return strerror(errn);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
122 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
124
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
125 std::string error()
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
127 #if defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 return error(WSAGetLastError());
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 #else
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 return error(errno);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
132 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
133
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
135
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
136 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 * SSL stuff
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
138 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
140
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 /* {{{ SSL initialization */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
142
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
143 #if !defined(SOCKET_NO_SSL)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
144
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
145 namespace ssl {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
146
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 namespace {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
148
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 std::mutex mutex;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 std::atomic<bool> initialized{false};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
151
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
152 } // !namespace
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
153
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
154 void finish() noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
155 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 ERR_free_strings();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
158
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
159 void init() noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 std::lock_guard<std::mutex> lock{mutex};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
162
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 if (!initialized) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
164 initialized = true;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
165
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 SSL_library_init();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 SSL_load_error_strings();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
168 OpenSSL_add_all_algorithms();
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
169
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
170 #if !defined(SOCKET_NO_AUTO_SSL_INIT)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
171 atexit(finish);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
172 #endif // SOCKET_NO_AUTO_SSL_INIT
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
174 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
175
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 } // !ssl
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
177
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
178 #endif // SOCKET_NO_SSL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
179
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
180 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
181
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
182 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
183 * Error class
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
184 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
185 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
186
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
187 /* {{{ Error */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
188
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
189 Error::Error(Code code, std::string function)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
190 : m_code{code}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
191 , m_function{std::move(function)}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
192 , m_error{error()}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
193 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
194 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
195
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
196 Error::Error(Code code, std::string function, int n)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
197 : m_code{code}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
198 , m_function{std::move(function)}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
199 , m_error{error(n)}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
200 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
201 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
202
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
203 Error::Error(Code code, std::string function, std::string error)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
204 : m_code{code}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
205 , m_function{std::move(function)}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
206 , m_error{std::move(error)}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
207 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
208 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
209
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
210 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
211
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
212 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
213 * Predefine addressed to be used
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
215 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
216
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
217 /* {{{ Addresses */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
218
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
219 namespace address {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
220
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
221 /* Default domain */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
222 int Ip::m_default{AF_INET};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
223
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
224 Ip::Ip(Type domain) noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
225 : m_domain(static_cast<int>(domain))
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
226 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 assert(m_domain == AF_INET6 || m_domain == AF_INET);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
228
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
229 if (m_domain == AF_INET6) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
230 std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
231 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 std::memset(&m_sin, 0, sizeof (sockaddr_in));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
233 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
234 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
235
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
236 Ip::Ip(const std::string &host, int port, Type domain)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
237 : m_domain(static_cast<int>(domain))
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
238 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
239 assert(m_domain == AF_INET6 || m_domain == AF_INET);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
240
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
241 if (host == "*") {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 if (m_domain == AF_INET6) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
243 std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
244
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
245 m_length = sizeof (sockaddr_in6);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
246 m_sin6.sin6_addr = in6addr_any;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
247 m_sin6.sin6_family = AF_INET6;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
248 m_sin6.sin6_port = htons(port);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
249 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
250 std::memset(&m_sin, 0, sizeof (sockaddr_in));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
251
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
252 m_length = sizeof (sockaddr_in);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
253 m_sin.sin_addr.s_addr = INADDR_ANY;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
254 m_sin.sin_family = AF_INET;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
255 m_sin.sin_port = htons(port);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
256 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
257 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
258 addrinfo hints, *res;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
259
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
260 std::memset(&hints, 0, sizeof (addrinfo));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
261 hints.ai_family = domain;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
262
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
263 auto error = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
264 if (error != 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
265 throw Error{Error::System, "getaddrinfo", gai_strerror(error)};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
266 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
267
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
268 if (m_domain == AF_INET6) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
269 std::memcpy(&m_sin6, res->ai_addr, res->ai_addrlen);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
270 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
271 std::memcpy(&m_sin, res->ai_addr, res->ai_addrlen);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
272 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
273
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
274 m_length = res->ai_addrlen;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
275 freeaddrinfo(res);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
276 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
277 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
278
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
279 Ip::Ip(const sockaddr_storage *ss, socklen_t length) noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
280 : m_length{length}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
281 , m_domain{ss->ss_family}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
282 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
283 assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
284
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
285 if (ss->ss_family == AF_INET6) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
286 std::memcpy(&m_sin6, ss, length);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
287 } else if (ss->ss_family == AF_INET) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
288 std::memcpy(&m_sin, ss, length);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
289 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
290 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
291
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
292 #if !defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
293
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
294 Local::Local() noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
295 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
296 std::memset(&m_sun, 0, sizeof (sockaddr_un));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
297 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
298
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
299 Local::Local(std::string path, bool rm) noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
300 : m_path{std::move(path)}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
301 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
302 /* Silently remove the file even if it fails */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
303 if (rm) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
304 ::remove(m_path.c_str());
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
305 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
306
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
307 /* Copy the path */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
308 std::memset(m_sun.sun_path, 0, sizeof (m_sun.sun_path));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
309 std::strncpy(m_sun.sun_path, m_path.c_str(), sizeof (m_sun.sun_path) - 1);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
310
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
311 /* Set the parameters */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
312 m_sun.sun_family = AF_LOCAL;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
313 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
314
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
315 Local::Local(const sockaddr_storage *ss, socklen_t length) noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
316 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
317 assert(ss->ss_family == AF_LOCAL);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
318
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
319 if (ss->ss_family == AF_LOCAL) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
320 std::memcpy(&m_sun, ss, length);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
321 m_path = reinterpret_cast<const sockaddr_un &>(m_sun).sun_path;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
322 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
323 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
324
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
325 #endif // !_WIN32
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
326
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
327 } // !address
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
328
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
329 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
330
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
331 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
332 * Select
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
333 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
334 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
335
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
336 /* {{{ Select */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
337
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
338 std::vector<ListenerStatus> Select::wait(const ListenerTable &table, int ms)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
339 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
340 timeval maxwait, *towait;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
341 fd_set readset;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
342 fd_set writeset;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
343
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
344 FD_ZERO(&readset);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
345 FD_ZERO(&writeset);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
346
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
347 Handle max = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
348
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
349 for (const auto &pair : table) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
350 if ((pair.second & Condition::Readable) == Condition::Readable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
351 FD_SET(pair.first, &readset);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
352 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
353 if ((pair.second & Condition::Writable) == Condition::Writable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
354 FD_SET(pair.first, &writeset);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
355 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
356
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
357 if (pair.first > max) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
358 max = pair.first;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
359 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
360 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
361
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
362 maxwait.tv_sec = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
363 maxwait.tv_usec = ms * 1000;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
364
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
365 // Set to nullptr for infinite timeout.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
366 towait = (ms < 0) ? nullptr : &maxwait;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
367
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
368 auto error = ::select(max + 1, &readset, &writeset, nullptr, towait);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
369 if (error == Failure) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
370 throw Error{Error::System, "select"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
371 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
372 if (error == 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
373 throw Error{Error::Timeout, "select", TIMEOUT_MSG};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
374 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
375
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
376 std::vector<ListenerStatus> sockets;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
377
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
378 for (const auto &pair : table) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
379 if (FD_ISSET(pair.first, &readset)) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
380 sockets.push_back(ListenerStatus{pair.first, Condition::Readable});
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
381 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
382 if (FD_ISSET(pair.first, &writeset)) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
383 sockets.push_back(ListenerStatus{pair.first, Condition::Writable});
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
384 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
385 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
386
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
387 return sockets;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
388 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
389
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
390 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
391
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
392 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
393 * Poll
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
394 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
395 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
396
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
397 /* {{{ Poll */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
398
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
399 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
400 * Poll implementation
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
401 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
402 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
403
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
404 #if defined(SOCKET_HAVE_POLL)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
405
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
406 #if defined(_WIN32)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
407 # define poll WSAPoll
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
408 #endif
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
409
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
410 short Poll::toPoll(Condition condition) const noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
411 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
412 short result(0);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
413
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
414 if ((condition & Condition::Readable) == Condition::Readable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
415 result |= POLLIN;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
416 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
417 if ((condition & Condition::Writable) == Condition::Writable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
418 result |= POLLOUT;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
419 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
420
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
421 return result;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
422 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
423
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
424 Condition Poll::toCondition(short &event) const noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
425 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
426 Condition condition{Condition::None};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
427
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
428 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
429 * Poll implementations mark the socket differently regarding
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
430 * the disconnection of a socket.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
431 *
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
432 * At least, even if POLLHUP or POLLIN is set, recv() always
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
433 * return 0 so we mark the socket as readable.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
434 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
435 if ((event & POLLIN) || (event & POLLHUP)) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
436 condition |= Condition::Readable;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
437 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
438 if (event & POLLOUT) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
439 condition |= Condition::Writable;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
440 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
441
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
442 /* Reset event for safety */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
443 event = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
444
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
445 return condition;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
446 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
447
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
448 void Poll::set(const ListenerTable &, Handle h, Condition condition, bool add)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
449 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
450 if (add) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
451 m_fds.push_back(pollfd{h, toPoll(condition), 0});
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
452 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
453 auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
454 return pfd.fd == h;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
455 });
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
456
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
457 it->events |= toPoll(condition);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
458 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
459 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
460
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
461 void Poll::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
462 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
463 auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
464 return pfd.fd == h;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
465 });
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
466
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
467 if (remove) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
468 m_fds.erase(it);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
469 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
470 it->events &= ~(toPoll(condition));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
471 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
472 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
473
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
474 std::vector<ListenerStatus> Poll::wait(const ListenerTable &, int ms)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
475 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
476 auto result = poll(m_fds.data(), m_fds.size(), ms);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
477 if (result == 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
478 throw Error{Error::Timeout, "select", TIMEOUT_MSG};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
479 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
480 if (result < 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
481 throw Error{Error::System, "poll"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
482 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
483
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
484 std::vector<ListenerStatus> sockets;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
485 for (auto &fd : m_fds) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
486 if (fd.revents != 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
487 sockets.push_back(ListenerStatus{fd.fd, toCondition(fd.revents)});
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
488 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
489 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
490
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
491 return sockets;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
492 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
493
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
494 #endif // !SOCKET_HAVE_POLL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
495
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
496 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
497
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
498 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
499 * Epoll implementation
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
500 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
501 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
502
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
503 /* {{{ Epoll */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
504
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
505 #if defined(SOCKET_HAVE_EPOLL)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
506
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
507 uint32_t Epoll::toEpoll(Condition condition) const noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
508 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
509 uint32_t events = 0;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
510
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
511 if ((condition & Condition::Readable) == Condition::Readable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
512 events |= EPOLLIN;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
513 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
514 if ((condition & Condition::Writable) == Condition::Writable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
515 events |= EPOLLOUT;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
516 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
517
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
518 return events;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
519 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
520
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
521 Condition Epoll::toCondition(uint32_t events) const noexcept
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
522 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
523 Condition condition{Condition::None};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
524
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
525 if ((events & EPOLLIN) || (events & EPOLLHUP)) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
526 condition |= Condition::Readable;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
527 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
528 if (events & EPOLLOUT) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
529 condition |= Condition::Writable;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
530 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
531
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
532 return condition;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
533 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
534
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
535 void Epoll::update(Handle h, int op, int eflags)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
536 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
537 epoll_event ev;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
538
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
539 std::memset(&ev, 0, sizeof (epoll_event));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
540
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
541 ev.events = eflags;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
542 ev.data.fd = h;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
543
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
544 if (epoll_ctl(m_handle, op, h, &ev) < 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
545 throw Error{Error::System, "epoll_ctl"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
546 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
547 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
548
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
549 Epoll::Epoll()
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
550 : m_handle{epoll_create1(0)}
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
551 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
552 if (m_handle < 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
553 throw Error{Error::System, "epoll_create"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
554 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
555 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
556
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
557 Epoll::~Epoll()
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
558 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
559 close(m_handle);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
560 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
561
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
562 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
563 * For set and unset, we need to apply the whole flags required, so if the socket
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
564 * was set to Connection::Readable and user add Connection::Writable, we must
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
565 * place both.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
566 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
567 void Epoll::set(const ListenerTable &table, Handle sc, Condition condition, bool add)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
568 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
569 if (add) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
570 update(sc, EPOLL_CTL_ADD, toEpoll(condition));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
571 m_events.resize(m_events.size() + 1);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
572 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
573 update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) | condition));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
574 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
575 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
576
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
577 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
578 * Unset is a bit complicated case because Listener tells us which
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
579 * flag to remove but to update epoll descriptor we need to pass
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
580 * the effective flags that we want to be applied.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
581 *
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
582 * So we put the same flags that are currently effective and remove the
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
583 * requested one.
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
584 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
585 void Epoll::unset(const ListenerTable &table, Handle sc, Condition condition, bool remove)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
586 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
587 if (remove) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
588 update(sc, EPOLL_CTL_DEL, 0);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
589 m_events.resize(m_events.size() - 1);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
590 } else {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
591 update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) & ~(condition)));
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
592 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
593 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
594
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
595 std::vector<ListenerStatus> Epoll::wait(const ListenerTable &, int ms)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
596 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
597 int ret = epoll_wait(m_handle, m_events.data(), m_events.size(), ms);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
598 std::vector<ListenerStatus> result;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
599
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
600 if (ret == 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
601 throw Error{Error::Timeout, "epoll_wait", TIMEOUT_MSG};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
602 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
603 if (ret < 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
604 throw Error{Error::System, "epoll_wait"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
605 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
606
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
607 for (int i = 0; i < ret; ++i) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
608 result.push_back(ListenerStatus{m_events[i].data.fd, toCondition(m_events[i].events)});
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
609 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
610
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
611 return result;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
612 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
613
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
614 #endif // !SOCKET_HAVE_EPOLL
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
615
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
616 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
617
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
618 /*
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
619 * Kqueue implementation
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
620 * ------------------------------------------------------------------
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
621 */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
622
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
623 /* {{{ Kqueue */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
624
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
625 #if defined(SOCKET_HAVE_KQUEUE)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
626
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
627 Kqueue::Kqueue()
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
628 : m_handle(kqueue())
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
629 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
630 if (m_handle < 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
631 throw Error{Error::System, "kqueue"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
632 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
633 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
634
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
635 Kqueue::~Kqueue()
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
636 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
637 close(m_handle);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
638 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
639
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
640 void Kqueue::update(Handle h, int filter, int kflags)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
641 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
642 struct kevent ev;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
643
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
644 EV_SET(&ev, h, filter, kflags, 0, 0, nullptr);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
645
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
646 if (kevent(m_handle, &ev, 1, nullptr, 0, nullptr) < 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
647 throw Error{Error::System, "kevent"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
648 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
649 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
650
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
651 void Kqueue::set(const ListenerTable &, Handle h, Condition condition, bool add)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
652 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
653 if ((condition & Condition::Readable) == Condition::Readable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
654 update(h, EVFILT_READ, EV_ADD | EV_ENABLE);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
655 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
656 if ((condition & Condition::Writable) == Condition::Writable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
657 update(h, EVFILT_WRITE, EV_ADD | EV_ENABLE);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
658 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
659
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
660 if (add) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
661 m_result.resize(m_result.size() + 1);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
662 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
663 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
664
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
665 void Kqueue::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
666 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
667 if ((condition & Condition::Readable) == Condition::Readable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
668 update(h, EVFILT_READ, EV_DELETE);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
669 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
670 if ((condition & Condition::Writable) == Condition::Writable) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
671 update(h, EVFILT_WRITE, EV_DELETE);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
672 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
673
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
674 if (remove) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
675 m_result.resize(m_result.size() - 1);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
676 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
677 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
678
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
679 std::vector<ListenerStatus> Kqueue::wait(const ListenerTable &, int ms)
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
680 {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
681 std::vector<ListenerStatus> sockets;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
682 timespec ts = { 0, 0 };
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
683 timespec *pts = (ms <= 0) ? nullptr : &ts;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
684
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
685 ts.tv_sec = ms / 1000;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
686 ts.tv_nsec = (ms % 1000) * 1000000;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
687
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
688 int nevents = kevent(m_handle, nullptr, 0, &m_result[0], m_result.capacity(), pts);
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
689
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
690 if (nevents == 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
691 throw Error{Error::Timeout, "kevent", TIMEOUT_MSG};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
692 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
693 if (nevents < 0) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
694 throw Error{Error::System, "kevent"};
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
695 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
696
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
697 for (int i = 0; i < nevents; ++i) {
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
698 sockets.push_back(ListenerStatus{
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
699 static_cast<Handle>(m_result[i].ident),
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
700 m_result[i].filter == EVFILT_READ ? Condition::Readable : Condition::Writable
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
701 });
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
702 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
703
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
704 return sockets;
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
705 }
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
706
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
707 #endif // !SOCKET_HAVE_KQUEUE
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
708
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
709 /* }}} */
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
710
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
711 } // !net
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
712
1158cffe5a5e Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
713 } // !irccd