Ejemplo n.º 1
0
 private void writeHuffmanEncodableValue(ByteBuffer target, String headerName, String val) {
   if (hpackHeaderFunction.shouldUseHuffman(headerName, val)) {
     if (!HPackHuffman.encode(target, val, false)) {
       writeValueString(target, val);
     }
   } else {
     writeValueString(target, val);
   }
 }
Ejemplo n.º 2
0
 private void writeHuffmanEncodableName(ByteBuffer target, String headerName) {
   if (hpackHeaderFunction.shouldUseHuffman(headerName)) {
     if (HPackHuffman.encode(target, headerName, true)) {
       return;
     }
   }
   target.put((byte) 0); // to use encodeInteger we need to place the first byte in the buffer.
   Hpack.encodeInteger(target, headerName.length(), 7);
   for (int j = 0; j < headerName.length(); ++j) {
     target.put(Hpack.toLower((byte) headerName.charAt(j)));
   }
 }
Ejemplo n.º 3
0
  /**
   * Encodes the headers into a buffer.
   *
   * @param headers The headers to encode
   * @param target The buffer to which to write the encoded headers
   * @return The state of the encoding process
   */
  public State encode(MimeHeaders headers, ByteBuffer target) {
    int it = headersIterator;
    if (headersIterator == -1) {
      handleTableSizeChange(target);
      // new headers map
      it = 0;
      currentHeaders = headers;
    } else {
      if (headers != currentHeaders) {
        throw new IllegalStateException();
      }
    }
    while (it < currentHeaders.size()) {
      // FIXME: Review lowercase policy
      String headerName = headers.getName(it).toString().toLowerCase(Locale.US);
      boolean skip = false;
      if (firstPass) {
        if (headerName.charAt(0) != ':') {
          skip = true;
        }
      } else {
        if (headerName.charAt(0) == ':') {
          skip = true;
        }
      }
      if (!skip) {
        String val = headers.getValue(it).toString();

        if (log.isDebugEnabled()) {
          log.debug(sm.getString("hpackEncoder.encodeHeader", headerName, val));
        }
        TableEntry tableEntry = findInTable(headerName, val);

        // We use 11 to make sure we have enough room for the
        // variable length integers
        int required = 11 + headerName.length() + 1 + val.length();

        if (target.remaining() < required) {
          this.headersIterator = it;
          return State.UNDERFLOW;
        }
        // Only index if it will fit
        boolean canIndex =
            hpackHeaderFunction.shouldUseIndexing(headerName, val)
                && (headerName.length() + val.length() + 32) < maxTableSize;
        if (tableEntry == null && canIndex) {
          // add the entry to the dynamic table
          target.put((byte) (1 << 6));
          writeHuffmanEncodableName(target, headerName);
          writeHuffmanEncodableValue(target, headerName, val);
          addToDynamicTable(headerName, val);
        } else if (tableEntry == null) {
          // literal never indexed
          target.put((byte) (1 << 4));
          writeHuffmanEncodableName(target, headerName);
          writeHuffmanEncodableValue(target, headerName, val);
        } else {
          // so we know something is already in the table
          if (val.equals(tableEntry.value)) {
            // the whole thing is in the table
            target.put((byte) (1 << 7));
            Hpack.encodeInteger(target, tableEntry.getPosition(), 7);
          } else {
            if (canIndex) {
              // add the entry to the dynamic table
              target.put((byte) (1 << 6));
              Hpack.encodeInteger(target, tableEntry.getPosition(), 6);
              writeHuffmanEncodableValue(target, headerName, val);
              addToDynamicTable(headerName, val);

            } else {
              target.put((byte) (1 << 4));
              Hpack.encodeInteger(target, tableEntry.getPosition(), 4);
              writeHuffmanEncodableValue(target, headerName, val);
            }
          }
        }
      }
      if (++it == currentHeaders.size() && firstPass) {
        firstPass = false;
        it = 0;
      }
    }
    headersIterator = -1;
    firstPass = true;
    return State.COMPLETE;
  }