Flow-IPC 3.0.0
Flow-IPC project: Full implementation reference.
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Types | Protected Member Functions | Static Protected Attributes | Private Attributes | List of all members
ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload > Class Template Reference

Internal type containing data and types common to internal types Server_session_impl and Client_session_impl which are the respective true cores of Server_session and Client_session respectively. More...

#include <session_base.hpp>

Inheritance diagram for ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >:
[legend]
Collaboration diagram for ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >:
[legend]

Classes

class  Graceful_finisher
 Optional to use by subclasses, this operates a simple state machine that carries out a graceful-session-end handshake procedure. More...
 

Public Types

using Persistent_mq_handle_from_cfg = std::conditional_t<!S_MQS_ENABLED, transport::Null_peer, std::conditional_t< MQ_TYPE_OR_NONE==schema::MqType::POSIX, transport::Posix_mq_handle, transport::Bipc_mq_handle > >
 Relevant only if S_MQS_ENABLED, this is the Persistent_mq_handle-concept impl type specified by the user via MQ_TYPE_OR_NONE. More...
 
using Channel_obj = std::conditional_t< S_MQS_ENABLED, std::conditional_t< TRANSMIT_NATIVE_HANDLES, transport::Mqs_socket_stream_channel< true, Persistent_mq_handle_from_cfg >, transport::Mqs_channel< true, Persistent_mq_handle_from_cfg > >, std::conditional_t< TRANSMIT_NATIVE_HANDLES, transport::Socket_stream_channel< true >, transport::Socket_stream_channel_of_blobs< true > > >
 See Session_mv (or Session concept). More...
 
using Channels = std::vector< Channel_obj >
 See Session_mv. Note: If changed from vector please update those doc headers too. More...
 
using Mdt_payload_obj = Mdt_payload
 See Session_mv (or Session concept). More...
 
using Mdt_reader_ptr = boost::shared_ptr< typename transport::struc::schema::Metadata< Mdt_payload_obj >::Reader >
 See Session_mv (or Session concept). More...
 
using Mdt_builder = typename transport::struc::schema::Metadata< Mdt_payload_obj >::Builder
 See Session_mv (or Session concept). More...
 
using Mdt_builder_ptr = boost::shared_ptr< Mdt_builder >
 See Session_mv (or Session concept). More...
 
using Structured_msg_builder_config = transport::struc::Heap_fixed_builder::Config
 See Session_mv (or Session concept). More...
 
using Structured_msg_reader_config = transport::struc::Heap_reader::Config
 See Session_mv (or Session concept). More...
 

Public Member Functions

const Shared_name & srv_namespace () const
 See Server_session_impl, Client_session_impl. More...
 
const Shared_name & cli_namespace () const
 See Server_session_impl, Client_session_impl. More...
 
const Client_app * cli_app_ptr () const
 See Server_session_impl, Client_session_impl. More...
 
Shared_name cur_ns_store_mutex_absolute_name () const
 Computes the name of the interprocess named-mutex used to control reading/writing to the file storing (written by server, read by client) the value for srv_namespace(). More...
 
fs::path cur_ns_store_absolute_path () const
 Computes the absolute path to file storing (written by server, read by client) the value for srv_namespace(). More...
 
Shared_name session_master_socket_stream_acceptor_absolute_name () const
 Computes the absolute name at which the server shall set up a transport::Native_socket_stream_acceptor to which client shall transport::Native_socket_stream::sync_connect() in order to establish a PEER-state session. More...
 

Static Public Member Functions

static Structured_msg_reader_config heap_reader_config (flow::log::Logger *logger_ptr)
 See Session_mv::heap_reader_config() (1-arg). More...
 

Public Attributes

const Server_app & m_srv_app_ref
 Reference to Server_app (referring to local process in Server_session_impl, opposing process in Client_session_impl). More...
 

Static Public Attributes

static constexpr bool S_MQS_ENABLED = MQ_TYPE_OR_NONE != schema::MqType::NONE
 See Session_mv. More...
 
static constexpr bool S_SOCKET_STREAM_ENABLED = (!S_MQS_ENABLED) || TRANSMIT_NATIVE_HANDLES
 See Session_mv. More...
 

Protected Types

using Master_structured_channel = transport::struc::Channel_via_heap< transport::Socket_stream_channel< true >, schema::detail::SessionMasterChannelMessageBody< Mdt_payload_obj > >
 The (internally used) session master channel is a transport::struc::Channel of this concrete type. More...
 
using Master_structured_channel_ptr = boost::shared_ptr< Master_structured_channel >
 Handle to Master_structured_channel. More...
 
