1
- use crate :: codec:: RecvError ;
1
+ use crate :: codec:: { RecvError , UserError } ;
2
+ use crate :: error:: Reason ;
2
3
use crate :: frame;
3
4
use crate :: proto:: * ;
4
5
use std:: task:: { Context , Poll } ;
5
6
6
7
#[ derive( Debug ) ]
7
8
pub ( crate ) struct Settings {
9
+ /// Our local SETTINGS sync state with the remote.
10
+ local : Local ,
8
11
/// Received SETTINGS frame pending processing. The ACK must be written to
9
12
/// the socket first then the settings applied **before** receiving any
10
13
/// further frames.
11
- pending : Option < frame:: Settings > ,
14
+ remote : Option < frame:: Settings > ,
15
+ }
16
+
17
+ #[ derive( Debug ) ]
18
+ enum Local {
19
+ /// We want to send these SETTINGS to the remote when the socket is ready.
20
+ ToSend ( frame:: Settings ) ,
21
+ /// We have sent these SETTINGS and are waiting for the remote to ACK
22
+ /// before we apply them.
23
+ WaitingAck ( frame:: Settings ) ,
24
+ /// Our local settings are in sync with the remote.
25
+ Synced ,
12
26
}
13
27
14
28
impl Settings {
15
- pub fn new ( ) -> Self {
16
- Settings { pending : None }
29
+ pub ( crate ) fn new ( local : frame:: Settings ) -> Self {
30
+ Settings {
31
+ // We assume the initial local SETTINGS were flushed during
32
+ // the handshake process.
33
+ local : Local :: WaitingAck ( local) ,
34
+ remote : None ,
35
+ }
17
36
}
18
37
19
- pub fn recv_settings ( & mut self , frame : frame:: Settings ) {
38
+ pub ( crate ) fn recv_settings < T , B , C , P > (
39
+ & mut self ,
40
+ frame : frame:: Settings ,
41
+ codec : & mut Codec < T , B > ,
42
+ streams : & mut Streams < C , P > ,
43
+ ) -> Result < ( ) , RecvError >
44
+ where
45
+ T : AsyncWrite + Unpin ,
46
+ B : Buf + Unpin ,
47
+ C : Buf + Unpin ,
48
+ P : Peer ,
49
+ {
20
50
if frame. is_ack ( ) {
21
- log:: debug!( "received remote settings ack" ) ;
22
- // TODO: handle acks
51
+ match & self . local {
52
+ Local :: WaitingAck ( local) => {
53
+ log:: debug!( "received settings ACK; applying {:?}" , local) ;
54
+
55
+ if let Some ( max) = local. max_frame_size ( ) {
56
+ codec. set_max_recv_frame_size ( max as usize ) ;
57
+ }
58
+
59
+ if let Some ( max) = local. max_header_list_size ( ) {
60
+ codec. set_max_recv_header_list_size ( max as usize ) ;
61
+ }
62
+
63
+ streams. apply_local_settings ( local) ;
64
+ self . local = Local :: Synced ;
65
+ Ok ( ( ) )
66
+ } ,
67
+ Local :: ToSend ( ..) | Local :: Synced => {
68
+ // We haven't sent any SETTINGS frames to be ACKed, so
69
+ // this is very bizarre! Remote is either buggy or malicious.
70
+ proto_err ! ( conn: "received unexpected settings ack" ) ;
71
+ Err ( RecvError :: Connection ( Reason :: PROTOCOL_ERROR ) )
72
+ }
73
+ }
23
74
} else {
24
- assert ! ( self . pending. is_none( ) ) ;
25
- self . pending = Some ( frame) ;
75
+ // We always ACK before reading more frames, so `remote` should
76
+ // always be none!
77
+ assert ! ( self . remote. is_none( ) ) ;
78
+ self . remote = Some ( frame) ;
79
+ Ok ( ( ) )
80
+ }
81
+ }
82
+
83
+ pub ( crate ) fn send_settings ( & mut self , frame : frame:: Settings ) -> Result < ( ) , UserError > {
84
+ assert ! ( !frame. is_ack( ) ) ;
85
+ match & self . local {
86
+ Local :: ToSend ( ..) | Local :: WaitingAck ( ..) => {
87
+ Err ( UserError :: SendSettingsWhilePending )
88
+ } ,
89
+ Local :: Synced => {
90
+ log:: trace!( "queue to send local settings: {:?}" , frame) ;
91
+ self . local = Local :: ToSend ( frame) ;
92
+ Ok ( ( ) )
93
+ } ,
26
94
}
27
95
}
28
96
29
- pub fn send_pending_ack < T , B , C , P > (
97
+ pub ( crate ) fn poll_send < T , B , C , P > (
30
98
& mut self ,
31
99
cx : & mut Context ,
32
100
dst : & mut Codec < T , B > ,
@@ -38,11 +106,8 @@ impl Settings {
38
106
C : Buf + Unpin ,
39
107
P : Peer ,
40
108
{
41
- log:: trace!( "send_pending_ack; pending={:?}" , self . pending) ;
42
-
43
- if let Some ( settings) = & self . pending {
109
+ if let Some ( settings) = & self . remote {
44
110
if !dst. poll_ready ( cx) ?. is_ready ( ) {
45
- log:: trace!( "failed to send ACK" ) ;
46
111
return Poll :: Pending ;
47
112
}
48
113
@@ -61,7 +126,22 @@ impl Settings {
61
126
streams. apply_remote_settings ( settings) ?;
62
127
}
63
128
64
- self . pending = None ;
129
+ self . remote = None ;
130
+
131
+ match & self . local {
132
+ Local :: ToSend ( settings) => {
133
+ if !dst. poll_ready ( cx) ?. is_ready ( ) {
134
+ return Poll :: Pending ;
135
+ }
136
+
137
+ // Buffer the settings frame
138
+ dst. buffer ( settings. clone ( ) . into ( ) ) . expect ( "invalid settings frame" ) ;
139
+ log:: trace!( "local settings sent; waiting for ack: {:?}" , settings) ;
140
+
141
+ self . local = Local :: WaitingAck ( settings. clone ( ) ) ;
142
+ } ,
143
+ Local :: WaitingAck ( ..) | Local :: Synced => { } ,
144
+ }
65
145
66
146
Poll :: Ready ( Ok ( ( ) ) )
67
147
}
0 commit comments