public StreamConnector(int bufferSize) { buffer = new ByteRingBuffer(bufferSize); in = new InputStream() { @Override public int read() throws IOException { if( closed.get() ) { close(); return -1; } return buffer.get(); } @Override public void close() throws IOException { super.close(); StreamConnector.this.close(); } }; out = new OutputStream() { @Override public void write(int b) throws IOException { buffer.put(b); } }; }
/** * Get all data available from the buffer * @return */ public byte[] readAll() { synchronized (access) { int size = getAvailable(); byte[] result = new byte[size]; for( int i=0; i<size; i++) result[i] = (byte) get(); return result; } }
/** * Put all the bytes to the buffer. Block until the operation is completed. * * @param buffer */ public void put(byte[] buffer) { for (byte b : buffer) put(b); }
@Override public int read() throws IOException { int nextByte = inputStream.read(); if (nextByte < 0) { readingFinished = true; end(); return -1; } else { ring.put(nextByte); try { int encrypted = ring.get(); hmac.update(encrypted); return transformer.transformByte(encrypted); } catch (EncryptionError encryptionError) { throw new IOException("failed to decrypt", encryptionError); } } }
EtaDecryptingStream(InputStream inputStream) throws IOException, EncryptionError { this.inputStream = inputStream; byte[] IV = new byte[getCipher().getBlockSize()]; inputStream.read(IV); transformer = new CTRTransformer(getCipher(), IV); hmac = new HMAC(key); // We should have always block bytes in the buffer to finish: ring = new ByteRingBuffer(hmac.getLength() + 8); for (int i = 0; i < hmac.getLength(); i++) ring.put(inputStream.read()); }
/** * Get several bytes from the queue (size can be any positive). Blocks until specified number of * bytes are written. */ public byte[] get(int size) { byte[] result = new byte[size]; for (int i = 0; i < size; i++) { result[i] = (byte)get(); } return result; }
public void dump() { new Bytes(buffer.readAll()).dump(); } }
/** * Get the next byte, block until available. */ @SuppressWarnings("unused") public int get() { synchronized (access) { while (rpos == wpos) try { access.wait(); } catch (InterruptedException e) { } int result = data[rpos] & 0xFF; rpos = advance(rpos); access.notifyAll(); return result; } }
/** * Nonblocking read. Reads bytes into specified buffer * * @param b * buffer to read into * * @return number of bytes read, 0 if the buffer is empty */ public int read(byte[] b) { int count = 0; while (count < b.length) { int res = read(); if (res >= 0) b[count++] = (byte) res; else break; } return count; }
/** * Nonblocking get the next byte. * * @return -1 of there is no data or the next available byte. */ public int read() { synchronized (access) { if (rpos == wpos) return -1; return get(); } }
private void end() throws IOException { byte[] readHmac = ring.readAll(); if (readHmac.length != hmac.getLength()) throw new IOException("stream corrupted: bad hmac record size:" + readHmac.length); if (!Arrays.equals(readHmac, hmac.digest())) { throw new AuthenticationFailed("HMAC authentication failed, data corrupted"); } } }
/** * put single byte. Block until the space is available. * * @param value */ @SuppressWarnings("unused") public void put(int value) { synchronized (access) { while (advance(wpos) == rpos) try { access.wait(); } catch (InterruptedException e) { e.printStackTrace(); } data[wpos] = (byte) (value & 0xFF); wpos = advance(wpos); access.notifyAll(); } }
/** * Read bytes from the buffer, blocking untili available, and convert them to the UTF-8 string * * @param size string exact size */ public String getString(int size) { return new String(get(size)); }
@Override public void write(int b) throws IOException { buffer.put(b); } };
@Override public int read() throws IOException { if( closed.get() ) { close(); return -1; } return buffer.get(); }
/** * Put all the bytes to the buffer. Blocks until the operation is completed. * * @param collection */ public <T extends Number> void put(Iterable<T> collection) { for (T x : collection) { put(x.intValue()); } }
/** * Put string in UTF-8 encoding into the buffer blocking until there is enough space. * * @param s string to put */ public void put(String s) { put(s.getBytes()); }