using Master_structured_channel_observer = boost::weak_ptr< Master_structured_channel >
 Observer of Master_structured_channel_ptr. See its doc header. More...
 
using Info_collector = session::Info_collector< Master_structured_channel >
 See Session_mv (or Session concept). More...
 
using On_passive_open_channel_func = Function< void(Channel_obj &&new_channel, Mdt_reader_ptr &&new_channel_mdt)>
 Concrete function type for the on-passive-open handler (if any), used for storage. More...
 

Protected Member Functions

 Session_base (const Client_app &cli_app_ref, const Server_app &srv_app_ref, flow::async::Task_asio_err &&on_err_func, On_passive_open_channel_func &&on_passive_open_channel_func_or_empty_arg)
 Constructs: Client_session_impl form (the user is the one constructing the object, though in NULL state). More...
 
 Session_base (const Server_app &srv_app_ref)
 Constructs: Server_session_impl form (Session_server is the one constructing the object, though in NULL state, before log-in has completed, but after the socket-stream connection has been established). More...
 
void set_srv_namespace (Shared_name &&srv_namespace_new)
 Sets srv_namespace() (do not call if already set). More...
 
void set_cli_namespace (Shared_name &&cli_namespace_new)
 Sets cli_namespace() (do not call if already set). More...
 
void reset_namespaces ()
 Restores srv_namespace() and cli_namespace() to the never-yet-set (empty) state. More...
 
void set_cli_app_ptr (const Client_app *cli_app_ptr_new)
 Sets cli_app_ptr() (do not call if already set). More...
 
void set_on_passive_open_channel_func (On_passive_open_channel_func &&on_passive_open_channel_func)
 Sets on_passive_open_channel_func_or_empty() (do not call if already set; do not call if user intends for passive-opens to be disabled on this side). More...
 
void set_on_err_func (flow::async::Task_asio_err &&on_err_func_arg)
 Sets on_err_func() (do not call if already set). More...
 
bool on_err_func_set () const
 Returns true if and only if set_on_err_func() has been called, or equivalently if error-handler was set via ctor. More...
 
const On_passive_open_channel_func & on_passive_open_channel_func_or_empty () const
 The on-passive-open handler (may be empty even in final state, meaning user wants passive-opens disabled on this side). More...
 
void hose (const Error_code &err_code)
 Marks this session as hosed for (truthy) reason err_code; and synchronously invokes on-error handler; only invoke if not already hosed(). More...
 
bool hosed () const
 Returns true if and only if hose() has been called. More...
 
void set_dtor_started ()
 Marks the *_session_impl dtor as having begun; from then on dtor_started() returns true, and callers shall not hose() (emit session-hosing errors to the user). More...
 
bool dtor_started () const
 Returns true if and only if set_dtor_started() has been called. More...
 

Static Protected Attributes

static constexpr util::Fine_duration S_OPEN_CHANNEL_TIMEOUT = boost::chrono::seconds{60}
 Internal timeout for open_channel(). More...
 
static constexpr size_t S_MQS_MAX_MSG_SZ = 8 * 1024
 The default max sendable MQ message size as decided by Server_session_impl::make_channel_mqs() (and imposed on both sides, both directions), if S_MQS_ENABLED and Server_session_impl::S_SHM_ENABLED is false, when a channel is opened (regardless of which side did the active-open or requested pre-opening at session start). More...
 

Private Attributes

std::atomic< const Client_app * > m_cli_app_ptr
 See cli_app_ptr(). More...
 
Shared_name m_srv_namespace
 See srv_namespace(). More...
 
Shared_name m_cli_namespace
 See cli_namespace(). More...
 
flow::async::Task_asio_err m_on_err_func
 See set_on_err_func(). More...
 
On_passive_open_channel_func m_on_passive_open_channel_func_or_empty
 See on_passive_open_channel_func_or_empty(). More...
 
Error_code m_peer_state_err_code_or_ok
 Starts falsy; becomes forever truthy (with a specific Error_code that will not change thereafter) once hose() is called (with that truthy value). More...
 
bool m_dtor_started
 Read/written in thread W only; false until the *_session_impl dtor – as its first act – posts a task calling set_dtor_started(); from then on session-hosing errors are not emitted to the user's on-error handler. More...
 

Detailed Description

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload>
class ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >

Internal type containing data and types common to internal types Server_session_impl and Client_session_impl which are the respective true cores of Server_session and Client_session respectively.

