view src/com/trilead/ssh2/crypto/cipher/CipherInputStream.java @ 99:eda03b809f48
move blocking test from socket read to queue take
author
Carl Byington <carl@five-ten-sg.com>
date
Tue, 17 Jun 2014 15:13:41 -0700 (2014-06-17)
parents
0ce5cc452d02
children
line source
+ −
+ − package com.trilead.ssh2.crypto.cipher;
+ −
+ − import java.io.IOException;
+ − import java.io.InputStream;
+ −
+ − /**
+ − * CipherInputStream.
+ − *
+ − * @author Christian Plattner, plattner@trilead.com
+ − * @version $Id: CipherInputStream.java,v 1.1 2007/10/15 12:49:55 cplattne Exp $
+ − */
+ − public class CipherInputStream {
+ − BlockCipher currentCipher;
+ − InputStream bi;
+ − byte[] buffer;
+ − byte[] enc;
+ − int blockSize;
+ − int pos;
+ −
+ − /*
+ − * We cannot use java.io.BufferedInputStream, since that is not available in
+ − * J2ME. Everything could be improved alot here.
+ − */
+ −
+ − final int BUFF_SIZE = 2048;
+ − byte[] input_buffer = new byte[BUFF_SIZE];
+ − int input_buffer_pos = 0;
+ − int input_buffer_size = 0;
+ −
+ − public CipherInputStream(BlockCipher tc, InputStream bi) {
+ − this.bi = bi;
+ − changeCipher(tc);
+ − }
+ −
+ − private int fill_buffer() throws IOException {
+ − input_buffer_pos = 0;
+ − input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE);
+ − return input_buffer_size;
+ − }
+ −
+ − private int internal_read(byte[] b, int off, int len) throws IOException {
+ − if (input_buffer_size < 0)
+ − return -1;
+ −
+ − if (input_buffer_pos >= input_buffer_size) {
+ − if (fill_buffer() <= 0)
+ − return -1;
+ − }
+ −
+ − int avail = input_buffer_size - input_buffer_pos;
+ − int thiscopy = (len > avail) ? avail : len;
+ − System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy);
+ − input_buffer_pos += thiscopy;
+ − return thiscopy;
+ − }
+ −
+ − public void changeCipher(BlockCipher bc) {
+ − this.currentCipher = bc;
+ − blockSize = bc.getBlockSize();
+ − buffer = new byte[blockSize];
+ − enc = new byte[blockSize];
+ − pos = blockSize;
+ − }
+ −
+ − private void getBlock() throws IOException {
+ − int n = 0;
+ −
+ − while (n < blockSize) {
+ − int len = internal_read(enc, n, blockSize - n);
+ −
+ − if (len < 0)
+ − throw new IOException("Cannot read full block, EOF reached.");
+ −
+ − n += len;
+ − }
+ −
+ − try {
+ − currentCipher.transformBlock(enc, 0, buffer, 0);
+ − }
+ − catch (Exception e) {
+ − throw new IOException("Error while decrypting block.");
+ − }
+ −
+ − pos = 0;
+ − }
+ −
+ − public int read(byte[] dst) throws IOException {
+ − return read(dst, 0, dst.length);
+ − }
+ −
+ − public int read(byte[] dst, int off, int len) throws IOException {
+ − int count = 0;
+ −
+ − while (len > 0) {
+ − if (pos >= blockSize)
+ − getBlock();
+ −
+ − int avail = blockSize - pos;
+ − int copy = Math.min(avail, len);
+ − System.arraycopy(buffer, pos, dst, off, copy);
+ − pos += copy;
+ − off += copy;
+ − len -= copy;
+ − count += copy;
+ − }
+ −
+ − return count;
+ − }
+ −
+ − public int read() throws IOException {
+ − if (pos >= blockSize) {
+ − getBlock();
+ − }
+ −
+ − return buffer[pos++] & 0xff;
+ − }
+ −
+ − public int readPlain(byte[] b, int off, int len) throws IOException {
+ − if (pos != blockSize)
+ − throw new IOException("Cannot read plain since crypto buffer is not aligned.");
+ −
+ − int n = 0;
+ −
+ − while (n < len) {
+ − int cnt = internal_read(b, off + n, len - n);
+ −
+ − if (cnt < 0)
+ − throw new IOException("Cannot fill buffer, EOF reached.");
+ −
+ − n += cnt;
+ − }
+ −
+ − return n;
+ − }
+ − }