table.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. var hpack = require('../hpack');
  2. var utils = hpack.utils;
  3. var assert = utils.assert;
  4. function Table(options) {
  5. this['static'] = hpack['static-table'];
  6. this.dynamic = [];
  7. this.size = 0;
  8. this.maxSize = 0;
  9. this.length = this['static'].table.length;
  10. this.protocolMaxSize = options.maxSize;
  11. this.maxSize = this.protocolMaxSize;
  12. this.lookupDepth = options.lookupDepth || 32;
  13. }
  14. module.exports = Table;
  15. Table.create = function create(options) {
  16. return new Table(options);
  17. };
  18. Table.prototype.lookup = function lookup(index) {
  19. assert(index !== 0, 'Zero indexed field');
  20. assert(index <= this.length, 'Indexed field OOB')
  21. if (index <= this['static'].table.length)
  22. return this['static'].table[index - 1];
  23. else
  24. return this.dynamic[this.length - index];
  25. };
  26. Table.prototype.reverseLookup = function reverseLookup(name, value) {
  27. var staticEntry = this['static'].map[name];
  28. if (staticEntry && staticEntry.values[value])
  29. return staticEntry.values[value];
  30. // Reverse search dynamic table (new items are at the end of it)
  31. var limit = Math.max(0, this.dynamic.length - this.lookupDepth);
  32. for (var i = this.dynamic.length - 1; i >= limit; i--) {
  33. var entry = this.dynamic[i];
  34. if (entry.name === name && entry.value === value)
  35. return this.length - i;
  36. if (entry.name === name) {
  37. // Prefer smaller index
  38. if (staticEntry)
  39. break;
  40. return -(this.length - i);
  41. }
  42. }
  43. if (staticEntry)
  44. return -staticEntry.index;
  45. return 0;
  46. };
  47. Table.prototype.add = function add(name, value, nameSize, valueSize) {
  48. var totalSize = nameSize + valueSize + 32;
  49. this.dynamic.push({
  50. name: name,
  51. value: value,
  52. nameSize: nameSize,
  53. totalSize: totalSize
  54. });
  55. this.size += totalSize;
  56. this.length++;
  57. this.evict();
  58. };
  59. Table.prototype.evict = function evict() {
  60. while (this.size > this.maxSize) {
  61. var entry = this.dynamic.shift();
  62. this.size -= entry.totalSize;
  63. this.length--;
  64. }
  65. assert(this.size >= 0, 'Table size sanity check failed');
  66. };
  67. Table.prototype.updateSize = function updateSize(size) {
  68. assert(size <= this.protocolMaxSize, 'Table size bigger than maximum');
  69. this.maxSize = size;
  70. this.evict();
  71. };