A Server_session_impl and Client_session_impl share many basic properties, some public. For example consider that a Server_session_impl on this side has 1 counterpart Client_session_impl on the other side (or vice versa); for both it is salient which Server_app is on the server side and which Client_app is on the client side. In terms of types/constants, on each side the two Session objects must be identically configured via various template params which results in non-trivial type aliases like the highly significant Channel_obj, exposed in the Session concept, and constants like S_SOCKET_STREAM_ENABLED.

Regarding data: an operational (PEER-state) Session (on either end) will need various members to be set before it is indeed in PEER state. This object stores such data, usually unset at first, and features protected setters to invoke once each, until all are set permanently for PEER state.

Session_base also has a protected inner class, Session_base::Graceful_finisher which certain variations (for which this is necessary) of Server_session_impl and Client_session_impl use to carry out a graceful-session-end handshake procedure. This is here in Session_base – despite being somewhat more algorithmic/stateful than the other stuff here – essentially because the Graceful_finisher (if needed at all) on each side acts completely symmetrically. Other items tend to be (internally) asymmetrical in behavior between Server_session_impl and Client_session_impl (and variants). More info on Session_base::Graceful_finisher in its own doc header.

Todo:
Session_base is in detail/ and is formally documented at the top of its doc header as "internal"; and indeed it is out-of-the-box; but the ipc::session hierarchies are also formally user-extensible, so Session_base should be publicly exposed after all. Hence remove the "internal" verbiage; move the file; and go over its source code/design, in case something about its API is too "Inside Baseball." To be clear, though, this is not of the highest priority: 1, detail/ or not it can still be sub-classed in a pinch; 2, arguably more saliently, extending ipc::session hierarchies is a rare thing for a user to want to do in practice. It's an API-versus-SPI situation that isn't fully clean here. (Generally in Flow-IPC we endeavour to keep that fully clean.)
Todo:
The to-do preceding this one in the source code has corollaries: There are probably some (not all) _imply classes/class templates that are in detail/ but should not be, given that formally ipc::session is user-extensible. Again, though: 1, detail/ or not it (for each "it") can still be accessed in a pinch; 2, arguably more saliently, extending ipc::session hierarchies is a rare thing for a user to want to do in practice. It's an API-versus-SPI situation that isn't fully clean here. (Generally in Flow-IPC we endeavour to keep that fully clean.)
Template Parameters
Mdt_payloadSee Server_session, Client_session (or Session concept).
MQ_TYPE_OR_NONESee Server_session, Client_session.
TRANSMIT_NATIVE_HANDLESSee Server_session, Client_session.

Definition at line 83 of file session_base.hpp.

Member Typedef Documentation

◆ Channel_obj

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Channel_obj = std::conditional_t<S_MQS_ENABLED, std::conditional_t <TRANSMIT_NATIVE_HANDLES, transport::Mqs_socket_stream_channel<true, Persistent_mq_handle_from_cfg>, transport::Mqs_channel<true, Persistent_mq_handle_from_cfg> >, std::conditional_t <TRANSMIT_NATIVE_HANDLES, transport::Socket_stream_channel<true>, transport::Socket_stream_channel_of_blobs<true> >>

See Session_mv (or Session concept).

Definition at line 127 of file session_base.hpp.

◆ Channels

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Channels = std::vector<Channel_obj>

See Session_mv. Note: If changed from vector please update those doc headers too.

Definition at line 138 of file session_base.hpp.

◆ Info_collector

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Info_collector = session::Info_collector<Master_structured_channel>
protected

See Session_mv (or Session concept).

Definition at line 369 of file session_base.hpp.

◆ Master_structured_channel

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Master_structured_channel = transport::struc::Channel_via_heap<transport::Socket_stream_channel<true>, schema::detail::SessionMasterChannelMessageBody <Mdt_payload_obj> >
protected

The (internally used) session master channel is a transport::struc::Channel of this concrete type.

