Example #1
0
  public static DataEmitter getBodyDecoder(
      DataEmitter emitter, RawHeaders headers, boolean server) {
    long _contentLength;
    try {
      _contentLength = Long.parseLong(headers.get("Content-Length"));
    } catch (Exception ex) {
      _contentLength = -1;
    }
    final long contentLength = _contentLength;
    if (-1 != contentLength) {
      if (contentLength < 0) {
        EndEmitter ender =
            EndEmitter.create(
                emitter.getServer(),
                new BodyDecoderException(
                    "not using chunked encoding, and no content-length found."));
        ender.setDataEmitter(emitter);
        emitter = ender;
        return emitter;
      }
      if (contentLength == 0) {
        EndEmitter ender = EndEmitter.create(emitter.getServer(), null);
        ender.setDataEmitter(emitter);
        emitter = ender;
        return emitter;
      }
      ContentLengthFilter contentLengthWatcher = new ContentLengthFilter(contentLength);
      contentLengthWatcher.setDataEmitter(emitter);
      emitter = contentLengthWatcher;
    } else if ("chunked".equalsIgnoreCase(headers.get("Transfer-Encoding"))) {
      ChunkedInputFilter chunker = new ChunkedInputFilter();
      chunker.setDataEmitter(emitter);
      emitter = chunker;
    } else {
      if ((server || headers.getStatusLine().contains("HTTP/1.1"))
          && !"close".equalsIgnoreCase(headers.get("Connection"))) {
        // if this is the server, and the client has not indicated a request body, the client is
        // done
        EndEmitter ender = EndEmitter.create(emitter.getServer(), null);
        ender.setDataEmitter(emitter);
        emitter = ender;
        return emitter;
      }
    }

    if ("gzip".equals(headers.get("Content-Encoding"))) {
      GZIPInputFilter gunzipper = new GZIPInputFilter();
      gunzipper.setDataEmitter(emitter);
      emitter = gunzipper;
    } else if ("deflate".equals(headers.get("Content-Encoding"))) {
      InflaterInputFilter inflater = new InflaterInputFilter();
      inflater.setDataEmitter(emitter);
      emitter = inflater;
    }

    // conversely, if this is the client (http 1.0), and the server has not indicated a request
    // body, we do not report
    // the close/end event until the server actually closes the connection.
    return emitter;
  }
  @Override
  @SuppressWarnings("unused")
  public void onDataAvailable(final DataEmitter emitter, ByteBufferList bb) {
    if (mNeedsHeader) {
      final PushParser parser = new PushParser(emitter);
      parser.readByteArray(
          10,
          new ParseCallback<byte[]>() {
            int flags;
            boolean hcrc;

            public void parsed(byte[] header) {
              short magic = peekShort(header, 0, ByteOrder.LITTLE_ENDIAN);
              if (magic != (short) GZIPInputStream.GZIP_MAGIC) {
                report(new IOException(String.format("unknown format (magic number %x)", magic)));
                emitter.setDataCallback(new NullDataCallback());
                return;
              }
              flags = header[3];
              hcrc = (flags & FHCRC) != 0;
              if (hcrc) {
                crc.update(header, 0, header.length);
              }
              if ((flags & FEXTRA) != 0) {
                parser.readByteArray(
                    2,
                    new ParseCallback<byte[]>() {
                      public void parsed(byte[] header) {
                        if (hcrc) {
                          crc.update(header, 0, 2);
                        }
                        int length = peekShort(header, 0, ByteOrder.LITTLE_ENDIAN) & 0xffff;
                        parser.readByteArray(
                            length,
                            new ParseCallback<byte[]>() {
                              public void parsed(byte[] buf) {
                                if (hcrc) {
                                  crc.update(buf, 0, buf.length);
                                }
                                next();
                              }
                            });
                      }
                    });
              } else {
                next();
              }
            }

            private void next() {
              PushParser parser = new PushParser(emitter);
              DataCallback summer =
                  new DataCallback() {
                    @Override
                    public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                      if (hcrc) {
                        while (bb.size() > 0) {
                          ByteBuffer b = bb.remove();
                          crc.update(b.array(), b.arrayOffset() + b.position(), b.remaining());
                          ByteBufferList.reclaim(b);
                        }
                      }
                      bb.recycle();
                      done();
                    }
                  };
              if ((flags & FNAME) != 0) {
                parser.until((byte) 0, summer);
                return;
              }
              if ((flags & FCOMMENT) != 0) {
                parser.until((byte) 0, summer);
                return;
              }

              done();
            }

            private void done() {
              if (hcrc) {
                parser.readByteArray(
                    2,
                    new ParseCallback<byte[]>() {
                      public void parsed(byte[] header) {
                        short crc16 = peekShort(header, 0, ByteOrder.LITTLE_ENDIAN);
                        if ((short) crc.getValue() != crc16) {
                          report(new IOException("CRC mismatch"));
                          return;
                        }
                        crc.reset();
                        mNeedsHeader = false;
                        setDataEmitter(emitter);
                        //                            emitter.setDataCallback(GZIPInputFilter.this);
                      }
                    });
              } else {
                mNeedsHeader = false;
                setDataEmitter(emitter);
              }
            }
          });
    } else {
      super.onDataAvailable(emitter, bb);
    }
  }