µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
posix-io/socket.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2015-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#ifndef CMSIS_PLUS_POSIX_IO_SOCKET_H_
13#define CMSIS_PLUS_POSIX_IO_SOCKET_H_
14
15// ----------------------------------------------------------------------------
16
17#if defined(__cplusplus)
18
19// ----------------------------------------------------------------------------
20
21#if defined(OS_USE_OS_APP_CONFIG_H)
22#include <cmsis-plus/os-app-config.h>
23#endif
24
28
29#include <mutex>
30
31// ----------------------------------------------------------------------------
32
33#pragma GCC diagnostic push
34#if defined(__clang__)
35#pragma clang diagnostic ignored "-Wc++98-compat"
36#endif
37
38// ----------------------------------------------------------------------------
39
40namespace os
41{
42 namespace posix
43 {
44 // ------------------------------------------------------------------------
45
46 class socket;
47 class socket_impl;
48 class net_stack;
49
50 // ------------------------------------------------------------------------
56#pragma GCC diagnostic push
57#if defined(__clang__)
58#elif defined(__GNUC__)
59#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
60#pragma GCC diagnostic ignored "-Wsuggest-final-types"
61#endif
62 class socket : public io
63 {
64 // ----------------------------------------------------------------------
70 public:
71 socket (socket_impl& impl, /* class */ net_stack& ns);
72
77 // The rule of five.
78 socket (const socket&) = delete;
79 socket (socket&&) = delete;
80 socket&
81 operator= (const socket&)
82 = delete;
83 socket&
84 operator= (socket&&)
85 = delete;
86
91 virtual ~socket () override;
92
97 // ----------------------------------------------------------------------
103 public:
104 virtual /* class */ socket*
105 accept (/* struct */ sockaddr* address, socklen_t* address_len);
106
107 virtual int
108 bind (const /* struct */ sockaddr* address, socklen_t address_len);
109
110 virtual int
111 connect (const /* struct */ sockaddr* address, socklen_t address_len);
112
113 virtual int
114 getpeername (/* struct */ sockaddr* address, socklen_t* address_len);
115
116 virtual int
117 getsockname (/* struct */ sockaddr* address, socklen_t* address_len);
118
119 virtual int
120 getsockopt (int level, int option_name, void* option_value,
121 socklen_t* option_len);
122
123 virtual int
124 listen (int backlog);
125
126 virtual ssize_t
127 recv (void* buffer, size_t length, int flags);
128
129 virtual ssize_t
130 recvfrom (void* buffer, size_t length, int flags,
131 /* struct */ sockaddr* address, socklen_t* address_len);
132
133 virtual ssize_t
134 recvmsg (/* struct */ msghdr* message, int flags);
135
136 virtual ssize_t
137 send (const void* buffer, size_t length, int flags);
138
139 virtual ssize_t
140 sendmsg (const /* struct */ msghdr* message, int flags);
141
142 virtual ssize_t
143 sendto (const void* message, size_t length, int flags,
144 const /* struct */ sockaddr* dest_addr, socklen_t dest_len);
145
146 virtual int
147 setsockopt (int level, int option_name, const void* option_value,
148 socklen_t option_len);
149
150 virtual int
151 shutdown (int how);
152
153 virtual int
154 sockatmark (void);
155
156 // ----------------------------------------------------------------------
157 // Support functions.
158
159#pragma GCC diagnostic push
160#if defined(__clang__)
161#elif defined(__GNUC__)
162#pragma GCC diagnostic ignored "-Wredundant-tags"
163#endif
164
165 class net_stack*
166 net_stack (void);
167
168#pragma GCC diagnostic pop
169
171 impl (void) const;
172
177 // ----------------------------------------------------------------------
178 public:
183 // Intrusive node used to link this socket to the deferred
184 // deallocation list. Must be public.
185 utils::double_list_links deferred_links_;
186
191 // ----------------------------------------------------------------------
192 protected:
197 class net_stack* net_stack_;
198
202 };
203#pragma GCC diagnostic pop
204
205 // ========================================================================
206
207 class socket_impl : public io_impl
208 {
209 // ----------------------------------------------------------------------
210
215 friend class socket;
216
221 // ----------------------------------------------------------------------
227 public:
228 socket_impl (void);
229
234 // The rule of five.
235 socket_impl (const socket_impl&) = delete;
236 socket_impl (socket_impl&&) = delete;
238 operator= (const socket_impl&)
239 = delete;
241 operator= (socket_impl&&)
242 = delete;
243
248 virtual ~socket_impl () override;
249
254 // ----------------------------------------------------------------------
260 public:
261 virtual /* class */ socket*
262 do_accept (/* struct */ sockaddr* address, socklen_t* address_len)
263 = 0;
264
265 virtual int
266 do_bind (const /* struct */ sockaddr* address, socklen_t address_len)
267 = 0;
268
269 virtual int
270 do_connect (const /* struct */ sockaddr* address, socklen_t address_len)
271 = 0;
272
273 virtual int
274 do_getpeername (/* struct */ sockaddr* address, socklen_t* address_len)
275 = 0;
276
277 virtual int
278 do_getsockname (/* struct */ sockaddr* address, socklen_t* address_len)
279 = 0;
280
281 virtual int
282 do_getsockopt (int level, int option_name, void* option_value,
283 socklen_t* option_len)
284 = 0;
285
286 virtual int
287 do_listen (int backlog)
288 = 0;
289
290 virtual ssize_t
291 do_recv (void* buffer, size_t length, int flags)
292 = 0;
293
294 virtual ssize_t
295 do_recvfrom (void* buffer, size_t length, int flags,
296 /* struct */ sockaddr* address, socklen_t* address_len)
297 = 0;
298
299 virtual ssize_t
300 do_recvmsg (/* struct */ msghdr* message, int flags)
301 = 0;
302
303 virtual ssize_t
304 do_send (const void* buffer, size_t length, int flags)
305 = 0;
306
307 virtual ssize_t
308 do_sendmsg (const /* struct */ msghdr* message, int flags)
309 = 0;
310
311 virtual ssize_t
312 do_sendto (const void* message, size_t length, int flags,
313 const /* struct */ sockaddr* dest_addr, socklen_t dest_len)
314 = 0;
315
316 virtual int
317 do_setsockopt (int level, int option_name, const void* option_value,
318 socklen_t option_len)
319 = 0;
320
321 virtual int
322 do_shutdown (int how)
323 = 0;
324
325 virtual int
327 = 0;
328
332 };
333
334 // ========================================================================
335
336 template <typename T>
338 {
339 // ----------------------------------------------------------------------
340
341 public:
342 using value_type = T;
343
344 // ---------------------------------------------------------------------
345
351 public:
353
358 // The rule of five.
362 operator= (const socket_implementable&)
363 = delete;
365 operator= (socket_implementable&&)
366 = delete;
367
372 virtual ~socket_implementable ();
373
378 // ----------------------------------------------------------------------
384 public:
385 // Support functions.
386
388 impl (void) const;
389
394 // ----------------------------------------------------------------------
395 protected:
400 value_type impl_instance_;
401
405 };
406
407 // ========================================================================
408
409 template <typename T, typename L>
410 class socket_lockable : public socket
411 {
412 // ----------------------------------------------------------------------
413
414 public:
415 using value_type = T;
416 using lockable_type = L;
417
418 // ----------------------------------------------------------------------
419
425 public:
426 socket_lockable (class net_stack& ns, lockable_type& locker);
427
432 // The rule of five.
433 socket_lockable (const socket_lockable&) = delete;
434 socket_lockable (socket_lockable&&) = delete;
436 operator= (const socket_lockable&)
437 = delete;
439 operator= (socket_lockable&&)
440 = delete;
441
446 virtual ~socket_lockable ();
447
452 // ----------------------------------------------------------------------
458 public:
459 virtual int
460 close (void) override;
461
462 virtual class socket*
463 accept (/* struct */ sockaddr* address, socklen_t* address_len) override;
464
465 virtual int
466 bind (const /* struct */ sockaddr* address,
467 socklen_t address_len) override;
468
469 virtual int
470 connect (const /* struct */ sockaddr* address,
471 socklen_t address_len) override;
472
473 virtual int
474 getpeername (/* struct */ sockaddr* address,
475 socklen_t* address_len) override;
476
477 virtual int
478 getsockname (/* struct */ sockaddr* address,
479 socklen_t* address_len) override;
480
481 virtual int
482 getsockopt (int level, int option_name, void* option_value,
483 socklen_t* option_len) override;
484
485 virtual int
486 listen (int backlog) override;
487
488 virtual ssize_t
489 recv (void* buffer, size_t length, int flags) override;
490
491 virtual ssize_t
492 recvfrom (void* buffer, size_t length, int flags,
493 /* struct */ sockaddr* address,
494 socklen_t* address_len) override;
495
496 virtual ssize_t
497 recvmsg (/* struct */ msghdr* message, int flags) override;
498
499 virtual ssize_t
500 send (const void* buffer, size_t length, int flags) override;
501
502 virtual ssize_t
503 sendmsg (const /* struct */ msghdr* message, int flags) override;
504
505 virtual ssize_t
506 sendto (const void* message, size_t length, int flags,
507 const /* struct */ sockaddr* dest_addr,
508 socklen_t dest_len) override;
509
510 virtual int
511 setsockopt (int level, int option_name, const void* option_value,
512 socklen_t option_len) override;
513
514 virtual int
515 shutdown (int how) override;
516
517 virtual int
518 sockatmark (void) override;
519
520 // ----------------------------------------------------------------------
521 // Support functions.
522
524 impl (void) const;
525
530 // ----------------------------------------------------------------------
531 protected:
536 value_type impl_instance_;
537
538 lockable_type& locker_;
539
543 };
544
545 // ========================================================================
546 } /* namespace posix */
547} /* namespace os */
548
549// ===== Inline & template implementations ====================================
550
551namespace os
552{
553 namespace posix
554 {
555 // ========================================================================
556
557 inline net_stack*
559 {
560 return net_stack_;
561 }
562
563 inline socket_impl&
564 socket::impl (void) const
565 {
566 return static_cast<socket_impl&> (impl_);
567 }
568
569 // ========================================================================
570
571 template <typename T>
573 : socket{ impl_instance_, ns }
574 {
575#if defined(OS_TRACE_POSIX_IO_SOCKET)
576 trace::printf ("socket_implementable::%s()=@%p\n", __func__, this);
577#endif
578 }
579
580 template <typename T>
582 {
583#if defined(OS_TRACE_POSIX_IO_SOCKET)
584 trace::printf ("socket_implementable::%s() @%p\n", __func__, this);
585#endif
586 }
587
588 template <typename T>
591 {
592 return static_cast<value_type&> (impl_);
593 }
594
595 // ========================================================================
596
597 template <typename T, typename L>
599 lockable_type& locker)
600 : socket{ impl_instance_, ns }, //
601 locker_ (locker)
602 {
603#if defined(OS_TRACE_POSIX_IO_SOCKET)
604 trace::printf ("socket_lockable::%s()=@%p\n", __func__, this);
605#endif
606 }
607
608 template <typename T, typename L>
610 {
611#if defined(OS_TRACE_POSIX_IO_SOCKET)
612 trace::printf ("socket_lockable::%s() @%p\n", __func__, this);
613#endif
614 }
615
616 // ------------------------------------------------------------------------
617
618 template <typename T, typename L>
619 int
621 {
622 std::lock_guard<L> lock{ locker_ };
623
624 return socket::close ();
625 }
626
627 template <typename T, typename L>
628 /* class */ socket*
630 socklen_t* address_len)
631 {
632 std::lock_guard<L> lock{ locker_ };
633
634 return socket::accept (address, address_len);
635 }
636
637 template <typename T, typename L>
638 int
639 socket_lockable<T, L>::bind (const /* struct */ sockaddr* address,
640 socklen_t address_len)
641 {
642 std::lock_guard<L> lock{ locker_ };
643
644 return socket::bind (address, address_len);
645 }
646
647 template <typename T, typename L>
648 int
649 socket_lockable<T, L>::connect (const /* struct */ sockaddr* address,
650 socklen_t address_len)
651 {
652 std::lock_guard<L> lock{ locker_ };
653
654 return socket::connect (address, address_len);
655 }
656
657 template <typename T, typename L>
658 int
660 socklen_t* address_len)
661 {
662 std::lock_guard<L> lock{ locker_ };
663
664 return socket::getpeername (address, address_len);
665 }
666
667 template <typename T, typename L>
668 int
670 socklen_t* address_len)
671 {
672 std::lock_guard<L> lock{ locker_ };
673
674 return socket::getsockname (address, address_len);
675 }
676
677 template <typename T, typename L>
678 int
679 socket_lockable<T, L>::getsockopt (int level, int option_name,
680 void* option_value,
681 socklen_t* option_len)
682 {
683 std::lock_guard<L> lock{ locker_ };
684
685 return socket::getsockopt (level, option_name, option_value, option_len);
686 }
687
688 template <typename T, typename L>
689 int
691 {
692 std::lock_guard<L> lock{ locker_ };
693
694 return socket::listen (backlog);
695 }
696
697 template <typename T, typename L>
698 ssize_t
699 socket_lockable<T, L>::recv (void* buffer, size_t length, int flags)
700 {
701 std::lock_guard<L> lock{ locker_ };
702
703 return socket::recv (buffer, length, flags);
704 }
705
706 template <typename T, typename L>
707 ssize_t
708 socket_lockable<T, L>::recvfrom (void* buffer, size_t length, int flags,
709 /* struct */ sockaddr* address,
710 socklen_t* address_len)
711 {
712 std::lock_guard<L> lock{ locker_ };
713
714 return socket::recvfrom (buffer, length, flags, address, address_len);
715 }
716
717 template <typename T, typename L>
718 ssize_t
719 socket_lockable<T, L>::recvmsg (/* struct */ msghdr* message, int flags)
720 {
721 std::lock_guard<L> lock{ locker_ };
722
723 return socket::recvmsg (message, flags);
724 }
725
726 template <typename T, typename L>
727 ssize_t
728 socket_lockable<T, L>::send (const void* buffer, size_t length, int flags)
729 {
730 std::lock_guard<L> lock{ locker_ };
731
732 return socket::send (buffer, length, flags);
733 }
734
735 template <typename T, typename L>
736 ssize_t
737 socket_lockable<T, L>::sendmsg (const /* struct */ msghdr* message,
738 int flags)
739 {
740 std::lock_guard<L> lock{ locker_ };
741
742 return socket::sendmsg (message, flags);
743 }
744
745 template <typename T, typename L>
746 ssize_t
747 socket_lockable<T, L>::sendto (const void* message, size_t length,
748 int flags,
749 const /* struct */ sockaddr* dest_addr,
750 socklen_t dest_len)
751 {
752 std::lock_guard<L> lock{ locker_ };
753
754 return socket::sendto (message, length, flags, dest_addr, dest_len);
755 }
756
757 template <typename T, typename L>
758 int
759 socket_lockable<T, L>::setsockopt (int level, int option_name,
760 const void* option_value,
761 socklen_t option_len)
762 {
763 std::lock_guard<L> lock{ locker_ };
764
765 return socket::setsockopt (level, option_name, option_value, option_len);
766 }
767
768 template <typename T, typename L>
769 int
771 {
772 std::lock_guard<L> lock{ locker_ };
773
774 return socket::shutdown (how);
775 }
776
777 template <typename T, typename L>
778 int
780 {
781 std::lock_guard<L> lock{ locker_ };
782
783 return socket::sockatmark ();
784 }
785
786 template <typename T, typename L>
789 {
790 return static_cast<value_type&> (impl_);
791 }
792
793 // ========================================================================
794 } /* namespace posix */
795} /* namespace os */
796
797#pragma GCC diagnostic pop
798
799// ----------------------------------------------------------------------------
800
801#endif /* __cplusplus */
802
803// ----------------------------------------------------------------------------
804
805#endif /* CMSIS_PLUS_POSIX_IO_SOCKET_H_ */
Base I/O class.
Definition io.h:86
virtual int close(void)
Definition io.cpp:164
Network stack class.
Definition net-stack.h:81
virtual int do_bind(const sockaddr *address, socklen_t address_len)=0
virtual int do_getpeername(sockaddr *address, socklen_t *address_len)=0
virtual int do_getsockopt(int level, int option_name, void *option_value, socklen_t *option_len)=0
virtual socket * do_accept(sockaddr *address, socklen_t *address_len)=0
virtual int do_listen(int backlog)=0
virtual ~socket_impl() override
Definition socket.cpp:224
virtual int do_setsockopt(int level, int option_name, const void *option_value, socklen_t option_len)=0
virtual ssize_t do_recvfrom(void *buffer, size_t length, int flags, sockaddr *address, socklen_t *address_len)=0
virtual ssize_t do_sendmsg(const msghdr *message, int flags)=0
virtual ssize_t do_recv(void *buffer, size_t length, int flags)=0
virtual ssize_t do_send(const void *buffer, size_t length, int flags)=0
virtual ssize_t do_sendto(const void *message, size_t length, int flags, const sockaddr *dest_addr, socklen_t dest_len)=0
virtual int do_getsockname(sockaddr *address, socklen_t *address_len)=0
virtual ssize_t do_recvmsg(msghdr *message, int flags)=0
virtual int do_connect(const sockaddr *address, socklen_t address_len)=0
virtual int do_sockatmark(void)=0
virtual int do_shutdown(int how)=0
value_type & impl(void) const
socket_implementable(class net_stack &ns)
virtual int sockatmark(void) override
virtual ssize_t send(const void *buffer, size_t length, int flags) override
virtual ssize_t recv(void *buffer, size_t length, int flags) override
virtual ssize_t sendmsg(const msghdr *message, int flags) override
virtual int setsockopt(int level, int option_name, const void *option_value, socklen_t option_len) override
virtual int listen(int backlog) override
virtual int close(void) override
virtual int shutdown(int how) override
virtual ssize_t sendto(const void *message, size_t length, int flags, const sockaddr *dest_addr, socklen_t dest_len) override
value_type & impl(void) const
virtual int getsockname(sockaddr *address, socklen_t *address_len) override
virtual ssize_t recvmsg(msghdr *message, int flags) override
virtual class socket * accept(sockaddr *address, socklen_t *address_len) override
socket_lockable(class net_stack &ns, lockable_type &locker)
virtual int bind(const sockaddr *address, socklen_t address_len) override
virtual ssize_t recvfrom(void *buffer, size_t length, int flags, sockaddr *address, socklen_t *address_len) override
virtual int connect(const sockaddr *address, socklen_t address_len) override
virtual int getpeername(sockaddr *address, socklen_t *address_len) override
virtual int getsockopt(int level, int option_name, void *option_value, socklen_t *option_len) override
Network socket.
virtual int setsockopt(int level, int option_name, const void *option_value, socklen_t option_len)
Definition socket.cpp:188
virtual int sockatmark(void)
Definition socket.cpp:208
virtual int listen(int backlog)
Definition socket.cpp:123
virtual int getsockname(sockaddr *address, socklen_t *address_len)
Definition socket.cpp:102
virtual socket * accept(sockaddr *address, socklen_t *address_len)
Definition socket.cpp:58
virtual int bind(const sockaddr *address, socklen_t address_len)
Definition socket.cpp:73
virtual ssize_t recv(void *buffer, size_t length, int flags)
Definition socket.cpp:132
virtual ssize_t sendto(const void *message, size_t length, int flags, const sockaddr *dest_addr, socklen_t dest_len)
Definition socket.cpp:178
virtual ssize_t send(const void *buffer, size_t length, int flags)
Definition socket.cpp:160
virtual int getpeername(sockaddr *address, socklen_t *address_len)
Definition socket.cpp:92
virtual ssize_t sendmsg(const msghdr *message, int flags)
Definition socket.cpp:169
virtual int connect(const sockaddr *address, socklen_t address_len)
Definition socket.cpp:82
virtual ssize_t recvfrom(void *buffer, size_t length, int flags, sockaddr *address, socklen_t *address_len)
Definition socket.cpp:141
virtual int shutdown(int how)
Definition socket.cpp:199
virtual ~socket() override
Definition socket.cpp:46
virtual ssize_t recvmsg(msghdr *message, int flags)
Definition socket.cpp:151
virtual int getsockopt(int level, int option_name, void *option_value, socklen_t *option_len)
Definition socket.cpp:112
socket_impl & impl(void) const
class net_stack * net_stack(void)
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
int socket(int domain, int type, int protocol)
System namespace.
uint32_t socklen_t