diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java b/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java index 16c96cc89..292bb28ea 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/AcceptingChannel.java @@ -7,11 +7,19 @@ import java.net.ConnectException; import java.nio.channels.SelectableChannel; /** + * As this does not (yet) extend ServerSocketChannel it cannot be returned by StandardServerSocket.getChannel(), + * until we implement an I2P SocketAddress class. + * + * Warning, this interface and implementation is preliminary and subject to change without notice. + * * @since 0.8.11 */ public abstract class AcceptingChannel extends SelectableChannel { + abstract I2PSocket accept() throws I2PException, ConnectException; - I2PSocketManager _socketManager; + + protected final I2PSocketManager _socketManager; + AcceptingChannel(I2PSocketManager manager) { this._socketManager = manager; } diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketAddress.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketAddress.java new file mode 100644 index 000000000..4ba55bdb1 --- /dev/null +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketAddress.java @@ -0,0 +1,107 @@ +package net.i2p.client.streaming; + +import java.net.SocketAddress; + +import net.i2p.I2PAppContext; +import net.i2p.data.Destination; +import net.i2p.data.DataHelper; + +/** + * A SocketAddress (Destination + port) so we can have SocketChannels. + * Ports are not widely used in I2P, in most cases the port will be zero. + * See InetSocketAddress for javadocs. + * + * Warning, this interface and implementation is preliminary and subject to change without notice. + * + * @since 0.9.1 + */ +public class I2PSocketAddress extends SocketAddress { + + private final int _port; + private final Destination _dest; + private final String _host; + + // no constructor for port-only "wildcard" address + + /** + * Does not do a reverse lookup. Host will be null. + */ + public I2PSocketAddress(Destination dest, int port) { + _port = port; + _dest = dest; + _host = null; + } + + /** + * Does a naming service lookup to resolve the dest. + * May take several seconds for b32. + */ + public I2PSocketAddress(String host, int port) { + _port = port; + _dest = I2PAppContext.getGlobalContext().namingService().lookup(host); + _host = host; + } + + public static I2PSocketAddress createUnresolved(String host, int port) { + return new I2PSocketAddress(port, host); + } + + /** unresolved */ + private I2PSocketAddress(int port, String host) { + _port = port; + _dest = null; + _host = host; + } + + public int getPort() { + return _port; + } + + public Destination getAddress() { + return _dest; + } + + /** + * @return the host only if given in the constructor. Does not do a reverse lookup. + */ + public String getHostName() { + return _host; + } + + public boolean isUnresolved() { + return _dest == null; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + if (_dest != null) + buf.append(_dest.calculateHash().toString()); + else + buf.append(_host); + buf.append(':'); + buf.append(_port); + return buf.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof I2PSocketAddress)) + return false; + I2PSocketAddress o = (I2PSocketAddress) obj; + if (_port != o._port) + return false; + if (_dest != null) + return _dest.equals(o._dest); + if (o._dest != null) + return false; + if (_host != null) + return _host.equals(o._host); + return o._host == null; + } + + @Override + public int hashCode() { + return DataHelper.hashCode(_dest) ^ DataHelper.hashCode(_host) ^ _port; + } +} diff --git a/apps/streaming/java/src/net/i2p/client/streaming/AcceptingChannelImpl.java b/apps/streaming/java/src/net/i2p/client/streaming/AcceptingChannelImpl.java index 89242afbc..61dc90170 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/AcceptingChannelImpl.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/AcceptingChannelImpl.java @@ -13,16 +13,21 @@ import java.nio.channels.spi.AbstractSelectionKey; import java.nio.channels.spi.SelectorProvider; /** + * As this does not (yet) extend ServerSocketChannel it cannot be returned by StandardServerSocket.getChannel(), + * until we implement an I2P SocketAddress class. + * + * Warning, this interface and implementation is preliminary and subject to change without notice. + * * @since 0.8.11 */ -public class AcceptingChannelImpl extends AcceptingChannel { - boolean _isRegistered = false; - SelectionKey whichKey = null; - SelectorProvider provider = null; - Selector sel = null; - Object lock = null; - I2PSocket next = null; - I2PServerSocket socket; +class AcceptingChannelImpl extends AcceptingChannel { + private boolean _isRegistered; + private SelectionKey whichKey; + private SelectorProvider provider; + private Selector sel; + private Object lock; + private volatile I2PSocket next; + private final I2PServerSocket socket; I2PSocket accept() throws I2PException, ConnectException { I2PSocket sock; @@ -31,9 +36,11 @@ public class AcceptingChannelImpl extends AcceptingChannel { } catch(SocketTimeoutException ex) { return null; } - I2PSocket temp = next; - next = sock; - return temp; + synchronized (this) { + I2PSocket temp = next; + next = sock; + return temp; + } } AcceptingChannelImpl(I2PSocketManager manager) { @@ -96,7 +103,7 @@ public class AcceptingChannelImpl extends AcceptingChannel { @Override public int readyOps() { - if((operations & OP_ACCEPT) != 0) + if((operations & OP_ACCEPT) != 0) { if(next != null) { return OP_ACCEPT; } else { @@ -107,6 +114,7 @@ public class AcceptingChannelImpl extends AcceptingChannel { if(next != null) return OP_ACCEPT; } + } return 0; } }; @@ -136,8 +144,9 @@ public class AcceptingChannelImpl extends AcceptingChannel { @Override protected void implCloseChannel() throws IOException { - if(next != null) { - next.close(); + I2PSocket nxt = next; + if(nxt != null) { + nxt.close(); } _socketManager.destroySocketManager(); } diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PServerSocketFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PServerSocketFull.java index 244664bf4..5eddc45c5 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/I2PServerSocketFull.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PServerSocketFull.java @@ -9,6 +9,7 @@ import net.i2p.I2PException; */ class I2PServerSocketFull implements I2PServerSocket { private final I2PSocketManagerFull _socketManager; + private volatile AcceptingChannel _channel; public I2PServerSocketFull(I2PSocketManagerFull mgr) { _socketManager = mgr; @@ -28,8 +29,10 @@ class I2PServerSocketFull implements I2PServerSocket { /** * @since 0.8.11 */ - public AcceptingChannel getChannel() { - return new AcceptingChannelImpl(_socketManager); + public synchronized AcceptingChannel getChannel() { + if (_channel == null) + _channel = new AcceptingChannelImpl(_socketManager); + return _channel; } public long getSoTimeout() { diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java index 6f1caeaf0..abca9b82f 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java @@ -16,6 +16,7 @@ class I2PSocketFull implements I2PSocket { private Connection _connection; private Destination _remotePeer; private Destination _localPeer; + private volatile MessageChannel _channel; public I2PSocketFull(Connection con) { _connection = con; @@ -70,8 +71,10 @@ class I2PSocketFull implements I2PSocket { /** * @since 0.8.9 */ - public SelectableChannel getChannel() { - return new MessageChannel(this); + public synchronized SelectableChannel getChannel() { + if (_channel == null) + _channel = new MessageChannel(this); + return _channel; } /** diff --git a/apps/streaming/java/src/net/i2p/client/streaming/MessageChannel.java b/apps/streaming/java/src/net/i2p/client/streaming/MessageChannel.java index 05ba76bb7..af10cf886 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/MessageChannel.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/MessageChannel.java @@ -15,18 +15,23 @@ import java.util.logging.Level; import java.util.logging.Logger; /** + * As this does not (yet) extend SocketChannel it cannot be returned by StandardSocket.getChannel(), + * until we implement an I2P SocketAddress class. + * + * Warning, this interface and implementation is preliminary and subject to change without notice. + * * @since 0.8.9 */ public class MessageChannel extends SelectableChannel implements ReadableByteChannel, WritableByteChannel { - final MessageInputStream in; - final MessageOutputStream out; - boolean _isRegistered = false; - SelectionKey whichKey = null; - SelectorProvider provider = null; - Selector sel = null; - Object lock = null; - I2PSocket socket; + private final MessageInputStream in; + private final MessageOutputStream out; + private boolean _isRegistered; + private SelectionKey whichKey; + private SelectorProvider provider; + private Selector sel; + private Object lock; + private final I2PSocket socket; MessageChannel(I2PSocket socket) { try { @@ -145,10 +150,10 @@ public class MessageChannel extends SelectableChannel implements ReadableByteCha * returns 0, which happens when there's * no more data available. */ - public int read(ByteBuffer buf) throws IOException { int amount = 0; for (;;) { + // TODO if buf.hasArray() ... getArray() ... getArrayOffset() ... byte[] lbuf = new byte[buf.remaining()]; int samount = in.read(lbuf); if (samount <= 0) { @@ -167,12 +172,12 @@ public class MessageChannel extends SelectableChannel implements ReadableByteCha * already set buffer size. Once it starts to fail * (wait timeout is 0) then put the bytes back and return. */ - public int write(ByteBuffer buf) throws IOException { int written = 0; for (;;) { if(buf.remaining()==0) return written; + // TODO if buf.hasArray() ... getArray() ... getArrayOffset() ... byte[] lbuf = new byte[Math.min(buf.remaining(), 0x1000)]; buf.get(lbuf); try { diff --git a/apps/streaming/java/src/net/i2p/client/streaming/StandardServerSocket.java b/apps/streaming/java/src/net/i2p/client/streaming/StandardServerSocket.java index 324d12687..1429fa606 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/StandardServerSocket.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/StandardServerSocket.java @@ -72,10 +72,11 @@ class StandardServerSocket extends ServerSocket { } /** - * @return null always + * @return null always, see AcceptingChannelImpl for more info */ @Override public ServerSocketChannel getChannel() { + //return _socket.getChannel(); return null; } diff --git a/apps/streaming/java/src/net/i2p/client/streaming/StandardSocket.java b/apps/streaming/java/src/net/i2p/client/streaming/StandardSocket.java index 94bac2642..30de8265a 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/StandardSocket.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/StandardSocket.java @@ -65,10 +65,11 @@ class StandardSocket extends Socket { } /** - * @return null always + * @return null always, see MessageChannel for more info */ @Override public SocketChannel getChannel() { + //return _socket.getChannel(); return null; } diff --git a/history.txt b/history.txt index 74e4e2d12..98ac2da20 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,15 @@ +2012-06-13 zzz + * I2PSocketEepGet: Set port to 80 + * I2PTunnel: + - Pass port through HTTP client proxy + - HTTP server proxy sets host header to + the value of "spoofedhost.xx" option for port xx + - Set client options more efficiently + * i2psnark: Possible fix for piece-after-choke + * Streaming: + - Channel cleanups and comments + - New I2PSocketAddress + 2012-06-11 zzz * i2psnark: - Display torrent file downloads in torrent area @@ -8,7 +20,7 @@ - Reduce delay between peer adds for faster startup - Thread the announces and reduce timeout when stopping * NativeBigInteger: Workaround for Raspberry Pi to load the correct lib - * Router: Don't let shutdown tasks hang the shutdown + * Router: Don't let shutdown tasks hang the shutdown (tickets #564, #566) 2012-06-08 zzz * i2psnark: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 7f4edb975..31c35f8c3 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 13; + public final static long BUILD = 14; /** for example "-test" */ public final static String EXTRA = "";