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: {cmd} FILE");
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.as_bytes(), value.as_bytes()));
87 }
88 }
89