private void connectionClosed() { boolean callClosed = false; lock.lock(); try { callClosed = !closeCalled; closeCalled = true; } finally { lock.unlock(); } if (callClosed) { checkState(connectedHandlers == null || connectedHandlers.remove(this)); connection.connectionClosed(); } }
@Override public synchronized void connectionOpened() { if (!closeOnOpen) upstreamConnection.connectionOpened(); }
private ConnectionHandler(@Nullable StreamConnection connection, SelectionKey key) { this.key = key; this.channel = checkNotNull(((SocketChannel)key.channel())); if (connection == null) { readBuff = null; return; } this.connection = connection; readBuff = ByteBuffer.allocateDirect(Math.min(Math.max(connection.getMaxMessageSize(), BUFFER_SIZE_LOWER_BOUND), BUFFER_SIZE_UPPER_BOUND)); connection.setWriteTarget(this); // May callback into us (eg closeConnection() now) connectedHandlers = null; }
/** * A blocking call that never returns, except by throwing an exception. It reads bytes from the input stream * and feeds them to the provided {@link StreamConnection}, for example, a {@link Peer}. */ public static void runReadLoop(InputStream stream, StreamConnection connection) throws Exception { ByteBuffer dbuf = ByteBuffer.allocateDirect(Math.min(Math.max(connection.getMaxMessageSize(), BUFFER_SIZE_LOWER_BOUND), BUFFER_SIZE_UPPER_BOUND)); byte[] readBuff = new byte[dbuf.capacity()]; while (true) { // TODO Kill the message duplication here checkState(dbuf.remaining() > 0 && dbuf.remaining() <= readBuff.length); int read = stream.read(readBuff, 0, Math.max(1, Math.min(dbuf.remaining(), stream.available()))); if (read == -1) return; dbuf.put(readBuff, 0, read); // "flip" the buffer - setting the limit to the current position and setting position to 0 dbuf.flip(); // Use connection.receiveBytes's return value as a double-check that it stopped reading at the right // location int bytesConsumed = connection.receiveBytes(dbuf); checkState(dbuf.position() == bytesConsumed); // Now drop the bytes which were read by compacting dbuf (resetting limit and keeping relative // position) dbuf.compact(); } }
@Override public void run() { Context.propagate(context); if (clientSet != null) clientSet.add(BlockingClient.this); try { socket.connect(serverAddress, connectTimeoutMillis); connection.connectionOpened(); connectFuture.set(serverAddress); InputStream stream = socket.getInputStream(); runReadLoop(stream, connection); } catch (Exception e) { if (!vCloseRequested) { log.error("Error trying to open/read from connection: {}: {}", serverAddress, e.getMessage()); connectFuture.setException(e); } } finally { try { socket.close(); } catch (IOException e1) { // At this point there isn't much we can do, and we can probably assume the channel is closed } if (clientSet != null) clientSet.remove(BlockingClient.this); connection.connectionClosed(); } } };
@Override public synchronized void setWriteTarget(MessageWriteTarget writeTarget) { if (closeOnOpen) writeTarget.closeConnection(); else { setTimeoutEnabled(false); this.writeTarget = writeTarget; upstreamConnection.setWriteTarget(writeTarget); } }
@Override public int receiveBytes(ByteBuffer buff) throws Exception { return upstreamConnection.receiveBytes(buff); }
@Override public int getMaxMessageSize() { return upstreamConnection.getMaxMessageSize(); } }
/** * A blocking call that never returns, except by throwing an exception. It reads bytes from the input stream * and feeds them to the provided {@link StreamConnection}, for example, a {@link Peer}. */ public static void runReadLoop(InputStream stream, StreamConnection connection) throws Exception { ByteBuffer dbuf = ByteBuffer.allocateDirect(Math.min(Math.max(connection.getMaxMessageSize(), BUFFER_SIZE_LOWER_BOUND), BUFFER_SIZE_UPPER_BOUND)); byte[] readBuff = new byte[dbuf.capacity()]; while (true) { // TODO Kill the message duplication here checkState(dbuf.remaining() > 0 && dbuf.remaining() <= readBuff.length); int read = stream.read(readBuff, 0, Math.max(1, Math.min(dbuf.remaining(), stream.available()))); if (read == -1) return; dbuf.put(readBuff, 0, read); // "flip" the buffer - setting the limit to the current position and setting position to 0 dbuf.flip(); // Use connection.receiveBytes's return value as a double-check that it stopped reading at the right // location int bytesConsumed = connection.receiveBytes(dbuf); checkState(dbuf.position() == bytesConsumed); // Now drop the bytes which were read by compacting dbuf (resetting limit and keeping relative // position) dbuf.compact(); } }
@Override public void run() { Context.propagate(context); if (clientSet != null) clientSet.add(BlockingClient.this); try { socket.connect(serverAddress, connectTimeoutMillis); connection.connectionOpened(); connectFuture.set(serverAddress); InputStream stream = socket.getInputStream(); runReadLoop(stream, connection); } catch (Exception e) { if (!vCloseRequested) { log.error("Error trying to open/read from connection: {}: {}", serverAddress, e.getMessage()); connectFuture.setException(e); } } finally { try { socket.close(); } catch (IOException e1) { // At this point there isn't much we can do, and we can probably assume the channel is closed } if (clientSet != null) clientSet.remove(BlockingClient.this); connection.connectionClosed(); } } };
@Override public synchronized void setWriteTarget(MessageWriteTarget writeTarget) { if (closeOnOpen) writeTarget.closeConnection(); else { setTimeoutEnabled(false); this.writeTarget = writeTarget; upstreamConnection.setWriteTarget(writeTarget); } }
@Override public int receiveBytes(ByteBuffer buff) throws Exception { return upstreamConnection.receiveBytes(buff); }
@Override public int getMaxMessageSize() { return upstreamConnection.getMaxMessageSize(); } }
private ConnectionHandler(@Nullable StreamConnection connection, SelectionKey key) { this.key = key; this.channel = checkNotNull(((SocketChannel)key.channel())); if (connection == null) { readBuff = null; return; } this.connection = connection; readBuff = ByteBuffer.allocateDirect(Math.min(Math.max(connection.getMaxMessageSize(), BUFFER_SIZE_LOWER_BOUND), BUFFER_SIZE_UPPER_BOUND)); connection.setWriteTarget(this); // May callback into us (eg closeConnection() now) connectedHandlers = null; }
/** * A blocking call that never returns, except by throwing an exception. It reads bytes from the input stream * and feeds them to the provided {@link StreamConnection}, for example, a {@link Peer}. */ public static void runReadLoop(InputStream stream, StreamConnection connection) throws Exception { ByteBuffer dbuf = ByteBuffer.allocateDirect(Math.min(Math.max(connection.getMaxMessageSize(), BUFFER_SIZE_LOWER_BOUND), BUFFER_SIZE_UPPER_BOUND)); byte[] readBuff = new byte[dbuf.capacity()]; while (true) { // TODO Kill the message duplication here checkState(dbuf.remaining() > 0 && dbuf.remaining() <= readBuff.length); int read = stream.read(readBuff, 0, Math.max(1, Math.min(dbuf.remaining(), stream.available()))); if (read == -1) return; dbuf.put(readBuff, 0, read); // "flip" the buffer - setting the limit to the current position and setting position to 0 dbuf.flip(); // Use connection.receiveBytes's return value as a double-check that it stopped reading at the right // location int bytesConsumed = connection.receiveBytes(dbuf); checkState(dbuf.position() == bytesConsumed); // Now drop the bytes which were read by compacting dbuf (resetting limit and keeping relative // position) dbuf.compact(); } }
@Override public void run() { Context.propagate(context); if (clientSet != null) clientSet.add(BlockingClient.this); try { socket.connect(serverAddress, connectTimeoutMillis); connection.connectionOpened(); connectFuture.set(serverAddress); InputStream stream = socket.getInputStream(); runReadLoop(stream, connection); } catch (Exception e) { if (!vCloseRequested) { log.error("Error trying to open/read from connection: {}: {}", serverAddress, e.getMessage()); connectFuture.setException(e); } } finally { try { socket.close(); } catch (IOException e1) { // At this point there isn't much we can do, and we can probably assume the channel is closed } if (clientSet != null) clientSet.remove(BlockingClient.this); connection.connectionClosed(); } } };
@Override public synchronized void connectionOpened() { if (!closeOnOpen) upstreamConnection.connectionOpened(); }
@Override public synchronized void setWriteTarget(MessageWriteTarget writeTarget) { if (closeOnOpen) writeTarget.closeConnection(); else { setTimeoutEnabled(false); this.writeTarget = writeTarget; upstreamConnection.setWriteTarget(writeTarget); } }
private void connectionClosed() { boolean callClosed = false; lock.lock(); try { callClosed = !closeCalled; closeCalled = true; } finally { lock.unlock(); } if (callClosed) { checkState(connectedHandlers == null || connectedHandlers.remove(this)); connection.connectionClosed(); } }
@Override public int receiveBytes(ByteBuffer buff) throws Exception { return upstreamConnection.receiveBytes(buff); }