lsqpack 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +82 -0
- data/LICENSE +21 -0
- data/README.md +36 -0
- data/Rakefile +19 -0
- data/Steepfile +6 -0
- data/ext/lsqpack/extconf.rb +18 -0
- data/ext/lsqpack/lsqpack.c +426 -0
- data/ext/lsqpack/lsqpack.h +6 -0
- data/lib/lsqpack/version.rb +5 -0
- data/lib/lsqpack.rb +30 -0
- data/ls-qpack/.appveyor.yml +14 -0
- data/ls-qpack/.cirrus.yml +6 -0
- data/ls-qpack/.travis.yml +32 -0
- data/ls-qpack/CMakeLists.txt +66 -0
- data/ls-qpack/LICENSE +21 -0
- data/ls-qpack/README.md +65 -0
- data/ls-qpack/bin/CMakeLists.txt +21 -0
- data/ls-qpack/bin/encode-int.c +87 -0
- data/ls-qpack/bin/fuzz-decode.c +247 -0
- data/ls-qpack/bin/interop-decode.c +433 -0
- data/ls-qpack/bin/interop-encode.c +554 -0
- data/ls-qpack/deps/xxhash/xxhash.c +941 -0
- data/ls-qpack/deps/xxhash/xxhash.h +160 -0
- data/ls-qpack/fuzz/decode/a/README +3 -0
- data/ls-qpack/fuzz/decode/a/preamble +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000000,sig_06,src_000390,op_havoc,rep_4 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000000,sig_06,src_000579,op_flip1,pos_14 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000000,src_000000,op_flip2,pos_12 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000001,sig_11,src_000579,op_havoc,rep_4 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000002,sig_11,src_000481,op_int16,pos_15,val_-1 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000002,src_000000,op_havoc,rep_8 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000006,src_000285,op_flip2,pos_14 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000008,src_000285,op_flip2,pos_20 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000010,src_000306,op_flip2,pos_75 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000011,src_000344,op_havoc,rep_2 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000014,src_000366,op_flip2,pos_28 +0 -0
- data/ls-qpack/fuzz/decode/b/README +1 -0
- data/ls-qpack/fuzz/decode/b/preamble +0 -0
- data/ls-qpack/fuzz/decode/b/test-cases/seed +0 -0
- data/ls-qpack/fuzz/decode/c/setup.sh +3 -0
- data/ls-qpack/fuzz/decode/c/test-cases/fb-req.qif.proxygen.out.256.100.0-chopped +0 -0
- data/ls-qpack/fuzz/decode/d/preamble +0 -0
- data/ls-qpack/fuzz/decode/d/setup.sh +3 -0
- data/ls-qpack/fuzz/decode/d/test-cases/fb-resp.minhq.256.128.0.ack +0 -0
- data/ls-qpack/fuzz/input/256.100.1/fb-req.out.256.100.1 +0 -0
- data/ls-qpack/fuzz/input/256.100.1/fb-resp.out.256.100.1 +0 -0
- data/ls-qpack/fuzz/input/256.100.1/netbsd.out.256.100.1 +0 -0
- data/ls-qpack/huff-tables.h +136247 -0
- data/ls-qpack/lsqpack.c +5547 -0
- data/ls-qpack/lsqpack.h +768 -0
- data/ls-qpack/test/CMakeLists.txt +76 -0
- data/ls-qpack/test/lsqpack-test.h +43 -0
- data/ls-qpack/test/qifs/fb-req.qif +4917 -0
- data/ls-qpack/test/qifs/fb-resp.qif +5982 -0
- data/ls-qpack/test/qifs/long-codes.qif +5984 -0
- data/ls-qpack/test/qifs/netbsd.qif +235 -0
- data/ls-qpack/test/run-qif.pl +97 -0
- data/ls-qpack/test/run-scenario.sh +68 -0
- data/ls-qpack/test/scenarios/0.95-reset.sce +10 -0
- data/ls-qpack/test/scenarios/cancel-stream.sce +22 -0
- data/ls-qpack/test/scenarios/drain-2.sce +37 -0
- data/ls-qpack/test/scenarios/drain.sce +37 -0
- data/ls-qpack/test/scenarios/end-dst-2.sce +14 -0
- data/ls-qpack/test/scenarios/end-dst.sce +14 -0
- data/ls-qpack/test/scenarios/incl-name.sce +13 -0
- data/ls-qpack/test/scenarios/multi-byte-int-dyn-ref-1.sce +110 -0
- data/ls-qpack/test/scenarios/multi-byte-int-dyn-ref-2.sce +161 -0
- data/ls-qpack/test/scenarios/post-base-1.sce +10 -0
- data/ls-qpack/test/scenarios/post-base-2.sce +13 -0
- data/ls-qpack/test/scenarios/post-base-nr.sce +10 -0
- data/ls-qpack/test/scenarios/set-max-cap.sce +15 -0
- data/ls-qpack/test/test_enc_str.c +139 -0
- data/ls-qpack/test/test_get_stx_id.c +144 -0
- data/ls-qpack/test/test_huff_dec.c +399 -0
- data/ls-qpack/test/test_int.c +220 -0
- data/ls-qpack/test/test_qpack.c +856 -0
- data/ls-qpack/test/test_read_enc_stream.c +256 -0
- data/ls-qpack/tools/har2qif.pl +139 -0
- data/ls-qpack/tools/randomize-cookies.pl +41 -0
- data/ls-qpack/tools/sort-qif.pl +31 -0
- data/ls-qpack/wincompat/getopt.c +758 -0
- data/ls-qpack/wincompat/getopt.h +131 -0
- data/ls-qpack/wincompat/getopt1.c +188 -0
- data/ls-qpack/wincompat/sys/queue.h +859 -0
- data/lsqpack.gemspec +39 -0
- data/sig/lsqpack.rbs +29 -0
- metadata +135 -0
@@ -0,0 +1,554 @@
|
|
1
|
+
/*
|
2
|
+
* QPACK Interop -- encode to intermediate format
|
3
|
+
*
|
4
|
+
* https://github.com/quicwg/base-drafts/wiki/QPACK-Offline-Interop
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include <assert.h>
|
8
|
+
|
9
|
+
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
10
|
+
#include <sys/endian.h>
|
11
|
+
#define bswap_16 bswap16
|
12
|
+
#define bswap_32 bswap32
|
13
|
+
#define bswap_64 bswap64
|
14
|
+
#elif defined(__APPLE__)
|
15
|
+
#include <libkern/OSByteOrder.h>
|
16
|
+
#define bswap_16 OSSwapInt16
|
17
|
+
#define bswap_32 OSSwapInt32
|
18
|
+
#define bswap_64 OSSwapInt64
|
19
|
+
#elif defined(WIN32)
|
20
|
+
#define bswap_16 _byteswap_ushort
|
21
|
+
#define bswap_32 _byteswap_ulong
|
22
|
+
#define bswap_64 _byteswap_uint64
|
23
|
+
#else
|
24
|
+
#include <byteswap.h>
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#include <errno.h>
|
28
|
+
#include <stdio.h>
|
29
|
+
#include <stdlib.h>
|
30
|
+
#include <string.h>
|
31
|
+
#ifdef WIN32
|
32
|
+
#include "getopt.h"
|
33
|
+
#else
|
34
|
+
#include <unistd.h>
|
35
|
+
#endif
|
36
|
+
#include <sys/types.h>
|
37
|
+
#include <sys/stat.h>
|
38
|
+
#include <fcntl.h>
|
39
|
+
#include <inttypes.h>
|
40
|
+
|
41
|
+
#include "lsqpack.h"
|
42
|
+
|
43
|
+
static int s_verbose;
|
44
|
+
|
45
|
+
unsigned char *
|
46
|
+
lsqpack_enc_int (unsigned char *dst, unsigned char *const end, uint64_t value,
|
47
|
+
unsigned prefix_bits);
|
48
|
+
|
49
|
+
static void
|
50
|
+
usage (const char *name)
|
51
|
+
{
|
52
|
+
fprintf(stderr,
|
53
|
+
"Usage: %s [options] [-i input] [-o output]\n"
|
54
|
+
"\n"
|
55
|
+
"Options:\n"
|
56
|
+
" -i FILE Input file. If not specified or set to `-', the input is\n"
|
57
|
+
" read from stdin.\n"
|
58
|
+
" -o FILE Output file. If not spepcified or set to `-', the output\n"
|
59
|
+
" is written to stdout.\n"
|
60
|
+
" -s NUMBER Maximum number of risked streams. Defaults to %u.\n"
|
61
|
+
" -t NUMBER Dynamic table size. Defaults to %u.\n"
|
62
|
+
" -a MODE Header acknowledgement mode. 0 means headers are never\n"
|
63
|
+
" acknowledged, non-zero means header blocks are acknowledged\n"
|
64
|
+
" immediately. Default value is 0.\n"
|
65
|
+
" -n Process annotations.\n"
|
66
|
+
" -S Server mode.\n"
|
67
|
+
" -D Do not emit \"Duplicate\" instructions.\n"
|
68
|
+
" -A Aggressive indexing.\n"
|
69
|
+
" -M Turn off memory guard.\n"
|
70
|
+
" -f Fast: use maximum output buffers.\n"
|
71
|
+
" -v Verbose: print various messages to stderr.\n"
|
72
|
+
"\n"
|
73
|
+
" -h Print this help screen and exit\n"
|
74
|
+
, name, LSQPACK_DEF_MAX_RISKED_STREAMS, LSQPACK_DEF_DYN_TABLE_SIZE);
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
static void
|
79
|
+
write_enc_stream (FILE *out, const unsigned char *enc_buf, size_t enc_sz)
|
80
|
+
{
|
81
|
+
uint64_t stream_id_enc;
|
82
|
+
uint32_t length_enc;
|
83
|
+
size_t written;
|
84
|
+
|
85
|
+
if (enc_sz <= 0)
|
86
|
+
return;
|
87
|
+
stream_id_enc = 0;
|
88
|
+
length_enc = enc_sz;
|
89
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
90
|
+
stream_id_enc = bswap_64(stream_id_enc);
|
91
|
+
length_enc = bswap_32(length_enc);
|
92
|
+
#endif
|
93
|
+
written = fwrite(&stream_id_enc, 1, sizeof(stream_id_enc), out);
|
94
|
+
if (written != sizeof(stream_id_enc))
|
95
|
+
{
|
96
|
+
perror("fwrite");
|
97
|
+
exit(EXIT_FAILURE);
|
98
|
+
}
|
99
|
+
written = fwrite(&length_enc, 1, sizeof(length_enc), out);
|
100
|
+
if (written != sizeof(length_enc))
|
101
|
+
{
|
102
|
+
perror("fwrite");
|
103
|
+
exit(EXIT_FAILURE);
|
104
|
+
}
|
105
|
+
written = fwrite(enc_buf, 1, enc_sz, out);
|
106
|
+
if (written != enc_sz)
|
107
|
+
{
|
108
|
+
perror("fwrite");
|
109
|
+
exit(EXIT_FAILURE);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
static void
|
115
|
+
write_enc_and_header_streams (FILE *out, unsigned stream_id,
|
116
|
+
const unsigned char *enc_buf, size_t enc_sz,
|
117
|
+
const unsigned char *pref_buf, size_t pref_sz,
|
118
|
+
const unsigned char *hea_buf, size_t hea_sz)
|
119
|
+
{
|
120
|
+
uint64_t stream_id_enc;
|
121
|
+
uint32_t length_enc;
|
122
|
+
size_t written;
|
123
|
+
|
124
|
+
if (s_verbose)
|
125
|
+
fprintf(stderr, "%s: stream %"PRIu32"\n", __func__, stream_id);
|
126
|
+
|
127
|
+
if (enc_sz)
|
128
|
+
{
|
129
|
+
stream_id_enc = 0;
|
130
|
+
length_enc = enc_sz;
|
131
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
132
|
+
stream_id_enc = bswap_64(stream_id_enc);
|
133
|
+
length_enc = bswap_32(length_enc);
|
134
|
+
#endif
|
135
|
+
written = fwrite(&stream_id_enc, 1, sizeof(stream_id_enc), out);
|
136
|
+
if (written != sizeof(stream_id_enc))
|
137
|
+
goto write_err;
|
138
|
+
written = fwrite(&length_enc, 1, sizeof(length_enc), out);
|
139
|
+
if (written != sizeof(length_enc))
|
140
|
+
goto write_err;
|
141
|
+
written = fwrite(enc_buf, 1, enc_sz, out);
|
142
|
+
if (written != enc_sz)
|
143
|
+
goto write_err;
|
144
|
+
}
|
145
|
+
|
146
|
+
stream_id_enc = stream_id;
|
147
|
+
length_enc = pref_sz + hea_sz;
|
148
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
149
|
+
stream_id_enc = bswap_64(stream_id_enc);
|
150
|
+
length_enc = bswap_32(length_enc);
|
151
|
+
#endif
|
152
|
+
written = fwrite(&stream_id_enc, 1, sizeof(stream_id_enc), out);
|
153
|
+
if (written != sizeof(stream_id_enc))
|
154
|
+
goto write_err;
|
155
|
+
written = fwrite(&length_enc, 1, sizeof(length_enc), out);
|
156
|
+
if (written != sizeof(length_enc))
|
157
|
+
goto write_err;
|
158
|
+
written = fwrite(pref_buf, 1, pref_sz, out);
|
159
|
+
if (written != pref_sz)
|
160
|
+
goto write_err;
|
161
|
+
written = fwrite(hea_buf, 1, hea_sz, out);
|
162
|
+
if (written != hea_sz)
|
163
|
+
goto write_err;
|
164
|
+
return;
|
165
|
+
|
166
|
+
write_err:
|
167
|
+
perror("fwrite");
|
168
|
+
exit(EXIT_FAILURE);
|
169
|
+
}
|
170
|
+
|
171
|
+
|
172
|
+
static unsigned s_saved_ins_count;
|
173
|
+
static int
|
174
|
+
ack_last_entry_id (struct lsqpack_enc *encoder)
|
175
|
+
{
|
176
|
+
unsigned char *end_cmd;
|
177
|
+
unsigned char cmd[80];
|
178
|
+
unsigned val;
|
179
|
+
|
180
|
+
if (s_verbose)
|
181
|
+
fprintf(stderr, "ACK entry ID %u\n", encoder->qpe_ins_count);
|
182
|
+
|
183
|
+
cmd[0] = 0x00;
|
184
|
+
val = encoder->qpe_ins_count - s_saved_ins_count;
|
185
|
+
s_saved_ins_count = encoder->qpe_ins_count;
|
186
|
+
end_cmd = lsqpack_enc_int(cmd, cmd + sizeof(cmd), val, 6);
|
187
|
+
assert(end_cmd > cmd);
|
188
|
+
return lsqpack_enc_decoder_in(encoder, cmd, end_cmd - cmd);
|
189
|
+
}
|
190
|
+
|
191
|
+
|
192
|
+
static int
|
193
|
+
ack_stream (struct lsqpack_enc *encoder, uint64_t stream_id)
|
194
|
+
{
|
195
|
+
unsigned char *end_cmd;
|
196
|
+
unsigned char cmd[80];
|
197
|
+
|
198
|
+
if (s_verbose)
|
199
|
+
fprintf(stderr, "ACK stream ID %"PRIu64"\n", stream_id);
|
200
|
+
|
201
|
+
cmd[0] = 0x80;
|
202
|
+
end_cmd = lsqpack_enc_int(cmd, cmd + sizeof(cmd), stream_id, 7);
|
203
|
+
assert(end_cmd > cmd);
|
204
|
+
return lsqpack_enc_decoder_in(encoder, cmd, end_cmd - cmd);
|
205
|
+
}
|
206
|
+
|
207
|
+
|
208
|
+
static int
|
209
|
+
sync_table (struct lsqpack_enc *encoder, uint64_t num_inserts)
|
210
|
+
{
|
211
|
+
unsigned char *end_cmd;
|
212
|
+
unsigned char cmd[80];
|
213
|
+
|
214
|
+
if (s_verbose)
|
215
|
+
fprintf(stderr, "Sync table num inserts %"PRIu64"\n", num_inserts);
|
216
|
+
|
217
|
+
cmd[0] = 0x00;
|
218
|
+
end_cmd = lsqpack_enc_int(cmd, cmd + sizeof(cmd), num_inserts, 6);
|
219
|
+
assert(end_cmd > cmd);
|
220
|
+
return lsqpack_enc_decoder_in(encoder, cmd, end_cmd - cmd);
|
221
|
+
}
|
222
|
+
|
223
|
+
|
224
|
+
static int
|
225
|
+
cancel_stream (struct lsqpack_enc *encoder, uint64_t stream_id)
|
226
|
+
{
|
227
|
+
unsigned char *end_cmd;
|
228
|
+
unsigned char cmd[80];
|
229
|
+
|
230
|
+
if (s_verbose)
|
231
|
+
fprintf(stderr, "Cancel stream ID %"PRIu64"\n", stream_id);
|
232
|
+
|
233
|
+
cmd[0] = 0x40;
|
234
|
+
end_cmd = lsqpack_enc_int(cmd, cmd + sizeof(cmd), stream_id, 6);
|
235
|
+
assert(end_cmd > cmd);
|
236
|
+
return lsqpack_enc_decoder_in(encoder, cmd, end_cmd - cmd);
|
237
|
+
}
|
238
|
+
|
239
|
+
|
240
|
+
int
|
241
|
+
main (int argc, char **argv)
|
242
|
+
{
|
243
|
+
FILE *in = stdin;
|
244
|
+
FILE *out = stdout;
|
245
|
+
int opt;
|
246
|
+
unsigned dyn_table_size = LSQPACK_DEF_DYN_TABLE_SIZE,
|
247
|
+
max_risked_streams = LSQPACK_DEF_MAX_RISKED_STREAMS;
|
248
|
+
unsigned lineno, stream_id;
|
249
|
+
struct lsqpack_enc encoder;
|
250
|
+
char *line, *end, *tab;
|
251
|
+
ssize_t pref_sz;
|
252
|
+
enum lsqpack_enc_status st;
|
253
|
+
enum lsqpack_enc_opts enc_opts = 0;
|
254
|
+
size_t enc_sz, hea_sz, enc_off, hea_off;
|
255
|
+
int header_opened, r;
|
256
|
+
unsigned arg;
|
257
|
+
enum { ACK_NEVER, ACK_IMMEDIATE, } ack_mode = ACK_NEVER;
|
258
|
+
int process_annotations = 0;
|
259
|
+
char line_buf[0x1000];
|
260
|
+
unsigned char tsu_buf[LSQPACK_LONGEST_SDTC];
|
261
|
+
size_t tsu_buf_sz;
|
262
|
+
enum lsqpack_enc_header_flags hflags;
|
263
|
+
int fast = 0;
|
264
|
+
unsigned char enc_buf[0x1000], hea_buf[0x1000], pref_buf[0x20];
|
265
|
+
|
266
|
+
while (-1 != (opt = getopt(argc, argv, "ADMSa:i:no:s:t:hvf")))
|
267
|
+
{
|
268
|
+
switch (opt)
|
269
|
+
{
|
270
|
+
case 'S':
|
271
|
+
enc_opts |= LSQPACK_ENC_OPT_SERVER;
|
272
|
+
break;
|
273
|
+
case 'D':
|
274
|
+
enc_opts |= LSQPACK_ENC_OPT_NO_DUP;
|
275
|
+
break;
|
276
|
+
case 'A':
|
277
|
+
enc_opts |= LSQPACK_ENC_OPT_IX_AGGR;
|
278
|
+
break;
|
279
|
+
case 'M':
|
280
|
+
enc_opts |= LSQPACK_ENC_OPT_NO_MEM_GUARD;
|
281
|
+
break;
|
282
|
+
case 'n':
|
283
|
+
++process_annotations;
|
284
|
+
break;
|
285
|
+
case 'a':
|
286
|
+
ack_mode = atoi(optarg) ? ACK_IMMEDIATE : ACK_NEVER;
|
287
|
+
break;
|
288
|
+
case 'i':
|
289
|
+
if (0 != strcmp(optarg, "-"))
|
290
|
+
{
|
291
|
+
in = fopen(optarg, "r");
|
292
|
+
if (!in)
|
293
|
+
{
|
294
|
+
fprintf(stderr, "cannot open `%s' for reading: %s\n",
|
295
|
+
optarg, strerror(errno));
|
296
|
+
exit(EXIT_FAILURE);
|
297
|
+
}
|
298
|
+
}
|
299
|
+
break;
|
300
|
+
case 'o':
|
301
|
+
if (0 != strcmp(optarg, "-"))
|
302
|
+
{
|
303
|
+
out = fopen(optarg, "wb");
|
304
|
+
if (!out)
|
305
|
+
{
|
306
|
+
fprintf(stderr, "cannot open `%s' for writing: %s\n",
|
307
|
+
optarg, strerror(errno));
|
308
|
+
exit(EXIT_FAILURE);
|
309
|
+
}
|
310
|
+
}
|
311
|
+
break;
|
312
|
+
case 's':
|
313
|
+
max_risked_streams = atoi(optarg);
|
314
|
+
break;
|
315
|
+
case 't':
|
316
|
+
dyn_table_size = atoi(optarg);
|
317
|
+
break;
|
318
|
+
case 'h':
|
319
|
+
usage(argv[0]);
|
320
|
+
exit(EXIT_SUCCESS);
|
321
|
+
case 'f':
|
322
|
+
fast = 1;
|
323
|
+
break;
|
324
|
+
case 'v':
|
325
|
+
++s_verbose;
|
326
|
+
break;
|
327
|
+
default:
|
328
|
+
exit(EXIT_FAILURE);
|
329
|
+
}
|
330
|
+
}
|
331
|
+
|
332
|
+
tsu_buf_sz = sizeof(tsu_buf);
|
333
|
+
if (0 != lsqpack_enc_init(&encoder, s_verbose ? stderr : NULL, dyn_table_size,
|
334
|
+
dyn_table_size, max_risked_streams, enc_opts, tsu_buf,
|
335
|
+
&tsu_buf_sz))
|
336
|
+
{
|
337
|
+
perror("lsqpack_enc_init");
|
338
|
+
exit(EXIT_FAILURE);
|
339
|
+
}
|
340
|
+
|
341
|
+
lineno = 0;
|
342
|
+
stream_id = 0;
|
343
|
+
enc_off = 0;
|
344
|
+
hea_off = 0;
|
345
|
+
header_opened = 0;
|
346
|
+
|
347
|
+
while (line = fgets(line_buf, sizeof(line_buf), in), line != NULL)
|
348
|
+
{
|
349
|
+
++lineno;
|
350
|
+
end = strchr(line, '\n');
|
351
|
+
if (!end)
|
352
|
+
{
|
353
|
+
fprintf(stderr, "no newline on line %u\n", lineno);
|
354
|
+
exit(EXIT_FAILURE);
|
355
|
+
}
|
356
|
+
*end = '\0';
|
357
|
+
|
358
|
+
if (end == line)
|
359
|
+
{
|
360
|
+
if (header_opened)
|
361
|
+
{
|
362
|
+
size_t sz, pref_max = sizeof(pref_buf);
|
363
|
+
for (sz = (fast ? pref_max : 0); sz <= pref_max; sz++)
|
364
|
+
{
|
365
|
+
pref_sz = lsqpack_enc_end_header(&encoder, pref_buf, sz, &hflags);
|
366
|
+
if (pref_sz > 0)
|
367
|
+
{
|
368
|
+
if (max_risked_streams == 0)
|
369
|
+
assert(!(hflags & LSQECH_REF_AT_RISK));
|
370
|
+
break;
|
371
|
+
}
|
372
|
+
}
|
373
|
+
assert(pref_sz <= lsqpack_enc_header_block_prefix_size(&encoder));
|
374
|
+
if (pref_sz < 0)
|
375
|
+
{
|
376
|
+
fprintf(stderr, "end_header failed: %s", strerror(errno));
|
377
|
+
exit(EXIT_FAILURE);
|
378
|
+
}
|
379
|
+
if (ack_mode == ACK_IMMEDIATE)
|
380
|
+
{
|
381
|
+
if (!(2 == pref_sz && pref_buf[0] == 0 && pref_buf[1] == 0))
|
382
|
+
r = ack_stream(&encoder, stream_id);
|
383
|
+
else
|
384
|
+
r = 0;
|
385
|
+
if (r == 0 && encoder.qpe_ins_count > s_saved_ins_count)
|
386
|
+
r = ack_last_entry_id(&encoder);
|
387
|
+
else
|
388
|
+
r = 0;
|
389
|
+
if (r != 0)
|
390
|
+
{
|
391
|
+
fprintf(stderr, "acking stream %u failed: %s", stream_id,
|
392
|
+
strerror(errno));
|
393
|
+
exit(EXIT_FAILURE);
|
394
|
+
}
|
395
|
+
}
|
396
|
+
if (s_verbose)
|
397
|
+
fprintf(stderr, "compression ratio: %.3f\n",
|
398
|
+
lsqpack_enc_ratio(&encoder));
|
399
|
+
write_enc_and_header_streams(out, stream_id, enc_buf, enc_off,
|
400
|
+
pref_buf, pref_sz, hea_buf, hea_off);
|
401
|
+
enc_off = 0;
|
402
|
+
hea_off = 0;
|
403
|
+
header_opened = 0;
|
404
|
+
}
|
405
|
+
continue;
|
406
|
+
}
|
407
|
+
|
408
|
+
if (*line == '#')
|
409
|
+
{
|
410
|
+
if (!process_annotations)
|
411
|
+
continue;
|
412
|
+
|
413
|
+
/* Lines starting with ## are potential annotations */
|
414
|
+
if (ack_mode != ACK_IMMEDIATE
|
415
|
+
/* Ignore ACK annotations in immediate ACK mode, as we do
|
416
|
+
* not tolerate duplicate ACKs.
|
417
|
+
*/
|
418
|
+
&& 1 == sscanf(line, "## %*[a] %u ", &arg))
|
419
|
+
{
|
420
|
+
if (0 != ack_stream(&encoder, arg))
|
421
|
+
{
|
422
|
+
fprintf(stderr, "ACKing stream ID %u failed\n", arg);
|
423
|
+
exit(EXIT_FAILURE);
|
424
|
+
}
|
425
|
+
}
|
426
|
+
else if (1 == sscanf(line, "## %*[s] %u", &arg))
|
427
|
+
sync_table(&encoder, arg);
|
428
|
+
else if (1 == sscanf(line, "## %*[c] %u", &arg))
|
429
|
+
cancel_stream(&encoder, arg);
|
430
|
+
else if (1 == sscanf(line, "## %*[t] %u", &arg))
|
431
|
+
{
|
432
|
+
tsu_buf_sz = sizeof(tsu_buf);
|
433
|
+
if (0 != lsqpack_enc_set_max_capacity(&encoder, arg, tsu_buf,
|
434
|
+
&tsu_buf_sz))
|
435
|
+
{
|
436
|
+
fprintf(stderr, "cannot set capacity to %u: %s\n", arg,
|
437
|
+
strerror(errno));
|
438
|
+
exit(EXIT_FAILURE);
|
439
|
+
}
|
440
|
+
write_enc_stream(out, tsu_buf, tsu_buf_sz);
|
441
|
+
}
|
442
|
+
continue;
|
443
|
+
}
|
444
|
+
|
445
|
+
tab = strchr(line, '\t');
|
446
|
+
if (!tab)
|
447
|
+
{
|
448
|
+
fprintf(stderr, "no TAB on line %u\n", lineno);
|
449
|
+
exit(EXIT_FAILURE);
|
450
|
+
}
|
451
|
+
|
452
|
+
if (!header_opened)
|
453
|
+
{
|
454
|
+
++stream_id;
|
455
|
+
if (0 != lsqpack_enc_start_header(&encoder, stream_id, 0))
|
456
|
+
{
|
457
|
+
fprintf(stderr, "start_header failed: %s\n", strerror(errno));
|
458
|
+
exit(EXIT_FAILURE);
|
459
|
+
}
|
460
|
+
header_opened = 1;
|
461
|
+
}
|
462
|
+
if (fast)
|
463
|
+
{
|
464
|
+
enc_sz = sizeof(enc_buf) - enc_off;
|
465
|
+
hea_sz = sizeof(hea_buf) - hea_off;
|
466
|
+
}
|
467
|
+
else
|
468
|
+
{
|
469
|
+
/* Increase buffers one by one to exercise error conditions */
|
470
|
+
enc_sz = 0;
|
471
|
+
hea_sz = 0;
|
472
|
+
}
|
473
|
+
while (1)
|
474
|
+
{
|
475
|
+
st = lsqpack_enc_encode(&encoder, enc_buf + enc_off, &enc_sz,
|
476
|
+
hea_buf + hea_off, &hea_sz, line, tab - line,
|
477
|
+
tab + 1, end - tab - 1, 0);
|
478
|
+
switch (st)
|
479
|
+
{
|
480
|
+
case LQES_NOBUF_ENC:
|
481
|
+
if (enc_sz < sizeof(enc_buf) - enc_off)
|
482
|
+
++enc_sz;
|
483
|
+
else
|
484
|
+
assert(0);
|
485
|
+
break;
|
486
|
+
case LQES_NOBUF_HEAD:
|
487
|
+
if (hea_sz < sizeof(hea_buf) - hea_off)
|
488
|
+
++hea_sz;
|
489
|
+
else
|
490
|
+
assert(0);
|
491
|
+
break;
|
492
|
+
default:
|
493
|
+
assert(st == LQES_OK);
|
494
|
+
goto end_encode_one_header;
|
495
|
+
}
|
496
|
+
}
|
497
|
+
if (st != LQES_OK)
|
498
|
+
{
|
499
|
+
/* It could only run of of output space, so it's not really an
|
500
|
+
* error, but we make no provision in the interop encoder to
|
501
|
+
* grow the buffers.
|
502
|
+
*/
|
503
|
+
fprintf(stderr, "Could not encode header on line %u: %u\n",
|
504
|
+
lineno, st);
|
505
|
+
exit(EXIT_FAILURE);
|
506
|
+
}
|
507
|
+
end_encode_one_header:
|
508
|
+
enc_off += enc_sz;
|
509
|
+
hea_off += hea_sz;
|
510
|
+
}
|
511
|
+
|
512
|
+
if (s_verbose)
|
513
|
+
fprintf(stderr, "exited while loop\n");
|
514
|
+
|
515
|
+
(void) fclose(in);
|
516
|
+
|
517
|
+
if (header_opened)
|
518
|
+
{
|
519
|
+
if (s_verbose)
|
520
|
+
fprintf(stderr, "close opened header\n");
|
521
|
+
pref_sz = lsqpack_enc_end_header(&encoder, pref_buf, sizeof(pref_buf),
|
522
|
+
&hflags);
|
523
|
+
if (pref_sz < 0)
|
524
|
+
{
|
525
|
+
fprintf(stderr, "end_header failed: %s", strerror(errno));
|
526
|
+
exit(EXIT_FAILURE);
|
527
|
+
}
|
528
|
+
if (max_risked_streams == 0)
|
529
|
+
assert(!(hflags & LSQECH_REF_AT_RISK));
|
530
|
+
if (ack_mode == ACK_IMMEDIATE
|
531
|
+
&& !(2 == pref_sz && pref_buf[0] == 0 && pref_buf[1] == 0)
|
532
|
+
&& 0 != ack_stream(&encoder, stream_id))
|
533
|
+
{
|
534
|
+
fprintf(stderr, "acking stream %u failed: %s", stream_id,
|
535
|
+
strerror(errno));
|
536
|
+
exit(EXIT_FAILURE);
|
537
|
+
}
|
538
|
+
if (s_verbose)
|
539
|
+
fprintf(stderr, "compression ratio: %.3f\n",
|
540
|
+
lsqpack_enc_ratio(&encoder));
|
541
|
+
write_enc_and_header_streams(out, stream_id, enc_buf, enc_off, pref_buf,
|
542
|
+
pref_sz, hea_buf, hea_off);
|
543
|
+
}
|
544
|
+
|
545
|
+
lsqpack_enc_cleanup(&encoder);
|
546
|
+
|
547
|
+
if (0 != fclose(out))
|
548
|
+
{
|
549
|
+
perror("fclose(out)");
|
550
|
+
exit(EXIT_FAILURE);
|
551
|
+
}
|
552
|
+
|
553
|
+
exit(EXIT_SUCCESS);
|
554
|
+
}
|