Flow-IPC 1.0.1
Flow-IPC project: Full implementation reference.
protocol_negotiator.cpp
Go to the documentation of this file.
1/* Flow-IPC: Core
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
22#include <flow/error/error.hpp>
23
24namespace ipc::transport
25{
26
27Protocol_negotiator::Protocol_negotiator(flow::log::Logger* logger_ptr, util::String_view nickname,
28 proto_ver_t local_max_proto_ver, proto_ver_t local_min_proto_ver) :
29 flow::log::Log_context(logger_ptr, Log_component::S_TRANSPORT),
30 m_nickname(nickname),
31 m_local_max_proto_ver(local_max_proto_ver),
32 m_local_min_proto_ver(local_min_proto_ver),
33 m_local_max_proto_ver_sent(false),
34 m_negotiated_proto_ver(S_VER_UNKNOWN)
35{
36 assert((m_local_min_proto_ver > 0) && "Broke contract.");
37 assert((m_local_max_proto_ver >= m_local_min_proto_ver) && "Broke contract.");
38
39 FLOW_LOG_INFO("Protocol_negotiator [" << m_nickname << "]: We speak protocol version range "
40 "[" << m_local_min_proto_ver << ", " << m_local_max_proto_ver << "].");
41}
42
45
47{
48 operator=(std::move(src));
49}
50
52{
53 if (this != &src)
54 {
55 operator=(static_cast<const Protocol_negotiator&>(src));
56 // This (which satisfies our contract, to make src as-if-just-cted) is the only reason we're not `= default`:
57 src.reset();
58 }
59 return *this;
60}
61
63{
66}
67
69{
71}
72
74{
75 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(bool, Protocol_negotiator::compute_negotiated_proto_ver,
76 opposing_max_proto_ver, _1);
77 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
78
80 {
81 FLOW_LOG_TRACE("Protocol_negotiator [" << m_nickname << "]: We were asked to compute negotiated protocol version "
82 "based on opposing max-version [" << opposing_max_proto_ver << "]; but we have already done so "
83 "in the past (result: [" << negotiated_proto_ver() << "]); no-op. "
84 "Tip: Check for negotiated_proto_ver()=UNKNOWN before calling us.");
85 return false;
86 }
87 // else: As advertised we validate opposing_max_proto_ver for the caller first.
88
89 if (opposing_max_proto_ver <= 0)
90 {
91 FLOW_LOG_WARNING("Protocol_negotiator [" << m_nickname << "]: Negotiation computation: "
92 "We speak preferred (highest) version [" << m_local_max_proto_ver << "]; "
93 "they speak at most [" << opposing_max_proto_ver << "]. The latter value is in and of itself "
94 "invalid -- we cannot trust the other side at all; or there may be a bug in user code here. "
95 "Presumably we will abruptly close this comm pathway shorly.");
98 }
99 // Use the simple algorithm explained/justified in class doc header.
100
101 else if (m_local_max_proto_ver <= opposing_max_proto_ver)
102 {
103 FLOW_LOG_INFO("Protocol_negotiator [" << m_nickname << "]: Negotiation computation: "
104 "We speak preferred (highest) version [" << m_local_max_proto_ver << "]; "
105 "they speak at most [" << opposing_max_proto_ver << "]; therefore we shall speak "
106 "[" << m_local_max_proto_ver << "], unless opposing side lacks backwards-compatibility with it, "
107 "in which case it will abruptly close this comm pathway shortly.");
109 }
110 else if (opposing_max_proto_ver >= m_local_min_proto_ver)
111 {
112 FLOW_LOG_INFO("Protocol_negotiator [" << m_nickname << "]: Negotiation computation: "
113 "We speak preferred (highest) version [" << m_local_max_proto_ver << "]; "
114 "they speak at most [" << opposing_max_proto_ver << "]; therefore we shall speak "
115 "[" << opposing_max_proto_ver << "], as we are backwards-compatible with that version.");
117 }
118 else
119 {
120 FLOW_LOG_WARNING("Protocol_negotiator [" << m_nickname << "]: Negotiation computation: "
121 "We speak preferred (highest) version [" << m_local_max_proto_ver << "]; "
122 "they speak at most [" << opposing_max_proto_ver << "]; therefore we lack backwards-compatibility "
123 "with that older version. Presumably we will abruptly close this comm pathway shorly.");
126 }
127
128 return true;
129} // Protocol_negotiator::compute_negotiated_proto_ver()
130
132{
134 {
135 return S_VER_UNKNOWN; // Don't spam logs; they might be calling this for every out-message.
136 }
137 // else
138 FLOW_LOG_INFO("Protocol_negotiator [" << m_nickname << "]: About to send our preferred (highest) version "
139 "[" << m_local_max_proto_ver << "] to opposing side for the first and only time.");
142}
143
144} // namespace ipc::transport
A simple state machine that, assuming the opposide side of a comm pathway uses an equivalent state ma...
static constexpr proto_ver_t S_VER_UNSUPPORTED
A proto_ver_t value, namely zero, which is a reserved value indicating "unsupported version"; it is n...
void reset()
Resets the negotiation state, meaning back to the state as-if just after ctor invoked.
std::string m_nickname
The nickname from ctor. Not const so as to support copyability.
int16_t proto_ver_t
Type sufficient to store a protocol version; positive values identify newer versions of a protocol; w...
Protocol_negotiator(flow::log::Logger *logger_ptr, util::String_view nickname, proto_ver_t local_max_proto_ver, proto_ver_t local_min_proto_ver)
Constructs a comm pathway's negotiator object in initial state wherein: (1) negotiated_proto_ver() re...
proto_ver_t local_max_proto_ver_for_sending()
To be called at most once, this returns local_max_proto_ver from ctor the first time and S_VER_UNKNOW...
bool compute_negotiated_proto_ver(proto_ver_t opposing_max_proto_ver, Error_code *err_code=0)
Based on the presumably-just-received-from-opposing-side value of their local_max_proto_ver,...
proto_ver_t m_local_max_proto_ver
local_max_proto_ver from ctor. Not const so as to support copyability.
proto_ver_t negotiated_proto_ver() const
Returns S_VER_UNKNOWN before compute_negotiated_proto_ver(); then either the positive version of the ...
static constexpr proto_ver_t S_VER_UNKNOWN
A proto_ver_t value, namely a negative one, which is a reserved value indicating "unknown version"; i...
proto_ver_t m_negotiated_proto_ver
See negotiated_proto_ver().
proto_ver_t m_local_min_proto_ver
local_min_proto_ver from ctor. Not const so as to support copyability.
bool m_local_max_proto_ver_sent
Init value false indicating has local_max_proto_ver_for_sending() has not been called; subsequently t...
Protocol_negotiator & operator=(const Protocol_negotiator &src)
Copy-assigns *this to be equal to src.
@ S_PROTOCOL_NEGOTIATION_OPPOSING_VER_INVALID
In protocol negotiation, opposing side sent invalid version value (not positive, not a number,...
@ S_PROTOCOL_NEGOTIATION_OPPOSING_VER_TOO_OLD
In protocol negotiation, opposing side reported its newest protocol version is even older than the mo...
Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...
flow::util::String_view String_view
Short-hand for Flow's String_view.
Definition: util_fwd.hpp:109
Log_component
The flow::log::Component payload enumeration containing various log components used by Flow-IPC inter...
Definition: common.hpp:322
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:297