Rationale for the chosen knob values:

  • To be able to open_channel() (and hence passive-open) a Channel_obj that can transmit native handles, certainly a handles pipe is required to transmit half of each socket-pair. That said, an Mqs_channel would work fine if S_SOCKET_STREAM_ENABLED is false. The real reason at least a handles pipe is required is that to establish this channel – unlike subsequent channels in the session – a client-server flow is required. This connection establishment is not possible with MQs, so of the available options only a socket stream would work.
    • There is no bulky data transfers over this channel, so adding a parallel MQ-based blobs pipe is overkill even if it could help performance; more so since the master channel is unlikely to be used frequently (open_channel() on either side shouldn't be that frequent). Since, again, the minute differences in perf versus a Unix-domain-socket-based transport are unlikely to be significant in this use case, it is easier to use a socket stream which lacks any kernel-persistent cleanup considerations – or even just distinct naming considerations for that matter.
    • So: use a transport::Socket_stream_channel.
  • Use the specially tailored (internal) session master channel capnp schema, whose key messages cover (at least):
    • session log-in at the start;
    • open-channel request/response.
  • As of this writing, for serializing/deserializing, it's either the heap-allocating engine on either side, or it's something SHM-based (which could be faster). However at least some SHM-based builders/readers themselves (internally) require a transport::Channel to function, which would require a Session typically, creating a cyclical feature dependency. Plus, SHM has cleanup considerations. So a heap-based engine on either side is the natural choice. The cost is some perf: one copies from heap into the session master transport; and from there into heap on the other side. In this context that's not a significant perf loss.

Definition at line 349 of file session_base.hpp.

◆ Master_structured_channel_observer

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Master_structured_channel_observer = boost::weak_ptr<Master_structured_channel>
protected

Observer of Master_structured_channel_ptr. See its doc header.

Definition at line 366 of file session_base.hpp.

◆ Master_structured_channel_ptr

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Master_structured_channel_ptr = boost::shared_ptr<Master_structured_channel>
protected

Handle to Master_structured_channel.

Rationale for type chosen

It's a handle at all, because at first and possibly later there may be no session master channel, so a null value is useful. (Though, std::optional could be used instead.) It's a ref-counted pointer as opposed to unique_ptr so that it can be observed via Master_structured_channel_observer (weak_ptr) which is not (and cannot) be available for unique_ptr. The observing is needed tactically for certain async lambda needs.

Definition at line 363 of file session_base.hpp.

◆ Mdt_builder

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Mdt_builder = typename transport::struc::schema::Metadata<Mdt_payload_obj>::Builder

See Session_mv (or Session concept).

Definition at line 148 of file session_base.hpp.

◆ Mdt_builder_ptr

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Mdt_builder_ptr = boost::shared_ptr<Mdt_builder>

See Session_mv (or Session concept).

Definition at line 152 of file session_base.hpp.

◆ Mdt_payload_obj

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Mdt_payload_obj = Mdt_payload

See Session_mv (or Session concept).

Definition at line 141 of file session_base.hpp.

◆ Mdt_reader_ptr

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Mdt_reader_ptr = boost::shared_ptr<typename transport::struc::schema::Metadata<Mdt_payload_obj>::Reader>

See Session_mv (or Session concept).

Definition at line 144 of file session_base.hpp.

◆ On_passive_open_channel_func

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::On_passive_open_channel_func = Function<void (Channel_obj&& new_channel, Mdt_reader_ptr&& new_channel_mdt)>
protected

Concrete function type for the on-passive-open handler (if any), used for storage.

Definition at line 372 of file session_base.hpp.

◆ Persistent_mq_handle_from_cfg

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Persistent_mq_handle_from_cfg = std::conditional_t<!S_MQS_ENABLED, transport::Null_peer, std::conditional_t<MQ_TYPE_OR_NONE == schema::MqType::POSIX, transport::Posix_mq_handle, transport::Bipc_mq_handle> >

Relevant only if S_MQS_ENABLED, this is the Persistent_mq_handle-concept impl type specified by the user via MQ_TYPE_OR_NONE.

Definition at line 119 of file session_base.hpp.

◆ Structured_msg_builder_config

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Structured_msg_builder_config = transport::struc::Heap_fixed_builder::Config

See Session_mv (or Session concept).

Definition at line 155 of file session_base.hpp.

◆ Structured_msg_reader_config

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
using ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Structured_msg_reader_config = transport::struc::Heap_reader::Config

See Session_mv (or Session concept).

Definition at line 158 of file session_base.hpp.

Constructor & Destructor Documentation

◆ Session_base() [1/2]

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Session_base ( const Client_app &  cli_app_ref,
const Server_app &  srv_app_ref,
flow::async::Task_asio_err &&  on_err_func,
On_passive_open_channel_func &&  on_passive_open_channel_func_or_empty_arg 
)
explicitprotected

Constructs: Client_session_impl form (the user is the one constructing the object, though in NULL state).

The values taken as args are set permanently (undefined behavior/assertion may trip if an attempt is made to modify one via mutator). The remaining values must be set via mutator before PEER state.

Parameters
cli_app_refSee cli_app_ptr().
srv_app_refSee m_srv_app_ref.
on_err_funcOn-error handler from user.
on_passive_open_channel_func_or_empty_argOn-passive-open handler from user (empty if user wishes to disable passive-opens on this side).

Definition at line 888 of file session_base.hpp.

◆ Session_base() [2/2]

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Session_base ( const Server_app &  srv_app_ref)
explicitprotected

Constructs: Server_session_impl form (Session_server is the one constructing the object, though in NULL state, before log-in has completed, but after the socket-stream connection has been established).

The values taken as args are set permanently (undefined behavior/assertion may trip if an attempt is made to modify one via mutator). The remaining values must be set via mutator before PEER state.

Parameters
srv_app_refSee m_srv_app_ref.

Definition at line 908 of file session_base.hpp.

Member Function Documentation

◆ cli_app_ptr()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
const Client_app * ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::cli_app_ptr

See Server_session_impl, Client_session_impl.

However in Session_base this value may be not-yet-set (null), or set (and immutable from then on). Note the value to which we refer is the actual pointer. (The Client_app that is pointed-to, itself, is certainly immutable too.)

This value shall be set from the start in a Client_session_impl but determined during a given Server_session_impl's log-in (the opposing Client_session_impl will transmit the Client_app::m_name). The log-in shall complete the Server_session's entry to PEER state.

Returns
See above.

Definition at line 984 of file session_base.hpp.

◆ cli_namespace()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
const Shared_name & ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::cli_namespace

See Server_session_impl, Client_session_impl.

However in Session_base this value may be not-yet-set (empty), or set (and immutable from then on).

This value shall be generated uniquely – process-wide, across all Session_servers in the process (see next_cli_namespace()) – for each new Server_session produced by Session_server; and Client_session_impl shall find that out while logging in (last part of entering PEER state).

Returns
See above.

Definition at line 996 of file session_base.hpp.

◆ cur_ns_store_absolute_path()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
fs::path ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::cur_ns_store_absolute_path

Computes the absolute path to file storing (written by server, read by client) the value for srv_namespace().

The file is located as cur_ns_store_absolute_path().

This may be called anytime.

Returns
See above.

Definition at line 1077 of file session_base.hpp.

References ipc::util::IPC_KERNEL_PERSISTENT_RUN_DIR.

◆ cur_ns_store_mutex_absolute_name()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
Shared_name ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::cur_ns_store_mutex_absolute_name

Computes the name of the interprocess named-mutex used to control reading/writing to the file storing (written by server, read by client) the value for srv_namespace().

The file is located as cur_ns_store_absolute_path().

This may be called anytime.

Returns
See above.

Definition at line 1044 of file session_base.hpp.

References ipc::session::build_conventional_shared_name(), ipc::util::Shared_name::ct(), ipc::util::Shared_name::S_RESOURCE_TYPE_ID_MUTEX, and ipc::util::Shared_name::S_SENTINEL.

Here is the call graph for this function:

◆ dtor_started()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
bool ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::dtor_started
protected

Returns true if and only if set_dtor_started() has been called.

Call from thread W only.

Returns
See above.

Definition at line 1038 of file session_base.hpp.

Referenced by ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Graceful_finisher::Graceful_finisher().

Here is the caller graph for this function:

◆ heap_reader_config()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Structured_msg_reader_config ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::heap_reader_config ( flow::log::Logger *  logger_ptr)
static

See Session_mv::heap_reader_config() (1-arg).

Parameters
logger_ptrSee above.
Returns
See above.

Definition at line 1212 of file session_base.hpp.

◆ hose()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::hose ( const Error_code &  err_code)
protected

Marks this session as hosed for (truthy) reason err_code; and synchronously invokes on-error handler; only invoke if not already hosed().

This utility is important and has certain pre-conditions (behavior undefined if not met; assertion may trip):

  • *this must be in PEER state. In particular on_err_func_set() must return true.
  • hosed() must return false.
  • err_code must be truthy (non-success).
  • This must be invoked from a thread such that it is OK to synchronously invoke on-error handler. As of this writing this is Server_session_impl's or Client_session_impl's thread W in practice, which is how thread safety of hose() versus hosed() is also guaranteed by those users.
Parameters
err_codeTruthy error.

Definition at line 1015 of file session_base.hpp.

Referenced by ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Graceful_finisher::Graceful_finisher().

Here is the caller graph for this function:

◆ hosed()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
bool ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::hosed
protected

Returns true if and only if hose() has been called.

If so then m_on_err_func has been executed already. *this must be in PEER state. In particular on_err_func_set() must return true.

Returns
Ditto.

Definition at line 1024 of file session_base.hpp.

Referenced by ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::Graceful_finisher::Graceful_finisher().

Here is the caller graph for this function:

◆ on_err_func_set()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
bool ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::on_err_func_set
protected

Returns true if and only if set_on_err_func() has been called, or equivalently if error-handler was set via ctor.

Returns
See above.

Definition at line 1009 of file session_base.hpp.

◆ on_passive_open_channel_func_or_empty()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
const Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::On_passive_open_channel_func & ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::on_passive_open_channel_func_or_empty
protected

The on-passive-open handler (may be empty even in final state, meaning user wants passive-opens disabled on this side).

Returns
See above.

Definition at line 1003 of file session_base.hpp.

◆ reset_namespaces()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::reset_namespaces
protected

Restores srv_namespace() and cli_namespace() to the never-yet-set (empty) state.

When to use: A Client_session connect attempt populates these along the way (set_srv_namespace() upon reading the server's CNS a/k/a PID file; set_cli_namespace() upon receiving the log-in response); and by public contract a failed attempt leaves the Client_session in NULL state, from which another attempt on the same object is permitted. Since these values are set-at-most-once-from-empty per attempt – and the next attempt may well obtain different values (e.g., the server restarted, hence a new srv-namespace/PID) – the failed attempt's go-back-to-NULL rollback must invoke this. (Server-side: a Server_session never legitimately re-sets these; do not use this from server-side code.)

Definition at line 961 of file session_base.hpp.

◆ session_master_socket_stream_acceptor_absolute_name()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
Shared_name ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::session_master_socket_stream_acceptor_absolute_name

Computes the absolute name at which the server shall set up a transport::Native_socket_stream_acceptor to which client shall transport::Native_socket_stream::sync_connect() in order to establish a PEER-state session.

This must be called no earlier than set_srv_namespace(); otherwise behavior undefined (assertion may trip).

Returns
See above.

Definition at line 1090 of file session_base.hpp.

References ipc::session::build_conventional_shared_name(), ipc::util::Shared_name::ct(), ipc::transport::Native_socket_stream_acceptor::S_RESOURCE_TYPE_ID, and ipc::util::Shared_name::S_SENTINEL.

Here is the call graph for this function:

◆ set_cli_app_ptr()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::set_cli_app_ptr ( const Client_app *  cli_app_ptr_new)
protected

Sets cli_app_ptr() (do not call if already set).

Parameters
cli_app_ptr_newValue.

Definition at line 928 of file session_base.hpp.

◆ set_cli_namespace()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::set_cli_namespace ( Shared_name &&  cli_namespace_new)
protected

Sets cli_namespace() (do not call if already set).

Parameters
cli_namespace_newValue.

Definition at line 951 of file session_base.hpp.

References ipc::util::Shared_name::S_SENTINEL.

◆ set_dtor_started()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::set_dtor_started
protected

Marks the *_session_impl dtor as having begun; from then on dtor_started() returns true, and callers shall not hose() (emit session-hosing errors to the user).

See m_dtor_started doc header for rationale and the (essential) requirement as to when to call this: as the dtor's first act, in thread W terms. Call from thread W only, at most once.

Definition at line 1031 of file session_base.hpp.

◆ set_on_err_func()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::set_on_err_func ( flow::async::Task_asio_err &&  on_err_func_arg)
protected

Sets on_err_func() (do not call if already set).

Parameters
on_err_func_argValue.

Definition at line 975 of file session_base.hpp.

◆ set_on_passive_open_channel_func()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::set_on_passive_open_channel_func ( On_passive_open_channel_func &&  on_passive_open_channel_func)
protected

Sets on_passive_open_channel_func_or_empty() (do not call if already set; do not call if user intends for passive-opens to be disabled on this side).

Parameters
on_passive_open_channel_funcValue.

Definition at line 968 of file session_base.hpp.

◆ set_srv_namespace()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
void ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::set_srv_namespace ( Shared_name &&  srv_namespace_new)
protected

Sets srv_namespace() (do not call if already set).

Parameters
srv_namespace_newValue.

Definition at line 941 of file session_base.hpp.

References ipc::util::Shared_name::S_SENTINEL.

◆ srv_namespace()

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
const Shared_name & ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::srv_namespace

See Server_session_impl, Client_session_impl.

However in Session_base this value may be not-yet-set (empty), or set (and immutable from then on).

This value shall be known and immutable from construction for Server_session_impl, since server namespace – PID as of this writing – can be determined from the start on the server side and applies to every server session that Session_server produces. Client_session_impl, however, determines it at the latest possible moment which is at Client_session_impl::async_connect() time, at which point it needs to determine the PID via PID file.

Returns
See above.

Definition at line 990 of file session_base.hpp.

Member Data Documentation

◆ m_cli_app_ptr

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
std::atomic<const Client_app*> ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_cli_app_ptr
private

See cli_app_ptr().

Rationale for it being atomic<>

It is for the following specific reason. Consider ostream<< of *this. *this is really either in Client_session_impl or Server_session_impl. In both cases these ostream<<s access only m_srv_app_ref, which is immutable throughout (so no problem there) and m_cli_app_ptr. For Client_session_impl m_cli_app_ptr is also immutable throughout (so no problem there). For Server_session_impl however it does change in one spot: Server_session_impl::async_accept_log_in() internal async handler for the log-in request shall, on success, call set_cli_app_ptr() and change it from null to non-null. This could cause concurrent access to the data member, even though it's a mere pointer (but we don't count on the alleged "atomicity" of this; it is generally considered not safe).

Now, as of this writing, there's exactly one spot where ostream<< could be invoked from thread U while it is being assigned in thread W: async_accept_log_in() is called by our internal code in Session_server and only once; the only thing that can occur in thread U until the log-in response handler is executed is that Server_session_impl dtor is called. Before that dtor stops that thread W, it does print the Server_session_impl once as of this writing. Therefore, out of sheer caution, this guy is atomic<>. That said there could be other such invocations, as code might change during maintenance in the future, in which case this atomic<>ness will quietly come in handy.

Definition at line 826 of file session_base.hpp.

◆ m_cli_namespace

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
Shared_name ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_cli_namespace
private

See cli_namespace().

Definition at line 832 of file session_base.hpp.

◆ m_dtor_started

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
bool ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_dtor_started
private

Read/written in thread W only; false until the *_session_impl dtor – as its first act – posts a task calling set_dtor_started(); from then on session-hosing errors are not emitted to the user's on-error handler.

Rationale

Nothing can – or tries to – prevent the on-error handler firing during dtor execution in general: an async error can always lose a race against the user's decision to destroy the Session, and the user must be able to handle that regardless (via standard async hygiene; or by using the sync_io variant, where nothing fires uninvited). However: (1) with Graceful_finisher in play, the graceful session-end protocol reliably delivers events – the opposing GracefulSessionEnd, then the opposing side's channel closure – while our dtor is blocked in Graceful_finisher::on_dtor_start(): absent this guard those would fire "errors" at the user as a deterministic part of every orderly shutdown; and (2) sans-Graceful_finisher, this shortens the coincidental-timing window as a by-product. (1) is what drove this. Either way an emission suppressed hereby is pointless by definition: the user, having entered the dtor, no longer benefits from any notification.

Why one flag, here, and not one per interested party

The interested parties are the *_session_impl (its hose() sites, chiefly its on-master-channel-error handler) and Graceful_finisher (its GracefulSessionEnd handler). Both must observe the same moment as the guarantee point – the dtor's first W-post – or a GracefulSessionEnd queued in thread W between that post and any later, party-specific, flag-setting post would slip through and hose() after all. (Graceful_finisher's on_dtor_start() posts at least one task after the dtor's first post(); so that gap is a real thing.) Hence the single flag lives here, in the class both parties can see.

Definition at line 875 of file session_base.hpp.

◆ m_on_err_func

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
flow::async::Task_asio_err ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_on_err_func
private

See set_on_err_func().

Definition at line 835 of file session_base.hpp.

◆ m_on_passive_open_channel_func_or_empty

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
On_passive_open_channel_func ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_on_passive_open_channel_func_or_empty
private

◆ m_peer_state_err_code_or_ok

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
Error_code ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_peer_state_err_code_or_ok
private

Starts falsy; becomes forever truthy (with a specific Error_code that will not change thereafter) once hose() is called (with that truthy value).

Note hose() may not be called before PEER state, which implies m_on_err_func is non-empty.

Concurrency

See hose() and hosed() doc headers. TL;DR: It is up to the caller to only call those, basically, from thread W only.

Definition at line 849 of file session_base.hpp.

◆ m_srv_app_ref

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
const Server_app& ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_srv_app_ref

Reference to Server_app (referring to local process in Server_session_impl, opposing process in Client_session_impl).

This is known from construction and immutable (both the reference, of course, and the Server_app itself).

Definition at line 250 of file session_base.hpp.

◆ m_srv_namespace

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
Shared_name ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::m_srv_namespace
private

See srv_namespace().

Definition at line 829 of file session_base.hpp.

◆ S_MQS_ENABLED

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
constexpr bool ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::S_MQS_ENABLED = MQ_TYPE_OR_NONE != schema::MqType::NONE
staticconstexpr

See Session_mv.

Definition at line 90 of file session_base.hpp.

◆ S_MQS_MAX_MSG_SZ

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
constexpr size_t ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::S_MQS_MAX_MSG_SZ = 8 * 1024
staticconstexprprotected

The default max sendable MQ message size as decided by Server_session_impl::make_channel_mqs() (and imposed on both sides, both directions), if S_MQS_ENABLED and Server_session_impl::S_SHM_ENABLED is false, when a channel is opened (regardless of which side did the active-open or requested pre-opening at session start).

By default we mean this is the knob's value unless overridden via Session_server::mq_msg_size_limit().

If *this belongs to Server_session_impl, that's what this is. If it belongs to Client_session_impl, then this is what the opposing process – if they're using the same code! – will have decided (again, unless overriden in the opposing process via Session_server::mq_msg_size_limit()).

Note
If Server_session_impl::S_SHM_ENABLED is true, then a different (much smaller) MQ message size limit default is configured. (Again, though, it can be overridden via Session_server::mq_msg_size_limit().)

While it looks simple, there is a number of subtleties one must understand if ever considering changing it.

bipc versus POSIX MQs

As of this writing the same constant value is used for both types of MQ configurable. The actual value is chosen due to a certain aspect of POSIX MQs (discussed just below); and we reuse it for bipc, though we absolutely do not have to, for simplicity/for lack of better ideas at the moment. It would be possible to bifurcate those two cases if really desired.

Why 8Ki?

By default in Linux POSIX MQs this happens to be the actual limit for message size – visible in /proc/sys/fs/mqueue/msgsize_max – so we cannot go higher typically. However that file can be modified. For now we assume a typical environment; or at least that it will not go below this typical default. If we did try a higher number here, opening of MQs by server will likely emit an error and refuse (Server_session_impl::make_channel_mqs()).

Things to consider if changing the value away from the above

  • Contemplate why you're doing it. bipc MQs are seen (in Boost source) to be a simple zero-copy data structure in an internally maintained kernel-persistent SHM pool; while I (ygoldfel) haven't verified via kernel source, likely Linux POSIX MQ impl is something very similar (reasoning omitted but trust me). So copy perf should not be a factor; only RAM use and the functional ability to transmit messages of a certain size.
    • If the plan is to use transport::struc::Heap_fixed_builder-backed for structured messages (via transport::struc::Channel), then the max size is quite important: if a leaf in your message exceeds this size when serialized, it is a fatal error.
    • If, however, the plan is to use SHM-backing (e.g., via shm::classic::*_session), then this constant does not get used (a much smaller value does – so small it would be ~meaningless to decrease it).
  • Suppose you have changed this value, and suppose the Heap_fixed_builder-based use case does matter. If ipc has not yet been released in production, ever, then it's fine (assuming, that is, it'll work in the first place given the aforementioned /proc/sys/... limit for POSIX MQs). If it has been released, but you can guarantee (via release process) that the client and server will always use the same ipc software, then you're still fine. Just change this value; done. (Note: A simple way to assure the opposing peer is appropriately upgraded is to carry out a Protocol_negotiator version(s) bump – without allowing backward-compatibility, meaning min-supported-version=max-supported-version. There are at least a couple potential layers at which to do this bump, so just pick the right one is all.)

