@Test public void testWriteEmptyFile() throws Exception { AbstractStreamWriteFilter<M> filter = createFilter(); M message = createMessage(new byte[0]); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.messageSent(session, writeRequest); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); /* * Verify. */ EasyMock.verify(nextFilter); assertTrue(writeRequest.getFuture().isWritten()); }
/** * Tests when the contents of the file fits into one write buffer. * * @throws Exception when something goes wrong */ @Test public void testWriteSingleBufferFile() throws Exception { byte[] data = new byte[] {1, 2, 3, 4}; AbstractStreamWriteFilter<M> filter = createFilter(); M message = createMessage(data); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.filterWrite( EasyMock.eq(session), eqWriteRequest(new DefaultWriteRequest(IoBuffer.wrap(data)))); nextFilter.messageSent(session, writeRequest); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); filter.messageSent(nextFilter, session, writeRequest); /* * Verify. */ EasyMock.verify(nextFilter); assertTrue(writeRequest.getFuture().isWritten()); }
/** * Tests that the filter just passes objects which aren't FileRegion's through to the next filter. * * @throws Exception when something goes wrong */ @Test public void testWriteNonFileRegionMessage() throws Exception { AbstractStreamWriteFilter<M> filter = createFilter(); Object message = new Object(); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.filterWrite(session, writeRequest); nextFilter.messageSent(session, writeRequest); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); filter.messageSent(nextFilter, session, writeRequest); /* * Verify. */ EasyMock.verify(nextFilter); }
@Override public void fire() { IoSession session = getSession(); NextFilter nextFilter = getNextFilter(); IoEventType type = getType(); if (DEBUG) { LOGGER.debug("Firing a {} event for session {}", type, session.getId()); } switch (type) { case MESSAGE_RECEIVED: Object parameter = getParameter(); nextFilter.messageReceived(session, parameter); break; case MESSAGE_SENT: WriteRequest writeRequest = (WriteRequest) getParameter(); nextFilter.messageSent(session, writeRequest); break; case WRITE: writeRequest = (WriteRequest) getParameter(); nextFilter.filterWrite(session, writeRequest); break; case CLOSE: nextFilter.filterClose(session); break; case EXCEPTION_CAUGHT: Throwable throwable = (Throwable) getParameter(); nextFilter.exceptionCaught(session, throwable); break; case SESSION_IDLE: nextFilter.sessionIdle(session, (IdleStatus) getParameter()); break; case SESSION_OPENED: nextFilter.sessionOpened(session); break; case SESSION_CREATED: nextFilter.sessionCreated(session); break; case SESSION_CLOSED: nextFilter.sessionClosed(session); break; default: throw new IllegalArgumentException("Unknown event type: " + type); } if (DEBUG) { LOGGER.debug("Event {} has been fired for session {}", type, session.getId()); } }
@Test public void testWritesWriteRequestQueueWhenFinished() throws Exception { AbstractStreamWriteFilter<M> filter = createFilter(); M message = createMessage(new byte[0]); WriteRequest wrs[] = new WriteRequest[] { new DefaultWriteRequest(new Object(), new DummyWriteFuture()), new DefaultWriteRequest(new Object(), new DummyWriteFuture()), new DefaultWriteRequest(new Object(), new DummyWriteFuture()) }; Queue<WriteRequest> queue = new LinkedList<WriteRequest>(); queue.add(wrs[0]); queue.add(wrs[1]); queue.add(wrs[2]); /* * Make up the situation. */ session.setAttribute(filter.CURRENT_STREAM, message); session.setAttribute(filter.CURRENT_WRITE_REQUEST, new DefaultWriteRequest(message)); session.setAttribute(filter.WRITE_REQUEST_QUEUE, queue); /* * Record expectations */ NextFilter nextFilter = EasyMock.createMock(NextFilter.class); nextFilter.filterWrite(session, wrs[0]); nextFilter.filterWrite(session, wrs[1]); nextFilter.filterWrite(session, wrs[2]); nextFilter.messageSent(EasyMock.eq(session), eqWriteRequest(new DefaultWriteRequest(message))); /* * Replay. */ EasyMock.replay(nextFilter); filter.messageSent(nextFilter, session, new DefaultWriteRequest(new Object())); assertEquals(0, queue.size()); /* * Verify. */ EasyMock.verify(nextFilter); }
/** * Tests when the contents of the file doesn't fit into one write buffer. * * @throws Exception when something goes wrong */ @Test public void testWriteSeveralBuffersStream() throws Exception { AbstractStreamWriteFilter<M> filter = createFilter(); filter.setWriteBufferSize(4); byte[] data = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; byte[] chunk1 = new byte[] {1, 2, 3, 4}; byte[] chunk2 = new byte[] {5, 6, 7, 8}; byte[] chunk3 = new byte[] {9, 10}; M message = createMessage(data); WriteRequest writeRequest = new DefaultWriteRequest(message, new DummyWriteFuture()); WriteRequest chunk1Request = new DefaultWriteRequest(IoBuffer.wrap(chunk1)); WriteRequest chunk2Request = new DefaultWriteRequest(IoBuffer.wrap(chunk2)); WriteRequest chunk3Request = new DefaultWriteRequest(IoBuffer.wrap(chunk3)); NextFilter nextFilter = EasyMock.createMock(NextFilter.class); /* * Record expectations */ nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk1Request)); nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk2Request)); nextFilter.filterWrite(EasyMock.eq(session), eqWriteRequest(chunk3Request)); nextFilter.messageSent(EasyMock.eq(session), eqWriteRequest(writeRequest)); /* * Replay. */ EasyMock.replay(nextFilter); filter.filterWrite(nextFilter, session, writeRequest); filter.messageSent(nextFilter, session, chunk1Request); filter.messageSent(nextFilter, session, chunk2Request); filter.messageSent(nextFilter, session, chunk3Request); /* * Verify. */ EasyMock.verify(nextFilter); assertTrue(writeRequest.getFuture().isWritten()); }
public void wrap(NextFilter nextFilter, WriteRequest writeRequest, IoBuffer buf) throws AuthException { int start = buf.position(); int len = buf.remaining() - LINE_TERMINATOR.length; if (len == 0) throw new AuthException("Decryption failed"); // HMAC(Ki, {SeqNum, msg})[0..9] byte[] originalMessage = new byte[len]; buf.get(originalMessage); byte[] mac = AuthDigestMD5IoFilter.computeMACBlock(session, originalMessage, false); // Calculate padding int bs = encCipher.getBlockSize(); byte[] padding; if (bs > 1) { int pad = bs - ((len + 10) % bs); // add 10 for HMAC[0..9] padding = new byte[pad]; for (int i = 0; i < pad; i++) padding[i] = (byte) pad; } else padding = EMPTY_BYTE_ARRAY; byte[] toBeEncrypted = new byte[len + padding.length + 10]; // {msg, pad, HMAC(Ki, {SeqNum, msg}[0..9])} System.arraycopy(originalMessage, start, toBeEncrypted, 0, len); System.arraycopy(padding, 0, toBeEncrypted, len, padding.length); System.arraycopy(mac, 0, toBeEncrypted, len + padding.length, 10); // CIPHER(Kc, {msg, pad, HMAC(Ki, {SeqNum, msg}[0..9])}) byte[] cipherBlock; try { // Do CBC (chaining) across packets cipherBlock = encCipher.update(toBeEncrypted); // update() can return null if (cipherBlock == null) throw new IllegalBlockSizeException("" + toBeEncrypted.length); } catch (IllegalBlockSizeException e) { throw new AuthException("Invalid block size for cipher", e); } IoBuffer out = IoBuffer.allocate(cipherBlock.length + 2 + 4 + LINE_TERMINATOR.length); out.put(cipherBlock); out.put(mac, 10, 6); // messageType & sequenceNum out.put(LINE_TERMINATOR); out.flip(); if (out.limit() > ((Integer) session.getAttribute(AuthDigestMD5Command.CLIENT_MAXBUF)).intValue()) throw new AuthException("Data exceeds client maxbuf capability"); nextFilter.filterWrite(session, new DefaultWriteRequest(out, writeRequest.getFuture())); }
public void unwrap(NextFilter nextFilter, IoBuffer buf) { try { int len = buf.remaining(); if (len == 0) throw new AuthException("Decryption failed"); byte[] encryptedMsg = new byte[len - 6]; byte[] msgType = new byte[2]; byte[] seqNum = new byte[4]; // Get cipherMsg; msgType; sequenceNum buf.get(encryptedMsg); buf.get(msgType); buf.get(seqNum); // Decrypt message - CIPHER(Kc, {msg, pad, HMAC(Ki, {SeqNum, msg}[0..9])}) byte[] decryptedMsg; try { // Do CBC (chaining) across packets decryptedMsg = decCipher.update(encryptedMsg); // update() can return null if (decryptedMsg == null) throw new IllegalBlockSizeException("" + encryptedMsg.length); } catch (IllegalBlockSizeException e) { throw new AuthException("Illegal block sizes used with chosen cipher", e); } byte[] msgWithPadding = new byte[decryptedMsg.length - 10]; byte[] mac = new byte[10]; System.arraycopy(decryptedMsg, 0, msgWithPadding, 0, msgWithPadding.length); System.arraycopy(decryptedMsg, msgWithPadding.length, mac, 0, 10); int msgLength = msgWithPadding.length; int blockSize = decCipher.getBlockSize(); if (blockSize > 1) { // get value of last octet of the byte array msgLength -= (int) msgWithPadding[msgWithPadding.length - 1]; if (msgLength < 0) // Discard message and do not increment sequence number throw new AuthException("Decryption failed"); } byte[] msg = new byte[msgLength]; System.arraycopy(msgWithPadding, 0, msg, 0, msgLength); // Re-calculate MAC to ensure integrity byte[] expectedMac = AuthDigestMD5IoFilter.computeMACBlock(session, msg, true); byte[] fullMac = new byte[16]; System.arraycopy(mac, 0, fullMac, 0, 10); System.arraycopy(msgType, 0, fullMac, 10, 2); System.arraycopy(seqNum, 0, fullMac, 12, 4); if (isValidMAC(fullMac, expectedMac)) { IoBuffer out = IoBuffer.allocate(msgLength + LINE_TERMINATOR.length); out.put(msg); out.put(LINE_TERMINATOR); out.flip(); nextFilter.messageReceived(session, out); } } catch (Exception ex) { log.debug(ex.getMessage()); nextFilter.messageReceived(session, "\r\n"); } if (session instanceof AbstractIoSession) ((AbstractIoSession) session).increaseReadMessages(System.currentTimeMillis()); }