Flow-IPC 1.0.0
Flow-IPC project: Full implementation reference.
msg_mdt_out.hpp
Go to the documentation of this file.
1/* Flow-IPC: Structured Transport
2 * Copyright (c) 2023 Akamai Technologies, Inc.; and other contributors.
3 * Each commit is copyright by its respective author or author's employer.
4 *
5 * Licensed under the MIT License:
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE. */
24
25/// @file
26#pragma once
27
29#include "ipc/transport/struc/schema/detail/structured_msg.capnp.h"
30#include <boost/endian.hpp>
31
33{
34
35// Types.
36
37/**
38 * Internally used (data-free) addendum on-top of Msg_out; really an alias
39 * to `Msg_out<schema::detail::StructuredMessage>`, where the latter is the internal-use
40 * set of metadata schema, with a convenience public mutating API wrapping around capnp-generated mutator API
41 * for things like message ID.
42 *
43 * @see Msg_in whose `public` + `protected` API = essentially the accessor counterpart of
44 * Msg_mdt_out and Msg_out<Message_body> mutator APIs.
45 *
46 * @tparam Struct_builder_config
47 * See struc::Channel.
48 */
49template<typename Struct_builder_config>
51 private Msg_out<schema::detail::StructuredMessage, typename Struct_builder_config::Builder>
52{
53private:
54 // Types.
55
56 /// Our base class.
58
59 /// Short-hand for capnp-generated mutating `Builder` nested class of #Body. See body_root().
61
62public:
63 // Types.
64
65 /// Short-hand for user-specified builder engine.
66 using Builder_config = Struct_builder_config;
67
68 /**
69 * In the event `*this` describes an internally-created message -- for internal purposes, not by the user --
70 * this is the equivalent of `Base::Body_builder` for the internal-message schema.
71 * Refer to structured_msg.capnp for clarity; you'll see a field there that stores either
72 * an `InternalMessageBody` or null.
73 */
75
76 // Constructors/destructor.
77
78 /**
79 * Constructs out-metadata-message describing a user-created message (not an internal message);
80 * or else both describing and containing an internal message (no user-created message associated).
81 *
82 * @param struct_builder_config
83 * See other ctor.
84 * @param session_token
85 * See other ctor.
86 * @param originating_msg_id_or_none
87 * 0 if the message is unsolicited; else the message ID of the out-message to which this
88 * is responding.
89 * @param id_or_none
90 * Out-message ID; 0 if internal message.
91 * @param n_serialization_segments_or_none
92 * # of segments serializing the user-created message described by `*this`; ignored
93 * if `id_or_none == 0`.
94 */
95 explicit Msg_mdt_out(const Builder_config& struct_builder_config,
96 const Session_token& session_token, msg_id_t originating_msg_id_or_none, msg_id_t id_or_none,
97 size_t n_serialization_segments_or_none);
98
99 // Methods.
100
101 /**
102 * Returns a builder for the internal-message root; to be called only if `id_or_none == 0` in ctor.
103 * (Behavior undefined/assertion may trip otherwise.) See #Internal_msg_body_builder doc header.
104 *
105 * We could return a pointer to something stored, but as of this writing such an optimization would
106 * be pointless, as it's really invoked just once in practice.
107 *
108 * @return See above.
109 */
111
112 /**
113 * Forwards to Msg_out::body_root() (`const` overload). May be useful for, say, pretty-printing it
114 * to log (e.g.: `capnp::prettyPrint(M.body_root()->asReader()).flatten().cStr()`).
115 *
116 * @return See above.
117 */
118 const Body_builder* body_root() const;
119
120 /**
121 * Returns the serialization in the form of a sequence of 1 `Blob`. Behavior is undefined if it is called
122 * more than once. (In reality it's probably fine, but this internal type and its API aren't meant for that,
123 * so it's easier to just say that and not worry about it.)
124 *
125 * ### Wait, why 1 Blob? ###
126 * This is an internal-use structure, and we've ensured "heuristically" it'll fit in any reasonable segment.
127 *
128 * @param err_code
129 * See `flow::Error_code` docs for error reporting semantics. See Msg_out::emit_serialization()
130 * which is the core of this guy here.
131 * @param session
132 * Specifies the opposing recipient for which the serialization is intended.
133 * See Msg_out::emit_serialization() which is the core of this guy here.
134 * @return What Msg_out::emit_serialization() would have placed in the target list container.
135 * In our case that container must have size 1, so we just return this.
136 */
137 flow::util::Blob* emit_serialization(const typename Base::Builder::Session& session, Error_code* err_code) const;
138}; // class Msg_mdt_out
139
140// Template implementations.
141
142template<typename Struct_builder_config>
144 (const Builder_config& struct_builder_config, const Session_token& session_token,
145 msg_id_t originating_msg_id_or_none, msg_id_t id_or_none, size_t n_serialization_segments_or_none) :
146
147 Base(struct_builder_config)
148{
149 using boost::endian::native_to_little;
150
151 const auto msg_root = Base::body_root();
152
153 /* Refer to structured_msg.capnp StructuredMessage. Base has initialized it for us. Now to fill it in:
154 * It is *now* serialization/send time, so we fill in everything.
155 * Let's go over it:
156 * - authHeader.sessionToken: We set it here.
157 * - id: It is used as a sequence #. We set it here; it may be zero indicating internal message.
158 * - originatingMessageOrNull: Used if and only if this is a response to a past incoming message.
159 * We set it here if so directed.
160 * - internalMessageBody: Similarly we initialize it if so directed. It's not dependent on any template params
161 * BTW. */
162
163 // Deal with sessionToken. Encode as mandated in .capnp Uuid doc header. @todo Factor this out into a util method.
164 auto capnp_uuid = msg_root->initAuthHeader().initSessionToken();
165 static_assert(std::remove_reference_t<decltype(session_token)>::static_size() == 2 * sizeof(uint64_t),
166 "World is broken: UUIDs expected to be 16 bytes!");
167 auto& first8 = *(reinterpret_cast<const uint64_t*>(session_token.data)); // capnp_uuid is aligned OK, so this is too.
168 auto& last8 = *(reinterpret_cast<const uint64_t*>(session_token.data + sizeof(uint64_t))); // As is this.
169 capnp_uuid.setFirst8(native_to_little(first8)); // Reminder: Likely no-op + copy of uint64_t.
170 capnp_uuid.setLast8(native_to_little(last8)); // Ditto.
171
172 msg_root->setId(id_or_none);
173
174 if (originating_msg_id_or_none != 0)
175 {
176 msg_root->initOriginatingMessageOrNull().setId(originating_msg_id_or_none);
177 }
178
179 if (id_or_none == 0)
180 {
181 msg_root->initInternalMessageBody();
182 }
183 else
184 {
185 assert((n_serialization_segments_or_none != 0)
186 && "If serializing a user message, you have to have some segs for it.");
187 msg_root->setNumBodySerializationSegments(n_serialization_segments_or_none);
188 }
189} // Msg_mdt_out::Msg_mdt_out()
190
191template<typename Struct_builder_config>
194{
195 return Base::body_root()->getInternalMessageBody();
196}
197
198template<typename Struct_builder_config>
201{
202 return Base::body_root();
203}
204
205template<typename Struct_builder_config>
206flow::util::Blob* Msg_mdt_out<Struct_builder_config>::emit_serialization(const typename Base::Builder::Session& session,
207 Error_code* err_code) const
208{
209 Segment_ptrs target_blobs;
210 Base::emit_serialization(&target_blobs, session, err_code);
211
212 assert((!target_blobs.empty()) && "That is just weird.");
213 assert((target_blobs.size() == 1) && "As described in our contract we should have ensured this internal-use "
214 "structure shall fit in one segment no matter the builder. Bug?");
215
216 return target_blobs.front();
217}
218
219} // namespace ipc::transport::struc
Internally used (data-free) addendum on-top of Msg_out; really an alias to Msg_out<schema::detail::St...
Definition: msg_mdt_out.hpp:52
Msg_mdt_out(const Builder_config &struct_builder_config, const Session_token &session_token, msg_id_t originating_msg_id_or_none, msg_id_t id_or_none, size_t n_serialization_segments_or_none)
Constructs out-metadata-message describing a user-created message (not an internal message); or else ...
Internal_msg_body_builder internal_msg_body_root()
Returns a builder for the internal-message root; to be called only if id_or_none == 0 in ctor.
flow::util::Blob * emit_serialization(const typename Base::Builder::Session &session, Error_code *err_code) const
Returns the serialization in the form of a sequence of 1 Blob.
typename Base::Body_builder Body_builder
Short-hand for capnp-generated mutating Builder nested class of Body. See body_root().
Definition: msg_mdt_out.hpp:60
const Body_builder * body_root() const
Forwards to Msg_out::body_root() (const overload).
Struct_builder_config Builder_config
Short-hand for user-specified builder engine.
Definition: msg_mdt_out.hpp:66
typename Base::Body::InternalMessageBody::Builder Internal_msg_body_builder
In the event *this describes an internally-created message – for internal purposes,...
Definition: msg_mdt_out.hpp:74
A structured out-message suitable to be sent via struc::Channel::send().
Definition: msg.hpp:154
typename Body::Builder Body_builder
Short-hand for capnp-generated mutating Builder nested class of Body. See body_root().
Definition: msg.hpp:162
Body_builder * body_root()
The Body root capnp-generated mutator object.
Definition: msg.hpp:1018
Builder< ipc::shm::classic::Pool_arena > Builder
Convenience alias: transport::struc::shm::Builder that works with boost.ipc.shm pools from ipc::shm::...
Definition: classic_fwd.hpp:36
Sub-module of Flow-IPC module ipc::transport providing transmission of structured messages specifical...
Definition: channel.cpp:31
boost::uuids::uuid Session_token
A type used by struc::Channel for internal safety/security/auth needs.
Definition: struc_fwd.hpp:113
std::vector< flow::util::Blob * > Segment_ptrs
Sequence of 1+ Blob pointers to blobs which must stay alive while these pointers may be dereferenced,...
Definition: struc_fwd.hpp:122
uint64_t msg_id_t
Message ID uniquely identifying outgoing message (Msg_out, among all other Msg_outs),...
Definition: struc_fwd.hpp:145
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:297