12
12
//!
13
13
use std:: time:: Duration ;
14
14
15
- use anyhow:: { anyhow, Context } ;
16
- use axum:: {
17
- body:: Body ,
18
- http:: { Method , Request , Response , Version } ,
19
- Router ,
20
- } ;
15
+ use anyhow:: Context ;
16
+ use axum:: { body:: Body , Router } ;
21
17
use bytes:: Bytes ;
18
+ use http:: { Method , Request , Response , Version } ;
22
19
use ic_base_types:: NodeId ;
23
20
use ic_logger:: { info, ReplicaLogger } ;
24
21
use ic_protobuf:: transport:: v1 as pb;
25
22
use prost:: Message ;
26
- use quinn:: { Connection , RecvStream , SendStream } ;
23
+ use quinn:: { RecvStream , SendStream } ;
27
24
use tower:: ServiceExt ;
28
25
use tracing:: instrument;
29
26
30
27
use crate :: {
28
+ connection_handle:: ConnectionHandle ,
31
29
metrics:: {
32
30
QuicTransportMetrics , ERROR_TYPE_ACCEPT , ERROR_TYPE_APP , ERROR_TYPE_FINISH ,
33
31
ERROR_TYPE_READ , ERROR_TYPE_STOPPED , ERROR_TYPE_WRITE , STREAM_TYPE_BIDI ,
@@ -37,12 +35,10 @@ use crate::{
37
35
38
36
const QUIC_METRIC_SCRAPE_INTERVAL : Duration = Duration :: from_secs ( 5 ) ;
39
37
40
- pub ( crate ) async fn run_stream_acceptor (
38
+ pub async fn run_stream_acceptor (
41
39
log : ReplicaLogger ,
42
40
peer_id : NodeId ,
43
- conn_id : ConnId ,
44
- connection : Connection ,
45
- metrics : QuicTransportMetrics ,
41
+ conn_handle : ConnectionHandle ,
46
42
router : Router ,
47
43
) {
48
44
let mut inflight_requests = tokio:: task:: JoinSet :: new ( ) ;
@@ -55,18 +51,18 @@ pub(crate) async fn run_stream_acceptor(
55
51
loop {
56
52
tokio:: select! {
57
53
_ = quic_metrics_scrape. tick( ) => {
58
- metrics. collect_quic_connection_stats( & connection, & peer_id) ;
54
+ conn_handle . metrics. collect_quic_connection_stats( & conn_handle . connection, & peer_id) ;
59
55
}
60
- bi = connection. accept_bi( ) => {
56
+ bi = conn_handle . connection. accept_bi( ) => {
61
57
match bi {
62
58
Ok ( ( bi_tx, bi_rx) ) => {
63
59
inflight_requests. spawn(
64
- metrics. request_task_monitor. instrument(
60
+ conn_handle . metrics. request_task_monitor. instrument(
65
61
handle_bi_stream(
66
62
log. clone( ) ,
67
63
peer_id,
68
- conn_id,
69
- metrics. clone( ) ,
64
+ conn_handle . conn_id,
65
+ conn_handle . metrics. clone( ) ,
70
66
router. clone( ) ,
71
67
bi_tx,
72
68
bi_rx
@@ -76,7 +72,7 @@ pub(crate) async fn run_stream_acceptor(
76
72
}
77
73
Err ( e) => {
78
74
info!( log, "Error accepting bi stream {}" , e. to_string( ) ) ;
79
- metrics
75
+ conn_handle . metrics
80
76
. request_handle_errors_total
81
77
. with_label_values( & [
82
78
STREAM_TYPE_BIDI ,
@@ -87,8 +83,8 @@ pub(crate) async fn run_stream_acceptor(
87
83
}
88
84
}
89
85
} ,
90
- _ = connection. accept_uni( ) => { } ,
91
- _ = connection. read_datagram( ) => { } ,
86
+ _ = conn_handle . connection. accept_uni( ) => { } ,
87
+ _ = conn_handle . connection. read_datagram( ) => { } ,
92
88
Some ( completed_request) = inflight_requests. join_next( ) => {
93
89
if let Err ( err) = completed_request {
94
90
// Cancelling tasks is ok. Panicking tasks are not.
@@ -181,33 +177,34 @@ async fn read_request(mut recv_stream: RecvStream) -> Result<Request<Body>, anyh
181
177
let request_proto = pb:: HttpRequest :: decode ( raw_msg. as_slice ( ) )
182
178
. with_context ( || "Failed to decode http request." ) ?;
183
179
184
- let mut request = Request :: builder ( )
185
- . method ( match pb:: HttpMethod :: try_from ( request_proto. method ) {
186
- Ok ( pb:: HttpMethod :: Get ) => Method :: GET ,
187
- Ok ( pb:: HttpMethod :: Post ) => Method :: POST ,
188
- Ok ( pb:: HttpMethod :: Put ) => Method :: PUT ,
189
- Ok ( pb:: HttpMethod :: Delete ) => Method :: DELETE ,
190
- Ok ( pb:: HttpMethod :: Head ) => Method :: HEAD ,
191
- Ok ( pb:: HttpMethod :: Options ) => Method :: OPTIONS ,
192
- Ok ( pb:: HttpMethod :: Connect ) => Method :: CONNECT ,
193
- Ok ( pb:: HttpMethod :: Patch ) => Method :: PATCH ,
194
- Ok ( pb:: HttpMethod :: Trace ) => Method :: TRACE ,
195
- Ok ( pb:: HttpMethod :: Unspecified ) => {
196
- return Err ( anyhow ! ( "received http method unspecified." ) ) ;
197
- }
198
- Err ( e) => {
199
- return Err ( anyhow ! ( "received invalid method {}" , e) ) ;
200
- }
201
- } )
180
+ let pb_http_method = pb:: HttpMethod :: try_from ( request_proto. method )
181
+ . with_context ( || "Failed to decode http method." ) ?;
182
+ let http_method = match pb_http_method {
183
+ pb:: HttpMethod :: Get => Some ( Method :: GET ) ,
184
+ pb:: HttpMethod :: Post => Some ( Method :: POST ) ,
185
+ pb:: HttpMethod :: Put => Some ( Method :: PUT ) ,
186
+ pb:: HttpMethod :: Delete => Some ( Method :: DELETE ) ,
187
+ pb:: HttpMethod :: Head => Some ( Method :: HEAD ) ,
188
+ pb:: HttpMethod :: Options => Some ( Method :: OPTIONS ) ,
189
+ pb:: HttpMethod :: Connect => Some ( Method :: CONNECT ) ,
190
+ pb:: HttpMethod :: Patch => Some ( Method :: PATCH ) ,
191
+ pb:: HttpMethod :: Trace => Some ( Method :: TRACE ) ,
192
+ pb:: HttpMethod :: Unspecified => None ,
193
+ } ;
194
+ let mut request_builder = Request :: builder ( ) ;
195
+ if let Some ( http_method) = http_method {
196
+ request_builder = request_builder. method ( http_method) ;
197
+ }
198
+ request_builder = request_builder
202
199
. version ( Version :: HTTP_3 )
203
200
. uri ( request_proto. uri ) ;
204
201
for h in request_proto. headers {
205
202
let pb:: HttpHeader { key, value } = h;
206
- request = request . header ( key, value) ;
203
+ request_builder = request_builder . header ( key, value) ;
207
204
}
208
205
// This consumes the body without requiring allocation or cloning the whole content.
209
206
let body_bytes = Bytes :: from ( request_proto. body ) ;
210
- request
207
+ request_builder
211
208
. body ( Body :: from ( body_bytes) )
212
209
. with_context ( || "Failed to build request." )
213
210
}
@@ -241,6 +238,5 @@ async fn write_response(
241
238
send_stream
242
239
. write_all ( & response_bytes)
243
240
. await
244
- . with_context ( || "Failed to write request to stream." ) ?;
245
- Ok ( ( ) )
241
+ . with_context ( || "Failed to write request to stream." )
246
242
}
0 commit comments