@@ -16,7 +16,9 @@ use log::error;
16
16
use sodiumoxide:: crypto:: secretstream:: xchacha20poly1305:: { ABYTES , HEADERBYTES } ;
17
17
use std:: time:: Duration ;
18
18
19
- const TIMEOUT_DURATION : Duration = Duration :: from_secs ( 60 * 60 ) ;
19
+ const CONNECT_TIMEOUT : Duration = Duration :: from_secs ( 1 ) ;
20
+ const RESPONSE_TIMEOUT : Duration = Duration :: from_secs ( 5 ) ;
21
+ const UPLOAD_TIMEOUT : Duration = Duration :: from_secs ( 3 * 60 ) ;
20
22
21
23
static FORWARD_REQUEST_HEADERS_TO_REMOVE : [ header:: HeaderName ; 4 ] = [
22
24
// Connection settings (keepalived) must not be resend
@@ -82,7 +84,8 @@ async fn forward(
82
84
83
85
let mut forwarded_req = client
84
86
. request_from ( put_url. as_str ( ) , req. head ( ) )
85
- . timeout ( TIMEOUT_DURATION ) ;
87
+ . force_close ( )
88
+ . timeout ( UPLOAD_TIMEOUT ) ;
86
89
87
90
let forward_length: Option < usize > = content_length ( req. headers ( ) ) . map ( |content_length| {
88
91
if config. noop {
@@ -96,7 +99,7 @@ async fn forward(
96
99
forwarded_req. headers_mut ( ) . remove ( header) ;
97
100
}
98
101
99
- let stream_to_send : Box < dyn Stream < Item = _ > + Unpin > = if config. noop {
102
+ let stream : Box < dyn Stream < Item = _ > + Unpin > = if config. noop {
100
103
Box :: new ( payload)
101
104
} else {
102
105
Box :: new ( Encoder :: new (
@@ -106,23 +109,27 @@ async fn forward(
106
109
) )
107
110
} ;
108
111
109
- let mut res = if let Some ( length) = forward_length {
112
+ let req_copy = req. clone ( ) ;
113
+ let stream_to_send = stream. map_err ( move |e| {
114
+ error ! ( "forward error with stream {:?}, {:?}" , e, req_copy) ;
115
+ Error :: from ( e)
116
+ } ) ;
117
+
118
+ let res_e = if let Some ( length) = forward_length {
110
119
forwarded_req
111
- . send_body ( SizedStream :: new (
112
- length as u64 ,
113
- stream_to_send. map_err ( Error :: from) ,
114
- ) )
120
+ . send_body ( SizedStream :: new ( length as u64 , stream_to_send) )
115
121
. await
116
- . map_err ( Error :: from) ?
117
122
} else {
118
- forwarded_req
119
- . send_stream ( stream_to_send. map_err ( Error :: from) )
120
- . await
121
- . map_err ( Error :: from) ?
123
+ forwarded_req. send_stream ( stream_to_send) . await
122
124
} ;
123
125
126
+ let mut res = res_e. map_err ( |e| {
127
+ error ! ( "forward fwk error {:?}, {:?}" , e, req) ;
128
+ Error :: from ( e)
129
+ } ) ?;
130
+
124
131
if res. status ( ) . is_client_error ( ) || res. status ( ) . is_server_error ( ) {
125
- error ! ( "forward error {:?} {:?}" , req, res) ;
132
+ error ! ( "forward status error {:?} {:?}" , req, res) ;
126
133
}
127
134
128
135
let mut client_resp = HttpResponse :: build ( res. status ( ) ) ;
@@ -148,16 +155,19 @@ async fn fetch(
148
155
149
156
let mut fetch_req = client
150
157
. request_from ( get_url. as_str ( ) , req. head ( ) )
151
- . timeout ( TIMEOUT_DURATION ) ;
158
+ . force_close ( ) ;
152
159
153
160
for header in & FETCH_REQUEST_HEADERS_TO_REMOVE {
154
161
fetch_req. headers_mut ( ) . remove ( header) ;
155
162
}
156
163
157
- let res = fetch_req. send_body ( body) . await . map_err ( Error :: from) ?;
164
+ let res = fetch_req. send_body ( body) . await . map_err ( |e| {
165
+ error ! ( "fetch fwk error {:?}, {:?}" , e, req) ;
166
+ Error :: from ( e)
167
+ } ) ?;
158
168
159
169
if res. status ( ) . is_client_error ( ) || res. status ( ) . is_server_error ( ) {
160
- error ! ( "fetch error {:?} {:?}" , req, res) ;
170
+ error ! ( "fetch status error {:?} {:?}" , req, res) ;
161
171
}
162
172
163
173
let mut client_resp = HttpResponse :: build ( res. status ( ) ) ;
@@ -204,9 +214,7 @@ async fn simple_proxy(
204
214
) -> Result < HttpResponse , Error > {
205
215
let url = config. create_url ( & req. uri ( ) ) ;
206
216
207
- let mut proxied_req = client
208
- . request_from ( url. as_str ( ) , req. head ( ) )
209
- . timeout ( TIMEOUT_DURATION ) ;
217
+ let mut proxied_req = client. request_from ( url. as_str ( ) , req. head ( ) ) . force_close ( ) ;
210
218
211
219
for header in & FETCH_REQUEST_HEADERS_TO_REMOVE {
212
220
proxied_req. headers_mut ( ) . remove ( header) ;
@@ -215,10 +223,13 @@ async fn simple_proxy(
215
223
proxied_req
216
224
. send_stream ( payload)
217
225
. await
218
- . map_err ( Error :: from)
226
+ . map_err ( |e| {
227
+ error ! ( "simple proxy fwk error {:?}, {:?}" , e, req) ;
228
+ Error :: from ( e)
229
+ } )
219
230
. map ( |res| {
220
231
if res. status ( ) . is_client_error ( ) || res. status ( ) . is_server_error ( ) {
221
- error ! ( "simple proxy error {:?} {:?}" , req, res) ;
232
+ error ! ( "simple proxy status error {:?} {:?}" , req, res) ;
222
233
}
223
234
224
235
let mut client_resp = HttpResponse :: build ( res. status ( ) ) ;
@@ -243,6 +254,10 @@ fn content_length(headers: &HeaderMap) -> Option<usize> {
243
254
}
244
255
245
256
fn encrypted_content_length ( clear_length : usize , chunk_size : usize ) -> usize {
257
+ if clear_length == 0 {
258
+ return 0 ;
259
+ }
260
+
246
261
let nb_chunk = clear_length / chunk_size;
247
262
let remainder = clear_length % chunk_size;
248
263
@@ -254,6 +269,10 @@ fn encrypted_content_length(clear_length: usize, chunk_size: usize) -> usize {
254
269
}
255
270
256
271
fn decrypted_content_length ( encrypted_length : usize , decipher : DecipherType ) -> usize {
272
+ if encrypted_length == 0 {
273
+ return 0 ;
274
+ }
275
+
257
276
match decipher {
258
277
DecipherType :: Encrypted { chunk_size } => {
259
278
// encrypted = header_ds + header_crypto + n ( abytes + chunk ) + a (abytes + remainder)
@@ -285,9 +304,20 @@ pub async fn main(config: Config) -> std::io::Result<()> {
285
304
let address = config. address . unwrap ( ) ;
286
305
let max_conn = config. max_connections ;
287
306
307
+ use actix_http;
308
+
288
309
HttpServer :: new ( move || {
289
310
App :: new ( )
290
- . data ( actix_web:: client:: Client :: new ( ) )
311
+ . data (
312
+ actix_web:: client:: ClientBuilder :: new ( )
313
+ . connector (
314
+ actix_web:: client:: Connector :: new ( )
315
+ . timeout ( CONNECT_TIMEOUT ) // max time to connect to remote host including dns name resolution
316
+ . finish ( ) ,
317
+ )
318
+ . timeout ( RESPONSE_TIMEOUT ) // the total time before a response must be received
319
+ . finish ( ) ,
320
+ )
291
321
. data ( config. clone ( ) )
292
322
. wrap ( middleware:: Logger :: default ( ) )
293
323
. service ( web:: resource ( "/ping" ) . guard ( guard:: Get ( ) ) . to ( ping) )
@@ -296,6 +326,7 @@ pub async fn main(config: Config) -> std::io::Result<()> {
296
326
. default_service ( web:: route ( ) . to ( simple_proxy) )
297
327
} )
298
328
. max_connections ( max_conn)
329
+ . keep_alive ( actix_http:: KeepAlive :: Disabled )
299
330
. bind_uds ( "/tmp/actix-uds.socket" ) ?
300
331
. bind ( address) ?
301
332
. run ( )
@@ -306,6 +337,22 @@ pub async fn main(config: Config) -> std::io::Result<()> {
306
337
mod tests {
307
338
use super :: * ;
308
339
340
+ #[ test]
341
+ fn test_decrypt_content_length_from_0 ( ) {
342
+ let original_length = 0 ;
343
+ let chunk_size = 16 ;
344
+ let encrypted_length = 0 ;
345
+
346
+ let decrypted_length = decrypted_content_length (
347
+ encrypted_length,
348
+ DecipherType :: Encrypted {
349
+ chunk_size : chunk_size,
350
+ } ,
351
+ ) ;
352
+
353
+ assert_eq ! ( original_length, decrypted_length) ;
354
+ }
355
+
309
356
#[ test]
310
357
fn test_decrypt_content_length_without_remainder ( ) {
311
358
let original_length = 32 ;
@@ -354,6 +401,18 @@ mod tests {
354
401
assert_eq ! ( original_length, decrypted_length) ;
355
402
}
356
403
404
+ #[ test]
405
+ fn test_encrypted_content_length_from_0 ( ) {
406
+ let original_length = 0 ;
407
+ let chunk_size = 16 ;
408
+ let encrypted_length = 0 ;
409
+
410
+ assert_eq ! (
411
+ encrypted_length,
412
+ encrypted_content_length( original_length, chunk_size)
413
+ ) ;
414
+ }
415
+
357
416
#[ test]
358
417
fn test_encrypted_content_length_without_remainder ( ) {
359
418
let original_length = 32 ;
0 commit comments