Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java
38918 views
/*1* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.net.httpserver;2627import java.io.*;28import java.net.*;29import com.sun.net.httpserver.*;30import com.sun.net.httpserver.spi.*;3132class ChunkedInputStream extends LeftOverInputStream {33ChunkedInputStream (ExchangeImpl t, InputStream src) {34super (t, src);35}3637private int remaining;3839/* true when a chunk header needs to be read */4041private boolean needToReadHeader = true;4243final static char CR = '\r';44final static char LF = '\n';45/*46* Maximum chunk header size of 2KB + 2 bytes for CRLF47*/48private final static int MAX_CHUNK_HEADER_SIZE = 2050;4950private int numeric (char[] arr, int nchars) throws IOException {51assert arr.length >= nchars;52int len = 0;53for (int i=0; i<nchars; i++) {54char c = arr[i];55int val=0;56if (c>='0' && c <='9') {57val = c - '0';58} else if (c>='a' && c<= 'f') {59val = c - 'a' + 10;60} else if (c>='A' && c<= 'F') {61val = c - 'A' + 10;62} else {63throw new IOException ("invalid chunk length");64}65len = len * 16 + val;66}67return len;68}6970/* read the chunk header line and return the chunk length71* any chunk extensions are ignored72*/73private int readChunkHeader () throws IOException {74boolean gotCR = false;75int c;76char[] len_arr = new char [16];77int len_size = 0;78boolean end_of_len = false;79int read = 0;8081while ((c=in.read())!= -1) {82char ch = (char) c;83read++;84if ((len_size == len_arr.length -1) ||85(read > MAX_CHUNK_HEADER_SIZE))86{87throw new IOException ("invalid chunk header");88}89if (gotCR) {90if (ch == LF) {91int l = numeric (len_arr, len_size);92return l;93} else {94gotCR = false;95}96if (!end_of_len) {97len_arr[len_size++] = ch;98}99} else {100if (ch == CR) {101gotCR = true;102} else if (ch == ';') {103end_of_len = true;104} else if (!end_of_len) {105len_arr[len_size++] = ch;106}107}108}109throw new IOException ("end of stream reading chunk header");110}111112protected int readImpl (byte[]b, int off, int len) throws IOException {113if (eof) {114return -1;115}116if (needToReadHeader) {117remaining = readChunkHeader();118if (remaining == 0) {119eof = true;120consumeCRLF();121t.getServerImpl().requestCompleted (t.getConnection());122return -1;123}124needToReadHeader = false;125}126if (len > remaining) {127len = remaining;128}129int n = in.read(b, off, len);130if (n > -1) {131remaining -= n;132}133if (remaining == 0) {134needToReadHeader = true;135consumeCRLF();136}137return n;138}139140private void consumeCRLF () throws IOException {141char c;142c = (char)in.read(); /* CR */143if (c != CR) {144throw new IOException ("invalid chunk end");145}146c = (char)in.read(); /* LF */147if (c != LF) {148throw new IOException ("invalid chunk end");149}150}151152/**153* returns the number of bytes available to read in the current chunk154* which may be less than the real amount, but we'll live with that155* limitation for the moment. It only affects potential efficiency156* rather than correctness.157*/158public int available () throws IOException {159if (eof || closed) {160return 0;161}162int n = in.available();163return n > remaining? remaining: n;164}165166/* called after the stream is closed to see if bytes167* have been read from the underlying channel168* and buffered internally169*/170public boolean isDataBuffered () throws IOException {171assert eof;172return in.available() > 0;173}174175public boolean markSupported () {return false;}176177public void mark (int l) {178}179180public void reset () throws IOException {181throw new IOException ("mark/reset not supported");182}183}184185186