package com.subgraph.orchid.circuits; import com.subgraph.orchid.Cell; import com.subgraph.orchid.CircuitNode; import com.subgraph.orchid.RelayCell; import com.subgraph.orchid.Router; import com.subgraph.orchid.TorException; public class CircuitNodeImpl implements CircuitNode { public static CircuitNode createAnonymous(CircuitNode previous, byte[] keyMaterial, byte[] verifyDigest) { return createNode(null, previous, keyMaterial, verifyDigest); } public static CircuitNode createFirstHop(Router r, byte[] keyMaterial, byte[] verifyDigest) { return createNode(r, null, keyMaterial, verifyDigest); } public static CircuitNode createNode(Router r, CircuitNode previous, byte[] keyMaterial, byte[] verifyDigest) { final CircuitNodeCryptoState cs = CircuitNodeCryptoState.createFromKeyMaterial(keyMaterial, verifyDigest); return new CircuitNodeImpl(r, previous, cs); } private final static int CIRCWINDOW_START = 1000; private final static int CIRCWINDOW_INCREMENT = 100; private final Router router; private final CircuitNodeCryptoState cryptoState; private final CircuitNode previousNode; private final Object windowLock; private int packageWindow; private int deliverWindow; private CircuitNodeImpl(Router router, CircuitNode previous, CircuitNodeCryptoState cryptoState) { previousNode = previous; this.router = router; this.cryptoState = cryptoState; windowLock = new Object(); packageWindow = CIRCWINDOW_START; deliverWindow = CIRCWINDOW_START; } public Router getRouter() { return router; } public CircuitNode getPreviousNode() { return previousNode; } public void encryptForwardCell(RelayCell cell) { cryptoState.encryptForwardCell(cell); } public boolean decryptBackwardCell(Cell cell) { return cryptoState.decryptBackwardCell(cell); } public void updateForwardDigest(RelayCell cell) { cryptoState.updateForwardDigest(cell); } public byte[] getForwardDigestBytes() { return cryptoState.getForwardDigestBytes(); } public String toString() { if(router != null) { return "|"+ router.getNickname() + "|"; } else { return "|()|"; } } public void decrementDeliverWindow() { synchronized(windowLock) { deliverWindow--; } } public boolean considerSendingSendme() { synchronized(windowLock) { if(deliverWindow <= (CIRCWINDOW_START - CIRCWINDOW_INCREMENT)) { deliverWindow += CIRCWINDOW_INCREMENT; return true; } return false; } } public void waitForSendWindow() { waitForSendWindow(false); } public void waitForSendWindowAndDecrement() { waitForSendWindow(true); } private void waitForSendWindow(boolean decrement) { synchronized(windowLock) { while(packageWindow == 0) { try { windowLock.wait(); } catch (InterruptedException e) { throw new TorException("Thread interrupted while waiting for circuit send window"); } } if(decrement) packageWindow--; } } public void incrementSendWindow() { synchronized(windowLock) { packageWindow += CIRCWINDOW_INCREMENT; windowLock.notifyAll(); } } }