PageRenderTime 52ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java

https://github.com/MIPS/libcore
Java | 197 lines | 86 code | 21 blank | 90 comment | 17 complexity | 9bae37c2db03fec226b03b3cb0116a74 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.harmony.xnet.provider.jsse;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import javax.net.ssl.SSLException;
  21. /**
  22. * This class provides input data stream functionality
  23. * for SSLSocket. It accumulates the application data
  24. * received by SSL protocol.
  25. */
  26. public final class SSLSocketInputStream
  27. extends InputStream {
  28. // The size of the internal data buffer.
  29. // It should not be less than maximum data chunk enclosed
  30. // in one ssl packet.
  31. private final int size = SSLRecordProtocol.MAX_DATA_LENGTH;
  32. // Internal buffer accumulating the received application data
  33. private byte[] buffer = new byte[size];
  34. // position of the next byte to read from the buffer
  35. private int pos;
  36. // position of the last byte to read + 1
  37. private int end;
  38. // the ssl socket owning the stream
  39. private final SSLSocketImpl owner;
  40. // the flag indicating that the end of the (owner's) input stream
  41. // has been reached
  42. private boolean end_reached = false;
  43. /**
  44. * Creates the application data input stream for specified socket.
  45. * @param owner the socket which will provide this input stream
  46. * to client applications.
  47. */
  48. protected SSLSocketInputStream(SSLSocketImpl owner) {
  49. this.owner = owner;
  50. }
  51. // The helper delivering the application data from the record layer
  52. protected Adapter dataPoint = new Adapter();
  53. /**
  54. * Tells to the stream that the end of the income data has
  55. * been reached.
  56. */
  57. protected void setEnd() {
  58. end_reached = true;
  59. }
  60. // ------------------ InputStream implementetion -------------------
  61. /**
  62. * Returns the number of bytes available for reading without blocking.
  63. * @return the number of available bytes.
  64. * @throws IOException
  65. */
  66. @Override
  67. public int available() throws IOException {
  68. return end - pos;
  69. }
  70. /**
  71. * Closes the stream
  72. * @throws IOException
  73. */
  74. @Override
  75. public void close() throws IOException {
  76. buffer = null;
  77. }
  78. /**
  79. * Reads one byte. If there is no data in the underlying buffer,
  80. * this operation can block until the data will be
  81. * available.
  82. * @return read value.
  83. * @throws IOException
  84. */
  85. @Override
  86. public int read() throws IOException {
  87. if (buffer == null) {
  88. throw new IOException("Stream was closed.");
  89. }
  90. while (pos == end) {
  91. if (end_reached) {
  92. return -1;
  93. }
  94. // If there is no data in the buffer
  95. // - will block untill the data will be provided by
  96. // record layer
  97. owner.needAppData();
  98. }
  99. return buffer[pos++] & 0xFF;
  100. }
  101. /**
  102. * Method acts as described in spec for superclass.
  103. * @see java.io.InputStream#read(byte[])
  104. */
  105. @Override
  106. public int read(byte[] b) throws IOException {
  107. return read(b, 0, b.length);
  108. }
  109. /**
  110. * Method acts as described in spec for superclass.
  111. * @see java.io.InputStream#read(byte[],int,int)
  112. */
  113. @Override
  114. public int read(byte[] b, int off, int len) throws IOException {
  115. int read_b;
  116. int i = 0;
  117. do {
  118. if ((read_b = read()) == -1) {
  119. return (i == 0) ? -1 : i;
  120. }
  121. b[off+i] = (byte) read_b;
  122. i++;
  123. } while ((available() != 0) && (i<len));
  124. return i;
  125. }
  126. /**
  127. * Method acts as described in spec for superclass.
  128. * @see java.io.InputStream#skip(long)
  129. */
  130. @Override
  131. public long skip(long n) throws IOException {
  132. long i = 0;
  133. int av = available();
  134. if (av < n) {
  135. n = av;
  136. }
  137. while ((i < n) && (read() != -1)) {
  138. i++;
  139. }
  140. return i;
  141. }
  142. // The helper class devivering the application data from the record layer
  143. // to this input stream.
  144. // It 'adapts' the InputStream interface to Appendable, which is used for
  145. // transmition of income data from the record protocol to its clients.
  146. private class Adapter implements org.apache.harmony.xnet.provider.jsse.Appendable {
  147. /**
  148. * Appends the data to the stream.
  149. * This method could be implemented in the outer class
  150. * itself, but it could be insecure.
  151. */
  152. public void append(byte[] src) {
  153. int length = src.length;
  154. if (size - (end - pos) < length) {
  155. // If the size of the buffer is greater than or equals to
  156. // SSLRecordProtocol.MAX_DATA_LENGTH this situation will
  157. // happen iff:
  158. // 1. the length of received data fragment is greater
  159. // than allowed by the spec
  160. // 2. it is rehandhaking stage and we have got several
  161. // extra app data messages.
  162. // In any case it is better to throw alert exception.
  163. throw new AlertException(AlertProtocol.INTERNAL_ERROR,
  164. new SSLException("Could not accept income app data."));
  165. }
  166. if (end + length > size) {
  167. // move the content of the buffer to the beginnig
  168. System.arraycopy(buffer, pos, buffer, 0, end-pos);
  169. end -= pos;
  170. pos = 0;
  171. }
  172. System.arraycopy(src, 0, buffer, end, length);
  173. end = end + length;
  174. }
  175. }
  176. }