📄 tunnel.java
字号:
package rabbit.proxy;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import rabbit.io.HandlerRegistration;import rabbit.io.SocketHandler;import rabbit.util.Logger;import rabbit.util.TrafficLogger;/** A handler that just tunnels data. * * @author <a href="mailto:robo@khelekore.org">Robert Olofsson</a> */class Tunnel implements SocketHandler { private Selector selector; private Logger logger; private SocketChannel from; private ByteBuffer fromBuffer; private TrafficLogger fromLogger; private SelectionKey fromSk = null; private SocketChannel to; private ByteBuffer toBuffer; private TrafficLogger toLogger; private SelectionKey toSk = null; private TunnelDoneListener listener; public Tunnel (Selector selector, Logger logger, SocketChannel from, ByteBuffer fromBuffer, TrafficLogger fromLogger, SocketChannel to, ByteBuffer toBuffer, TrafficLogger toLogger, TunnelDoneListener listener) throws IOException { this.selector = selector; this.logger = logger; this.from = from; this.fromBuffer = fromBuffer; this.fromLogger = fromLogger; this.to = to; if (toBuffer == null) { toBuffer = ByteBuffer.allocate (2048); toBuffer.limit (0); // set initial state: no bytes to write } this.toBuffer = toBuffer; this.toLogger = toLogger; this.listener = listener; sendBuffers (); } private void registerRead () throws IOException { fromBuffer.clear (); toBuffer.clear (); HandlerRegistration hr = new HandlerRegistration (this, Long.MAX_VALUE); fromSk = from.register (selector, SelectionKey.OP_READ, hr); hr = new HandlerRegistration (this, Long.MAX_VALUE); toSk = to.register (selector, SelectionKey.OP_READ, hr); } private void sendBuffers () throws IOException { boolean needMore1 = sendBuffer (fromBuffer, to, toLogger); if (needMore1) { HandlerRegistration hr = new HandlerRegistration (this, Long.MAX_VALUE); toSk = to.register (selector, SelectionKey.OP_WRITE, hr); } boolean needMore2 = sendBuffer (toBuffer, from, fromLogger); if (needMore2) { HandlerRegistration hr = new HandlerRegistration (this, Long.MAX_VALUE); fromSk = from.register (selector, SelectionKey.OP_WRITE, hr); } if (!(needMore1 || needMore2)) registerRead (); } /** Send the buffer to the channel. * @return true if more data needs to be written. */ private boolean sendBuffer (ByteBuffer buffer, SocketChannel channel, TrafficLogger tl) throws IOException { if (buffer.hasRemaining ()) { int written; do { written = channel.write (buffer); tl.write (written); } while (written > 0 && buffer.remaining () > 0); } if (buffer.remaining () == 0) { return false; } else { return true; } } private boolean readBuffers () throws IOException { boolean read1 = readBuffer (from, fromBuffer, fromLogger); boolean read2 = readBuffer (to, toBuffer, toLogger); return (read1 || read2); } private boolean readBuffer (SocketChannel channel, ByteBuffer buffer, TrafficLogger tl) throws IOException { int read = channel.read (buffer); buffer.flip (); if (read == -1) { closeDown (); return false; } tl.read (read); return true; } private Logger getLogger () { return logger; } public boolean useSeparateThread () { return false; } public void timeout () { getLogger ().logWarn ("Tunnel: timeout during handling"); throw new IllegalStateException ("Tunnels should not get timeout"); } public void run () { try { if (fromBuffer.position () == 0 && toBuffer.position () == 0) if (readBuffers ()) sendBuffers (); } catch (IOException e) { getLogger ().logWarn ("Tunnel: failed to handle: " + e); closeDown (); } } private void closeDown () { // we do not want to close the channels, // it is up to the listener to do that. listener.tunnelClosed (); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -