22#include <boost/move/make_unique.hpp>
23#include <boost/array.hpp>
36 if (!start_ops<Op::S_SND>(std::move(ev_wait_func)))
46 &&
"Protocol_negotiator not properly marking the once-only sending-out of protocol version?");
58 const auto fake_meta_length_raw
60 const Blob_const payload_blob{&fake_meta_length_raw,
sizeof(fake_meta_length_raw)};
62 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Want to send protocol-negotiation info. "
63 "About to send payload 1 of 1; "
64 "contains low-level blob of size [" << payload_blob.size() <<
"] "
65 "located @ [" << payload_blob.data() <<
"].");
81 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Wanted to send protocol-negotiation info; "
82 "but we've marked it as already-sent, even though we are in start_*_ops() in PEER state. "
83 "Probably we come from a .release()d Native_socket_stream which has already done it; cool.");
89 snd_log_stats(
"start_send_native_handle_ops(): while sync-processing: proto-neg-send => snd-pipe hosed");
110 using flow::util::buffers_dump_string;
111 using boost::chrono::round;
112 using boost::chrono::milliseconds;
114 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(
bool,
send_native_handle, hndl_or_null, meta_blob, _1);
119 if ((!op_started<Op::S_SND>(
"send_native_handle()")) || (!
state_peer(
"send_native_handle()")))
127 const size_t meta_size = meta_blob.size();
128 assert(((!hndl_or_null.
null()) || (meta_size != 0))
129 &&
"Native_socket_stream::send_blob() blob must have length 1+; "
130 "Native_socket_stream::send_native_handle() must have same or non-null hndl_or_null or both.");
132 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Will send handle [" << hndl_or_null <<
"] with "
133 "meta-blob of size [" << meta_size <<
"].");
137 FLOW_LOG_DATA(
"Socket stream [" << *
this <<
"]: Meta-blob contents are "
138 "[\n" << buffers_dump_string(meta_blob,
" ") <<
"].");
158 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: Send: User argument length [" << meta_size <<
"] "
162 else if (was_hosed_already)
171 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: An error was detected earlier and saved for any subsequent "
172 "send attempts like this. Will not proceed with send. More info in WARNING below.");
197 len_t meta_length_raw;
204 meta_length_raw =
static_cast<len_t
>(meta_size);
207 const Blob_const meta_length_blob{&meta_length_raw,
sizeof(meta_length_raw)};
211 const auto logger_ptr = get_logger();
212 if (logger_ptr && logger_ptr->should_log(flow::log::Sev::S_TRACE, get_log_component()))
214 FLOW_LOG_TRACE_WITHOUT_CHECKING
215 (
"Socket stream [" << *
this <<
"]: Wanted to send handle [" << hndl_or_null <<
"] with "
216 "meta-blob of size [" << meta_size <<
"]. About to send payload 1 (includes handle above and "
217 "low-level sub-blob of size [" <<
sizeof(len_t) <<
"] located @ [" << &meta_length_raw <<
"]).");
220 FLOW_LOG_TRACE_WITHOUT_CHECKING
221 (
"Socket stream [" << *
this <<
"]: ...plus: "
222 "About to send payload 2 (low-level sub-blob of size [" << meta_size <<
"] "
223 "located @ [" << meta_blob.data() <<
"]).");
252 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Wanted to send user message but detected error "
254 "Error code details follow: [" << *err_code <<
"] [" << err_code->message() <<
"]. "
255 "Saved error code to return in next user send attempt if any, after this attempt also "
256 "returns that error code synchronously first.");
266 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Send request from user; hence rescheduled "
267 "auto-ping to occur in "
269 "again upon any other outgoing traffic that might be requested before then). As a result "
270 "[" << n_canceled <<
"] previously scheduled auto-pings have been canceled; 1 is most likely; "
271 "0 means an auto-ping is *just* about to fire (we lost the race -- which is fine).");
282 assert((n_canceled == 0) &&
"We only invoke one timer async_wait() at a time.");
295 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: Wanted to send handle [" << hndl_or_null <<
"] with "
296 "meta-blob of size [" << meta_size <<
"], but an error (not necessarily new error) "
297 "encountered on pipe or in user API args. Error code details follow: "
298 "[" << *err_code <<
"] [" << err_code->message() <<
"]; "
299 "pipe hosed (sys/protocol error)? = "
302 "sending disabled by user? = "
309 snd_log_stats(
"send_native_handle(): while sync-processing snd-pipe hosed");
321 flow::async::Task_asio_err&& on_done_func)
323 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(
bool,
async_end_sending, _1, std::move(on_done_func));
331 flow::async::Task_asio_err&& on_done_func_or_empty)
334 using flow::async::Task_asio_err;
336 assert(
bool(sync_err_code_ptr_or_null) == (!on_done_func_or_empty.empty()));
340 if ((!op_started<Op::S_SND>(
"async_end_sending()")) || (!
state_peer(
"async_end_sending()")))
383 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: User wants to end sending, but we're in sends-finished "
384 "state already. Ignoring.");
389 bool became_hosed =
false;
403 const Blob_const blob_with_0{&ZERO_SIZE_RAW,
sizeof(ZERO_SIZE_RAW)};
415 if (qd && sync_err_code_ptr_or_null)
435 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: User wanted to end sending, but an error (not necessarily "
436 "new error) encountered on pipe synchronously when trying to send graceful-close. "
437 "Nevertheless locally sends-finished state is now active. Will report completion via "
438 "sync-args (if any). Error code details follow: "
444 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: User wanted to end sending. Success so far but out-queue "
445 "has payloads -- at least the graceful-close payload -- still pending while waiting for "
446 "writability. Locally sends-finished state is now active, and the other side will be informed "
447 "of this barring subsequent system errors. "
448 "We cannot report completion via sync-args (if any).");
452 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: User wanted to end sending. Immediate success: out-queue "
453 "flushed permanently. "
454 "Locally sends-finished state is now active, and the other side will be informed of this. "
455 "Locally will report completion via sync-args (if any).");
458 if (sync_err_code_ptr_or_null)
468 snd_log_stats(
"async_end_sending_impl(): while sync-processing snd-pipe hosed");
479 using boost::chrono::round;
480 using boost::chrono::milliseconds;
482 if ((!op_started<Op::S_SND>(
"auto_ping()")) || (!
state_peer(
"auto_ping()")))
488 assert(period.count() > 0);
492 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: User wants to start auto-pings, but we're in "
493 "sends-finished state already. Ignoring.");
507 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: User wants to start auto-pings, but this "
508 "has already been engaged earlier. Ignoring.");
514 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: User wants to start auto-pings so that there are "
515 "outgoing messages at least as frequently as every "
517 "first subsequent auto-ping; it may be rescheduled if more user traffic occurs before then.");
523 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: User wanted to start auto-pings, but an error was "
524 "previously encountered on pipe; so will not auto-ping. "
550 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: Wanted to send initial auto-ping but detected error "
554 "Saved error code to return in next user send attempt if any; otherwise ignoring; "
555 "will not schedule periodic auto-pings.");
559 snd_log_stats(
"auto_ping(): while sync-processing: auto-ping-send => snd-pipe hosed");
578 boost::make_shared<Task>
609 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: Auto-ping timer fired, but an error was "
610 "previously encountered in 2-way pipe; so will neither auto-ping nor schedule next auto-ping. "
620 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: "
621 "Auto-ping timer fired; but graceful-close API earlier instructed us to no-op. No-op.");
627 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: "
628 "Auto-ping timer fired; sending/queueing auto-ping; scheduling for next time; it may be "
629 "rescheduled if more user traffic occurs before then.");
648 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: Wanted to send non-initial auto-ping but detected error "
652 "Saved error code to return in next user send attempt if any; otherwise ignoring; "
653 "will not continue scheduling periodic auto-pings.");
657 snd_log_stats(
"snd_on_ev_auto_ping_now_timer_fired(): while attempting to send auto-ping snd-pipe hosed");
664 boost::make_shared<Task>
672 bool* dropped_or_null)
674 using flow::util::Blob;
683 *dropped_or_null =
false;
686 size_t n_sent_or_zero;
689 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Want to send low-level payload(s): "
690 "handle [" << hndl_or_null <<
"]; "
691 "payload 1 sized [" << blob1.size() <<
"] @ [" << blob1.data() <<
"]; "
692 "payload 2 sized [" << blob2_or_none.size() <<
"] @ "
693 "[" << ((blob2_or_none.size() != 0) ? blob2_or_none.data() :
nullptr) <<
"]. "
694 "No write is pending so proceeding immediately. "
695 "Will drop if all of it would-block? = [" << avoid_qing <<
"].");
700 assert(n_sent_or_zero == 0);
705 if (n_sent_or_zero == (blob1.size() + blob2_or_none.size()))
734 assert((n_sent_or_zero == 0)
735 &&
"In message-boundary-respecting mode nevertheless OS-write indicated a partially successful "
736 "write; this is thought to be impossible. Bug?");
741 sent_none = (n_sent_or_zero == 0);
746 assert(hndl_or_null.
null()
747 &&
"Internal bug? Do not ask to drop a payload with a native handle inside under any circumstances.");
753 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: Want to send low-level payload(s): "
754 "handle [" << hndl_or_null <<
"]; "
755 "payload 1 sized [" << blob1.size() <<
"] @ [" << blob1.data() <<
"]; "
756 "payload 2 sized [" << blob2_or_none.size() <<
"] @ "
757 "[" << ((blob2_or_none.size() != 0) ? blob2_or_none.data() :
nullptr) <<
"]; "
758 "result was would-block for all of its bytes (either because blocked-queue was non-empty "
759 "already, or it was empty, but all of payload's bytes would-block at this time). "
760 "Therefore dropping payload (done for auto-pings at least). Out-queue size remains "
761 "[" << q_size <<
"].");
765 *dropped_or_null =
true;
779 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: Want to send low-level payload(s): "
780 "handle [" << hndl_or_null <<
"]; "
781 "payload 1 sized [" << blob1.size() <<
"] @ [" << blob1.data() <<
"]; "
782 "payload 2 sized [" << blob2_or_none.size() <<
"] @ "
783 "[" << ((blob2_or_none.size() != 0) ? blob2_or_none.data() :
nullptr) <<
"]; "
784 "result was would-block for all but [" << n_sent_or_zero <<
"] of its bytes (blocked-queue "
785 "was empty, so nb-send was attempted, and some -- but not all -- of payload's bytes "
786 "would-block at this time). We cannot \"get back\" the sent bytes and thus are forced "
787 "to queue the remaining ones (would have dropped payload if all the bytes would-block).");
794 auto new_low_lvl_payload = boost::movelib::make_unique<Snd_low_lvl_payload>();
795 if ((!hndl_or_null.
null()) && sent_none)
805 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: Want to send low-level payload(s) with handle "
806 "[" << hndl_or_null <<
"]; must queue it (would-block); but duplicating the handle for that "
807 "purpose failed. Outgoing-direction pipe is hosed. Details follow.");
808 FLOW_ERROR_SYS_ERROR_LOG_WARNING();
824 auto& tgt_blob = new_low_lvl_payload->m_blob = Blob{get_logger(), blob1.size() + blob2_or_none.size()};
825 tgt_blob.emplace_copy
826 (tgt_blob.emplace_copy(tgt_blob.begin(), blob1),
837 const auto n_unsent =
static_cast<size_t>(blob1.size() + blob2_or_none.size() - n_sent_or_zero);
838 auto& tgt_blob = new_low_lvl_payload->m_blob = Blob{get_logger(), n_unsent};
839 if (n_sent_or_zero < blob1.size())
841 tgt_blob.emplace_copy
842 (tgt_blob.emplace_copy(tgt_blob.begin(), blob1 + n_sent_or_zero),
849 tgt_blob.emplace_copy(tgt_blob.begin(), blob2_or_none + (blob2_or_none.size() - n_unsent));
853 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Want to send pending-from-would-block low-level payload: "
854 "handle [" << new_low_lvl_payload->m_hndl_or_null.get() <<
"] with "
855 "new blob of size [" << new_low_lvl_payload->m_blob.size() <<
"] "
856 "located @ [" << new_low_lvl_payload->m_blob.const_buffer().data() <<
"]; "
894 using flow::util::Lock_guard;
903 size_t n_sent_or_zero = 0;
911 if (hndl_or_null.
null())
924 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Setting boost.asio peer socket non-blocking mode.");
936 FLOW_LOG_TRACE(
"Writing low-level blob directly via boost.asio (blob details logged above hopefully).");
944 if (blob2_or_none.size() == 0)
950 array<Blob_const, 2> buf_seq = { blob1, blob2_or_none };
964 if (blob2_or_none.size() == 0)
966 n_sent_or_zero = nb_write_some_with_native_handle<Native_socket_stream_cfg::Protocol>
967 (get_logger(),
m_peer_socket.get(), hndl_or_null, blob1, err_code);
971 array<Blob_const, 2> buf_seq = { blob1, blob2_or_none };
972 n_sent_or_zero = nb_write_some_with_native_handle<Native_socket_stream_cfg::Protocol>
973 (get_logger(),
m_peer_socket.get(), hndl_or_null, buf_seq, err_code);
981 assert(((!*err_code) && (n_sent_or_zero != 0))
982 || (*err_code && (n_sent_or_zero == 0)));
983 if (*err_code == boost::asio::error::would_block)
990 if (hndl_or_null.
null())
998 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: Tried to write payload "
999 "(sized [" << blob1.size() <<
"] + [" << blob2_or_none.size() <<
"] bytes, sans "
1000 "native handle) via plain boost.asio API; but an unrecoverable error "
1001 "[" << *err_code <<
"] [" << err_code->message() <<
"] occurred. Nothing sent.");
1010 assert((!
m_peer_socket_hosed) &&
"m_peer_socket_hosed must start as null and only become non-null once. Bug?");
1012 assert((!
m_peer_socket) &&
"Shocking unique_ptr misbehavior!");
1025 || (n_sent_or_zero == 0));
1029 FLOW_LOG_TRACE(
"Sent nothing due to error [" << *err_code <<
"] [" << err_code->message() <<
"].");
1033 FLOW_LOG_TRACE(
"Send: no error. Was able to send [" << n_sent_or_zero <<
"] of "
1034 "[" << (blob1.size() + blob2_or_none.size()) <<
"] bytes.");
1035 if (!hndl_or_null.
null())
1037 FLOW_LOG_TRACE(
"Able to send the native handle? = [" << (n_sent_or_zero != 0) <<
"].");
1041 return n_sent_or_zero;
1047 using flow::util::Lock_guard;
1068 boost::make_shared<Task>
1086 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: User-performed wait-for-writable finished (writable or error, "
1087 "we do not know which yet). We endeavour to send->pop->send->... as much of the queue as we "
1088 "can until would-block or total success.");
1090 assert((!
m_snd_pending_payloads_q.empty()) &&
"Send-queue should not be touched while async-write of head is going.");
1099 &&
"*end_sending() should have reported synchronously, given already-hosed state. Bug?");
1101 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: User-performed wait-for-writable finished; but out-pipe "
1102 "was hosed meanwhile (previous logging should have explained). Nothing to do.");
1108 bool would_block =
false;
1112 const auto hndl_or_null = low_lvl_payload.m_hndl_or_null.get();
1113 auto& low_lvl_blob = low_lvl_payload.m_blob;
1114 auto low_lvl_blob_view = low_lvl_blob.const_buffer();
1116 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: "
1118 "want to send handle [" << hndl_or_null <<
"] with "
1119 "low-level blob of size [" << low_lvl_blob_view.size() <<
"] "
1120 "located @ [" << low_lvl_blob_view.data() <<
"].");
1122 const auto n_sent_or_zero
1130 if (n_sent_or_zero == low_lvl_blob_view.size())
1141 assert((n_sent_or_zero == 0)
1142 &&
"In message-boundary-respecting mode nevertheless OS-write indicated a partially successful "
1143 "write; this is thought to be impossible. Bug?");
1151 if (n_sent_or_zero != 0)
1154 low_lvl_payload.m_hndl_or_null.reset();
1157 low_lvl_payload.m_blob.start_past_prefix_inc(n_sent_or_zero);
1170 FLOW_LOG_TRACE(
"Out-queue has not been emptied. Must keep async-send chain going.");
1187 bool invoke_on_done =
false;
1191 FLOW_LOG_WARNING(
"Socket stream [" << *
this <<
"]: User-performed wait-for-writable reported completion; "
1192 "wanted to nb-send any queued data and possibly initiated another wait-for-writable; "
1193 "got error during an nb-send or when initiating wait; TRACE details above. "
1194 "Error code details follow: "
1196 "Saved error code to return in next user send attempt if any. "
1197 "Will run graceful-sends-close completion handler? = [" << invoke_on_done <<
"].");
1203 FLOW_LOG_TRACE(
"Out-queue has been emptied.");
1208 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: "
1209 "We sent graceful-close and any preceding user messages with success. Will now inform user via "
1210 "graceful-sends-close completion handler.");
1211 invoke_on_done =
true;
1220 snd_log_stats(
"snd_on_ev_peer_socket_writable_or_error(): while processing ev-ready snd-pipe hosed");
1225 FLOW_LOG_TRACE(
"Socket stream [" << *
this <<
"]: Executing end-sending completion handler now.");
1230 FLOW_LOG_TRACE(
"Handler completed.");
1236 using flow::util::stat::print;
1240 FLOW_LOG_INFO(
"Socket stream [" << *
this <<
"]: In context [" << context <<
"]: Stats: "
uint16_t low_lvl_payload_blob_length_t
The type used to encode the internal meta-blob length/type-indicator for sync_io::Native_socket_strea...
static constexpr low_lvl_payload_blob_length_t S_PING_SENTINEL
For sync_io::Native_socket_stream and derivative(s): Value for the length/type-indicator field in eac...
static constexpr size_t S_MAX_META_BLOB_LENGTH
The maximum length of a blob that can be sent by the protocol internally used by sync_io::Native_sock...
static constexpr bool S_USE_OS_DGRAM_SUPPORT
Whether the OS provides, and we shall use for sync_io::Native_socket_stream and derivative(s),...
proto_ver_t local_max_proto_ver_for_sending()
Returns local_max_proto_ver from ctor the first time it is called and S_VER_ALREADY_SENT subsequently...
static constexpr proto_ver_t S_VER_ALREADY_SENT
An proto_ver_t value, namely a negative one, which is a reserved value specifically for return by loc...
void native_handle_send_stats_reset()
See Native_socket_stream counterpart.
util::sync_io::Event_wait_func m_snd_ev_wait_func
Function (set forever in start_send_*_ops()) through which we invoke the outside event loop's async-w...
util::sync_io::Timer_event_emitter m_timer_worker
As typical in timer-needing sync_io-pattern-implementing objects, maintains a thread exclusively for ...
decltype(m_peer_socket) m_peer_socket_hosed
Null to start, this takes on the value from m_peer_socket when and only when m_peer_socket is nullifi...
bool send_blob(const util::Blob_const &blob, Error_code *err_code)
See Native_socket_stream counterpart.
flow::util::Timer m_snd_auto_ping_timer
Timer that fires snd_on_ev_auto_ping_now_timer_fired() (which sends an auto-ping) and is always sched...
void snd_async_write_q_head_payload()
Initiates async-write over m_peer_socket of the low-level payload at the head of out-queue m_snd_pend...
bool end_sending()
See Native_socket_stream counterpart.
bool m_snd_finished
false at start; set to true forever on the first *end_sending() invocation; true will prevent any sub...
size_t snd_nb_write_low_lvl_payload(Native_handle hndl_or_null, const util::Blob_const &blob1, const util::Blob_const &blob2_or_none, Error_code *err_code)
Utility that sends non-empty blob1, with (unless null) hndl_or_null associated with its 1st byte,...
size_t send_blob_max_size() const
See Native_socket_stream counterpart.
util::Fine_duration m_snd_auto_ping_period
Equals zero() before auto_ping(); immutably equals period (auto_ping() arg) subsequently to that firs...
bool async_end_sending(Error_code *sync_err_code, flow::async::Task_asio_err &&on_done_func)
See Native_socket_stream counterpart.
bool start_send_blob_ops(util::sync_io::Event_wait_func &&ev_wait_func)
See Native_socket_stream counterpart.
util::sync_io::Timer_event_emitter::Timer_fired_read_end * m_snd_auto_ping_timer_fired_peer
Read-end of IPC-mechanism used by m_timer_worker to ferry timer-fired events from m_snd_auto_ping_tim...
void snd_on_ev_auto_ping_now_timer_fired()
Handler for the async-wait, via util::sync_io::Timer_event_emitter, of the auto-ping timer firing; if...
void blob_send_stats_reset()
See Native_socket_stream counterpart.
util::sync_io::Asio_waitable_native_handle m_ev_wait_hndl_peer_socket
Descriptor waitable by outside event loop async-waits – storing the same Native_handle as (and thus b...
stat::Blob_snd_stats m_snd_stats
Outgoing-direction (send-pipe) stats. Updated only from send-ops context.
bool async_end_sending_impl(Error_code *sync_err_code_ptr_or_null, flow::async::Task_asio_err &&on_done_func_or_empty)
*end_sending() body.
util::sync_io::Asio_waitable_native_handle m_snd_ev_wait_hndl_auto_ping_timer_fired_peer
Descriptor waitable by outside event loop async-waits – storing the same Native_handle as (and thus b...
boost::movelib::unique_ptr< asio_local_stream_socket::Peer_socket< Native_socket_stream_cfg::Protocol > > m_peer_socket
The peer Unix domain socket; or null pointer if we've detected the connection has become hosed and he...
bool state_peer(util::String_view context) const
Checks whether m_state has reached State::S_PEER; if so returns true; if not logs WARNING and returns...
size_t send_meta_blob_max_size() const
See Native_socket_stream counterpart.
Error_code m_snd_pending_err_code
The first and only connection-hosing error condition detected when attempting to low-level-write on m...
std::queue< Snd_low_lvl_payload::Ptr > m_snd_pending_payloads_q
Queue storing (at head) the currently in-progress async write-op of a Snd_low_lvl_payload; followed b...
flow::util::Mutex_non_recursive m_peer_socket_mutex
Protects m_peer_socket and its bros m_ev_wait_hndl_peer_socket and m_peer_socket_hosed.
bool send_native_handle(Native_handle hndl_or_null, const util::Blob_const &meta_blob, Error_code *err_code)
See Native_socket_stream counterpart.
bool start_send_native_handle_ops(util::sync_io::Event_wait_func &&ev_wait_func)
See Native_socket_stream counterpart.
Protocol_negotiator m_protocol_negotiator
Handles the protocol negotiation at the start of the pipe.
Blob_snd_stats blob_send_stats() const
See Native_socket_stream counterpart.
Blob_snd_stats native_handle_send_stats() const
See Native_socket_stream counterpart.
State m_state
The current state of *this.
@ S_PEER
Is or was a connected peer.
bool snd_sync_write_or_q_payload(Native_handle hndl_or_null, const util::Blob_const &blob1, const util::Blob_const &blob2_or_none, bool avoid_qing, bool *dropped_or_null=nullptr)
Either synchronously sends hndl_or_null handle (if any) and the given low-level blob(s) over m_peer_s...
void snd_on_ev_peer_socket_writable_or_error()
Completion handler, from outside event loop via sync_io pattern, for the async-wait initiated by snd_...
bool auto_ping(util::Fine_duration period)
See Native_socket_stream counterpart.
flow::async::Task_asio_err m_snd_pending_on_last_send_done_func_or_empty
Function passed to async_end_sending(), if it returned true and was unable to synchronously flush eve...
void snd_log_stats(util::String_view context) const
INFO-logs current snd-half stats: as log_stats() but callable from send-op context (see "Which halves...
void consume_timer_firing_signal(Timer_fired_read_end *read_end)
Must be called after a timer_async_wait()-triggered timer fired, before invoking that method for the ...
void timer_async_wait(flow::util::Timer *timer, Timer_fired_read_end *read_end)
To be used on a timer T returned by create_timer(), this is the replacement for the usual T....
size_t nb_write_some_with_native_handle(flow::log::Logger *logger_ptr, Peer_socket< Protocol > *peer_socket_ptr, Native_handle payload_hndl, const Const_buffer_sequence &payload_blob, Error_code *err_code)
boost.asio extension similar to peer_socket->non_blocking(true); auto n = peer_socket->send(payload_b...
@ S_SENDS_FINISHED_CANNOT_SEND
Will not send message: local user already ended sending via API marking this.
@ S_SYNC_IO_WOULD_BLOCK
A sync_io operation could not immediately complete; it will complete contingent on active async-wait ...
@ S_INVALID_ARGUMENT
User called an API with 1 or more arguments against the API spec.
@ S_LOW_LVL_TRANSPORT_HOSED_CANNOT_SEND
Unable to send outgoing traffic: an earlier-reported, or at least logged, system error had hosed the ...
sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::transport.
Function< void(Asio_waitable_native_handle *hndl_of_interest, bool ev_of_interest_snd_else_rcv, Task_ptr &&on_active_ev_func)> Event_wait_func
In sync_io pattern, concrete type storing user-supplied function invoked by pattern-implementing ipc:...
flow::async::Task Task
Short-hand for polymorphic function (a-la std::function<>) that takes no arguments and returns nothin...
Own_native_handle duped_native_handle(Native_handle src, Error_code *err_code)
Returns Own_native_handle{src.dup(err_code)}: an auto-closing duplicate of src; on error the result i...
flow::Fine_duration Fine_duration
Short-hand for Flow's Fine_duration.
boost::asio::const_buffer Blob_const
Short-hand for an immutable blob somewhere in memory, stored as exactly a void const * and a size_t.
flow::util::String_view String_view
Short-hand for Flow's String_view.
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Cumulative stats from the outgoing-direction (send) pipe of a Blob_sender or Native_handle_sender con...
uint64_t m_auto_pings
Number of auto-pings sent (initial from auto_ping() plus periodic timer-fired pings).
flow::util::stat::Histogram_counter m_histo_payload_sz
Payload-size histogram for sent user messages.
uint64_t m_msgs_with_hndls
Number of messages sent that carried at least one native handle. Currently at most 1 handle per messa...
uint64_t m_total_bytes
Total user blob bytes sent (sum of blob sizes from send_*()).
size_t m_snd_q_depth
Current depth of the pending-payloads send queue (queue added-to when would-block occurs).
uint64_t m_total_low_lvl_bytes
Total low-level bytes sent (user blob bytes plus protocol headers and framing).
uint64_t m_total_msgs
Total user messages successfully passed to the low-level send path via send_*().
uint64_t m_would_block_count
Number of times a would-block condition required payload queueing (low-level transport's internal buf...
size_t m_snd_q_hi_wmark
Max of m_snd_q_depth observed so far.
A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.
constexpr bool null() const noexcept
Returns true if and only if m_native_handle equals S_NULL_HANDLE.