1 // Copyright (C) 2019, Cloudflare, Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright notice,
9 //       this list of conditions and the following disclaimer.
10 //
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #[macro_use]
28 extern crate log;
29 
30 use std::fs::File;
31 
32 use std::io::prelude::*;
33 use std::io::BufReader;
34 
35 use quiche::h3;
36 
main()37 fn main() {
38     let mut args = std::env::args();
39 
40     let cmd = &args.next().unwrap();
41 
42     if args.len() != 1 {
43         println!("Usage: {} FILE", cmd);
44         return;
45     }
46 
47     let file = File::open(&args.next().unwrap()).unwrap();
48     let file = BufReader::new(&file);
49 
50     let mut enc = h3::qpack::Encoder::new();
51 
52     let mut headers: Vec<h3::Header> = Vec::new();
53 
54     let mut stream_id = 1u64;
55 
56     for line in file.lines().map(Result::unwrap) {
57         if line.starts_with('#') {
58             continue;
59         }
60 
61         if line.is_empty() {
62             let mut out = [0u8; 65535];
63 
64             let len = enc.encode(&headers, &mut out).unwrap();
65 
66             debug!("Writing header block stream={} len={}", stream_id, len);
67 
68             std::io::stdout()
69                 .write_all(&stream_id.to_be_bytes())
70                 .unwrap();
71             std::io::stdout()
72                 .write_all(&(len as u32).to_be_bytes())
73                 .unwrap();
74             std::io::stdout().write_all(&out[..len]).unwrap();
75 
76             stream_id += 1;
77 
78             headers.clear();
79 
80             continue;
81         }
82 
83         let name = line.split('\t').next().unwrap();
84         let value = line.split('\t').last().unwrap();
85 
86         headers.push(h3::Header::new(name, value));
87     }
88 }
89