@@ -23,10 +23,11 @@ use std::{
23
23
24
24
use neqo_common:: { event:: Provider , hex, qdebug, qerror, qinfo, qwarn, Datagram , Header } ;
25
25
use neqo_crypto:: { AuthenticationStatus , ResumptionToken } ;
26
- use neqo_http3:: { Error , Http3Client , Http3ClientEvent , Http3Parameters , Http3State , Priority } ;
26
+ use neqo_http3:: {
27
+ ConnectUdpEvent , Error , Http3Client , Http3ClientEvent , Http3Parameters , Http3State , Priority ,
28
+ } ;
27
29
use neqo_transport:: {
28
- AppError , CloseReason , Connection , EmptyConnectionIdGenerator , Error as TransportError ,
29
- OutputBatch , RandomConnectionIdGenerator , StreamId ,
30
+ AppError , CloseReason , Connection , DatagramTracking , EmptyConnectionIdGenerator , Error as TransportError , OutputBatch , RandomConnectionIdGenerator , StreamId
30
31
} ;
31
32
use rustc_hash:: FxHashMap as HashMap ;
32
33
use url:: Url ;
@@ -82,7 +83,7 @@ pub fn create_client(
82
83
cid_generator,
83
84
local_addr,
84
85
remote_addr,
85
- args. shared . quic_parameters . get ( args. shared . alpn . as_str ( ) ) ,
86
+ args. shared . quic_parameters . get ( args. shared . alpn . as_str ( ) ) . datagram_size ( 1500 ) ,
86
87
Instant :: now ( ) ,
87
88
) ?;
88
89
let ciphers = args. get_ciphers ( ) ;
@@ -95,7 +96,9 @@ pub fn create_client(
95
96
. max_table_size_encoder ( args. shared . max_table_size_encoder )
96
97
. max_table_size_decoder ( args. shared . max_table_size_decoder )
97
98
. max_blocked_streams ( args. shared . max_blocked_streams )
98
- . max_concurrent_push_streams ( args. max_concurrent_push_streams ) ,
99
+ . max_concurrent_push_streams ( args. max_concurrent_push_streams )
100
+ . http3_datagram ( true )
101
+ . connect ( true ) ,
99
102
) ;
100
103
101
104
let qlog = qlog_new ( args, hostname, client. connection_id ( ) ) ?;
@@ -258,6 +261,29 @@ impl super::Handler for Handler<'_> {
258
261
self . url_handler . process_urls ( client) ;
259
262
}
260
263
Http3ClientEvent :: ResumptionToken ( t) => self . token = Some ( t) ,
264
+ Http3ClientEvent :: ConnectUdp ( event) => match event {
265
+ ConnectUdpEvent :: Negotiated ( _) => todo ! ( ) ,
266
+ ConnectUdpEvent :: Session {
267
+ stream_id,
268
+ status,
269
+ headers,
270
+ } => {
271
+ client. connect_udp_send_datagram (
272
+ stream_id,
273
+ b"Hello World!" ,
274
+ DatagramTracking :: None ,
275
+ ) . unwrap ( ) ;
276
+ }
277
+ ConnectUdpEvent :: SessionClosed {
278
+ stream_id,
279
+ reason,
280
+ headers,
281
+ } => todo ! ( ) ,
282
+ ConnectUdpEvent :: Datagram {
283
+ session_id,
284
+ datagram,
285
+ } => panic ! ( "Received datagram on session {session_id}: {}" , String :: from_utf8_lossy( & datagram) ) ,
286
+ } ,
261
287
_ => {
262
288
qwarn ! ( "Unhandled event {event:?}" ) ;
263
289
}
@@ -363,6 +389,26 @@ impl StreamHandler for UploadStreamHandler {
363
389
}
364
390
}
365
391
392
+ struct ConnectUdpStreamHandler {
393
+ stream_id : StreamId ,
394
+ }
395
+
396
+ impl StreamHandler for ConnectUdpStreamHandler {
397
+ fn process_data_readable (
398
+ & mut self ,
399
+ _stream_id : StreamId ,
400
+ _fin : bool ,
401
+ _data : & [ u8 ] ,
402
+ _output_read_data : bool ,
403
+ ) -> Res < ( ) > {
404
+ todo ! ( )
405
+ }
406
+
407
+ fn process_data_writable ( & mut self , _________client : & mut Http3Client , _stream_id : StreamId ) {
408
+ todo ! ( )
409
+ }
410
+ }
411
+
366
412
struct UrlHandler < ' a > {
367
413
url_queue : VecDeque < Url > ,
368
414
handled_urls : Vec < Url > ,
@@ -391,53 +437,65 @@ impl UrlHandler<'_> {
391
437
}
392
438
393
439
fn next_url ( & mut self , client : & mut Http3Client ) -> bool {
440
+ if !client. state ( ) . active ( ) {
441
+ return false ;
442
+ }
443
+
394
444
let url = self
395
445
. url_queue
396
446
. pop_front ( )
397
447
. expect ( "download_next called with empty queue" ) ;
398
- match client. fetch (
399
- Instant :: now ( ) ,
400
- & self . args . method ,
401
- & url,
402
- & to_headers ( & self . args . header ) ,
403
- Priority :: default ( ) ,
404
- ) {
405
- Ok ( client_stream_id) => {
406
- qdebug ! ( "Successfully created stream id {client_stream_id} for {url}" ) ;
407
-
408
- let handler: Box < dyn StreamHandler > = match self . args . method . as_str ( ) {
409
- "GET" => {
410
- let out_file = get_output_file (
411
- & url,
412
- self . args . output_dir . as_ref ( ) ,
413
- & mut self . all_paths ,
414
- ) ;
415
- client. stream_close_send ( client_stream_id) . unwrap ( ) ;
416
- Box :: new ( DownloadStreamHandler { out_file } )
417
- }
418
- "POST" => Box :: new ( UploadStreamHandler {
419
- data : SendData :: zeroes ( self . args . upload_size ) ,
420
- start : Instant :: now ( ) ,
421
- } ) ,
422
- _ => unimplemented ! ( ) ,
423
- } ;
424
-
425
- self . stream_handlers . insert ( client_stream_id, handler) ;
426
- self . handled_urls . push ( url) ;
427
- true
428
- }
429
- Err (
430
- Error :: Transport ( TransportError :: StreamLimit )
431
- | Error :: StreamLimit
432
- | Error :: Unavailable ,
433
- ) => {
434
- self . url_queue . push_front ( url) ;
435
- false
436
- }
437
- Err ( e) => {
438
- panic ! ( "Can't create stream {e}" ) ;
439
- }
440
- }
448
+ dbg ! ( & url) ;
449
+ let stream_id = client
450
+ . connect_udp_create_session ( Instant :: now ( ) , & url, & [ ] )
451
+ . unwrap ( ) ;
452
+ self . stream_handlers
453
+ . insert ( stream_id, Box :: new ( ConnectUdpStreamHandler { stream_id } ) ) ;
454
+
455
+ true
456
+ // match client.fetch(
457
+ // Instant::now(),
458
+ // &self.args.method,
459
+ // &url,
460
+ // &to_headers(&self.args.header),
461
+ // Priority::default(),
462
+ // ) {
463
+ // Ok(client_stream_id) => {
464
+ // qdebug!("Successfully created stream id {client_stream_id} for {url}");
465
+
466
+ // let handler: Box<dyn StreamHandler> = match self.args.method.as_str() {
467
+ // "GET" => {
468
+ // let out_file = get_output_file(
469
+ // &url,
470
+ // self.args.output_dir.as_ref(),
471
+ // &mut self.all_paths,
472
+ // );
473
+ // client.stream_close_send(client_stream_id).unwrap();
474
+ // Box::new(DownloadStreamHandler { out_file })
475
+ // }
476
+ // "POST" => Box::new(UploadStreamHandler {
477
+ // data: SendData::zeroes(self.args.upload_size),
478
+ // start: Instant::now(),
479
+ // }),
480
+ // _ => unimplemented!(),
481
+ // };
482
+
483
+ // self.stream_handlers.insert(client_stream_id, handler);
484
+ // self.handled_urls.push(url);
485
+ // true
486
+ // }
487
+ // Err(
488
+ // Error::Transport(TransportError::StreamLimit)
489
+ // | Error::StreamLimit
490
+ // | Error::Unavailable,
491
+ // ) => {
492
+ // self.url_queue.push_front(url);
493
+ // false
494
+ // }
495
+ // Err(e) => {
496
+ // panic!("Can't create stream {e}");
497
+ // }
498
+ // }
441
499
}
442
500
443
501
fn done ( & self ) -> bool {
0 commit comments