Chops Net IP
Loading...
Searching...
No Matches
net_entity.hpp
Go to the documentation of this file.
1
16#ifndef NET_ENTITY_HPP_INCLUDED
17#define NET_ENTITY_HPP_INCLUDED
18
19
20#include <memory> // std::shared_ptr, std::weak_ptr
21#include <cstddef> // std::size_t
22#include <utility> // std::move, std::forward
23#include <variant>
24#include <type_traits> // std::is_invocable
25#include <system_error> // std::make_error, std::error_code
26#include <string_view>
27
28#include "nonstd/expected.hpp"
29
31
35
37
39
40namespace chops {
41namespace net {
42
43namespace detail {
44// std::visit utility taken directly from cppreference
45 template<class... Ts>
46 struct overloaded : Ts... { using Ts::operator()...; };
47}
48
83private:
84 using udp_wp = detail::udp_entity_io_weak_ptr;
85 using acc_wp = detail::tcp_acceptor_weak_ptr;
86 using conn_wp = detail::tcp_connector_weak_ptr;
87
88private:
89 std::variant<udp_wp, acc_wp, conn_wp> m_wptr;
90
91private:
92 friend class net_ip;
93
94public:
95
103 net_entity () = default;
104
105 net_entity(const net_entity&) = default;
106 net_entity(net_entity&&) = default;
107
108 net_entity& operator=(const net_entity&) = default;
109 net_entity& operator=(net_entity&&) = default;
110
116 template <typename ET>
117 explicit net_entity (const std::shared_ptr<ET>& p) noexcept : m_wptr(p) { }
118
126 bool is_valid() const noexcept {
127 return std::visit([] (const auto& wp) { return !wp.expired(); }, m_wptr);
128 }
129
137 auto is_started() const ->
138 nonstd::expected<bool, std::error_code> {
139 return std::visit(detail::overloaded {
140 [] (const udp_wp& wp) -> nonstd::expected<bool, std::error_code> {
141 return detail::wp_access<bool>(wp,
142 [] (detail::udp_entity_io_shared_ptr sp) { return sp->is_started(); } );
143 },
144 [] (const acc_wp& wp) -> nonstd::expected<bool, std::error_code> {
145 return detail::wp_access<bool>(wp,
146 [] (detail::tcp_acceptor_shared_ptr sp) { return sp->is_started(); } );
147 },
148 [] (const conn_wp& wp) -> nonstd::expected<bool, std::error_code> {
149 return detail::wp_access<bool>(wp,
150 [] (detail::tcp_connector_shared_ptr sp) { return sp->is_started(); } );
151 },
152 }, m_wptr);
153 }
154
175 template <typename F>
176 auto visit_socket(F&& func) const ->
177 nonstd::expected<void, std::error_code> {
178 return std::visit(detail::overloaded {
179 [&func] (const udp_wp& wp) -> nonstd::expected<void, std::error_code> {
180 if constexpr (std::is_invocable_v<F, asio::ip::udp::socket&>) {
181 return detail::wp_access_void(wp,
182 [&func] (detail::udp_entity_io_shared_ptr sp) { sp->visit_socket(func); return std::error_code(); } );
183 }
184 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
185 },
186 [&func] (const acc_wp& wp) -> nonstd::expected<void, std::error_code> {
187 if constexpr (std::is_invocable_v<F, asio::ip::tcp::acceptor&>) {
188 return detail::wp_access_void(wp,
189 [&func] (detail::tcp_acceptor_shared_ptr sp) { sp->visit_socket(func); return std::error_code(); } );
190 }
191 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
192 },
193 [&func] (const conn_wp& wp) -> nonstd::expected<void, std::error_code> {
194 if constexpr (std::is_invocable_v<F, asio::ip::tcp::socket&>) {
195 return detail::wp_access_void(wp,
196 [&func] (detail::tcp_connector_shared_ptr sp) { sp->visit_socket(func); return std::error_code(); } );
197 }
198 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
199 },
200 }, m_wptr);
201 }
202
225 template <typename F>
226 auto visit_io_output(F&& func) const ->
227 nonstd::expected<std::size_t, std::error_code> {
228 return std::visit(detail::overloaded {
229 [&func] (const udp_wp& wp)-> nonstd::expected<std::size_t, std::error_code> {
230 if constexpr (std::is_invocable_v<F, chops::net::udp_io_output>) {
231 return detail::wp_access<std::size_t>(wp,
232 [&func] (detail::udp_entity_io_shared_ptr sp) { return sp->visit_io_output(func); } );
233 }
234 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
235 },
236 [&func] (const acc_wp& wp)-> nonstd::expected<std::size_t, std::error_code> {
237 if constexpr (std::is_invocable_v<F, chops::net::tcp_io_output>) {
238 return detail::wp_access<std::size_t>(wp,
239 [&func] (detail::tcp_acceptor_shared_ptr sp) { return sp->visit_io_output(func); } );
240 }
241 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
242 },
243 [&func] (const conn_wp& wp)-> nonstd::expected<std::size_t, std::error_code> {
244 if constexpr (std::is_invocable_v<F, chops::net::tcp_io_output>) {
245 return detail::wp_access<std::size_t>(wp,
246 [&func] (detail::tcp_connector_shared_ptr sp) { return sp->visit_io_output(func); } );
247 }
248 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
249 },
250 }, m_wptr);
251 }
252
343 template <typename F1, typename F2>
344 auto start(F1&& io_state_chg_func, F2&& err_func) ->
345 nonstd::expected<void, std::error_code> {
346 return std::visit(detail::overloaded {
347 [&io_state_chg_func, &err_func] (const udp_wp& wp)->nonstd::expected<void, std::error_code> {
348 if constexpr (std::is_invocable_v<F1, udp_io_interface, std::size_t, bool> &&
349 std::is_invocable_v<F2, udp_io_interface, std::error_code>) {
350 return detail::wp_access_void(wp,
351 [&io_state_chg_func, &err_func] (detail::udp_entity_io_shared_ptr sp)
352 { return sp->start(io_state_chg_func, err_func); } );
353 }
354 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
355 },
356 [&io_state_chg_func, &err_func] (const acc_wp& wp)->nonstd::expected<void, std::error_code> {
357 if constexpr (std::is_invocable_v<F1, tcp_io_interface, std::size_t, bool> &&
358 std::is_invocable_v<F2, tcp_io_interface, std::error_code>) {
359 return detail::wp_access_void(wp,
360 [&io_state_chg_func, &err_func] (detail::tcp_acceptor_shared_ptr sp)
361 { return sp->start(io_state_chg_func, err_func); } );
362 }
363 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
364 },
365 [&io_state_chg_func, &err_func] (const conn_wp& wp)->nonstd::expected<void, std::error_code> {
366 if constexpr (std::is_invocable_v<F1, tcp_io_interface, std::size_t, bool> &&
367 std::is_invocable_v<F2, tcp_io_interface, std::error_code>) {
368 return detail::wp_access_void(wp,
369 [&io_state_chg_func, &err_func] (detail::tcp_connector_shared_ptr sp)
370 { return sp->start(io_state_chg_func, err_func); } );
371 }
372 return nonstd::make_unexpected(std::make_error_code(net_ip_errc::functor_variant_mismatch));
373 },
374 }, m_wptr);
375 }
376
390 auto stop() ->
391 nonstd::expected<void, std::error_code> {
392 return std::visit(detail::overloaded {
393 [] (const udp_wp& wp)->nonstd::expected<void, std::error_code> {
394 return detail::wp_access_void(wp,
395 [] (detail::udp_entity_io_shared_ptr sp) { return sp->stop(); } );
396 },
397 [] (const acc_wp& wp)->nonstd::expected<void, std::error_code> {
398 return detail::wp_access_void(wp,
399 [] (detail::tcp_acceptor_shared_ptr sp) { return sp->stop(); } );
400 },
401 [] (const conn_wp& wp)->nonstd::expected<void, std::error_code> {
402 return detail::wp_access_void(wp,
403 [] (detail::tcp_connector_shared_ptr sp) { return sp->stop(); } );
404 },
405 }, m_wptr);
406 }
407
416 std::string_view stream_out() const noexcept {
417 return std::visit(detail::overloaded {
418 [] (const udp_wp& wp) { return "[UDP network entity]"; },
419 [] (const acc_wp& wp) { return "[TCP acceptor network entity]"; },
420 [] (const conn_wp& wp) { return "[TCP connector network entity]"; },
421 }, m_wptr);
422 }
423
424 friend bool operator==(const net_entity&, const net_entity&) noexcept;
425 friend bool operator<(const net_entity&, const net_entity&) noexcept;
426
427};
428
444inline bool operator==(const net_entity& lhs, const net_entity& rhs) noexcept {
445 return std::visit(detail::overloaded {
446 [] (const net_entity::udp_wp& lwp, const net_entity::udp_wp& rwp) {
447 return lwp.lock() == rwp.lock();
448 },
449 [] (const net_entity::udp_wp& lwp, const net_entity::acc_wp& rwp) {
450 return false;
451 },
452 [] (const net_entity::udp_wp& lwp, const net_entity::conn_wp& rwp) {
453 return false;
454 },
455 [] (const net_entity::acc_wp& lwp, const net_entity::acc_wp& rwp) {
456 return lwp.lock() == rwp.lock();
457 },
458 [] (const net_entity::acc_wp& lwp, const net_entity::udp_wp& rwp) {
459 return false;
460 },
461 [] (const net_entity::acc_wp& lwp, const net_entity::conn_wp& rwp) {
462 return false;
463 },
464 [] (const net_entity::conn_wp& lwp, const net_entity::conn_wp& rwp) {
465 return lwp.lock() == rwp.lock();
466 },
467 [] (const net_entity::conn_wp& lwp, const net_entity::udp_wp& rwp) {
468 return false;
469 },
470 [] (const net_entity::conn_wp& lwp, const net_entity::acc_wp& rwp) {
471 return false;
472 },
473 }, lhs.m_wptr, rhs.m_wptr);
474}
475
489inline bool operator<(const net_entity& lhs, const net_entity& rhs) noexcept {
490 return std::visit(detail::overloaded {
491 [] (const net_entity::udp_wp& lwp, const net_entity::udp_wp& rwp) {
492 return lwp.lock() < rwp.lock();
493 },
494 [] (const net_entity::udp_wp& lwp, const net_entity::acc_wp& rwp) {
495 return true;
496 },
497 [] (const net_entity::udp_wp& lwp, const net_entity::conn_wp& rwp) {
498 return true;
499 },
500 [] (const net_entity::acc_wp& lwp, const net_entity::acc_wp& rwp) {
501 return lwp.lock() < rwp.lock();
502 },
503 [] (const net_entity::acc_wp& lwp, const net_entity::udp_wp& rwp) {
504 return false;
505 },
506 [] (const net_entity::acc_wp& lwp, const net_entity::conn_wp& rwp) {
507 return true;
508 },
509 [] (const net_entity::conn_wp& lwp, const net_entity::conn_wp& rwp) {
510 return lwp.lock() < rwp.lock();
511 },
512 [] (const net_entity::conn_wp& lwp, const net_entity::udp_wp& rwp) {
513 return false;
514 },
515 [] (const net_entity::conn_wp& lwp, const net_entity::acc_wp& rwp) {
516 return false;
517 },
518 }, lhs.m_wptr, rhs.m_wptr);
519 }
520
527template <typename IOT>
528void empty_error_func(basic_io_interface<IOT>, std::error_code) { }
529
536inline void tcp_empty_error_func(tcp_io_interface, std::error_code) { }
537
544inline void udp_empty_error_func(udp_io_interface, std::error_code) { }
545
546
547} // end net namespace
548} // end chops namespace
549
550#endif
551
The basic_io_interface class template provides access to an underlying network IO handler (TCP or UDP...
Definition basic_io_interface.hpp:100
The net_entity class provides the primary application interface into the TCP acceptor,...
Definition net_entity.hpp:82
friend bool operator==(const net_entity &, const net_entity &) noexcept
Compare two net_entity objects for equality.
Definition net_entity.hpp:444
auto stop() -> nonstd::expected< void, std::error_code >
Stop network processing on the associated network entity.
Definition net_entity.hpp:390
auto is_started() const -> nonstd::expected< bool, std::error_code >
Query whether the associated net entity is in a started or stopped state.
Definition net_entity.hpp:137
bool is_valid() const noexcept
Query whether an internal net entity is associated with this object.
Definition net_entity.hpp:126
void empty_error_func(basic_io_interface< IOT >, std::error_code)
A "do nothing" error function template that can be used in the net_entity start method.
Definition net_entity.hpp:528
std::string_view stream_out() const noexcept
Provide a display string of the internal type, whether for logging or debugging purposes.
Definition net_entity.hpp:416
friend bool operator<(const net_entity &, const net_entity &) noexcept
Compare two net_entity objects for ordering purposes.
Definition net_entity.hpp:489
void tcp_empty_error_func(tcp_io_interface, std::error_code)
A "do nothing" error function used in the net_entity start method, for TCP basic_io_interface objects...
Definition net_entity.hpp:536
auto start(F1 &&io_state_chg_func, F2 &&err_func) -> nonstd::expected< void, std::error_code >
Start network processing on the associated net entity with the application providing IO state change ...
Definition net_entity.hpp:344
auto visit_io_output(F &&func) const -> nonstd::expected< std::size_t, std::error_code >
Call an application supplied function object with all basic_io_output objects that are active on asso...
Definition net_entity.hpp:226
auto visit_socket(F &&func) const -> nonstd::expected< void, std::error_code >
Call an application supplied function object with a reference to the associated net entity asio socke...
Definition net_entity.hpp:176
net_entity()=default
Default construct a net_entity object.
net_entity(const std::shared_ptr< ET > &p) noexcept
Construct with a shared weak pointer to an internal net entity, this is an internal constructor only ...
Definition net_entity.hpp:117
void udp_empty_error_func(udp_io_interface, std::error_code)
A "do nothing" error function used in the net_entity start method, for UDP basic_io_interface objects...
Definition net_entity.hpp:544
Primary class for the Chops Net IP library and the initial API point for providing TCP acceptor,...
Definition net_ip.hpp:122
IO type declarations, relating to the basic_io_interface and basic_io_output class templates.
bool operator<(const net_entity &lhs, const net_entity &rhs) noexcept
Compare two net_entity objects for ordering purposes.
Definition net_entity.hpp:489
bool operator==(const net_entity &lhs, const net_entity &rhs) noexcept
Compare two net_entity objects for equality.
Definition net_entity.hpp:444
Error codes, exception class, and error category within Chops net_ip library.
Definition net_entity.hpp:46
TCP acceptor, for internal use.
TCP connector class, for internal use.
Internal class that combines a UDP entity and UDP io handler.
Common code for accessing std::weak_ptr referenced objects, used in basic_io_interface and net_entity...