Definition at line 318 of file session_base.hpp.

◆ S_OPEN_CHANNEL_TIMEOUT

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
constexpr util::Fine_duration ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::S_OPEN_CHANNEL_TIMEOUT = boost::chrono::seconds{60}
staticconstexprprotected

Internal timeout for open_channel().

The value

We initially tried something much less generous, 500ms. It worked fine, but some people encountered the timeout due to unrelated reasons, and it was natural to blame it on the timeout. This much longer timeout should make it obvious, in such a situation, that it's not about some slowness inside Flow-IPC but a pathological application problem – particularly around session-open time. For example not calling Server_session_impl::init_handlers(), or calling it late, as of this writing can cause issues with this.

The downside is it makes Session::open_channel() potentially blocking formally speaking, whereas 500ms could still claim to be non-blocking. It's a matter of perspective really. This value just seems to cause less confusion. We might reconsider the whole thing however.

Definition at line 269 of file session_base.hpp.

◆ S_SOCKET_STREAM_ENABLED

template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload >
constexpr bool ipc::session::Session_base< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::S_SOCKET_STREAM_ENABLED = (!S_MQS_ENABLED) || TRANSMIT_NATIVE_HANDLES
staticconstexpr

See Session_mv.

Definition at line 93 of file session_base.hpp.


The documentation for this class was generated from the following file: