/**
   * Add to or set a field. If the field is allowed to have multiple values, add will add multiple
   * headers of the same name.
   *
   * @param name the name of the field
   * @param value the value of the field.
   * @exception IllegalArgumentException If the name is a single valued field and already has a
   *     value.
   */
  public void add(Buffer name, Buffer value) throws IllegalArgumentException {
    if (value == null) throw new IllegalArgumentException("null value");

    if (!(name instanceof CachedBuffer)) name = HttpHeaders.CACHE.lookup(name);
    name = name.asImmutableBuffer();

    if (!(value instanceof CachedBuffer)
        && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name)))
      value = HttpHeaderValues.CACHE.lookup(value);
    value = value.asImmutableBuffer();

    Field field = _names.get(name);
    Field last = null;
    while (field != null) {
      last = field;
      field = field._next;
    }

    // create the field
    field = new Field(name, value);
    _fields.add(field);

    // look for chain to add too
    if (last != null) last._next = field;
    else _names.put(name, field);
  }
Exemple #2
0
    /* ------------------------------------------------------------ */
    public InputStream getInputStream() throws IOException {
      Buffer indirect = getIndirectBuffer();
      if (indirect != null && indirect.array() != null)
        return new ByteArrayInputStream(indirect.array(), indirect.getIndex(), indirect.length());

      return _resource.getInputStream();
    }
Exemple #3
0
 private ByteBuffer wrap(Buffer b) {
   byte[] array = b.array();
   if (array != null) {
     return ByteBuffer.wrap(array, b.getIndex(), b.length());
   } else {
     return ByteBuffer.wrap(b.asArray(), 0, b.length());
   }
 }
 public void encode(Buffer buffer) throws IOException {
   for (Record record : _records) {
     getMessage().getCompression().encodeName(record.getName(), buffer);
     record.getType().encode(buffer);
     record.getDnsClass().encode(buffer);
     BufferUtil.putInt(buffer, record.getTtl());
     int index = buffer.putIndex();
     buffer.setPutIndex(index + 2);
     record.doEncode(buffer, getMessage().getCompression());
     BufferUtil.poke16(buffer, index, buffer.putIndex() - index - 2);
   }
 }
    public void startResponse(Buffer version, int status, Buffer reason) {
      request = false;
      f0 = version.toString();
      f1 = Integer.toString(status);
      f2 = reason == null ? null : reason.toString();

      fields = new HttpFields();
      hdr = new String[9];
      val = new String[9];

      messageCompleted = false;
      headerCompleted = false;
    }
  private synchronized int expelBuffer(long blockFor) throws IOException {
    if (_buffer == null) return 0;
    int result = flushBuffer();
    _buffer.compact();
    if (!_endp.isBlocking()) {
      while (_buffer.space() == 0) {
        boolean ready = _endp.blockWritable(blockFor);
        if (!ready) throw new IOException("Write timeout");

        result += flushBuffer();
        _buffer.compact();
      }
    }
    return result;
  }
    public void onFrame(byte flags, byte opcode, Buffer buffer) {
      try {
        byte[] array = buffer.array();

        if (opcode == 0) {
          if (_websocket instanceof WebSocket.OnTextMessage)
            ((WebSocket.OnTextMessage) _websocket).onMessage(buffer.toString(StringUtil.__UTF8));
        } else {
          if (_websocket instanceof WebSocket.OnBinaryMessage)
            ((WebSocket.OnBinaryMessage) _websocket)
                .onMessage(array, buffer.getIndex(), buffer.length());
        }
      } catch (Throwable th) {
        LOG.warn(th);
      }
    }
  private synchronized int flushBuffer() throws IOException {
    if (!_endp.isOpen()) throw new EofException();

    if (_buffer != null && _buffer.hasContent()) return _endp.flush(_buffer);

    return 0;
  }
 public synchronized int flush() throws IOException {
   int flushed = flushBuffer();
   if (_buffer != null && _buffer.length() == 0) {
     _buffers.returnBuffer(_buffer);
     _buffer = null;
   }
   return flushed;
 }
Exemple #10
0
 /* ------------------------------------------------------------ */
 protected Buffer getIndirectBuffer(Resource resource) {
   try {
     int len = (int) resource.length();
     if (len < 0) {
       LOG.warn("invalid resource: " + String.valueOf(resource) + " " + len);
       return null;
     }
     Buffer buffer = new IndirectNIOBuffer(len);
     InputStream is = resource.getInputStream();
     buffer.readFrom(is, len);
     is.close();
     return buffer;
   } catch (IOException e) {
     LOG.warn(e);
     return null;
   }
 }
  /* (non-Javadoc)
   * @see org.eclipse.jetty.websocket.AbstractExtension#onFrame(byte, byte, org.eclipse.jetty.io.Buffer)
   */
  @Override
  public void onFrame(byte flags, byte opcode, Buffer buffer) {
    if (getConnection().isControl(opcode) || !isFlag(flags, 1)) {
      super.onFrame(flags, opcode, buffer);
      return;
    }

    if (buffer.array() == null) buffer = buffer.asMutableBuffer();

    int length = 0xff & buffer.get();
    if (length >= 0x7e) {
      int b = (length == 0x7f) ? 8 : 2;
      length = 0;
      while (b-- > 0) length = 0x100 * length + (0xff & buffer.get());
    }

    // TODO check a max framesize

    _inflater.setInput(buffer.array(), buffer.getIndex(), buffer.length());
    ByteArrayBuffer buf = new ByteArrayBuffer(length);
    try {
      while (_inflater.getRemaining() > 0) {
        int inflated = _inflater.inflate(buf.array(), buf.putIndex(), buf.space());
        if (inflated == 0) throw new DataFormatException("insufficient data");
        buf.setPutIndex(buf.putIndex() + inflated);
      }

      super.onFrame(clearFlag(flags, 1), opcode, buf);
    } catch (DataFormatException e) {
      LOG.warn(e);
      getConnection().close(WebSocketConnectionRFC6455.CLOSE_BAD_PAYLOAD, e.toString());
    }
  }
    public void startRequest(Buffer tok0, Buffer tok1, Buffer tok2) {
      try {
        request = true;
        h = -1;
        hdr = new String[9];
        val = new String[9];
        f0 = tok0.toString();
        f1 = new String(tok1.array(), tok1.getIndex(), tok1.length(), StringUtil.__UTF8);
        if (tok2 != null) f2 = tok2.toString();
        else f2 = null;

        fields = new HttpFields();
      } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
      }

      messageCompleted = false;
      headerCompleted = false;
    }
    /*
     *
     * @see org.eclipse.jetty.server.server.HttpParser.EventHandler#startRequest(org.eclipse.io.Buffer,
     *      org.eclipse.io.Buffer, org.eclipse.io.Buffer)
     */
    @Override
    public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException {
      uri = uri.asImmutableBuffer();

      _host = false;
      _expect = false;
      _expect100Continue = false;
      _expect102Processing = false;
      _delayedHandling = false;
      _charset = null;

      if (_request.getTimeStamp() == 0) _request.setTimeStamp(System.currentTimeMillis());
      _request.setMethod(method.toString());

      try {
        _head = false;
        switch (HttpMethods.CACHE.getOrdinal(method)) {
          case HttpMethods.CONNECT_ORDINAL:
            _uri.parseConnect(uri.array(), uri.getIndex(), uri.length());
            break;

          case HttpMethods.HEAD_ORDINAL:
            _head = true;
            // fall through

          default:
            _uri.parse(uri.array(), uri.getIndex(), uri.length());
        }

        _request.setUri(_uri);

        if (version == null) {
          _request.setProtocol(HttpVersions.HTTP_0_9);
          _version = HttpVersions.HTTP_0_9_ORDINAL;
        } else {
          version = HttpVersions.CACHE.get(version);
          if (version == null) throw new HttpException(HttpStatus.BAD_REQUEST_400, null);
          _version = HttpVersions.CACHE.getOrdinal(version);
          if (_version <= 0) _version = HttpVersions.HTTP_1_0_ORDINAL;
          _request.setProtocol(version.toString());
        }
      } catch (Exception e) {
        LOG.debug(e);
        if (e instanceof HttpException) throw (HttpException) e;
        throw new HttpException(HttpStatus.BAD_REQUEST_400, null, e);
      }
    }
  @Test
  public void testReuse() throws Exception {
    HttpFields header = new HttpFields();
    Buffer n1 = new ByteArrayBuffer("name1");
    Buffer va = new ByteArrayBuffer("value1");
    Buffer vb = new ByteArrayBuffer(10);
    vb.put((byte) 'v');
    vb.put((byte) 'a');
    vb.put((byte) 'l');
    vb.put((byte) 'u');
    vb.put((byte) 'e');
    vb.put((byte) '1');

    header.put("name0", "value0");
    header.put(n1, va);
    header.put("name2", "value2");

    assertEquals("value0", header.getStringField("name0"));
    assertEquals("value1", header.getStringField("name1"));
    assertEquals("value2", header.getStringField("name2"));
    assertNull(header.getStringField("name3"));

    header.remove(n1);
    assertNull(header.getStringField("name1"));
    header.put(n1, vb);
    assertEquals("value1", header.getStringField("name1"));

    int matches = 0;
    Enumeration e = header.getFieldNames();
    while (e.hasMoreElements()) {
      Object o = e.nextElement();
      if ("name0".equals(o)) matches++;
      if ("name1".equals(o)) matches++;
      if ("name2".equals(o)) matches++;
    }
    assertEquals(3, matches);

    e = header.getValues("name1");
    assertEquals(true, e.hasMoreElements());
    assertEquals(e.nextElement(), "value1");
    assertEquals(false, e.hasMoreElements());
  }
