Path: blob/master/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedInputStream.java
41159 views
/*1* Copyright (c) 2005, 2017, 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}137if (n < 0 && !eof)138throw new IOException("connection closed before all data received");139return n;140}141142private void consumeCRLF () throws IOException {143char c;144c = (char)in.read(); /* CR */145if (c != CR) {146throw new IOException ("invalid chunk end");147}148c = (char)in.read(); /* LF */149if (c != LF) {150throw new IOException ("invalid chunk end");151}152}153154/**155* returns the number of bytes available to read in the current chunk156* which may be less than the real amount, but we'll live with that157* limitation for the moment. It only affects potential efficiency158* rather than correctness.159*/160public int available () throws IOException {161if (eof || closed) {162return 0;163}164int n = in.available();165return n > remaining? remaining: n;166}167168/* called after the stream is closed to see if bytes169* have been read from the underlying channel170* and buffered internally171*/172public boolean isDataBuffered () throws IOException {173assert eof;174return in.available() > 0;175}176177public boolean markSupported () {return false;}178179public void mark (int l) {180}181182public void reset () throws IOException {183throw new IOException ("mark/reset not supported");184}185}186187188