1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  this work for additional information regarding copyright ownership.
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  the License.  You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.xnet.provider.jsse.AlertException;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.xnet.provider.jsse.SSLInputStream;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintStream;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.MessageDigest;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.net.ssl.SSLHandshakeException;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class provides Input/Output data functionality
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for handshake layer. It provides read and write operations
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and accumulates all sent/received handshake's data.
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class can be presented as a combination of 2 data pipes.
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The first data pipe is a pipe of income data: append method
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * places the data at the beginning of the pipe, and read methods
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * consume the data from the pipe. The second pipe is an outcoming
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data pipe: write operations plases the data into the pipe,
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and getData methods consume the data.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is important to note that work with pipe cound not be
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * started if there is unconsumed data in another pipe. It is
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reasoned by the following: handshake protocol performs read
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and write operations consecuently. I.e. it first reads all
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * income data and only than produces the responce and places it
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into the stream.
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The read operations of the stream presented by the methods
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of SSLInputStream which in its turn is an extension of InputStream.
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * So this stream can be used as an InputStream parameter for
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * certificate generation.
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Also input stream functionality supports marks. The marks
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * help to reset the position of the stream in case of incompleate
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * handshake records. Note that in case of exhausting
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of income data the EndOfBufferException is thown which implies
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the following:
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  1. the stream contains scrappy handshake record,
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  2. the read position should be reseted to marked,
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  3. and more income data is expected.
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The throwing of the exception (instead of returning of -1 value
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or incompleate filling of destination buffer)
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * helps to speed up the process of scrappy data recognition and
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * processing.
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For more information about TLS handshake process see
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TLS v 1 specification at http://www.ietf.org/rfc/rfc2246.txt.
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class HandshakeIODataStream
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        extends SSLInputStream implements org.apache.harmony.xnet.provider.jsse.Appendable, DataStream {
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Objects are used to compute digests of data passed
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // during the handshake phase
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final MessageDigest md5;
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final MessageDigest sha;
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static {
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            md5 = MessageDigest.getInstance("MD5");
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sha = MessageDigest.getInstance("SHA-1");
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception e) {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            e.printStackTrace();
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException(
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Could not initialize the Digest Algorithms.");
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public HandshakeIODataStream() {}
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // buffer is used to keep the handshaking data;
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int buff_size = 1024;
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int inc_buff_size = 1024;
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] buffer = new byte[buff_size];
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ---------------- Input related functionality -----------------
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position of the next byte to read
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int read_pos;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int marked_pos;
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position of the last byte to read + 1
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int read_pos_end;
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
99a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson    @Override
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int available() {
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return read_pos_end - read_pos;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson    @Override
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean markSupported() {
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson    @Override
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void mark(int limit) {
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        marked_pos = read_pos;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void mark() {
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        marked_pos = read_pos;
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson    @Override
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void reset() {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = marked_pos;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Removes the data from the marked position to
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the current read position. The method is usefull when it is needed
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to delete one message from the internal buffer.
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void removeFromMarkedPosition() {
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, read_pos,
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer, marked_pos, read_pos_end - read_pos);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos_end -= (read_pos - marked_pos);
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = marked_pos;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * read an opaque value;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   byte:   byte
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
140a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson    @Override
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int read() throws IOException {
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (read_pos == read_pos_end) {
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //return -1;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new EndOfBufferException();
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return buffer[read_pos++] & 0xFF;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * reads vector of opaque values
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   new:    long
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
154a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson    @Override
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] read(int length) throws IOException {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (length > available()) {
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new EndOfBufferException();
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] res = new byte[length];
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, read_pos, res, 0, length);
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = read_pos + length;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return res;
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
165a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson    @Override
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int read(byte[] dest, int offset, int length) throws IOException {
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (length > available()) {
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new EndOfBufferException();
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, read_pos, dest, offset, length);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = read_pos + length;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return length;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ------------------- Extending of the input data ---------------------
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Appends the income data to be read by handshake protocol.
179a055db83f05034fcd5564ab5930e8d16d4ececfbJesse Wilson     * The attempts to overflow the buffer by means of this methods
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * seem to be futile because of:
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * 1. The SSL protocol specifies the maximum size of the record
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and record protocol does not pass huge messages.
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (see TLS v1 specification http://www.ietf.org/rfc/rfc2246.txt ,
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * p 6.2)
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * 2. After each call of this method, handshake protocol should
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * start (and starts) the operations on received data and recognize
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the fake data if such was provided (to check the size of certificate
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for example).
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void append(byte[] src) {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        append(src, 0, src.length);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void append(byte[] src, int from, int length) {
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (read_pos == read_pos_end) {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // start reading state after writing
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (write_pos_beg != write_pos) {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // error: outboud handshake data was not sent,
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // but inbound handshake data has been received.
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new AlertException(
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    AlertProtocol.UNEXPECTED_MESSAGE,
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    new SSLHandshakeException(
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "Handshake message has been received before "
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + "the last oubound message had been sent."));
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (read_pos < write_pos) {
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                read_pos = write_pos;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                read_pos_end = read_pos;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (read_pos_end + length > buff_size) {
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            enlargeBuffer(read_pos_end+length-buff_size);
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(src, from, buffer, read_pos_end, length);
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos_end += length;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void enlargeBuffer(int size) {
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buff_size = (size < inc_buff_size)
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ? buff_size + inc_buff_size
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            : buff_size + size;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] new_buff = new byte[buff_size];
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, 0, new_buff, 0, buffer.length);
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer = new_buff;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void clearBuffer() {
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = 0;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        marked_pos = 0;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos_end = 0;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        write_pos = 0;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        write_pos_beg = 0;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Arrays.fill(buffer, (byte) 0);
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ------------------- Output related functionality --------------------
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position in the buffer available for write
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int write_pos;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position in the buffer where the last write session has begun
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int write_pos_beg;
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // checks if the data can be written in the buffer
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void check(int length) {
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // (write_pos == write_pos_beg) iff:
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // 1. there were not write operations yet
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // 2. all written data was demanded by getData methods
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (write_pos == write_pos_beg) {
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // just started to write after the reading
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (read_pos != read_pos_end) {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // error: attempt to write outbound data into the stream before
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // all the inbound handshake data had been read
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new AlertException(
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        AlertProtocol.INTERNAL_ERROR,
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        new SSLHandshakeException("Data was not fully read: "
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + read_pos + " " + read_pos_end));
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // set up the write positions
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (write_pos_beg < read_pos_end) {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                write_pos_beg = read_pos_end;
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                write_pos = write_pos_beg;
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // if there is not enought free space in the buffer - enlarge it:
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (write_pos + length >= buff_size) {
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            enlargeBuffer(length);
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes an opaque value
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   byte:   byte
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void write(byte b) {
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(1);
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = b;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint8 value
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last byte)
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint8(long n) {
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(1);
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint16 value
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last 2 bytes)
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint16(long n) {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(2);
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint24 value
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last 3 bytes)
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint24(long n) {
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(3);
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint32 value
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last 4 bytes)
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint32(long n) {
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(4);
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24);
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint64 value
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint64(long n) {
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(8);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00000000000000L) >> 56);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff000000000000L) >> 48);
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000000000L) >> 40);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00000000L) >> 32);
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24);
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * writes vector of opaque values
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param  vector the vector to be written
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void write(byte[] vector) {
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(vector.length);
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(vector, 0, buffer, write_pos, vector.length);
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        write_pos += vector.length;
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ------------------- Retrieve the written bytes ----------------------
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean hasData() {
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (write_pos > write_pos_beg);
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * returns the chunk of stored data with the length no more than specified.
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   length: int
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] getData(int length) {
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] res;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (write_pos - write_pos_beg < length) {
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            res = new byte[write_pos - write_pos_beg];
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(buffer, write_pos_beg,
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    res, 0, write_pos-write_pos_beg);
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            write_pos_beg = write_pos;
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            res = new byte[length];
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(buffer, write_pos_beg, res, 0, length);
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            write_pos_beg += length;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return res;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ---------------------- Debud functionality -------------------------
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void printContent(PrintStream outstream) {
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int perLine = 20;
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String prefix = " ";
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String delimiter = "";
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i=write_pos_beg; i<write_pos; i++) {
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String tail = Integer.toHexString(
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    0x00ff & buffer[i]).toUpperCase();
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (tail.length() == 1) {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tail = "0" + tail;
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            outstream.print(prefix + tail + delimiter);
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (((i-write_pos_beg+1)%10) == 0) {
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outstream.print(" ");
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (((i-write_pos_beg+1)%perLine) == 0) {
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outstream.println();
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outstream.println();
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ---------------------- Message Digest Functionality ----------------
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the MD5 digest of the data passed throught the stream
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return MD5 digest
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestMD5() {
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (md5) {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = (read_pos_end > write_pos)
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ? read_pos_end
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                : write_pos;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            md5.update(buffer, 0, len);
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return md5.digest();
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the SHA-1 digest of the data passed throught the stream
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return SHA-1 digest
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestSHA() {
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (sha) {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = (read_pos_end > write_pos)
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ? read_pos_end
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                : write_pos;
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sha.update(buffer, 0, len);
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return sha.digest();
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the MD5 digest of the data passed throught the stream
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * except last message
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return MD5 digest
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestMD5withoutLast() {
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (md5) {
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            md5.update(buffer, 0, marked_pos);
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return md5.digest();
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the SHA-1 digest of the data passed throught the stream
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * except last message
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return SHA-1 digest
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestSHAwithoutLast() {
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (sha) {
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sha.update(buffer, 0, marked_pos);
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return sha.digest();
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns all the data passed throught the stream
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return all the data passed throught the stream at the moment
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getMessages() {
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int len = (read_pos_end > write_pos) ? read_pos_end : write_pos;
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] res = new byte[len];
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, 0, res, 0, len);
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return res;
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
465