mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-12-24 20:53:48 +01:00
Message order flip
This commit is contained in:
parent
dfdeaaefa6
commit
0c5dda057e
42
draft-fabaccess-protocol.md
Normal file
42
draft-fabaccess-protocol.md
Normal file
@ -0,0 +1,42 @@
|
||||
# Stream initiation
|
||||
|
||||
In a session there are two parties: The initiating entity and the receiving
|
||||
entity. This terminology does not refer to information flow but rather to the
|
||||
side opening a connection respectively the one listening for connection
|
||||
attempts.
|
||||
In the currently envisioned use-case the initiating entity is a) a client
|
||||
(i.e. interactive or batch/automated program) trying to interact in some way or
|
||||
other with a server b) a server trying to exchange / request information
|
||||
with/from another server (i.e. federating). The receiving entity however is
|
||||
already a server.
|
||||
|
||||
Additionally the amount and type of clients is likely to be more diverse and
|
||||
less up to date than the servers.
|
||||
Conclusions I draw from this:
|
||||
- Clients are more likely to implement an outdated version of the communication
|
||||
protocol.
|
||||
- The place for backwards-compatability should be the servers.
|
||||
- Thus the client (initiating entity) should send the expected API version
|
||||
first, the server then using that as a basis to decide with which API
|
||||
version to answer.
|
||||
|
||||
# Stream negotiation
|
||||
|
||||
Since the receiving entity for a connection is responsible for the machines it
|
||||
controls it imposes conditions for connecting either as client or as federating
|
||||
server. At least every initiating entity is required to authenticate itself to
|
||||
the receiving entity before attempting further actions or requesting
|
||||
information. But a receiving entity can require other features, such as
|
||||
transport layer encryption.
|
||||
To this end a receiving entity informs the initiating entity about features that
|
||||
it requires from the initiating entity before taking any further action and
|
||||
features that are voluntary to negotiate but may improve qualities of the stream
|
||||
(such as message compression)
|
||||
|
||||
A varying set of conditions implies negotiation needs to take place. Since
|
||||
features potentially require a strict order (e.g. Encryption before
|
||||
Authentication) negotiation has to be a multi-stage process. Further
|
||||
restrictions are imposed because some features may only be offered after others
|
||||
have been established (e.g. SASL authentication only becoming available after
|
||||
encryption, EXTERNAL mechanism only being available to local sockets or
|
||||
connections providing a certificate)
|
@ -15,38 +15,42 @@ pub async fn handle_connection(log: Logger, mut stream: TcpStream) -> Result<()>
|
||||
let program = "Difluoroborane-0.1.0";
|
||||
let version = (0u32,1u32);
|
||||
|
||||
let mut message = capnp::message::Builder::new_default();
|
||||
let greet_outer = message.init_root::<gen::message::Builder>();
|
||||
let mut greeting = greet_outer.init_greet();
|
||||
greeting.set_host(host);
|
||||
greeting.set_program(program);
|
||||
greeting.set_major(version.0);
|
||||
greeting.set_minor(version.1);
|
||||
|
||||
capnp_futures::serialize::write_message(&mut stream, message).await?;
|
||||
{
|
||||
let receive_options = capnp::message::ReaderOptions::default();
|
||||
let message = capnp_futures::serialize::read_message(&mut stream, receive_options).await.unwrap().unwrap();
|
||||
let m = message.get_root::<gen::message::Reader>().unwrap();
|
||||
|
||||
stream.flush().await?;
|
||||
|
||||
let receive_options = capnp::message::ReaderOptions::default();
|
||||
let message = capnp_futures::serialize::read_message(&mut stream, receive_options).await.unwrap().unwrap();
|
||||
let body: capnp::any_pointer::Reader = message.get_root().unwrap();
|
||||
let m = body.get_as::<gen::message::Reader>().unwrap();
|
||||
|
||||
if m.has_greet() {
|
||||
match m.which() {
|
||||
Ok(gen::message::Which::Greet(Ok(r))) => {
|
||||
println!("Host {} with program {} is saying hello. They speak API version {}.{}.",
|
||||
r.get_host().unwrap(),
|
||||
r.get_program().unwrap(),
|
||||
r.get_major(),
|
||||
r.get_minor())
|
||||
},
|
||||
_ => {
|
||||
// We *JUST* checked that it's a greeting. This can not happen
|
||||
unreachable!()
|
||||
if m.has_greet() {
|
||||
match m.which() {
|
||||
Ok(gen::message::Which::Greet(Ok(r))) => {
|
||||
println!("Host {} with program {} is saying hello. They speak API version {}.{}.",
|
||||
r.get_host().unwrap(),
|
||||
r.get_program().unwrap(),
|
||||
r.get_major(),
|
||||
r.get_minor())
|
||||
},
|
||||
_ => {
|
||||
// We *JUST* checked that it's a greeting. This can not happen
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut message = capnp::message::Builder::new_default();
|
||||
let greet_outer = message.init_root::<gen::message::Builder>();
|
||||
let mut greeting = greet_outer.init_greet();
|
||||
greeting.set_host(host);
|
||||
greeting.set_program(program);
|
||||
greeting.set_major(version.0);
|
||||
greeting.set_minor(version.1);
|
||||
|
||||
capnp_futures::serialize::write_message(&mut stream, message).await?;
|
||||
}
|
||||
|
||||
stream.flush().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user