Flow-IPC 3.0.0
Flow-IPC project: Full implementation reference.
session_fwd.hpp
Go to the documentation of this file.
1/* Flow-IPC: Sessions
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19#pragma once
20
24#include "ipc/util/util_fwd.hpp"
26
27/**
28 * Flow-IPC module providing the broad lifecycle and shared-resource organization -- via the *session* concept --
29 * in such a way as to make it possible for a given pair of processes A and B to set up ipc::transport
30 * structured- or unstructured-message channels for general IPC, as well as to share data in
31 * SHared Memory (SHM). See namespace ::ipc doc header for an overview of Flow-IPC modules
32 * including how ipc::session relates to the others. Then return here. A synopsis follows:
33 *
34 * @see The guided Manual chapters, starting at @ref session_setup, cover these topics; see also @ref chan_open,
35 * @ref session_app_org, @ref safety_perms, and @ref universes.
36 *
37 * It is possible to use the structured layer of ipc::transport, namely the big daddy transport::struc::Channel,
38 * without any help from ipc::session. (It's also possible to establish unstructured transport::Channel and
39 * the various lower-level IPC pipes it might comprise.) And, indeed,
40 * once a given `struc::Channel` (or `Channel`) is "up," one can and *should*
41 * simply use it to send/receive stuff. The problem that ipc::session solves is in establishing
42 * the infrastructure that makes it simple to (1) open new `struc::Channel`s or `Channel`s or SHM areas;
43 * and (2) properly deal with process lifecycle events such as the starting and ending (gracefully or otherwise) of
44 * the local and partner process.
45 *
46 * Regarding (1), in particular (just to give a taste of what one means):
47 * - What underlying low-level transports will we even be using? MQs? Local (Unix domain) stream sockets?
48 * Both?
49 * - For each of those, we must connect or otherwise establish each one. In the case of MQs, say, there has
50 * to be an agreed-upon util::Shared_name for the MQ in each direction... so what is that name?
51 * How to prevent collisions in this name?
52 *
53 * While ipc::transport lets one do whatever one wants, with great flexibility, ipc::session establishes conventions
54 * for all these things -- typically hiding/encapsulating them away.
55 *
56 * Regarding (2) (again, just giving a taste):
57 * - To what process are we even talking? What if we want to talk to 2, or 3, processes? What if we want to talk
58 * to 1+ processes of application X and 1+ processes of application Y? How might we segregate the data
59 * between these?
60 * - What happens if 1 of 5 instances of application X, to whom we're speaking, goes down? How to ensure cleanup
61 * of any kernel-persistence resources, such as the potentially used POSIX MQs, or even of SHM (ipc::shm)?
62 *
63 * Again -- ipc::session establishes conventions for these lifecycle matters and provides key utilities such as
64 * kernel-persistent resource cleanup.
65 *
66 * ### Basic concepts ###
67 * An *application* is, at least roughly speaking, 1-1 with a distinct executable presumably interested in
68 * communicating with another such executable. A *process* is a/k/a *instance* of an application that has begun
69 * execution at some point. In the IPC *universe* that uses ::ipc, on a given machine, there is some number
70 * of distinct applications. If two processes A and B want to engage in IPC, then their apps A and B comprise
71 * a meta-application *split*, in that (in a sense) they are one meta-application that have been split into two.
72 *
73 * A process that is actively operating, at least in the IPC sense, is called an *active* process. A zombie
74 * process in particular is not active, nor is one that has not yet initialized IPC or has shut it down, typically
75 * during graceful (or otherwise) termination.
76 *
77 * In the ipc::session model, any two processes A-B must establish a *session* before engaging in IPC. This
78 * *session* comprises all *shared resources* pertaining to those two *processes* engaging in IPC. (Spoiler alert:
79 * at a high level these resources comprise, at least, *channels* of communication -- see transport::Channel --
80 * between them; and may also optionally comprise SHared Memory (SHM).) The session ends when either A terminates
81 * or B terminates (gracefully or otherwise), and no earlier. The session begins at roughly the earliest time
82 * when *both* A and B are active simultaneously. (It is possible either process may run before IPC and after IPC,
83 * but for purposes of our discussion we'll ignore such phases are irrelevant for simplicity of exposition.)
84 * An important set of shared resources is therefore *per-session shared resources*. (However, as we're about to
85 * explain, it is not the only type.)
86 *
87 * In the ipc::session model, in a given A-B split, one must be chosen as the *client*, the other as the *server*;
88 * let's by convention here assume they're always listed in server-client order. The decision must be made which
89 * one is which, at compile time. The decision as to which is which is an important one, when using ipc::session
90 * and IPC in that model. While a complete discussion of making that decision is outside the scope here, the main
91 * points are that in the A-B split (A the server, B the client):
92 * - For each *process* pair A-B, there are per-session shared resources, as described above, and as pertains
93 * to these per-session resources A is no different from B. Once either terminates, these resources
94 * are not usable and shall be cleaned up as soon as possible to free RAM/etc.
95 * - There may be multiple (active) instances of B at a given time but only one (active) instance of A.
96 * - Accordingly, A is special in that it may maintain some *per-app shared resources* (cf. per-session ones)
97 * which persist even when a given B *process* terminates (thus that A-B session ends) and are available
98 * for access both by
99 * - other concurrently active instances of B; and
100 * - any future active instances of B.
101 *
102 * More specifically/practically:
103 * - *Channels* are between the 2 processes A-B in session A-B. If B1 and B2 are instances of (client) app Bp,
104 * a channel cannot be established between B1 and B2; only A-B1 and A-B2. So channels are always *per-session*.
105 * - A *SHM area* may exist in the *per-session* scope. Hence A-B1 have a per-session SHM area; and A-B2 have
106 * a per-session SHM area. When the session ends, that SHM area goes away.
107 * - A *SHM area* may exist in the *per-app* scope. Hence A-B* have a per-app-B SHM area, which persists
108 * throughout the lifetime of (server) process A and remains available as B1, B2, ... start and stop.
109 * It disappears once A stops. It appears when the first instance of B establishes a session with A
110 * (i.e., lazily).
111 *
112 * ### Brief illustration ###
113 * Suppose A is a memory cache, while B is a cache reader of objects. A starts;
114 * B1 and B2 start; so sessions A-B1 and A-B2 now exist. Now each of B1, B2 might establish channel(s) and then
115 * use it/them to issue messages and receive messages back. Now A<->B1 channel(s) and A<->B2 channel(s) are
116 * established. No B1<->B2 channel(s) can be established. (Note: transport::Channel and other
117 * ipc::transport IPC techniques are -- in and of themselves -- session-unaware. So B1 could speak to B2.
118 * They just cannot use ipc::session to do so. ipc::session facilitates establishing channels and SHM
119 * in an organized fashion, and that organization currently does not support channels between instances of
120 * the same client application. ipc::session is not the only option for doing so.)
121 *
122 * Suppose, in this illustration, that A is responsible both for acquiring network objects (on behalf of B*)
123 * and memory-caching them. Then B1 might say, via an A-B1 channel, "give me object X." A does not have it
124 * in cache yet, so it loads it from network, and saves it in the *per-app-B* SHM area and replies (via
125 * same A-B1 channel) "here is object X: use this SHM handle X'." B1 then accesses X' directly in SHM.
126 * Say B2 also says "give me object X." It is cached, so A sends it X' again. Now, say A-B1 session ends,
127 * because B1 stops. All A-B1 channels go away -- they are per-session resources -- and any per-session-A-B1 SHM
128 * area (which we haven't mentioned in this illustration) also goes away similarly.
129 *
130 * A-B2 continues. B2 could request X again, and it would work. Say B3 now starts and requests X. Again,
131 * the per-app-B SHM area persists; A would send X' to B3 as well.
132 *
133 * Now suppose A stops, due to a restart. This ends A-B2 and A-B3 sessions; and the per-app-B SHM area goes
134 * away too. Thus the server process's lifetime encompasses all shared resources in the A-B split.
135 * Processes B2 and B3 continue, but they must await for a new active A process (instance) to appear, so that
136 * they can establish new A-B2 and A-B3 sessions. In the meantime, it is IPC no-man's-land: there is
137 * no active per-app-B shared resources (SHM in our illustration) and certainly no per-session-A-B* shared
138 * resources either. Once A-B2 and A-B3 (new) sessions are established, shared resources can begin to be
139 * acquired again.
140 *
141 * This illustrates that:
142 * - A is the cache server and expected to service multiple cache clients Bs. This is asymmetric.
143 * - A can maintain shared resources, especially SHM, that outlive any individual B process. This is asymmetric.
144 * - A-B channels are relevant only to a given A-B* session. (Such per-session SHM areas can also exist.)
145 * This is symmetric between A and a given B instance.
146 * - No shared resources survive beyond a given cache server A process. A given client B* must be prepared
147 * to establish a new session with A when another active instance of A appears, before it can access IPC
148 * channels or SHM. In that sense a given *session* is symmetric: it begins when both A and a B* are active,
149 * and it ends when either of the 2 stops.
150 *
151 * ### 2+ splits co-existing ###
152 * The above discussion concerned a particular A-B split, in which by definition A is the server (only 1 active
153 * instance at a time), while B is the client (0+ active instances at a time).
154 *
155 * Take A, in split A-B. Suppose there is app Cp also. An A-C split is also possible (as is A-D, A-E, etc.).
156 * Everything written so far applies in natural fashion. Do note, however, that the per-app scope applies to
157 * a given (client) application, not all client applications. So the per-app-B SHM area is independent of the
158 * per-app-C SHM area (both maintained by A). Once the 1st instance of B establishes a session, that SHM area
159 * is lazily created. Once the 1st instance of C does the same, that separate SHM area is lazily created.
160 * So B1, B2, ... access one per-app SHM area, while C1, C2, ... access another.
161 *
162 * Now consider app K, in split K-A. Here K is the server, A is the client. This, also, is allowed, despite
163 * the fact A is server in splits A-B, A-C. However, there is a natural constraint on A: there can only be
164 * one active process of it at a time, because it is the server in at least 1 split. It can be a client to
165 * server K; but there would only ever be 1 instance of it establishing sessions against K.
166 *
167 * Informally: This is not necessarily frowned upon. After all the ability to have multiple concurrently active
168 * processes of a given app is somewhat exotic in the first place. That said, very vaguely speaking, it is more
169 * flexible to design a given app to only be server in every split in which it participates.
170 *
171 * ### Overview of relevant APIs ###
172 * With the above explained, here is how the ipc::session API operates over these various ideas.
173 *
174 * The simplest items are App (description of an application, which might a client or a server or both),
175 * Client_app (description of an application in its role as a client), and Server_app (you get the idea).
176 * See their doc headers, of course, but basically these are very simple data stores describing the basic
177 * structure of the IPC universe. Each application generally shall load the same values into its master
178 * lists of these structures. References to immutable Client_app and Server_app objects are passed into
179 * actual APIs having to do with the Session concept, to establish who can establish sessions with whom and
180 * how. Basically they describe the allowed splits.
181 *
182 * As noted at the very top, the real goal is to open channels between processes and possibly to share data in
183 * SHM between them and others. To get there for a given process pair A-B, one must establish session A-B, as
184 * described above. Having chosen which one is A (server) and which is B (client), and loaded Client_app
185 * and Server_app structures to that effect, it is time to manage the sessions.
186 *
187 * An established session is said to be a session in PEER state and is represented on each side by an object
188 * that implements the Session concept (see its important doc header). On the client side, this impl
189 * is the class template #Client_session. On the server side, this impl is the class template #Server_session.
190 * Once each respective side has its PEER-state Session impl object, opening channels and operating SHM areas
191 * on a per-session basis is well documented in the Session (concept) doc header and is fully symmetrical
192 * in terms of the API.
193 *
194 * #Client_session does not begin in PEER state. One constructs it in NULL state, then invokes
195 * `Client_session::sync_connect()` to connect to the server process if any exists; once it fires its handler
196 * successfully, the #Client_session is a Session in PEER state. If #Client_session, per Session concept requirements,
197 * indicates the session has finished (due to the other side ending session), one must create a new #Client_session
198 * and start over (w/r/t IPC and relevant shared resources).
199 *
200 * Asymmetrically, on the server side, one must be ready to open potentially multiple `Server_session`s.
201 * Firstly create a Session_server (see its doc header). To open 1 #Server_session, default-construct one
202 * (hence in NULL state), then pass it as the target to Session_server::async_accept(). Once it fires
203 * your handler, you have an (almost-)PEER state Server_session, and moreover you may call
204 * `Server_session::client_app()` to determine the identity of the connecting client app
205 * (via Client_app) which should (in multi-split situations) help decide what to further do with this
206 * Server_session (also, as on the opposing side, now a PEER-state Session concept impl).
207 * (If A participates in splits A-B and A-C, then the types of IPC work it might do
208 * with a B1 or B2 is likely to be quite different from same with a C1 or C2 or C3. If only split A-B is relevant
209 * to A, then that is not a concern.)
210 *
211 * As noted, in terms of per-session shared resources, most notably channel communication, a `Server_session` and
212 * `Client_session` have identical APIs with identical capabilities, each implementing the PEER-state Session concept
213 * to the letter.
214 *
215 * ### SHM ###
216 * Extremely important (for performance at least) functionality is provided in the sub-namespace of ipc::session:
217 * ipc::session::shm. Please read its doc header now before using the types directly within ipc::session.
218 * That will allow you to make an informed choice.
219 *
220 * Design thoughts / Extensibility / Future work
221 * ---------------------------------------------
222 * If one looks at various Flow-IPC modules outside of ipc::session (e.g.: unstructured transport ipc::transport,
223 * structured transport ipc::transport::struc, SHM-providers SHM-classic ipc::shm::classic and SHM-jemalloc
224 * ipc::shm::arena_lend::jemalloc), one might notice a repeating pattern in the docs. Given such a module M:
225 * - Module M can be used independently. (E.g, you can create a transport::Native_socket_stream and connect it
226 * to another, without involving any other major module in Flow-IPC. You can create/access a SHM-classic arena
227 * by directly instantiating a shm::classic::Pool_arena across 2 processes.)
228 * - ...However: it's easier and recommended to instead use ipc::session, which will take care of various,
229 * practically speaking, difficult and annoying activities for you. You'll just get your desired module-M
230 * "thing" in ready-to-go state, so you can just use it. (E.g., open a `Session`, and you will have N channels
231 * already opened, each one with a connected `Native_socket_stream` inside; you specify N when opening said
232 * `Session`. You can open more such channels on-demand too. You will have SHM arena(s), of specified type,
233 * available. All this without specifying any SHM-pool name(s), Unix-domain socket name(s), etc.)
234 *
235 * That is, of course, good. There is something of a bird's-eye-view *design catch* to this, though. Consider
236 * module M itself. Typically each M is designed so that the user can, themselves, extend things within it --
237 * without touching Flow-IPC code itself. (E.g., ipc::transport defines concepts like Blob_sender and Blob_receiver,
238 * so if you want to do low-level transport that Flow-IPC doesn't provide, you can implement them -- and then
239 * plug-in to the higher layer transport::struc, as another example, so that structured messages can travel over
240 * your new transport.) Now to get closer to describing the aforementioned *catch*:
241 *
242 * Various modules M1, M2, ... can sometimes -- where it's natural at least -- directly plug-in to each other.
243 * (E.g., again: struc::Channel will work given any impls of the Blob_sender, Blob_receiver et al concepts, provided
244 * one passes-in instance(s) of such an impl already in PEER -- a/k/a connected -- state.) However, in practice,
245 * for everything to work together, it's best to use ipc::session. The *catch* is this:
246 * - ipc::session, viewed from the point of view of a Flow-IPC *maintainer/developer*, is -- yes -- reasonably
247 * extensible so as to support extensions to modules M1, M2, .... (There's a hierarchy, the Session concept,
248 * a documented internal capnp schema for channel-opening, reusable pieces; all that good stuff.)
249 * - ...However: ipc::session, viewed from the point of view of a Flow-IPC *user* (who does not modify Flow-IPC
250 * code itself) is *not formally extensible* so as to support extensions to modules M1, M2, .... A user -- you --
251 * wouldn't be able to just subclass some ipc::session classes and, boom, you can now open `Session`s that
252 * can (e.g.) open channels with your new type of `Blob_sender`/`Blob_receiver` over some cool IPC primitive
253 * Flow-IPC doesn't already handle. You'd pretty much have to fork an ipc::session code-base and add to it
254 * as needed. So the preceding bullet would apply -- that's good; but without modifying Flow-IPC you can't
255 * proceed -- that's (all else being equal) not as good.
256 *
257 * In short: ipc::session is reasonably extensible by adding to Flow-IPC's own ipc::session code; but it is not
258 * directly extensible by merely adding one's own `session`-y code on top. Thus: ipc::session -- which ties
259 * together most other modules in Flow-IPC -- is not itself user-extensible at the moment, while those other modules
260 * are user-extensible.
261 *
262 * Future work can certainly tackle this, rejiggering ipc::session in such a way as to make it extensible.
263 * It is a matter of priorities. So far, historically, the from-day-1 concept-y design of the other modules has
264 * has paid for itself; e.g., pluggability of different low-level IPC primitives makes both use and dev of Flow-IPC much
265 * more pleasant than the counterfactual; same thing w/r/t conceptual classification of SHM-providers as arena-sharing
266 * versus arena-lending (see ipc::shm doc header if interested). ipc::session,
267 * however, is by its nature a meta-module that pulls together other modules, so making it *itself* extensible is...
268 * hmm. Let's say it's a meta-challenge. Designing it that way from day 1, at least for the author writing this
269 * (ygoldfel), would've involved an unreasonable amount of foreknowledge. In short, it was too hard to predict the
270 * best way to do it. It is easier now that all the modules M1, M2, ... exist and have been plugged in to this
271 * ecosystem; but it's still no joke.
272 *
273 * `sync_io`: integrate with `poll()`-ish event loops
274 * --------------------------------------------------
275 * ipc::session APIs feature exactly the following asynchronous (blocking, background, not-non-blocking, long...)
276 * operations:
277 * - ipc::session::Session on-error and (optionally) on-passive-channel-open handlers.
278 * - `ipc::session::Client_session::async_connect()` (same for other, including SHM-aware, variants).
279 * - ipc::session::Session_server::async_accept() (same for SHM-aware variants).
280 *
281 * All APIs mentioned so far operation broadly in the async-I/O pattern: Each event in question is reported from
282 * some unspecified background thread; it is up to the user to "post" the true handling onto their worker thread(s)
283 * as desired.
284 *
285 * If one desires to be informed, instead, in a fashion friendly to old-school reactor loops -- centered on
286 * `poll()`, `epoll_wait()`, or similar -- a `sync_io` alternate API is available. It is no faster, but it may
287 * be more convenient for some applications.
288 *
289 * To use the alternate `sync_io` interface: Look into session::sync_io and its 3 adapter templates:
290 * - ipc::session::sync_io::Server_session_adapter;
291 * - ipc::session::sync_io::Client_session_adapter;
292 * - ipc::session::sync_io::Session_server_adapter.
293 *
294 * Exactly the aforementioned async APIs are affected. All other APIs are available without change.
295 */
296namespace ipc::session
297{
298
299// Types.
300
301/// Convenience alias for the commonly used type util::Shared_name.
303
304/// Convenience alias for the commonly used type transport::struc::Session_token.
306
307// Find doc headers near the bodies of these compound types.
308
309struct App;
310struct Server_app;
311struct Client_app;
312
313class Session_cfg;
314
315template<typename Master_structured_channel_t>
316class Info_collector;
317
318template<typename Session_impl_t>
319class Session_mv;
320
321template<typename Server_session_impl_t>
323template<typename Client_session_impl_t>
325
326template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload = ::capnp::Void>
327class Session_server;
328
329/**
330 * A vanilla `Server_session` with no optional capabilities. See Server_session_mv (+doc header) for full API as
331 * well as its doc header for possible alternatives that add optional capabilities (such as, at least, SHM
332 * setup/access). Opposing peer object: #Client_session. Emitted by: Session_server.
333 *
334 * The following important template parameters are *knobs* that control the properties of the session;
335 * the opposing #Client_session must use identical settings.
336 *
337 * @tparam MQ_TYPE_OR_NONE
338 * Identical to #Client_session.
339 * @tparam TRANSMIT_NATIVE_HANDLES
340 * Identical to #Client_session.
341 * @tparam Mdt_payload
342 * See Session concept. In addition the same type may be used for `mdt_from_cli_or_null` (and srv->cli
343 * counterpart) in Session_server::async_accept(). (Recall that you can use a capnp-`union` internally
344 * for various purposes.)
345 *
346 * @see Server_session_mv for full API and its documentation.
347 * @see Session: implemented concept.
348 */
349template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload = ::capnp::Void>
352
353/**
354 * A vanilla `Client_session` with no optional capabilities. See Client_session_mv (+doc header) for full API as
355 * well as its doc header for possible alternatives that add optional capabilities (such as, at least, SHM
356 * setup/access). Opposing peer object: #Server_session.
357 *
358 * The following important template parameters are *knobs* that control the properties of the session;
359 * the opposing #Server_session must use identical settings.
360 *
361 * @tparam MQ_TYPE_OR_NONE
362 * Session::Channel_obj (channel openable via `open_channel()` on this or other side) type config:
363 * Enumeration constant that specifies which type of MQ to use (corresponding to all available
364 * transport::Persistent_mq_handle concept impls) or to not use one (`NONE`). Note: This `enum` type is
365 * capnp-generated; see `common.capnp` for values and brief docs.
366 * @tparam TRANSMIT_NATIVE_HANDLES
367 * Session::Channel_obj (channel openable via `open_channel()` on this or other side) type config:
368 * Whether it shall be possible to transmit a native handle via the channel.
369 * @tparam Mdt_payload
370 * See Session concept. In addition the same type may be used for `mdt` or `mdt_from_srv_or_null`
371 * in `*_connect()`. (If it is used for `open_channel()` and/or passive-open and/or `*connect()`
372 * `mdt` and/or `mdt_from_srv_or_null`, recall that you can use a capnp-`union` internally for various
373 * purposes.)
374 *
375 * @see Client_session_mv for full API and its documentation.
376 * @see Session: implemented concept.
377 */
378template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES,
379 typename Mdt_payload = ::capnp::Void>
382
383// Free functions.
384
385/**
386 * Utility, used internally but exposed in public API in case it is of general use, that checks that the
387 * owner of the given resource (at the supplied file system path) is
388 * as specified in the given App (App::m_user_id et al). If the resource cannot be accessed (not found,
389 * permissions...) that system Error_code shall be emitted. If it can, but the owner does not match,
390 * error::Code::S_RESOURCE_OWNER_UNEXPECTED shall be emitted.
391 *
392 * @param logger_ptr
393 * Logger to use for logging (WARNING, on error only, including `S_RESOURCE_OWNER_UNEXPECTED`).
394 * @param path
395 * Path to resource. Symlinks are followed, and the target is the resource in question (not the symlink).
396 * @param app
397 * Describes the app with the expected owner info prescribed therein.
398 * @param err_code
399 * See `flow::Error_code` docs for error reporting semantics. #Error_code generated:
400 * error::Code::S_RESOURCE_OWNER_UNEXPECTED (check did not pass),
401 * system error codes if ownership cannot be checked.
402 */
403void ensure_resource_owner_is_app(flow::log::Logger* logger_ptr, const fs::path& path, const App& app,
404 Error_code* err_code = nullptr);
405
406/**
407 * Identical to the other ensure_resource_owner_is_app() overload but operates on a pre-opened `Native_handle`
408 * (a/k/a handle, socket, file descriptor) to the resource in question.
409 *
410 * @param logger_ptr
411 * See other overload.
412 * @param handle
413 * See above. `handle.null() == true` causes undefined behavior (assertion may trip).
414 * Closed/invalid/etc. handle will yield civilized Error_code emission.
415 * @param app
416 * See other overload.
417 * @param err_code
418 * See `flow::Error_code` docs for error reporting semantics. #Error_code generated:
419 * error::Code::S_RESOURCE_OWNER_UNEXPECTED (check did not pass),
420 * system error codes if ownership cannot be checked (invalid descriptor, un-opened descriptor, etc.).
421 */
422void ensure_resource_owner_is_app(flow::log::Logger* logger_ptr, util::Native_handle handle, const App& app,
423 Error_code* err_code = nullptr);
424
425
426/**
427 * Prints string representation of the given `App` to the given `ostream`.
428 *
429 * @relatesalso App
430 *
431 * @param os
432 * Stream to which to write.
433 * @param val
434 * Object to serialize.
435 * @return `os`.
436 */
437std::ostream& operator<<(std::ostream& os, const App& val);
438
439/**
440 * Prints string representation of the given `Client_app` to the given `ostream`.
441 *
442 * @relatesalso Client_app
443 *
444 * @param os
445 * Stream to which to write.
446 * @param val
447 * Object to serialize.
448 * @return `os`.
449 */
450std::ostream& operator<<(std::ostream& os, const Client_app& val);
451
452/**
453 * Prints string representation of the given `Server_app` to the given `ostream`.
454 *
455 * @relatesalso Server_app
456 *
457 * @param os
458 * Stream to which to write.
459 * @param val
460 * Object to serialize.
461 * @return `os`.
462 */
463std::ostream& operator<<(std::ostream& os, const Server_app& val);
464
465/**
466 * Prints the entire Info_collector stats bundle to the given `ostream`, formatted per `val.m_fmt`
467 * (see Info_collector doc header); or a note that the stats are unavailable, if `!val.master_channel_live()`.
468 *
469 * @relatesalso Info_collector
470 *
471 * @param os
472 * Stream to which to write.
473 * @param val
474 * Object to serialize.
475 * @return `os`.
476 */
477template<typename Master_structured_channel_t>
478std::ostream& operator<<(std::ostream& os,
480
481/**
482 * Prints string representation of the given `Session_mv` to the given `ostream`.
483 *
484 * @relatesalso Session_mv
485 *
486 * @param os
487 * Stream to which to write.
488 * @param val
489 * Object to serialize.
490 * @return `os`.
491 */
492template<typename Session_impl_t>
493std::ostream& operator<<(std::ostream& os,
494 const Session_mv<Session_impl_t>& val);
495
496/**
497 * Prints string representation of the given `Server_session_mv` to the given `ostream`.
498 *
499 * @relatesalso Server_session_mv
500 *
501 * @param os
502 * Stream to which to write.
503 * @param val
504 * Object to serialize.
505 * @return `os`.
506 */
507template<typename Server_session_impl_t>
508std::ostream& operator<<(std::ostream& os,
510
511/**
512 * Prints string representation of the given `Client_session_mv` to the given `ostream`.
513 *
514 * @relatesalso Client_session_mv
515 *
516 * @param os
517 * Stream to which to write.
518 * @param val
519 * Object to serialize.
520 * @return `os`.
521 */
522template<typename Client_session_impl_t>
523std::ostream& operator<<(std::ostream& os, const Client_session_mv<Client_session_impl_t>& val);
524
525/**
526 * Prints string representation of the given `Session_server` to the given `ostream`.
527 *
528 * @relatesalso Session_server
529 *
530 * @param os
531 * Stream to which to write.
532 * @param val
533 * Object to serialize.
534 * @return `os`.
535 */
536template<schema::MqType MQ_TYPE_OR_NONE, bool TRANSMIT_NATIVE_HANDLES, typename Mdt_payload>
537std::ostream& operator<<(std::ostream& os,
539
540} // namespace ipc::session
541
542/**
543 * `sync_io`-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::session.
544 *
545 * In this case they are given as only a small handful of adapter templates. Just check out their doc headers.
546 */
548{
549
550// Types.
551
552template<typename Session>
554template<typename Session>
556template<typename Session_server>
558
559// Free functions.
560
561/**
562 * Prints string representation of the given `Server_session_adapter` to the given `ostream`.
563 *
564 * @relatesalso Server_session_adapter
565 *
566 * @param os
567 * Stream to which to write.
568 * @param val
569 * Object to serialize.
570 * @return `os`.
571 */
572template<typename Session>
573std::ostream& operator<<(std::ostream& os,
575
576/**
577 * Prints string representation of the given `Client_session_adapter` to the given `ostream`.
578 *
579 * @relatesalso Client_session_adapter
580 *
581 * @param os
582 * Stream to which to write.
583 * @param val
584 * Object to serialize.
585 * @return `os`.
586 */
587template<typename Session>
588std::ostream& operator<<(std::ostream& os,
590
591/**
592 * Prints string representation of the given `Session_server_adapter` to the given `ostream`.
593 *
594 * @relatesalso Session_server_adapter
595 *
596 * @param os
597 * Stream to which to write.
598 * @param val
599 * Object to serialize.
600 * @return `os`.
601 */
602template<typename Session_server>
603std::ostream& operator<<(std::ostream& os,
605
606} // namespace ipc::session::sync_io
Implements Session concept on the Client_app end: a Session_mv that first achieves PEER state by conn...
Bundles access to stats from the session master channel (SMC) – the internal struc::Channel each Sess...
Implements Session concept on the Server_app end: a Session that is emitted in almost-PEER state by l...
Grouping of compile-time config/knobs (as of this writing: constants) governing some of the behavior ...
Definition: session_cfg.hpp:44
Implements the Session concept when it is in PEER state.
Definition: session.hpp:558
To be instantiated typically once in a given process, an object of this type asynchronously listens f...
sync_io-pattern counterpart to async-I/O-pattern session::Client_session types and all their SHM-awar...
sync_io-pattern counterpart to async-I/O-pattern session::Server_session types and all their SHM-awar...
sync_io-pattern counterpart to async-I/O-pattern session::Session_server types and all their SHM-awar...
String-wrapping abstraction representing a name uniquely distinguishing a kernel-persistent entity fr...
sync_io-pattern counterparts to async-I/O-pattern object types in parent namespace ipc::session.
std::ostream & operator<<(std::ostream &os, const Server_session_adapter< Session > &val)
Prints string representation of the given Server_session_adapter to the given ostream.
Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...
Definition: app.cpp:29
std::ostream & operator<<(std::ostream &os, const App &val)
Prints string representation of the given App to the given ostream.
Definition: app.cpp:130
util::Shared_name Shared_name
Convenience alias for the commonly used type util::Shared_name.
void ensure_resource_owner_is_app(flow::log::Logger *logger_ptr, const fs::path &path, const App &app, Error_code *err_code)
Utility, used internally but exposed in public API in case it is of general use, that checks that the...
Definition: app.cpp:33
transport::struc::Session_token Session_token
Convenience alias for the commonly used type transport::struc::Session_token.
boost::uuids::uuid Session_token
A type used by struc::Channel for internal safety/security/auth needs.
Definition: struc_fwd.hpp:121
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:313
A description of an application in this ipc::session inter-process communication universe.
Definition: app.hpp:88
An App that is used as a client in at least one client-server IPC split.
Definition: app.hpp:220
An App that is used as a server in at least one client-server IPC split.
Definition: app.hpp:241
A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.