1 | // |
2 | // Socket.h |
3 | // |
4 | // Library: Net |
5 | // Package: Sockets |
6 | // Module: Socket |
7 | // |
8 | // Definition of the Socket class. |
9 | // |
10 | // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Net_Socket_INCLUDED |
18 | #define Net_Socket_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Net/Net.h" |
22 | #include "Poco/Net/SocketImpl.h" |
23 | #include <vector> |
24 | |
25 | |
26 | namespace Poco { |
27 | namespace Net { |
28 | |
29 | |
30 | class Net_API Socket |
31 | /// Socket is the common base class for |
32 | /// StreamSocket, ServerSocket, DatagramSocket and other |
33 | /// socket classes. |
34 | /// |
35 | /// It provides operations common to all socket types. |
36 | { |
37 | public: |
38 | typedef SocketBufVec BufVec; |
39 | |
40 | enum SelectMode |
41 | /// The mode argument to poll() and select(). |
42 | { |
43 | SELECT_READ = 1, |
44 | SELECT_WRITE = 2, |
45 | SELECT_ERROR = 4 |
46 | }; |
47 | |
48 | typedef std::vector<Socket> SocketList; |
49 | |
50 | Socket(); |
51 | /// Creates an uninitialized socket. |
52 | |
53 | Socket(const Socket& socket); |
54 | /// Copy constructor. |
55 | /// |
56 | /// Attaches the SocketImpl from the other socket and |
57 | /// increments the reference count of the SocketImpl. |
58 | |
59 | Socket& operator = (const Socket& socket); |
60 | /// Assignment operator. |
61 | /// |
62 | /// Releases the socket's SocketImpl and |
63 | /// attaches the SocketImpl from the other socket and |
64 | /// increments the reference count of the SocketImpl. |
65 | |
66 | virtual ~Socket(); |
67 | /// Destroys the Socket and releases the |
68 | /// SocketImpl. |
69 | |
70 | bool operator == (const Socket& socket) const; |
71 | /// Returns true if both sockets share the same |
72 | /// SocketImpl, false otherwise. |
73 | |
74 | bool operator != (const Socket& socket) const; |
75 | /// Returns false if both sockets share the same |
76 | /// SocketImpl, true otherwise. |
77 | |
78 | bool operator < (const Socket& socket) const; |
79 | /// Compares the SocketImpl pointers. |
80 | |
81 | bool operator <= (const Socket& socket) const; |
82 | /// Compares the SocketImpl pointers. |
83 | |
84 | bool operator > (const Socket& socket) const; |
85 | /// Compares the SocketImpl pointers. |
86 | |
87 | bool operator >= (const Socket& socket) const; |
88 | /// Compares the SocketImpl pointers. |
89 | |
90 | void close(); |
91 | /// Closes the socket. |
92 | |
93 | static int select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout); |
94 | /// Determines the status of one or more sockets, |
95 | /// using a call to select(). |
96 | /// |
97 | /// ReadList contains the list of sockets which should be |
98 | /// checked for readability. |
99 | /// |
100 | /// WriteList contains the list of sockets which should be |
101 | /// checked for writeability. |
102 | /// |
103 | /// ExceptList contains a list of sockets which should be |
104 | /// checked for a pending error. |
105 | /// |
106 | /// Returns the number of sockets ready. |
107 | /// |
108 | /// After return, |
109 | /// * readList contains those sockets ready for reading, |
110 | /// * writeList contains those sockets ready for writing, |
111 | /// * exceptList contains those sockets with a pending error. |
112 | /// |
113 | /// If the total number of sockets passed in readList, writeList and |
114 | /// exceptList is zero, select() will return immediately and the |
115 | /// return value will be 0. |
116 | /// |
117 | /// If one of the sockets passed to select() is closed while |
118 | /// select() runs, select will return immediately. However, |
119 | /// the closed socket will not be included in any list. |
120 | /// In this case, the return value may be greater than the sum |
121 | /// of all sockets in all list. |
122 | |
123 | bool poll(const Poco::Timespan& timeout, int mode) const; |
124 | /// Determines the status of the socket, using a |
125 | /// call to poll() or select(). |
126 | /// |
127 | /// The mode argument is constructed by combining the values |
128 | /// of the SelectMode enumeration. |
129 | /// |
130 | /// Returns true if the next operation corresponding to |
131 | /// mode will not block, false otherwise. |
132 | |
133 | int available() const; |
134 | /// Returns the number of bytes available that can be read |
135 | /// without causing the socket to block. |
136 | |
137 | void setSendBufferSize(int size); |
138 | /// Sets the size of the send buffer. |
139 | |
140 | int getSendBufferSize() const; |
141 | /// Returns the size of the send buffer. |
142 | /// |
143 | /// The returned value may be different than the |
144 | /// value previously set with setSendBufferSize(), |
145 | /// as the system is free to adjust the value. |
146 | |
147 | void setReceiveBufferSize(int size); |
148 | /// Sets the size of the receive buffer. |
149 | |
150 | int getReceiveBufferSize() const; |
151 | /// Returns the size of the receive buffer. |
152 | /// |
153 | /// The returned value may be different than the |
154 | /// value previously set with setReceiveBufferSize(), |
155 | /// as the system is free to adjust the value. |
156 | |
157 | void setSendTimeout(const Poco::Timespan& timeout); |
158 | /// Sets the send timeout for the socket. |
159 | |
160 | Poco::Timespan getSendTimeout() const; |
161 | /// Returns the send timeout for the socket. |
162 | /// |
163 | /// The returned timeout may be different than the |
164 | /// timeout previously set with setSendTimeout(), |
165 | /// as the system is free to adjust the value. |
166 | |
167 | void setReceiveTimeout(const Poco::Timespan& timeout); |
168 | /// Sets the send timeout for the socket. |
169 | /// |
170 | /// On systems that do not support SO_RCVTIMEO, a |
171 | /// workaround using poll() is provided. |
172 | |
173 | Poco::Timespan getReceiveTimeout() const; |
174 | /// Returns the receive timeout for the socket. |
175 | /// |
176 | /// The returned timeout may be different than the |
177 | /// timeout previously set with getReceiveTimeout(), |
178 | /// as the system is free to adjust the value. |
179 | |
180 | void setOption(int level, int option, int value); |
181 | /// Sets the socket option specified by level and option |
182 | /// to the given integer value. |
183 | |
184 | void setOption(int level, int option, unsigned value); |
185 | /// Sets the socket option specified by level and option |
186 | /// to the given integer value. |
187 | |
188 | void setOption(int level, int option, unsigned char value); |
189 | /// Sets the socket option specified by level and option |
190 | /// to the given integer value. |
191 | |
192 | void setOption(int level, int option, const Poco::Timespan& value); |
193 | /// Sets the socket option specified by level and option |
194 | /// to the given time value. |
195 | |
196 | void setOption(int level, int option, const IPAddress& value); |
197 | /// Sets the socket option specified by level and option |
198 | /// to the given time value. |
199 | |
200 | void getOption(int level, int option, int& value) const; |
201 | /// Returns the value of the socket option |
202 | /// specified by level and option. |
203 | |
204 | void getOption(int level, int option, unsigned& value) const; |
205 | /// Returns the value of the socket option |
206 | /// specified by level and option. |
207 | |
208 | void getOption(int level, int option, unsigned char& value) const; |
209 | /// Returns the value of the socket option |
210 | /// specified by level and option. |
211 | |
212 | void getOption(int level, int option, Poco::Timespan& value) const; |
213 | /// Returns the value of the socket option |
214 | /// specified by level and option. |
215 | |
216 | void getOption(int level, int option, IPAddress& value) const; |
217 | /// Returns the value of the socket option |
218 | /// specified by level and option. |
219 | |
220 | void setLinger(bool on, int seconds); |
221 | /// Sets the value of the SO_LINGER socket option. |
222 | |
223 | void getLinger(bool& on, int& seconds) const; |
224 | /// Returns the value of the SO_LINGER socket option. |
225 | |
226 | void setNoDelay(bool flag); |
227 | /// Sets the value of the TCP_NODELAY socket option. |
228 | |
229 | bool getNoDelay() const; |
230 | /// Returns the value of the TCP_NODELAY socket option. |
231 | |
232 | void setKeepAlive(bool flag); |
233 | /// Sets the value of the SO_KEEPALIVE socket option. |
234 | |
235 | bool getKeepAlive() const; |
236 | /// Returns the value of the SO_KEEPALIVE socket option. |
237 | |
238 | void setReuseAddress(bool flag); |
239 | /// Sets the value of the SO_REUSEADDR socket option. |
240 | |
241 | bool getReuseAddress() const; |
242 | /// Returns the value of the SO_REUSEADDR socket option. |
243 | |
244 | void setReusePort(bool flag); |
245 | /// Sets the value of the SO_REUSEPORT socket option. |
246 | /// Does nothing if the socket implementation does not |
247 | /// support SO_REUSEPORT. |
248 | |
249 | bool getReusePort() const; |
250 | /// Returns the value of the SO_REUSEPORT socket option. |
251 | /// |
252 | /// Returns false if the socket implementation does not |
253 | /// support SO_REUSEPORT. |
254 | |
255 | void setOOBInline(bool flag); |
256 | /// Sets the value of the SO_OOBINLINE socket option. |
257 | |
258 | bool getOOBInline() const; |
259 | /// Returns the value of the SO_OOBINLINE socket option. |
260 | |
261 | void setBlocking(bool flag); |
262 | /// Sets the socket in blocking mode if flag is true, |
263 | /// disables blocking mode if flag is false. |
264 | |
265 | bool getBlocking() const; |
266 | /// Returns the blocking mode of the socket. |
267 | /// This method will only work if the blocking modes of |
268 | /// the socket are changed via the setBlocking method! |
269 | |
270 | SocketAddress address() const; |
271 | /// Returns the IP address and port number of the socket. |
272 | |
273 | SocketAddress peerAddress() const; |
274 | /// Returns the IP address and port number of the peer socket. |
275 | |
276 | SocketImpl* impl() const; |
277 | /// Returns the SocketImpl for this socket. |
278 | |
279 | bool secure() const; |
280 | /// Returns true iff the socket's connection is secure |
281 | /// (using SSL or TLS). |
282 | |
283 | static bool supportsIPv4(); |
284 | /// Returns true if the system supports IPv4. |
285 | |
286 | static bool supportsIPv6(); |
287 | /// Returns true if the system supports IPv6. |
288 | |
289 | void init(int af); |
290 | /// Creates the underlying system socket for the given |
291 | /// address family. |
292 | /// |
293 | /// Normally, this method should not be called directly, as |
294 | /// socket creation will be handled automatically. There are |
295 | /// a few situations where calling this method after creation |
296 | /// of the Socket object makes sense. One example is setting |
297 | /// a socket option before calling bind() on a ServerSocket. |
298 | |
299 | static SocketBuf makeBuffer(void* buffer, std::size_t length); |
300 | /// Creates and returns buffer. Suitable for creating |
301 | /// the appropriate buffer for the platform. |
302 | |
303 | static SocketBufVec makeBufVec(std::size_t size, std::size_t bufLen); |
304 | /// Creates and returns a vector of requested size, with |
305 | /// allocated buffers and lengths set accordingly. |
306 | /// This utility function works well when all buffers are |
307 | /// of same size. |
308 | |
309 | static void destroyBufVec(SocketBufVec& buf); |
310 | /// Releases the memory pointed to by vector members |
311 | /// and shrinks the vector to size 0. |
312 | /// The vector must be created by makeBufVec(size_t, size_t). |
313 | |
314 | static SocketBufVec makeBufVec(const std::vector<char*>& vec); |
315 | /// Creates and returns a vector of requested size, with |
316 | /// buffers pointing to the supplied data (so, `vec` must |
317 | /// remain available at the time of use) and lengths set |
318 | /// accordingly. |
319 | /// Notes: |
320 | /// - data length is determined using `strlen`, so this |
321 | /// function is not meant to be used with binary data. |
322 | /// |
323 | /// - if the returned buffer is used for read operations |
324 | /// (ie. operations that write to the bufer), pointing |
325 | /// to string literals will result in undefined behavior, |
326 | /// in best case an I/O error and subsequent exception |
327 | |
328 | static SocketBufVec makeBufVec(const std::vector<std::string>& vec); |
329 | /// Creates and returns a vector of requested size, with |
330 | /// buffers pointing to the supplied data (so, `vec` must |
331 | /// remain available at the time of use) and lengths set |
332 | /// accordingly. |
333 | /// Note:: this function is not suitable for creation |
334 | /// of buffers used for writing (ie. reading from socket |
335 | /// into buffers). |
336 | |
337 | protected: |
338 | Socket(SocketImpl* pImpl); |
339 | /// Creates the Socket and attaches the given SocketImpl. |
340 | /// The socket takes ownership of the SocketImpl. |
341 | |
342 | poco_socket_t sockfd() const; |
343 | /// Returns the socket descriptor for this socket. |
344 | |
345 | private: |
346 | |
347 | #if defined(POCO_HAVE_FD_POLL) |
348 | class FDCompare |
349 | /// Utility functor used to compare socket file descriptors. |
350 | /// Used in poll() member function. |
351 | { |
352 | public: |
353 | FDCompare(int fd): _fd(fd) { } |
354 | inline bool operator()(const Socket& socket) const |
355 | { return socket.sockfd() == _fd; } |
356 | |
357 | private: |
358 | FDCompare(); |
359 | int _fd; |
360 | }; |
361 | #endif |
362 | |
363 | SocketImpl* _pImpl; |
364 | }; |
365 | |
366 | |
367 | // |
368 | // inlines |
369 | // |
370 | inline bool Socket::operator == (const Socket& socket) const |
371 | { |
372 | return _pImpl == socket._pImpl; |
373 | } |
374 | |
375 | |
376 | inline bool Socket::operator != (const Socket& socket) const |
377 | { |
378 | return _pImpl != socket._pImpl; |
379 | } |
380 | |
381 | |
382 | inline bool Socket::operator < (const Socket& socket) const |
383 | { |
384 | return _pImpl < socket._pImpl; |
385 | } |
386 | |
387 | |
388 | inline bool Socket::operator <= (const Socket& socket) const |
389 | { |
390 | return _pImpl <= socket._pImpl; |
391 | } |
392 | |
393 | |
394 | inline bool Socket::operator > (const Socket& socket) const |
395 | { |
396 | return _pImpl > socket._pImpl; |
397 | } |
398 | |
399 | |
400 | inline bool Socket::operator >= (const Socket& socket) const |
401 | { |
402 | return _pImpl >= socket._pImpl; |
403 | } |
404 | |
405 | |
406 | inline void Socket::close() |
407 | { |
408 | _pImpl->close(); |
409 | } |
410 | |
411 | |
412 | inline bool Socket::poll(const Poco::Timespan& timeout, int mode) const |
413 | { |
414 | return _pImpl->poll(timeout, mode); |
415 | } |
416 | |
417 | |
418 | inline int Socket::available() const |
419 | { |
420 | return _pImpl->available(); |
421 | } |
422 | |
423 | |
424 | inline void Socket::setSendBufferSize(int size) |
425 | { |
426 | _pImpl->setSendBufferSize(size); |
427 | } |
428 | |
429 | |
430 | inline int Socket::getSendBufferSize() const |
431 | { |
432 | return _pImpl->getSendBufferSize(); |
433 | } |
434 | |
435 | |
436 | inline void Socket::setReceiveBufferSize(int size) |
437 | { |
438 | _pImpl->setReceiveBufferSize(size); |
439 | } |
440 | |
441 | |
442 | inline int Socket::getReceiveBufferSize() const |
443 | { |
444 | return _pImpl->getReceiveBufferSize(); |
445 | } |
446 | |
447 | |
448 | inline void Socket::setSendTimeout(const Poco::Timespan& timeout) |
449 | { |
450 | _pImpl->setSendTimeout(timeout); |
451 | } |
452 | |
453 | |
454 | inline Poco::Timespan Socket::getSendTimeout() const |
455 | { |
456 | return _pImpl->getSendTimeout(); |
457 | } |
458 | |
459 | |
460 | inline void Socket::setReceiveTimeout(const Poco::Timespan& timeout) |
461 | { |
462 | _pImpl->setReceiveTimeout(timeout); |
463 | } |
464 | |
465 | |
466 | inline Poco::Timespan Socket::getReceiveTimeout() const |
467 | { |
468 | return _pImpl->getReceiveTimeout(); |
469 | } |
470 | |
471 | |
472 | inline void Socket::setOption(int level, int option, int value) |
473 | { |
474 | _pImpl->setOption(level, option, value); |
475 | } |
476 | |
477 | |
478 | inline void Socket::setOption(int level, int option, unsigned value) |
479 | { |
480 | _pImpl->setOption(level, option, value); |
481 | } |
482 | |
483 | |
484 | inline void Socket::setOption(int level, int option, unsigned char value) |
485 | { |
486 | _pImpl->setOption(level, option, value); |
487 | } |
488 | |
489 | |
490 | inline void Socket::setOption(int level, int option, const Poco::Timespan& value) |
491 | { |
492 | _pImpl->setOption(level, option, value); |
493 | } |
494 | |
495 | |
496 | inline void Socket::setOption(int level, int option, const IPAddress& value) |
497 | { |
498 | _pImpl->setOption(level, option, value); |
499 | } |
500 | |
501 | |
502 | inline void Socket::getOption(int level, int option, int& value) const |
503 | { |
504 | _pImpl->getOption(level, option, value); |
505 | } |
506 | |
507 | |
508 | inline void Socket::getOption(int level, int option, unsigned& value) const |
509 | { |
510 | _pImpl->getOption(level, option, value); |
511 | } |
512 | |
513 | |
514 | inline void Socket::getOption(int level, int option, unsigned char& value) const |
515 | { |
516 | _pImpl->getOption(level, option, value); |
517 | } |
518 | |
519 | |
520 | inline void Socket::getOption(int level, int option, Poco::Timespan& value) const |
521 | { |
522 | _pImpl->getOption(level, option, value); |
523 | } |
524 | |
525 | |
526 | inline void Socket::getOption(int level, int option, IPAddress& value) const |
527 | { |
528 | _pImpl->getOption(level, option, value); |
529 | } |
530 | |
531 | |
532 | inline void Socket::setLinger(bool on, int seconds) |
533 | { |
534 | _pImpl->setLinger(on, seconds); |
535 | } |
536 | |
537 | |
538 | inline void Socket::getLinger(bool& on, int& seconds) const |
539 | { |
540 | _pImpl->getLinger(on, seconds); |
541 | } |
542 | |
543 | |
544 | inline void Socket::setNoDelay(bool flag) |
545 | { |
546 | _pImpl->setNoDelay(flag); |
547 | } |
548 | |
549 | |
550 | inline bool Socket::getNoDelay() const |
551 | { |
552 | return _pImpl->getNoDelay(); |
553 | } |
554 | |
555 | |
556 | inline void Socket::setKeepAlive(bool flag) |
557 | { |
558 | _pImpl->setKeepAlive(flag); |
559 | } |
560 | |
561 | |
562 | inline bool Socket::getKeepAlive() const |
563 | { |
564 | return _pImpl->getKeepAlive(); |
565 | } |
566 | |
567 | |
568 | inline void Socket::setReuseAddress(bool flag) |
569 | { |
570 | _pImpl->setReuseAddress(flag); |
571 | } |
572 | |
573 | |
574 | inline bool Socket::getReuseAddress() const |
575 | { |
576 | return _pImpl->getReuseAddress(); |
577 | } |
578 | |
579 | |
580 | inline void Socket::setReusePort(bool flag) |
581 | { |
582 | _pImpl->setReusePort(flag); |
583 | } |
584 | |
585 | |
586 | inline bool Socket::getReusePort() const |
587 | { |
588 | return _pImpl->getReusePort(); |
589 | } |
590 | |
591 | |
592 | inline void Socket::setOOBInline(bool flag) |
593 | { |
594 | _pImpl->setOOBInline(flag); |
595 | } |
596 | |
597 | |
598 | inline bool Socket::getOOBInline() const |
599 | { |
600 | return _pImpl->getOOBInline(); |
601 | } |
602 | |
603 | |
604 | inline void Socket::setBlocking(bool flag) |
605 | { |
606 | _pImpl->setBlocking(flag); |
607 | } |
608 | |
609 | |
610 | inline bool Socket::getBlocking() const |
611 | { |
612 | return _pImpl->getBlocking(); |
613 | } |
614 | |
615 | |
616 | inline SocketImpl* Socket::impl() const |
617 | { |
618 | return _pImpl; |
619 | } |
620 | |
621 | |
622 | inline poco_socket_t Socket::sockfd() const |
623 | { |
624 | return _pImpl->sockfd(); |
625 | } |
626 | |
627 | |
628 | inline SocketAddress Socket::address() const |
629 | { |
630 | return _pImpl->address(); |
631 | } |
632 | |
633 | |
634 | inline SocketAddress Socket::peerAddress() const |
635 | { |
636 | return _pImpl->peerAddress(); |
637 | } |
638 | |
639 | |
640 | inline bool Socket::secure() const |
641 | { |
642 | return _pImpl->secure(); |
643 | } |
644 | |
645 | |
646 | inline bool Socket::supportsIPv4() |
647 | { |
648 | return true; |
649 | } |
650 | |
651 | |
652 | inline bool Socket::supportsIPv6() |
653 | { |
654 | #if defined(POCO_HAVE_IPv6) |
655 | return true; |
656 | #else |
657 | return false; |
658 | #endif |
659 | } |
660 | |
661 | |
662 | inline void Socket::init(int af) |
663 | { |
664 | _pImpl->init(af); |
665 | } |
666 | |
667 | |
668 | } } // namespace Poco::Net |
669 | |
670 | |
671 | #endif // Net_Socket_INCLUDED |
672 | |