Exemple #15
0
  public void addContent(Buffer content, boolean last) throws IOException {
    LOG.debug("addContent {} {}", content.length(), last);
    if (_noContent) {
      content.clear();
      return;
    }

    if (content.isImmutable()) throw new IllegalArgumentException("immutable");

    if (_last || _state == STATE_END) {
      LOG.debug("Ignoring extra content {}", content);
      content.clear();
      return;
    }
    _last = last;

    if (!_endp.isOpen()) {
      _state = STATE_END;
      return;
    }

    // Handle any unfinished business?
    if (_content != null && _content.length() > 0) {
      flushBuffer();
      if (_content != null && _content.length() > 0) throw new IllegalStateException("FULL");
    }

    _content = content;

    _contentWritten += content.length();

    // Handle the _content
    if (_head) {
      content.clear();
      _content = null;
    } else if (!last || _buffer != null) {
      // Yes - so we better check we have a buffer
      initBuffer();
      // Copy _content to buffer;
      int len = 0;
      len = _buffer.put(_content);

      // make sure there is space for a trailing null   (???)
      if (len > 0 && _buffer.space() == 0) {
        len--;
        _buffer.setPutIndex(_buffer.putIndex() - 1);
      }

      LOG.debug("copied {} to buffer", len);

      _content.skip(len);

      if (_content.length() == 0) _content = null;
    }
  }
  public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length)
      throws IOException {
    long blockFor = _endp.getMaxIdleTime();

    if (_buffer == null) _buffer = _buffers.getDirectBuffer();

    if (_buffer.space() == 0) expelBuffer(blockFor);

    bufferPut(opcode, blockFor);

    if (isLengthFrame(opcode)) {
      // Send a length delimited frame

      // How many bytes we need for the length ?
      // We have 7 bits available, so log2(length) / 7 + 1
      // For example, 50000 bytes is 2 8-bytes: 11000011 01010000
      // but we need to write it in 3 7-bytes 0000011 0000110 1010000
      // 65536 == 1 00000000 00000000 => 100 0000000 0000000
      int lengthBytes = new BigInteger(String.valueOf(length)).bitLength() / 7 + 1;
      for (int i = lengthBytes - 1; i > 0; --i) {
        byte lengthByte = (byte) (0x80 | (0x7F & (length >> 7 * i)));
        bufferPut(lengthByte, blockFor);
      }
      bufferPut((byte) (0x7F & length), blockFor);
    }

    int remaining = length;
    while (remaining > 0) {
      int chunk = remaining < _buffer.space() ? remaining : _buffer.space();
      _buffer.put(content, offset + (length - remaining), chunk);
      remaining -= chunk;
      if (_buffer.space() > 0) {
        if (!isLengthFrame(opcode)) _buffer.put((byte) 0xFF);
        // Gently flush the data, issuing a non-blocking write
        flushBuffer();
      } else {
        // Forcibly flush the data, issuing a blocking write
        expelBuffer(blockFor);
        if (remaining == 0) {
          if (!isLengthFrame(opcode)) _buffer.put((byte) 0xFF);
          // Gently flush the data, issuing a non-blocking write
          flushBuffer();
        }
      }
    }
  }
 private synchronized void bufferPut(byte data) throws IOException {
   _buffer.put((byte) (data ^ _mask[+_m++ % 4]));
 }
  public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length)
      throws IOException {
    // System.err.printf("<< %s %s
    // %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length);

    long blockFor = _endp.getMaxIdleTime();

    if (_buffer == null)
      _buffer = (_maskGen != null) ? _buffers.getBuffer() : _buffers.getDirectBuffer();

    boolean last = WebSocketConnectionD06.isLastFrame(flags);
    opcode = (byte) (((0xf & flags) << 4) + 0xf & opcode);

    int space = (_maskGen != null) ? 14 : 10;

    do {
      opcode = _opsent ? WebSocketConnectionD06.OP_CONTINUATION : opcode;
      _opsent = true;

      int payload = length;
      if (payload + space > _buffer.capacity()) {
        // We must fragement, so clear FIN bit
        opcode &= (byte) 0x7F; // Clear the FIN bit
        payload = _buffer.capacity() - space;
      } else if (last) opcode |= (byte) 0x80; // Set the FIN bit

      // ensure there is space for header
      if (_buffer.space() <= space) expelBuffer(blockFor);

      // write mask
      if ((_maskGen != null)) {
        _maskGen.genMask(_mask);
        _m = 0;
        _buffer.put(_mask);
      }

      // write the opcode and length
      if (payload > 0xffff) {
        bufferPut(
            new byte[] {
              opcode,
              (byte) 0x7f,
              (byte) 0,
              (byte) 0,
              (byte) 0,
              (byte) 0,
              (byte) ((payload >> 24) & 0xff),
              (byte) ((payload >> 16) & 0xff),
              (byte) ((payload >> 8) & 0xff),
              (byte) (payload & 0xff)
            });
      } else if (payload >= 0x7e) {
        bufferPut(new byte[] {opcode, (byte) 0x7e, (byte) (payload >> 8), (byte) (payload & 0xff)});
      } else {
        bufferPut(opcode);
        bufferPut((byte) payload);
      }

      // write payload
      int remaining = payload;
      while (remaining > 0) {
        _buffer.compact();
        int chunk = remaining < _buffer.space() ? remaining : _buffer.space();

        if ((_maskGen != null)) {
          for (int i = 0; i < chunk; i++) bufferPut(content[offset + (payload - remaining) + i]);
        } else _buffer.put(content, offset + (payload - remaining), chunk);

        remaining -= chunk;
        if (_buffer.space() > 0) {
          // Gently flush the data, issuing a non-blocking write
          flushBuffer();
        } else {
          // Forcibly flush the data, issuing a blocking write
          expelBuffer(blockFor);
          if (remaining == 0) {
            // Gently flush the data, issuing a non-blocking write
            flushBuffer();
          }
        }
      }
      offset += payload;
      length -= payload;
    } while (length > 0);
    _opsent = !last;
  }
  /* ------------------------------------------------------------ */
  public Connection handle() throws IOException {
    try {
      // handle stupid hixie random bytes
      if (_hixieBytes != null) {

        // take any available bytes from the parser buffer, which may have already been read
        Buffer buffer = _parser.getBuffer();
        if (buffer != null && buffer.length() > 0) {
          int l = buffer.length();
          if (l > (8 - _hixieBytes.length())) l = 8 - _hixieBytes.length();
          _hixieBytes.put(buffer.peek(buffer.getIndex(), l));
          buffer.skip(l);
        }

        // while we are not blocked
        while (_endp.isOpen()) {
          // do we now have enough
          if (_hixieBytes.length() == 8) {
            // we have the silly random bytes
            // so let's work out the stupid 16 byte reply.
            doTheHixieHixieShake();
            _endp.flush(_hixieBytes);
            _hixieBytes = null;
            _endp.flush();
            break;
          }

          // no, then let's fill
          int filled = _endp.fill(_hixieBytes);
          if (filled < 0) {
            _endp.flush();
            _endp.close();
            break;
          }
        }

        if (_websocket instanceof OnFrame) ((OnFrame) _websocket).onHandshake(this);
        _websocket.onOpen(this);
        return this;
      }

      // handle the framing protocol
      boolean progress = true;

      while (progress) {
        int flushed = _generator.flush();
        int filled = _parser.parseNext();

        progress = flushed > 0 || filled > 0;

        _endp.flush();

        if (_endp instanceof AsyncEndPoint && ((AsyncEndPoint) _endp).hasProgressed())
          progress = true;
      }
    } catch (IOException e) {
      LOG.debug(e);
      try {
        if (_endp.isOpen()) _endp.close();
      } catch (IOException e2) {
        LOG.ignore(e2);
      }
      throw e;
    } finally {
      if (_endp.isOpen()) {
        if (_endp.isInputShutdown() && _generator.isBufferEmpty()) _endp.close();
        else checkWriteable();

        checkWriteable();
      }
    }
    return this;
  }
 public synchronized boolean isBufferEmpty() {
   return _buffer == null || _buffer.length() == 0;
 }
 public void parsedHeader(Buffer name, Buffer value) {
   hdr[++h] = name.toString(StringUtil.__ISO_8859_1);
   val[h] = value.toString(StringUtil.__ISO_8859_1);
 }
 private synchronized void bufferPut(byte datum, long blockFor) throws IOException {
   if (_buffer == null) _buffer = _buffers.getDirectBuffer();
   _buffer.put(datum);
   if (_buffer.space() == 0) expelBuffer(blockFor);
 }
    /*
     * @see org.eclipse.jetty.server.server.HttpParser.EventHandler#parsedHeaderValue(org.eclipse.io.Buffer)
     */
    @Override
    public void parsedHeader(Buffer name, Buffer value) {
      int ho = HttpHeaders.CACHE.getOrdinal(name);
      switch (ho) {
        case HttpHeaders.HOST_ORDINAL:
          // TODO check if host matched a host in the URI.
          _host = true;
          break;

        case HttpHeaders.EXPECT_ORDINAL:
          value = HttpHeaderValues.CACHE.lookup(value);
          switch (HttpHeaderValues.CACHE.getOrdinal(value)) {
            case HttpHeaderValues.CONTINUE_ORDINAL:
              _expect100Continue = _generator instanceof HttpGenerator;
              break;

            case HttpHeaderValues.PROCESSING_ORDINAL:
              _expect102Processing = _generator instanceof HttpGenerator;
              break;

            default:
              String[] values = value.toString().split(",");
              for (int i = 0; values != null && i < values.length; i++) {
                CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());
                if (cb == null) _expect = true;
                else {
                  switch (cb.getOrdinal()) {
                    case HttpHeaderValues.CONTINUE_ORDINAL:
                      _expect100Continue = _generator instanceof HttpGenerator;
                      break;
                    case HttpHeaderValues.PROCESSING_ORDINAL:
                      _expect102Processing = _generator instanceof HttpGenerator;
                      break;
                    default:
                      _expect = true;
                  }
                }
              }
          }
          break;

        case HttpHeaders.ACCEPT_ENCODING_ORDINAL:
        case HttpHeaders.USER_AGENT_ORDINAL:
          value = HttpHeaderValues.CACHE.lookup(value);
          break;

        case HttpHeaders.CONTENT_TYPE_ORDINAL:
          value = MimeTypes.CACHE.lookup(value);
          _charset = MimeTypes.getCharsetFromContentType(value);
          break;

        case HttpHeaders.CONNECTION_ORDINAL:
          // looks rather clumsy, but the idea is to optimize for a single valued header
          switch (HttpHeaderValues.CACHE.getOrdinal(value)) {
            case -1:
              {
                String[] values = value.toString().split(",");
                for (int i = 0; values != null && i < values.length; i++) {
                  CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());

                  if (cb != null) {
                    switch (cb.getOrdinal()) {
                      case HttpHeaderValues.CLOSE_ORDINAL:
                        _responseFields.add(
                            HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
                        _generator.setPersistent(false);
                        break;

                      case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
                        if (_version == HttpVersions.HTTP_1_0_ORDINAL)
                          _responseFields.add(
                              HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.KEEP_ALIVE_BUFFER);
                        break;
                    }
                  }
                }
                break;
              }
            case HttpHeaderValues.CLOSE_ORDINAL:
              _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
              _generator.setPersistent(false);
              break;

            case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
              if (_version == HttpVersions.HTTP_1_0_ORDINAL)
                _responseFields.put(
                    HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.KEEP_ALIVE_BUFFER);
              break;
          }
      }

      _requestFields.add(name, value);
    }
    /* ------------------------------------------------------------ */
    public void putTo(Buffer buffer) throws IOException {
      int o = (_name instanceof CachedBuffer) ? ((CachedBuffer) _name).getOrdinal() : -1;
      if (o >= 0) buffer.put(_name);
      else {
        int s = _name.getIndex();
        int e = _name.putIndex();
        while (s < e) {
          byte b = _name.peek(s++);
          switch (b) {
            case '\r':
            case '\n':
            case ':':
              continue;
            default:
              buffer.put(b);
          }
        }
      }

      buffer.put((byte) ':');
      buffer.put((byte) ' ');

      o = (_value instanceof CachedBuffer) ? ((CachedBuffer) _value).getOrdinal() : -1;
      if (o >= 0) buffer.put(_value);
      else {
        int s = _value.getIndex();
        int e = _value.putIndex();
        while (s < e) {
          byte b = _value.peek(s++);
          switch (b) {
            case '\r':
            case '\n':
              continue;
            default:
              buffer.put(b);
          }
        }
      }

      BufferUtil.putCRLF(buffer);
    }
    /* ------------------------------------------------------------ */
    public void sendContent(Object content) throws IOException {
      Resource resource = null;

      if (isClosed()) throw new IOException("Closed");

      if (super._generator.isWritten()) throw new IllegalStateException("!empty");

      // Convert HTTP content to contentl
      if (content instanceof HttpContent) {
        HttpContent httpContent = (HttpContent) content;
        Buffer contentType = httpContent.getContentType();
        if (contentType != null && !_responseFields.containsKey(HttpHeaders.CONTENT_TYPE_BUFFER)) {
          String enc = _response.getSetCharacterEncoding();
          if (enc == null) _responseFields.add(HttpHeaders.CONTENT_TYPE_BUFFER, contentType);
          else {
            if (contentType instanceof CachedBuffer) {
              CachedBuffer content_type = ((CachedBuffer) contentType).getAssociate(enc);
              if (content_type != null)
                _responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER, content_type);
              else {
                _responseFields.put(
                    HttpHeaders.CONTENT_TYPE_BUFFER,
                    contentType + ";charset=" + QuotedStringTokenizer.quoteIfNeeded(enc, ";= "));
              }
            } else {
              _responseFields.put(
                  HttpHeaders.CONTENT_TYPE_BUFFER,
                  contentType + ";charset=" + QuotedStringTokenizer.quoteIfNeeded(enc, ";= "));
            }
          }
        }
        if (httpContent.getContentLength() > 0)
          _responseFields.putLongField(
              HttpHeaders.CONTENT_LENGTH_BUFFER, httpContent.getContentLength());
        Buffer lm = httpContent.getLastModified();
        long lml = httpContent.getResource().lastModified();
        if (lm != null) _responseFields.put(HttpHeaders.LAST_MODIFIED_BUFFER, lm);
        else if (httpContent.getResource() != null) {
          if (lml != -1) _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, lml);
        }

        boolean direct =
            _connector instanceof NIOConnector
                && ((NIOConnector) _connector).getUseDirectBuffers()
                && !(_connector instanceof SslConnector);
        content = direct ? httpContent.getDirectBuffer() : httpContent.getIndirectBuffer();
        if (content == null) content = httpContent.getInputStream();
      } else if (content instanceof Resource) {
        resource = (Resource) content;
        _responseFields.putDateField(HttpHeaders.LAST_MODIFIED_BUFFER, resource.lastModified());
        content = resource.getInputStream();
      }

      // Process content.
      if (content instanceof Buffer) {
        super._generator.addContent((Buffer) content, Generator.LAST);
        commitResponse(Generator.LAST);
      } else if (content instanceof InputStream) {
        InputStream in = (InputStream) content;

        try {
          int max = super._generator.prepareUncheckedAddContent();
          Buffer buffer = super._generator.getUncheckedBuffer();

          int len = buffer.readFrom(in, max);

          while (len >= 0) {
            super._generator.completeUncheckedAddContent();
            _out.flush();

            max = super._generator.prepareUncheckedAddContent();
            buffer = super._generator.getUncheckedBuffer();
            len = buffer.readFrom(in, max);
          }
          super._generator.completeUncheckedAddContent();
          _out.flush();
        } finally {
          if (resource != null) resource.release();
          else in.close();
        }
      } else throw new IllegalArgumentException("unknown content type?");
    }
 private synchronized void bufferPut(byte[] data) throws IOException {
   if (_maskGen != null) for (int i = 0; i < data.length; i++) data[i] ^= _mask[+_m++ % 4];
   _buffer.put(data);
 }