Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
ConnectionlessSocket.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_IO_Network_ConnectionlessSocket_h_
5#define _Stroika_Foundation_IO_Network_ConnectionlessSocket_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include "Socket.h"
10
12
13 /**
14 * \brief ConnectionlessSocket is typically a UDP socket you use for packet oriented communications (ie not tcp/streams)
15 *
16 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter">C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter</a>
17 */
18 namespace ConnectionlessSocket {
19 using namespace Socket;
20
21 class _IRep;
22
23 /**
24 * \par Example Usage
25 * \code
26 * ConnectionlessSocket::Ptr cs = ConnectionlessSocket::New (Socket::INET, Socket::DGRAM);
27 * \endcode
28 *
29 * \note Since ConnectionlessSocket::Ptr is a smart pointer, the constness of the methods depends on whether they modify the smart pointer itself, not
30 * the underlying thread object.
31 *
32 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter">C++-Standard-Thread-Safety-For-Envelope-But-Ambiguous-Thread-Safety-For-Letter</a>
33 */
34 class Ptr : public Socket::Ptr {
35 private:
36 using inherited = Socket::Ptr;
37
38 public:
39 /**
40 */
41 Ptr () = delete;
42 Ptr (nullptr_t);
43 Ptr (const Ptr& src) = default;
44 Ptr (Ptr&& src) = default;
45 Ptr (shared_ptr<_IRep>&& rep);
46 Ptr (const shared_ptr<_IRep>& rep);
47
48 public:
49 /**
50 */
51 nonvirtual Ptr& operator= (const Ptr& rhs) = default;
52 nonvirtual Ptr& operator= (Ptr&& rhs) = default;
53
54 public:
55 /**
56 */
57 nonvirtual void JoinMulticastGroup (const InternetAddress& iaddr, const InternetAddress& onInterface = V4::kAddrAny) const;
58
59 public:
60 /**
61 */
62 nonvirtual void LeaveMulticastGroup (const InternetAddress& iaddr, const InternetAddress& onInterface = V4::kAddrAny) const;
63
64 public:
65 /**
66 * This specifies the number of networks to traverse in sending the multicast message.
67 * It defaults to 1.
68 */
69 nonvirtual uint8_t GetMulticastTTL () const;
70
71 public:
72 /**
73 * This specifies the number of networks to traverse in sending the multicast message.
74 * It defaults to 1.
75 */
76 nonvirtual void SetMulticastTTL (uint8_t ttl) const;
77
78 public:
79 /**
80 * This determines whether the data sent will be looped back to sender host or not.
81 */
82 nonvirtual bool GetMulticastLoopMode () const;
83
84 public:
85 /**
86 * This determines whether the data sent will be looped back to sender host or not.
87 */
88 nonvirtual void SetMulticastLoopMode (bool loopMode) const;
89
90 public:
91 /**
92 * Send the argument data to the argument socket address.
93 *
94 * @see https://linux.die.net/man/2/sendto
95 */
96 nonvirtual void SendTo (span<const byte> data, const SocketAddress& sockAddr) const;
97
98 public:
99 /**
100 * Read the next message (typically a full packet) from the socket.
101 *
102 * @see https://linux.die.net/man/2/recvfrom
103 *
104 * if fromAddress != nullptr (legal to pass nullptr) - then it it is filled in with the source address the packet came from.
105 *
106 * returns a subspan (initial segment) of into, of length number of bytes read in packet.
107 *
108 * @todo DOCUMENT WHAT HAPPENS IF PACKET DOESNT FIT IN BUF!????
109 *
110 * \note ***Cancelation Point***
111 */
112 nonvirtual span<byte> ReceiveFrom (span<byte> into, int flag, SocketAddress* fromAddress, Time::DurationSeconds timeout = Time::kInfinity) const;
113
114 protected:
115 /**
116 */
117 nonvirtual shared_ptr<_IRep> _GetSharedRep () const;
118
119 protected:
120 /**
121 * \pre fRep_ != nullptr
122 */
123 nonvirtual _IRep& _ref () const;
124
125 protected:
126 /**
127 * \pre fRep_ != nullptr
128 */
129 nonvirtual const _IRep& _cref () const;
130
131 public:
132 [[deprecated ("Since Stroika 3.0d15 use span{} overload")]] size_t ReceiveFrom (byte* intoStart, byte* intoEnd, int flag,
133 SocketAddress* fromAddress,
134 Time::DurationSeconds timeout = Time::kInfinity) const
135 {
136 return ReceiveFrom (span{intoStart, intoEnd}, flag, fromAddress, timeout).size ();
137 }
138 [[deprecated ("Since Stroika v3.0d15 use span overload")]] void SendTo (const byte* start, const byte* end, const SocketAddress& sockAddr) const
139 {
140 SendTo (span<const byte>{start, end}, sockAddr);
141 }
142 };
143
144 /**
145 */
146 class _IRep : public Socket::_IRep {
147 public:
148 virtual ~_IRep () = default;
149
150 virtual void SendTo (const byte* start, const byte* end, const SocketAddress& sockAddr) = 0;
151 virtual size_t ReceiveFrom (byte* intoStart, byte* intoEnd, int flag, SocketAddress* fromAddress, Time::DurationSeconds timeout) = 0;
152 virtual void JoinMulticastGroup (const InternetAddress& iaddr, const InternetAddress& onInterface) = 0;
153 virtual void LeaveMulticastGroup (const InternetAddress& iaddr, const InternetAddress& onInterface) = 0;
154 virtual uint8_t GetMulticastTTL () const = 0;
155 virtual void SetMulticastTTL (uint8_t ttl) = 0;
156 virtual bool GetMulticastLoopMode () const = 0;
157 virtual void SetMulticastLoopMode (bool loopMode) = 0;
158 };
159
160 /**
161 * \par Example Usage
162 * \code
163 * ConnectionlessSocket::Ptr s = ConnectionlessSocket::New (SocketAddress::INET, Socket::DGRAM);
164 * \endcode
165 *
166 * \pre socketKind != SOCK_STREAM
167 *
168 * \note unless you call @Detach() - socket is CLOSED in DTOR of rep, so when final reference goes away
169 *
170 * \note ConnectionlessSocket is not copyable, but it can be copied into a ConnectionlessSocket::Ptr or
171 * Socket::Ptr. This is critical to save them in a container, for example.
172 */
173 ConnectionlessSocket::Ptr New (SocketAddress::FamilyType family, Type socketKind, const optional<IPPROTO>& protocol = nullopt);
174
175 /**
176 * This function associates a Platform native socket handle with a Stroika wrapper object.
177 *
178 * Once a PlatformNativeHandle is attached to Socket object, it will be automatically closed
179 * when the last reference to the socket disappears (or when someone calls close).
180 *
181 * To prevent that behavior, you can Detach the PlatformNativeHandle before destroying
182 * the associated Socket object.
183 */
185
186 };
187
188}
189
191
192 // Specialize to override GetSDKPollable
193 template <typename T>
194 struct WaitForIOReady_Traits;
195 template <>
196 struct WaitForIOReady_Traits<IO::Network::ConnectionlessSocket::Ptr> {
197 using HighLevelType = IO::Network::ConnectionlessSocket::Ptr;
198 static inline auto GetSDKPollable (const HighLevelType& t)
199 {
200 return t.GetNativeSocket ();
201 }
202 };
203
204}
205
206/*
207 ********************************************************************************
208 ***************************** Implementation Details ***************************
209 ********************************************************************************
210 */
211#include "ConnectionlessSocket.inl"
212
213#endif /*_Stroika_Foundation_IO_Network_ConnectionlessSocket_h_*/
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Definition Realtime.h:57
nonvirtual void SendTo(span< const byte > data, const SocketAddress &sockAddr) const
nonvirtual span< byte > ReceiveFrom(span< byte > into, int flag, SocketAddress *fromAddress, Time::DurationSeconds timeout=Time::kInfinity) const
a smart pointer wrapper (like shared_ptr <_IRep>).
Definition Socket.h:178
nonvirtual PlatformNativeHandle GetNativeSocket() const
Definition Socket.inl:52
FamilyType
Socket address family - also sometimes referred to as domain (argument to ::socket calls it domain)
ConnectionlessSocket::Ptr New(SocketAddress::FamilyType family, Type socketKind, const optional< IPPROTO > &protocol=nullopt)