@@ -4,24 +4,35 @@ use openmina_core::{bug_condition, fuzz_maybe, fuzzed_maybe, Substate, SubstateA
44
55use crate :: P2pLimits ;
66
7- use self :: p2p_network_yamux_state:: {
8- YamuxFlags , YamuxFrame , YamuxFrameInner , YamuxFrameParseError , YamuxSessionError ,
9- YamuxStreamState ,
10- } ;
7+ use self :: p2p_network_yamux_state:: { YamuxFlags , YamuxFrame , YamuxFrameInner , YamuxStreamState } ;
118
129use super :: { super :: * , * } ;
1310
1411impl P2pNetworkYamuxState {
15- pub fn set_err ( & mut self , err : YamuxFrameParseError ) {
16- self . terminated = Some ( Err ( err) ) ;
17- }
18-
19- pub fn set_res ( & mut self , res : Result < ( ) , YamuxSessionError > ) {
20- self . terminated = Some ( Ok ( res) ) ;
21- }
22-
23- /// Substate is accessed
12+ /// Handles the main reducer logic for Yamux protocol actions. It processes incoming and outgoing
13+ /// data, selects appropriate behavior based on frame types, and manages the state of streams
14+ /// within a Yamux session.
15+ ///
16+ /// # High-Level Overview
17+ ///
18+ /// - When data arrives, it is appended to an internal buffer. The buffer is then parsed for
19+ /// valid Yamux frames (using protocol-specific header fields and logic). Incomplete data
20+ /// remains in the buffer for future parsing.
21+ /// - On successful parsing, frames are enqueued for further handling (e.g., dispatching
22+ /// actions to notify higher-level protocols or responding to pings).
23+ /// - If protocol inconsistencies or invalid headers are encountered, it marks an error or
24+ /// terminates gracefully, preventing further processing of unexpected data.
25+ /// - Outgoing data is prepared as frames that respect the window constraints and established
26+ /// flags (e.g., SYN, ACK, FIN), and they are dispatched for transmission.
27+ /// - Once frames are processed, the function checks if the buffer has grown beyond a certain
28+ /// threshold relative to its initial capacity. If so, and if the remaining data is small,
29+ /// it resets the buffer capacity to a default size to avoid excessive memory usage.
30+ /// - The function also manages streams and their states, ensuring that proper handshake
31+ /// flags are set (SYN, ACK) when a new stream is opened or accepted, enforcing limits on
32+ /// the number of streams, and notifying higher-level components about events like
33+ /// incoming data or connection errors.
2434 pub fn reducer < State , Action > (
35+ // Substate is accessed
2536 mut state_context : Substate < Action , State , P2pNetworkSchedulerState > ,
2637 action : redux:: ActionWithMeta < P2pNetworkYamuxAction > ,
2738 ) -> Result < ( ) , String >
@@ -47,103 +58,10 @@ impl P2pNetworkYamuxState {
4758
4859 match action {
4960 P2pNetworkYamuxAction :: IncomingData { data, addr } => {
50- yamux_state. buffer . extend_from_slice ( & data) ;
51- let mut offset = 0 ;
52- loop {
53- let buf = & yamux_state. buffer [ offset..] ;
54- if buf. len ( ) >= 12 {
55- let _version = match buf[ 0 ] {
56- 0 => 0 ,
57- unknown => {
58- yamux_state. set_err ( YamuxFrameParseError :: Version ( unknown) ) ;
59- break ;
60- }
61- } ;
62- let flags = u16:: from_be_bytes ( buf[ 2 ..4 ] . try_into ( ) . expect ( "cannot fail" ) ) ;
63- let Some ( flags) = YamuxFlags :: from_bits ( flags) else {
64- yamux_state. set_err ( YamuxFrameParseError :: Flags ( flags) ) ;
65- break ;
66- } ;
67- let stream_id =
68- u32:: from_be_bytes ( buf[ 4 ..8 ] . try_into ( ) . expect ( "cannot fail" ) ) ;
69- let b = buf[ 8 ..12 ] . try_into ( ) . expect ( "cannot fail" ) ;
70-
71- match buf[ 1 ] {
72- 0 => {
73- let len = u32:: from_be_bytes ( b) as usize ;
74- if len > yamux_state. message_size_limit {
75- yamux_state. set_res ( Err ( YamuxSessionError :: Internal ) ) ;
76- break ;
77- }
78- if buf. len ( ) >= 12 + len {
79- let frame = YamuxFrame {
80- flags,
81- stream_id,
82- inner : YamuxFrameInner :: Data (
83- buf[ 12 ..( 12 + len) ] . to_vec ( ) . into ( ) ,
84- ) ,
85- } ;
86- yamux_state. incoming . push_back ( frame) ;
87- offset += 12 + len;
88- continue ;
89- }
90- }
91- 1 => {
92- let difference = u32:: from_be_bytes ( b) ;
93- let frame = YamuxFrame {
94- flags,
95- stream_id,
96- inner : YamuxFrameInner :: WindowUpdate { difference } ,
97- } ;
98- yamux_state. incoming . push_back ( frame) ;
99- offset += 12 ;
100- continue ;
101- }
102- 2 => {
103- let opaque = u32:: from_be_bytes ( b) ;
104- let frame = YamuxFrame {
105- flags,
106- stream_id,
107- inner : YamuxFrameInner :: Ping { opaque } ,
108- } ;
109- yamux_state. incoming . push_back ( frame) ;
110- offset += 12 ;
111- continue ;
112- }
113- 3 => {
114- let code = u32:: from_be_bytes ( b) ;
115- let result = match code {
116- 0 => Ok ( ( ) ) ,
117- 1 => Err ( YamuxSessionError :: Protocol ) ,
118- 2 => Err ( YamuxSessionError :: Internal ) ,
119- unknown => {
120- yamux_state
121- . set_err ( YamuxFrameParseError :: ErrorCode ( unknown) ) ;
122- break ;
123- }
124- } ;
125- let frame = YamuxFrame {
126- flags,
127- stream_id,
128- inner : YamuxFrameInner :: GoAway ( result) ,
129- } ;
130- yamux_state. incoming . push_back ( frame) ;
131- offset += 12 ;
132- continue ;
133- }
134- unknown => {
135- yamux_state. set_err ( YamuxFrameParseError :: Type ( unknown) ) ;
136- break ;
137- }
138- }
139- }
140-
141- break ;
142- }
143-
144- yamux_state. buffer = yamux_state. buffer [ offset..] . to_vec ( ) ;
61+ yamux_state. extend_buffer ( & data) ;
62+ yamux_state. parse_frames ( ) ;
14563
146- let frame_count = yamux_state. incoming . len ( ) ;
64+ let frame_count = yamux_state. incoming_frame_count ( ) ;
14765 let dispatcher = state_context. into_dispatcher ( ) ;
14866
14967 for _ in 0 ..frame_count {
0 commit comments