1 /** 2 * Deflater 3 * 4 * Copyright: 5 * (C) 2012-2015 Tatsuhiro Tsujikawa 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Distributed under the terms of the MIT license with an additional section 1.2 of the curl/libcurl project. 10 * Consult the provided LICENSE.md file for details 11 */ 12 module libhttp2.deflater; 13 14 import libhttp2.constants; 15 import libhttp2.types; 16 import libhttp2.buffers; 17 import libhttp2.huffman; 18 19 struct Deflater 20 { 21 HDTable ctx; 22 23 /// The upper limit of the header table size the deflater accepts. 24 size_t deflate_hd_table_bufsize_max = DEFAULT_MAX_DEFLATE_BUFFER_SIZE; 25 26 /// Minimum header table size notified in the next context update 27 size_t min_hd_table_bufsize_max; 28 29 /// If nonzero, send header table size using encoding context update in the next deflate process 30 bool notify_table_size_change; 31 32 /* 33 * Initializes |deflater| for deflating header fields. 34 * 35 * The encoder only uses up to DEFAULT_MAX_DEFLATE_BUFFER_SIZE bytes 36 * for header table even if the larger value is specified later in changeTableSize(). 37 */ 38 this(size_t _deflate_hd_table_bufsize_max) 39 { 40 ctx = Mem.alloc!HDTable(); 41 42 if (_deflate_hd_table_bufsize_max < HD_DEFAULT_MAX_BUFFER_SIZE) { 43 notify_table_size_change = true; 44 ctx.hd_table_bufsize_max = _deflate_hd_table_bufsize_max; 45 } else { 46 notify_table_size_change = false; 47 } 48 49 deflate_hd_table_bufsize_max = _deflate_hd_table_bufsize_max; 50 min_hd_table_bufsize_max = uint.max; 51 } 52 53 void free() 54 { 55 Mem.free(ctx); 56 } 57 58 /* 59 * Deflates the |hfa|, which has |hfa.length| header fields, into 60 * the |bufs|. 61 * 62 * This function expands |bufs| as necessary to store the result. If 63 * buffers is full and the process still requires more space, this 64 * funtion fails and returns ErrorCode.HEADER_COMP. 65 * 66 * After this function returns, it is safe to delete the |hfa|. 67 * 68 * This function returns 0 if it succeeds, or one of the following 69 * negative error codes: 70 * 71 * ErrorCode.HEADER_COMP 72 * Deflation process has failed. 73 * ErrorCode.BUFFER_ERROR 74 * Out of buffer space. 75 */ 76 ErrorCode deflate(Buffers bufs, in HeaderField[] hfa) { 77 size_t i; 78 ErrorCode rv; 79 80 if (ctx.bad) 81 return ErrorCode.HEADER_COMP; 82 83 if (notify_table_size_change) { 84 size_t _min_hd_table_bufsize_max = min_hd_table_bufsize_max; 85 86 notify_table_size_change = false; 87 min_hd_table_bufsize_max = uint.max; 88 89 if (ctx.hd_table_bufsize_max > _min_hd_table_bufsize_max) { 90 91 rv = emitTableSize(bufs, _min_hd_table_bufsize_max); 92 93 if (rv != 0) { 94 goto fail; 95 } 96 } 97 98 rv = emitTableSize(bufs, ctx.hd_table_bufsize_max); 99 100 if (rv != 0) { 101 goto fail; 102 } 103 } 104 105 for (i = 0; i < hfa.length; ++i) { 106 rv = deflate(bufs, hfa[i]); 107 if (rv != 0) 108 goto fail; 109 } 110 111 LOGF("deflatehd: success"); 112 113 return ErrorCode.OK; 114 fail: 115 LOGF("deflatehd: error return %d", rv); 116 117 ctx.bad = 1; 118 return rv; 119 } 120 121 /** 122 * Deflates the |hfa|, which has |hfa.length| header fields, into 123 * the |buf| of length |buf.length|. 124 * 125 * If |buf| is not large enough to store the deflated header block, 126 * this function fails with $(D ErrorCode.INSUFF_BUFSIZE). The 127 * caller should use `Deflater.upperBound()` to know the upper 128 * bound of buffer size required to deflate given header fields. 129 * 130 * Once this function fails, subsequent call of this function always 131 * returns $(D ErrorCode.HEADER_COMP). 132 * 133 * After this function returns, it is safe to delete the |hfa|. 134 * 135 * This function returns 0 if it succeeds, or one of the following 136 * negative error codes: 137 * 138 * $(D ErrorCode.HEADER_COMP) 139 * Deflation process has failed. 140 * $(D ErrorCode.INSUFF_BUFSIZE) 141 * The provided |buflen| size is too small to hold the output. 142 */ 143 int deflate(ubyte[] buf, in HeaderField[] hfa) 144 { 145 Buffers bufs = Mem.alloc!Buffers(buf); 146 ErrorCode rv; 147 148 rv = deflate(bufs, hfa); 149 150 size_t buflen = bufs.length; 151 152 bufs.free(); 153 Mem.free(bufs); 154 155 if (rv == ErrorCode.BUFFER_ERROR) 156 return ErrorCode.INSUFF_BUFSIZE; 157 return cast(int)buflen; 158 } 159 160 /** 161 * Returns an upper bound on the compressed size after deflation of |hfa| 162 */ 163 size_t upperBound(in HeaderField[] hfa) { 164 size_t n = 0; 165 size_t i; 166 167 /* Possible Maximum Header Table Size Change. Encoding (1u << 31) - 168 1 using 4 bit prefix requires 6 bytes. We may emit this at most 169 twice. 170 */ 171 n += 12; 172 173 /* Use Literal Header Field without indexing - New Name, since it is 174 most space consuming format. Also we choose the less one between 175 non-huffman and huffman, so using literal byte count is 176 sufficient for upper bound. 177 178 Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes. We 179 need 2 of this for |hflen| header fields. 180 */ 181 n += 6 * 2 * hfa.length; 182 183 for (i = 0; i < hfa.length; ++i) 184 { 185 n += hfa[i].name.length + hfa[i].value.length; 186 } 187 188 return n; 189 } 190 191 /** 192 * Changes header table size of the |Deflater| to 193 * |settings_hd_table_bufsize_max| bytes. This may trigger eviction 194 * in the dynamic table. 195 * 196 * The |settings_hd_table_bufsize_max| should be the value received in 197 * SettingsID.HEADER_TABLE_SIZE. 198 * 199 * The deflater never uses more memory than ``hd_table_bufsize_max`` bytes 200 * specified in the constructor. Therefore, if |settings_hd_table_bufsize_max| > 201 * ``hd_table_bufsize_max``, resulting maximum table size becomes ``hd_table_bufsize_max``. 202 */ 203 void changeTableSize(size_t settings_hd_table_bufsize_max) { 204 import std.algorithm : min; 205 206 size_t next_bufsize = min(settings_hd_table_bufsize_max, deflate_hd_table_bufsize_max); 207 208 ctx.hd_table_bufsize_max = next_bufsize; 209 210 min_hd_table_bufsize_max = min(min_hd_table_bufsize_max, next_bufsize); 211 212 notify_table_size_change = true; 213 214 ctx.shrink(); 215 216 } 217 218 219 package: 220 ErrorCode deflate(Buffers bufs, const ref HeaderField hf) { 221 ErrorCode rv; 222 int res; 223 bool found; 224 int idx; 225 bool incidx; 226 uint name_hash = hf.name.hash(); 227 uint value_hash = hf.value.hash(); 228 229 LOGF("deflatehd: deflating %s: %s", hf.name, hf.value); 230 231 res = ctx.search(hf, name_hash, value_hash, found); 232 233 idx = res; 234 235 if (found) { 236 237 LOGF("deflatehd: name/value match index=%d", idx); 238 239 rv = emitIndexedBlock(bufs, idx); 240 241 if (rv != 0) 242 return rv; 243 244 return ErrorCode.OK; 245 } 246 247 if (idx != -1) 248 LOGF("deflatehd: name match index=%d", res); 249 250 251 if (shouldIndex(hf)) 252 { 253 HDEntry new_ent; 254 if (idx != -1 && idx < cast(int) static_table.length) { 255 HeaderField hf_indname; 256 hf_indname = hf; 257 hf_indname.name = ctx.get(idx).hf.name; 258 new_ent = ctx.add(hf_indname, name_hash, value_hash, HDFlags.VALUE_ALLOC); 259 } else 260 new_ent = ctx.add(hf, name_hash, value_hash, HDFlags.NAME_ALLOC | HDFlags.VALUE_ALLOC); 261 262 if (!new_ent) 263 return ErrorCode.HEADER_COMP; 264 if (new_ent.refcnt == 0) 265 Mem.free(new_ent); 266 267 incidx = true; 268 } 269 270 if (idx == -1) 271 rv = emitNewNameBlock(bufs, hf, incidx); 272 else 273 rv = emitIndexedNameBlock(bufs, idx, hf, incidx); 274 275 if (rv != 0) 276 return rv; 277 278 279 return ErrorCode.OK; 280 } 281 282 bool shouldIndex(in HeaderField hf) 283 { 284 if ((hf.flag & HeaderFlag.NO_INDEX) || entryRoom(hf.name.length, hf.value.length) > ctx.hd_table_bufsize_max * 3 / 4) 285 { 286 return false; 287 } 288 289 return !name_match(hf, ":path") && !name_match(hf, "content-length") && 290 !name_match(hf, "set-cookie") && !name_match(hf, "etag") && 291 !name_match(hf, "if-modified-since") && 292 !name_match(hf, "if-none-match") && !name_match(hf, "location") && 293 !name_match(hf, "age"); 294 } 295 private bool name_match(in HeaderField hf, string name) { 296 return hf.name == name; 297 } 298 } 299 300 package: 301 302 ErrorCode emitIndexedNameBlock(Buffers bufs, size_t idx, const ref HeaderField hf, bool inc_indexing) { 303 ErrorCode rv; 304 ubyte* bufp; 305 size_t blocklen; 306 ubyte[16] sb; 307 size_t prefixlen; 308 bool no_index; 309 310 no_index = (hf.flag & HeaderFlag.NO_INDEX) != 0; 311 312 if (inc_indexing) 313 prefixlen = 6; 314 else 315 prefixlen = 4; 316 317 LOGF("deflatehd: emit indname index=%d, valuelen=%d, indexing=%d, no_index=%d", idx, hf.value.length, inc_indexing, no_index); 318 319 blocklen = countEncodedLength(idx + 1, prefixlen); 320 321 if (sb.length < blocklen) { 322 return ErrorCode.HEADER_COMP; 323 } 324 325 bufp = sb.ptr; 326 327 *bufp = packFirstByte(inc_indexing, no_index); 328 329 encodeLength(bufp, idx + 1, prefixlen); 330 331 rv = bufs.add(cast(string)sb[0 .. blocklen]); 332 if (rv != 0) 333 return rv; 334 335 rv = emitString(bufs, hf.value); 336 if (rv != 0) 337 return rv; 338 339 return ErrorCode.OK; 340 } 341 342 ErrorCode emitNewNameBlock(Buffers bufs, in HeaderField hf, bool inc_indexing) { 343 ErrorCode rv; 344 bool no_index; 345 346 no_index = (hf.flag & HeaderFlag.NO_INDEX) != 0; 347 348 LOGF("deflatehd: emit newname namelen=%d, valuelen=%d, indexing=%d, no_index=%d", hf.name.length, hf.value.length, inc_indexing, no_index); 349 350 rv = bufs.add(packFirstByte(inc_indexing, no_index)); 351 if (rv != 0) { 352 return rv; 353 } 354 355 rv = emitString(bufs, hf.name); 356 if (rv != 0) { 357 return rv; 358 } 359 360 rv = emitString(bufs, hf.value); 361 if (rv != 0) { 362 return rv; 363 } 364 365 return ErrorCode.OK; 366 } 367 368 ErrorCode emitIndexedBlock(Buffers bufs, size_t idx) { 369 ErrorCode rv; 370 size_t blocklen; 371 ubyte[16] sb; 372 ubyte *bufp; 373 374 blocklen = countEncodedLength(idx + 1, 7); 375 376 LOGF("deflatehd: emit indexed index=%d, %d bytes", idx, 377 blocklen); 378 379 if (sb.length < blocklen) { 380 return ErrorCode.HEADER_COMP; 381 } 382 383 bufp = sb.ptr; 384 *bufp = 0x80; 385 encodeLength(bufp, idx + 1, 7); 386 387 rv = bufs.add(cast(string)sb[0 .. blocklen]); 388 if (rv != 0) { 389 return rv; 390 } 391 392 return ErrorCode.OK; 393 } 394 395 ErrorCode emitString(Buffers bufs, in string str) { 396 ErrorCode rv; 397 size_t len = str.length; 398 ubyte[16] sb; 399 ubyte *bufp; 400 size_t blocklen; 401 size_t enclen; 402 bool huffman; 403 404 { // count the required bytes for encoding str 405 size_t i; 406 size_t nbits = 0; 407 408 for (i = 0; i < len; ++i) { 409 nbits += symbol_table[cast(ubyte)str[i]].nbits; 410 } 411 /* pad the prefix of EOS (256) */ 412 enclen = (nbits + 7) / 8; 413 } 414 415 if (enclen < len) 416 huffman = true; 417 else 418 enclen = len; 419 420 blocklen = countEncodedLength(enclen, 7); 421 422 LOGF("deflatehd: emit string str=%s, length=%d, huffman=%d, encoded_length=%d", str, len, huffman, enclen); 423 424 if (sb.length < blocklen) { 425 return ErrorCode.HEADER_COMP; 426 } 427 428 bufp = sb.ptr; 429 *bufp = huffman ? 1 << 7 : 0; 430 encodeLength(bufp, enclen, 7); 431 432 rv = bufs.add(cast(string)sb[0 .. blocklen]); 433 if (rv != 0) 434 return rv; 435 436 if (huffman) { 437 rv = encodeHuffman(bufs, str); 438 } else { 439 assert(enclen == len); 440 rv = bufs.add(str); 441 } 442 443 return rv; 444 } 445 446 447 ErrorCode emitTableSize(Buffers bufs, size_t table_size) { 448 ErrorCode rv; 449 ubyte *bufp; 450 size_t blocklen; 451 ubyte[16] sb; 452 453 LOGF("deflatehd: emit table_size=%d", table_size); 454 455 blocklen = countEncodedLength(table_size, 5); 456 457 if (sb.length < blocklen) { 458 return ErrorCode.HEADER_COMP; 459 } 460 461 bufp = sb.ptr; 462 463 *bufp = 0x20; 464 465 encodeLength(bufp, table_size, 5); 466 467 rv = bufs.add(cast(string)sb[0 .. blocklen]); 468 if (rv != 0) 469 return rv; 470 471 return ErrorCode.OK; 472 } 473 474 ubyte packFirstByte(bool inc_indexing, bool no_index) { 475 if (inc_indexing) 476 return 0x40; 477 if (no_index) 478 return 0x10; 479 return 0x00; 480 } 481 482 size_t encodeLength(ubyte* buf, size_t n, size_t prefix) { 483 size_t k = (1 << prefix) - 1; 484 ubyte *begin = buf; 485 486 *buf &= ~cast(int)(cast(ubyte) k); 487 488 if (n < k) { 489 *buf |= cast(ubyte) n; 490 return 1; 491 } 492 493 *buf++ |= (cast(ubyte)k); 494 n -= k; 495 496 for (; n >= 128; n >>= 7) { 497 *buf++ = cast(ubyte)((1 << 7) | ((cast(ubyte)n) & 0x7f)); 498 } 499 500 *buf++ = cast(ubyte) n; 501 502 return cast(size_t)(buf - begin); 503 } 504 505 506 /* 507 * Encodes the given data |src| with length |srclen| to the |bufs|. 508 * This function expands extra buffers in |bufs| if necessary. 509 * 510 * This function returns 0 if it succeeds, or one of the following 511 * negative error codes: 512 * 513 * ErrorCode.BUFFER_ERROR 514 * Out of buffer space. 515 */ 516 ErrorCode encodeHuffman(Buffers bufs, in string src) 517 { 518 ErrorCode rv; 519 int rembits = 8; 520 size_t i; 521 size_t avail; 522 523 avail = bufs.curAvailable; 524 525 for (i = 0; i < src.length; ++i) 526 { 527 Symbol sym = symbol_table[src[i]]; 528 if (rembits == 8) { 529 if (avail) { 530 bufs.addHold(0); 531 } else { 532 rv = bufs.addHold(0); 533 if (rv != 0) { 534 return rv; 535 } 536 avail = bufs.curAvailable; 537 } 538 } 539 rembits = sym.encode(bufs, avail, rembits); 540 if (rembits < 0) { 541 return cast(ErrorCode) rembits; 542 } 543 } 544 /* 256 is special terminal symbol, pad with its prefix */ 545 if (rembits < 8) { 546 /* if rembits < 8, we should have at least 1 buffer space available */ 547 const Symbol sym = symbol_table[256]; 548 assert(avail); 549 /* Caution we no longer adjust avail here */ 550 bufs.fastOr(cast(ubyte)(sym.code >> (sym.nbits - rembits))); 551 } 552 553 return ErrorCode.OK; 554 } 555 556 size_t countEncodedLength(size_t n, size_t prefix) { 557 size_t k = (1 << prefix) - 1; 558 size_t len = 0; 559 560 if (n < k) { 561 return 1; 562 } 563 564 n -= k; 565 ++len; 566 567 for (; n >= 128; n >>= 7, ++len) 568 continue; 569 570 return len + 1; 571 }