Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crates/busbar-contract/include/busbar_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -3322,6 +3322,8 @@ struct bb_transport_EmitIn {
bb_transport_FramerSink sink;
uint64_t deadline_ns;
const bb_transport_DatagramLane *lane;
uint32_t status;
uint32_t _status_reserved;
};

/* `encode`'s `in`. The rendered bytes go into `sink.wire`. */
Expand Down Expand Up @@ -5708,7 +5710,7 @@ BB_ASSERT(offsetof(bb_transport_IngestIn, end) == 112, "bb_transport_IngestIn.en
BB_ASSERT(offsetof(bb_transport_IngestIn, _reserved) == 116, "bb_transport_IngestIn._reserved: offset");
BB_ASSERT(offsetof(bb_transport_IngestIn, sink) == 120, "bb_transport_IngestIn.sink: offset");
BB_ASSERT(offsetof(bb_transport_IngestIn, lane) == 200, "bb_transport_IngestIn.lane: offset");
BB_ASSERT(sizeof(bb_transport_EmitIn) == 224, "bb_transport_EmitIn: size");
BB_ASSERT(sizeof(bb_transport_EmitIn) == 232, "bb_transport_EmitIn: size");
BB_ASSERT(BB_ALIGNOF(bb_transport_EmitIn) == 8, "bb_transport_EmitIn: alignment");
BB_ASSERT(offsetof(bb_transport_EmitIn, head) == 0, "bb_transport_EmitIn.head: offset");
BB_ASSERT(offsetof(bb_transport_EmitIn, framing) == 88, "bb_transport_EmitIn.framing: offset");
Expand All @@ -5720,6 +5722,8 @@ BB_ASSERT(offsetof(bb_transport_EmitIn, flags) == 124, "bb_transport_EmitIn.flag
BB_ASSERT(offsetof(bb_transport_EmitIn, sink) == 128, "bb_transport_EmitIn.sink: offset");
BB_ASSERT(offsetof(bb_transport_EmitIn, deadline_ns) == 208, "bb_transport_EmitIn.deadline_ns: offset");
BB_ASSERT(offsetof(bb_transport_EmitIn, lane) == 216, "bb_transport_EmitIn.lane: offset");
BB_ASSERT(offsetof(bb_transport_EmitIn, status) == 224, "bb_transport_EmitIn.status: offset");
BB_ASSERT(offsetof(bb_transport_EmitIn, _status_reserved) == 228, "bb_transport_EmitIn._status_reserved: offset");
BB_ASSERT(sizeof(bb_transport_EncodeIn) == 232, "bb_transport_EncodeIn: size");
BB_ASSERT(BB_ALIGNOF(bb_transport_EncodeIn) == 8, "bb_transport_EncodeIn: alignment");
BB_ASSERT(offsetof(bb_transport_EncodeIn, head) == 0, "bb_transport_EncodeIn.head: offset");
Expand Down
26 changes: 26 additions & 0 deletions crates/busbar-contract/src/abi/tests/transport_check_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,3 +917,29 @@ fn a_streams_final_status_is_judged_against_its_claims_numbering() {
f(Rule::NullWithCount, "finish.final_bytes")
);
}

/// THE ANSWER'S STATUS ON AN EMIT (INBOUND-LISTEN, l.4913): stated on the emit that carries an
/// accepted stream's answer head, and on no other emit.
#[test]
fn an_emit_states_a_status_only_on_an_accepted_streams_answer_head() {
let mut i: EmitIn = z();
assert_eq!(check_emit_status(&i, false), Ok(()));
i.status = 200;
assert_eq!(check_emit_status(&i, true), Ok(()));
i.status = 101;
assert_eq!(check_emit_status(&i, true), Ok(()));
// RED: a status on an emit that carries no answer head.
assert_eq!(
check_emit_status(&i, false),
f(Rule::Contradiction, "emit.status")
);
// RED: an accepted stream's answer head with no status.
i.status = 0;
assert_eq!(check_emit_status(&i, true), f(Rule::Missing, "emit.status"));
// RED: the padding is not a channel.
i._status_reserved = 1;
assert_eq!(
check_emit_status(&i, false),
f(Rule::UnknownCode, "emit._status_reserved")
);
}
33 changes: 26 additions & 7 deletions crates/busbar-contract/src/abi/transport/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
pub use crate::abi::mechanism::check::{Fault, Rule};

use super::{
AcceptOut, ArrivalOut, Claim, ConnFacts, FinishIn, FramePiece, FrameSpan, FramerOut, HeadSlots,
IoOut, ListenOut, LocateOut, SettingDecl, StatusRow, TransportTail, CANCEL_COMPLETED,
CANCEL_NOTHING_MOVED, FACT_DECODES_PAYLOAD, FACT_SIGNS_NOTHING_AFTER_AUTH, FRAMING_DATAGRAM,
FRAMING_STREAM, MAX_ADDR, PIECE_CONTINUED, PIECE_END_OF_FRAME, PIECE_FIELDS, PIECE_HAS_CODE,
PIECE_HAS_RETRY_AFTER, PIECE_STREAM_FAILED, PIECE_TEXT, PIECE_WRITABLE, ROLE_CARRIER,
ROLE_FRAMER, SETTING_FLAG, SETTING_TEXT, STATUS_AT_TERMINAL, STATUS_OTHER, STATUS_SUCCESS,
UNIT0_HANDSHAKE, YIELD_ENDED, YIELD_HAS_DEADLINE, YIELD_MORE, YIELD_STREAM_FULL,
AcceptOut, ArrivalOut, Claim, ConnFacts, EmitIn, FinishIn, FramePiece, FrameSpan, FramerOut,
HeadSlots, IoOut, ListenOut, LocateOut, SettingDecl, StatusRow, TransportTail,
CANCEL_COMPLETED, CANCEL_NOTHING_MOVED, FACT_DECODES_PAYLOAD, FACT_SIGNS_NOTHING_AFTER_AUTH,
FRAMING_DATAGRAM, FRAMING_STREAM, MAX_ADDR, PIECE_CONTINUED, PIECE_END_OF_FRAME, PIECE_FIELDS,
PIECE_HAS_CODE, PIECE_HAS_RETRY_AFTER, PIECE_STREAM_FAILED, PIECE_TEXT, PIECE_WRITABLE,
ROLE_CARRIER, ROLE_FRAMER, SETTING_FLAG, SETTING_TEXT, STATUS_AT_TERMINAL, STATUS_OTHER,
STATUS_SUCCESS, UNIT0_HANDSHAKE, YIELD_ENDED, YIELD_HAS_DEADLINE, YIELD_MORE,
YIELD_STREAM_FULL,
};
use super::{
DatagramRoute, KeyingMaterial, RendezvousTerms, FINGERPRINT_BYTES, HANDSHAKE_ANSWERS,
Expand Down Expand Up @@ -687,6 +688,24 @@ pub fn check_final_status(i: &FinishIn, rows: &[StatusRow], claim: u32) -> Resul
Ok(())
}

/// An `emit`'s STATUS ([`EmitIn::status`], INBOUND-LISTEN, `BUSBAR-1.6.0.md` l.4913): stated on
/// the emit that carries an ACCEPTED stream's answer head (`answers_head`), and on no other. The
/// framer refuses the emit that breaks it, before any byte of it reaches the wire.
///
/// # Errors
///
/// The rule the emit breaks.
pub fn check_emit_status(i: &EmitIn, answers_head: bool) -> Result<(), Fault> {
if i._status_reserved != 0 {
return Err(fault(Rule::UnknownCode, "emit._status_reserved"));
}
match (answers_head, i.status) {
(true, 0) => Err(fault(Rule::Missing, "emit.status")),
(false, s) if s != 0 => Err(fault(Rule::Contradiction, "emit.status")),
_ => Ok(()),
}
}

/// Every setting: a path and a known kind.
///
/// # Errors
Expand Down
9 changes: 9 additions & 0 deletions crates/busbar-contract/src/abi/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,15 @@ pub struct EmitIn {
pub deadline_ns: u64,
/// The datagram lane ([`datagram`]): NULL for a stream framer. A tail addition (pre-tag v1).
pub lane: *const DatagramLane,
/// THE ANSWER'S STATUS (INBOUND-LISTEN, `BUSBAR-1.6.0.md` l.4913): on an ACCEPTED stream's FIRST
/// emit, the one carrying the answer's head (its bytes `encode` rendered), the status the answer
/// carries, in the numbering of the claim the stream arrived on; a status that asks the far end
/// to switch protocols hands the connection to the claimed upgrade framer ([`slot::DETACH`]).
/// `0` on every other emit, where a stated status is refused
/// ([`check::check_emit_status`]). Never a `:status` field. A tail addition (pre-tag v1).
pub status: u32,
/// Alignment padding.
pub _status_reserved: u32,
}

/// `encode`'s `in`. The rendered bytes go into `sink.wire`.
Expand Down
4 changes: 3 additions & 1 deletion crates/busbar-contract/tests/golden/abi-layout.golden
Original file line number Diff line number Diff line change
Expand Up @@ -1800,7 +1800,9 @@ tkind::EmitIn.flags=124
tkind::EmitIn.sink=128
tkind::EmitIn.deadline_ns=208
tkind::EmitIn.lane=216
tkind::EmitIn.__size=224
tkind::EmitIn.status=224
tkind::EmitIn._status_reserved=228
tkind::EmitIn.__size=232
tkind::EmitIn.__align=8
tkind::EncodeIn.head=0
tkind::EncodeIn.fields=88
Expand Down
4 changes: 3 additions & 1 deletion crates/busbar-contract/tests/layout_golden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1613,7 +1613,9 @@ fn compute_layout() -> String {
flags,
sink,
deadline_ns,
lane
lane,
status,
_status_reserved
]
);
record!(
Expand Down