Mercurial > code
annotate C++/Socket.cpp @ 288:b500a445be97
Zip: file needed for tests
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 12 Nov 2014 12:46:30 +0100 |
parents | ea55a3886da0 |
children | 9b3270513f40 |
rev | line source |
---|---|
170 | 1 /* |
2 * Socket.cpp -- portable C++ socket wrappers | |
3 * | |
4 * Copyright (c) 2013, David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
176
ba62ab219fc4
add cstring for strerror
David Demelier <markand@malikania.fr>
parents:
175
diff
changeset
|
19 #include <cstring> |
170 | 20 |
21 #include "Socket.h" | |
22 #include "SocketAddress.h" | |
23 | |
24 /* -------------------------------------------------------- | |
258 | 25 * Socket exceptions |
170 | 26 * -------------------------------------------------------- */ |
27 | |
258 | 28 namespace error { |
29 | |
276 | 30 Timeout::Timeout(std::string func) |
31 : m_error(func + ": Timeout exception") | |
32 { | |
33 } | |
34 | |
258 | 35 const char *Timeout::what() const noexcept |
170 | 36 { |
276 | 37 return m_error.c_str(); |
38 } | |
39 | |
40 InProgress::InProgress(std::string func) | |
41 : m_error(func + ": Operation in progress") | |
42 { | |
170 | 43 } |
44 | |
258 | 45 const char *InProgress::what() const noexcept |
170 | 46 { |
276 | 47 return m_error.c_str(); |
48 } | |
49 | |
50 WouldBlock::WouldBlock(std::string func) | |
51 : m_error(func + ": Operation would block") | |
52 { | |
170 | 53 } |
54 | |
258 | 55 const char *WouldBlock::what() const noexcept |
56 { | |
276 | 57 return m_error.c_str(); |
58 } | |
59 | |
60 Failure::Failure(std::string func, std::string message) | |
61 : m_error(func + ": " + message) | |
62 { | |
63 } | |
64 | |
65 const char *Failure::what() const noexcept | |
66 { | |
67 return m_error.c_str(); | |
258 | 68 } |
69 | |
70 } // !error | |
71 | |
170 | 72 /* -------------------------------------------------------- |
73 * Socket implementation | |
74 * -------------------------------------------------------- */ | |
75 | |
76 void Socket::init() | |
77 { | |
78 #if defined(_WIN32) | |
79 WSADATA wsa; | |
80 WSAStartup(MAKEWORD(2, 2), &wsa); | |
81 #endif | |
82 } | |
83 | |
258 | 84 void Socket::finish() |
85 { | |
86 #if defined(_WIN32) | |
87 WSACleanup(); | |
88 #endif | |
89 } | |
90 | |
170 | 91 /* -------------------------------------------------------- |
92 * System dependent code | |
93 * -------------------------------------------------------- */ | |
94 | |
95 #if defined(_WIN32) | |
96 | |
258 | 97 std::string Socket::syserror(int errn) |
170 | 98 { |
99 LPSTR str = nullptr; | |
188
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
176
diff
changeset
|
100 std::string errmsg = "Unknown error"; |
170 | 101 |
102 FormatMessageA( | |
103 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, | |
104 NULL, | |
258 | 105 errn, |
170 | 106 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
107 (LPSTR)&str, 0, NULL); | |
108 | |
109 | |
188
ce3e1c3d6fed
Update sockets to style and using instead of typedef
David Demelier <markand@malikania.fr>
parents:
176
diff
changeset
|
110 if (str) { |
260 | 111 errmsg = std::string(str); |
170 | 112 LocalFree(str); |
113 } | |
114 | |
115 return errmsg; | |
116 } | |
117 | |
118 #else | |
119 | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
120 #include <cerrno> |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
121 |
258 | 122 std::string Socket::syserror(int errn) |
170 | 123 { |
258 | 124 return strerror(errn); |
170 | 125 } |
126 | |
127 #endif | |
128 | |
258 | 129 std::string Socket::syserror() |
170 | 130 { |
131 #if defined(_WIN32) | |
258 | 132 return syserror(WSAGetLastError()); |
133 #else | |
134 return syserror(errno); | |
170 | 135 #endif |
136 } | |
137 | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
138 /* -------------------------------------------------------- |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
139 * Standard clear implementation |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
140 * -------------------------------------------------------- */ |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
141 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
142 class Standard final : public SocketInterface { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
143 public: |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
144 void bind(Socket &s, const SocketAddress &address) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
145 void close(Socket &s) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
146 void connect(Socket &s, const SocketAddress &address) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
147 Socket accept(Socket &s, SocketAddress &info) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
148 void listen(Socket &s, int max) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
149 unsigned recv(Socket &s, void *data, unsigned len) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
150 unsigned recvfrom(Socket &s, void *data, unsigned len, SocketAddress &info) override ; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
151 unsigned send(Socket &s, const void *data, unsigned len) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
152 unsigned sendto(Socket &s, const void *data, unsigned len, const SocketAddress &info) override; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
153 }; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
154 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
155 void Standard::bind(Socket &s, const SocketAddress &addr) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
156 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
157 auto &sa = addr.address(); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
158 auto addrlen = addr.length(); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
159 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
160 if (::bind(s.handle(), (sockaddr *)&sa, addrlen) == SOCKET_ERROR) |
276 | 161 throw error::Failure("bind", Socket::syserror()); |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
162 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
163 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
164 void Standard::connect(Socket &s, const SocketAddress &addr) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
165 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
166 auto &sa = addr.address(); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
167 auto addrlen = addr.length(); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
168 |
258 | 169 if (::connect(s.handle(), (sockaddr *)&sa, addrlen) == SOCKET_ERROR) { |
170 /* | |
171 * Determine if the error comes from a non-blocking connect that cannot be | |
172 * accomplished yet. | |
173 */ | |
174 #if defined(_WIN32) | |
175 if (WSAGetLastError() == WSAEWOULDBLOCK) | |
276 | 176 throw error::InProgress("connect"); |
258 | 177 |
276 | 178 throw error::Failure("connect", Socket::syserror()); |
258 | 179 #else |
180 if (errno == EINPROGRESS) | |
276 | 181 throw error::InProgress("connect"); |
258 | 182 |
276 | 183 throw error::Failure("connect", Socket::syserror()); |
258 | 184 #endif |
185 } | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
186 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
187 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
188 Socket Standard::accept(Socket &s, SocketAddress &info) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
189 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
190 Socket::Handle handle; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
191 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
192 // Store the information |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
193 sockaddr_storage address; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
194 socklen_t addrlen; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
195 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
196 addrlen = sizeof (sockaddr_storage); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
197 handle = ::accept(s.handle(), (sockaddr *)&address, &addrlen); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
198 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
199 if (handle == INVALID_SOCKET) |
276 | 200 throw error::Failure("accept", Socket::syserror()); |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
201 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
202 // Usually accept works only with SOCK_STREAM |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
203 info = SocketAddress(address, addrlen); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
204 |
280 | 205 return Socket(handle, std::make_shared<Standard>()); |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
206 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
207 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
208 void Standard::listen(Socket &s, int max) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
209 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
210 if (::listen(s.handle(), max) == SOCKET_ERROR) |
276 | 211 throw error::Failure("listen", Socket::syserror()); |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
212 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
213 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
214 unsigned Standard::recv(Socket &s, void *data, unsigned dataLen) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
215 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
216 int nbread; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
217 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
218 nbread = ::recv(s.handle(), (Socket::Arg)data, dataLen, 0); |
258 | 219 if (nbread == SOCKET_ERROR) { |
220 #if defined(_WIN32) | |
221 if (WSAGetLastError() == WSAEWOULDBLOCK) | |
276 | 222 throw error::WouldBlock("recv"); |
258 | 223 |
276 | 224 throw error::Failure("recv", Socket::syserror()); |
258 | 225 #else |
226 if (errno == EAGAIN || errno == EWOULDBLOCK) | |
276 | 227 throw error::WouldBlock("recv"); |
258 | 228 |
276 | 229 throw error::Failure("recv", Socket::syserror()); |
258 | 230 #endif |
231 } | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
232 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
233 return (unsigned)nbread; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
234 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
235 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
236 unsigned Standard::send(Socket &s, const void *data, unsigned dataLen) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
237 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
238 int nbsent; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
239 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
240 nbsent = ::send(s.handle(), (Socket::ConstArg)data, dataLen, 0); |
258 | 241 if (nbsent == SOCKET_ERROR) { |
242 #if defined(_WIN32) | |
243 if (WSAGetLastError() == WSAEWOULDBLOCK) | |
276 | 244 throw error::WouldBlock("send"); |
258 | 245 |
276 | 246 throw error::Failure("send", Socket::syserror()); |
258 | 247 #else |
248 if (errno == EAGAIN || errno == EWOULDBLOCK) | |
276 | 249 throw error::WouldBlock("send"); |
258 | 250 |
276 | 251 throw error::Failure("send", Socket::syserror()); |
258 | 252 #endif |
253 } | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
254 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
255 return (unsigned)nbsent; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
256 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
257 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
258 unsigned Standard::recvfrom(Socket &s, void *data, unsigned dataLen, SocketAddress &info) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
259 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
260 int nbread; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
261 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
262 // Store information |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
263 sockaddr_storage address; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
264 socklen_t addrlen; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
265 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
266 addrlen = sizeof (struct sockaddr_storage); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
267 nbread = ::recvfrom(s.handle(), (Socket::Arg)data, dataLen, 0, (sockaddr *)&address, &addrlen); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
268 |
259
0b3fcc5ed8eb
Socket: forget to add address in recvfrom
David Demelier <markand@malikania.fr>
parents:
258
diff
changeset
|
269 info = SocketAddress(address, addrlen); |
0b3fcc5ed8eb
Socket: forget to add address in recvfrom
David Demelier <markand@malikania.fr>
parents:
258
diff
changeset
|
270 |
258 | 271 if (nbread == SOCKET_ERROR) { |
272 #if defined(_WIN32) | |
273 if (WSAGetLastError() == WSAEWOULDBLOCK) | |
276 | 274 throw error::WouldBlock("recvfrom"); |
258 | 275 |
276 | 276 throw error::Failure("recvfrom", Socket::syserror()); |
258 | 277 #else |
278 if (errno == EAGAIN || errno == EWOULDBLOCK) | |
276 | 279 throw error::WouldBlock("recvfrom"); |
258 | 280 |
276 | 281 throw error::Failure("recvfrom", Socket::syserror()); |
258 | 282 #endif |
283 } | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
284 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
285 return (unsigned)nbread; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
286 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
287 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
288 unsigned Standard::sendto(Socket &s, const void *data, unsigned dataLen, const SocketAddress &info) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
289 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
290 int nbsent; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
291 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
292 nbsent = ::sendto(s.handle(), (Socket::ConstArg)data, dataLen, 0, (const sockaddr *)&info.address(), info.length()); |
258 | 293 if (nbsent == SOCKET_ERROR) { |
294 #if defined(_WIN32) | |
295 if (WSAGetLastError() == WSAEWOULDBLOCK) | |
276 | 296 throw error::WouldBlock("sendto"); |
258 | 297 |
276 | 298 throw error::Failure("sendto", Socket::syserror()); |
258 | 299 #else |
300 if (errno == EAGAIN || errno == EWOULDBLOCK) | |
276 | 301 throw error::WouldBlock("sendto"); |
258 | 302 |
276 | 303 throw error::Failure("sendto", Socket::syserror()); |
258 | 304 #endif |
305 } | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
306 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
307 return (unsigned)nbsent; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
308 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
309 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
310 void Standard::close(Socket &s) |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
311 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
312 (void)closesocket(s.handle()); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
313 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
314 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
315 /* -------------------------------------------------------- |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
316 * Socket code |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
317 * -------------------------------------------------------- */ |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
318 |
280 | 319 Socket::Socket() |
320 : m_interface(std::make_shared<Standard>()) | |
321 { | |
322 } | |
323 | |
170 | 324 Socket::Socket(int domain, int type, int protocol) |
280 | 325 : Socket() |
170 | 326 { |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
327 m_handle = socket(domain, type, protocol); |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
328 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
329 if (m_handle == INVALID_SOCKET) |
276 | 330 throw error::Failure("socket", syserror()); |
170 | 331 } |
332 | |
282 | 333 Socket::Socket(Handle handle, std::shared_ptr<SocketInterface> iface) |
334 : m_interface(std::move(iface)) | |
247 | 335 , m_handle(handle) |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
336 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
337 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
338 |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
339 Socket::Handle Socket::handle() const |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
340 { |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
341 return m_handle; |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
342 } |
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
343 |
170 | 344 void Socket::blockMode(bool block) |
345 { | |
346 #if defined(O_NONBLOCK) && !defined(_WIN32) | |
347 int flags; | |
348 | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
349 if ((flags = fcntl(m_handle, F_GETFL, 0)) == -1) |
170 | 350 flags = 0; |
351 | |
258 | 352 if (block) |
170 | 353 flags &= ~(O_NONBLOCK); |
354 else | |
355 flags |= O_NONBLOCK; | |
356 | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
357 if (fcntl(m_handle, F_SETFL, flags) == -1) |
276 | 358 throw error::Failure("blockMode", Socket::syserror()); |
170 | 359 #else |
360 unsigned long flags = (block) ? 0 : 1; | |
361 | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
362 if (ioctlsocket(m_handle, FIONBIO, &flags) == SOCKET_ERROR) |
276 | 363 throw error::Failure("blockMode", Socket::syserror()); |
170 | 364 #endif |
365 } | |
366 | |
367 Socket Socket::accept() | |
368 { | |
369 SocketAddress dummy; | |
370 | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
371 return m_interface->accept(*this, dummy); |
170 | 372 } |
373 | |
374 unsigned Socket::send(const std::string &message) | |
375 { | |
376 return Socket::send(message.c_str(), message.length()); | |
377 } | |
378 | |
379 unsigned Socket::recvfrom(void *data, unsigned dataLen) | |
380 { | |
381 SocketAddress dummy; | |
382 | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
383 return m_interface->recvfrom(*this, data, dataLen, dummy); |
170 | 384 } |
385 | |
386 unsigned Socket::sendto(const std::string &message, const SocketAddress &info) | |
387 { | |
388 return sendto(message.c_str(), message.length(), info); | |
389 } | |
390 | |
391 bool operator==(const Socket &s1, const Socket &s2) | |
392 { | |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
393 return s1.handle() == s2.handle(); |
170 | 394 } |
174
9f22bd478f21
Add operator less because widely used
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
395 |
175 | 396 bool operator<(const Socket &s1, const Socket &s2) |
174
9f22bd478f21
Add operator less because widely used
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
397 { |
245
3c12f0e8bbb9
Converter: add cstring missing
David Demelier <markand@malikania.fr>
parents:
236
diff
changeset
|
398 return s1.handle() < s2.handle(); |
174
9f22bd478f21
Add operator less because widely used
David Demelier <markand@malikania.fr>
parents:
170
diff
changeset
|
399 } |