diff --git a/apps/syndie/java/src/net/i2p/syndie/web/PostBean.java b/apps/syndie/java/src/net/i2p/syndie/web/PostBean.java
index 57baf2086..f0d24f43f 100644
--- a/apps/syndie/java/src/net/i2p/syndie/web/PostBean.java
+++ b/apps/syndie/java/src/net/i2p/syndie/web/PostBean.java
@@ -172,6 +172,7 @@ public class PostBean {
private static final int MAX_SIZE = 256*1024;
private void cacheAttachments() throws IOException {
+ if (_user == null) throw new IOException("User not specified");
File postCacheDir = new File(BlogManager.instance().getTempDir(), _user.getBlog().toBase64());
if (!postCacheDir.exists())
postCacheDir.mkdirs();
diff --git a/apps/syndie/java/src/net/i2p/syndie/web/PostServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/PostServlet.java
index a7cc3d7e8..b063b4d90 100644
--- a/apps/syndie/java/src/net/i2p/syndie/web/PostServlet.java
+++ b/apps/syndie/java/src/net/i2p/syndie/web/PostServlet.java
@@ -49,6 +49,8 @@ public class PostServlet extends BaseServlet {
String action = req.getParameter(PARAM_ACTION);
if (!empty(action) && ACTION_CONFIRM.equals(action)) {
postEntry(user, req, archive, post, out);
+ post.reinitialize();
+ post.setUser(user);
} else {
String contentType = req.getContentType();
if (!empty(contentType) && (contentType.indexOf("boundary=") != -1)) {
@@ -73,8 +75,8 @@ public class PostServlet extends BaseServlet {
out.write("
");
- post.reinitialize();
- post.setUser(user);
+ //post.reinitialize();
+ //post.setUser(user);
boolean inNewThread = getInNewThread(req.getString(PARAM_IN_NEW_THREAD));
boolean refuseReplies = getRefuseReplies(req.getString(PARAM_REFUSE_REPLIES));
@@ -343,6 +345,7 @@ public class PostServlet extends BaseServlet {
bean = new PostBean();
req.getSession().setAttribute(ATTR_POST_BEAN, bean);
}
+ bean.setUser(user);
return bean;
}
diff --git a/history.txt b/history.txt
index 31316feb4..e5b95b6c1 100644
--- a/history.txt
+++ b/history.txt
@@ -1,4 +1,16 @@
-$Id: history.txt,v 1.337 2005/11/29 11:58:01 jrandom Exp $
+$Id: history.txt,v 1.338 2005/11/29 12:56:03 jrandom Exp $
+
+2005-11-30 jrandom
+ * Don't let the TCP transport alone shitlist a peer, since other
+ transports may be working. Also display whether TCP connections are
+ inbound or outbound on the peers page.
+ * Fixed some substantial bugs in the SSU introducers where we wouldn't
+ talk to anyone who didn't expose an IP (even if they had introducers),
+ among other goofy things.
+ * When dealing with SSU introducers, send them all a packet at 3s/6s/9s,
+ rather than sending one a packet at 3s, then another a packet at 6s,
+ and a third a packet at 9s.
+ * Fixed Syndie attachments (oops)
2005-11-29 zzz
* Added a link to orion's jump page on the 'key not found' error page.
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index fb921acea..9dd14eaf9 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
- public final static String ID = "$Revision: 1.304 $ $Date: 2005/11/29 11:58:02 $";
+ public final static String ID = "$Revision: 1.305 $ $Date: 2005/11/29 12:56:02 $";
public final static String VERSION = "0.6.1.6";
- public final static long BUILD = 4;
+ public final static long BUILD = 5;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
index 15ecfebcb..920e6567a 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
@@ -68,8 +68,8 @@ class FloodfillPeerSelector extends PeerSelector {
}
public List getFloodfillParticipants() { return _floodfillMatches; }
public void add(Hash entry) {
- if (_context.profileOrganizer().isFailing(entry))
- return;
+ //if (_context.profileOrganizer().isFailing(entry))
+ // return;
if ( (_toIgnore != null) && (_toIgnore.contains(entry)) )
return;
if (entry.equals(_context.routerHash()))
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
index 484b46c76..8501383c3 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
@@ -657,8 +657,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
}
} else if (routerInfo.getPublished() > now + Router.CLOCK_FUDGE_FACTOR) {
long age = routerInfo.getPublished() - _context.clock().now();
- if (_log.shouldLog(Log.WARN))
- _log.warn("Peer " + key.toBase64() + " published their routerInfo in the future?! ["
+ if (_log.shouldLog(Log.INFO))
+ _log.info("Peer " + key.toBase64() + " published their routerInfo in the future?! ["
+ new Date(routerInfo.getPublished()) + "]", new Exception("Rejecting store"));
return "Peer " + key.toBase64() + " published " + DataHelper.formatDuration(age) + " in the future?!";
} else if (_enforceNetId && (routerInfo.getNetworkId() != Router.NETWORK_ID) ){
diff --git a/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java b/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java
index b037c4242..a9ba87576 100644
--- a/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java
+++ b/router/java/src/net/i2p/router/transport/tcp/ConnectionHandler.java
@@ -169,6 +169,7 @@ public class ConnectionHandler {
if (_error == null) {
if (_log.shouldLog(Log.INFO))
_log.info("Establishment successful! returning the con");
+ con.setIsOutbound(false);
return con;
} else {
if (_log.shouldLog(Log.INFO))
diff --git a/router/java/src/net/i2p/router/transport/tcp/TCPConnection.java b/router/java/src/net/i2p/router/transport/tcp/TCPConnection.java
index 3da0b01f1..cedf13449 100644
--- a/router/java/src/net/i2p/router/transport/tcp/TCPConnection.java
+++ b/router/java/src/net/i2p/router/transport/tcp/TCPConnection.java
@@ -43,6 +43,7 @@ public class TCPConnection {
private long _lastRead;
private long _lastWrite;
private long _offsetReceived;
+ private boolean _isOutbound;
public TCPConnection(RouterContext ctx) {
_context = ctx;
@@ -60,6 +61,7 @@ public class TCPConnection {
_lastRead = 0;
_lastWrite = 0;
_offsetReceived = 0;
+ _isOutbound = false;
_runner = new ConnectionRunner(_context, this);
_context.statManager().createRateStat("tcp.probabalisticDropQueueSize", "How many bytes were queued to be sent when a message as dropped probabalistically?", "TCP", new long[] { 60*1000l, 10*60*1000l, 60*60*1000l, 24*60*60*1000l } );
_context.statManager().createRateStat("tcp.queueSize", "How many bytes were queued on a connection?", "TCP", new long[] { 60*1000l, 10*60*1000l, 60*60*1000l, 24*60*60*1000l } );
@@ -86,6 +88,8 @@ public class TCPConnection {
public long getOffsetReceived() { return _offsetReceived; }
public void setOffsetReceived(long ms) { _offsetReceived = ms; }
public TCPTransport getTransport() { return _transport; }
+ public boolean getIsOutbound() { return _isOutbound; }
+ public void setIsOutbound(boolean outbound) { _isOutbound = outbound; }
/**
* Actually start processing the messages on the connection (and reading
diff --git a/router/java/src/net/i2p/router/transport/tcp/TCPConnectionEstablisher.java b/router/java/src/net/i2p/router/transport/tcp/TCPConnectionEstablisher.java
index 84b78f6a0..ae2991495 100644
--- a/router/java/src/net/i2p/router/transport/tcp/TCPConnectionEstablisher.java
+++ b/router/java/src/net/i2p/router/transport/tcp/TCPConnectionEstablisher.java
@@ -47,14 +47,17 @@ public class TCPConnectionEstablisher implements Runnable {
+ info.getIdentity().getHash().toBase64(), e);
}
if (con != null) {
+ con.setIsOutbound(true);
_transport.connectionEstablished(con);
} else {
if (!_context.router().isAlive()) return;
_transport.addConnectionErrorMessage(cb.getError());
Hash peer = info.getIdentity().getHash();
_context.profileManager().commErrorOccurred(peer);
- _context.shitlist().shitlistRouter(peer, "Unable to contact");
- _context.netDb().fail(peer);
+ // disabling in preparation for dropping tcp, since other transports may work, and
+ // hence shitlisting is not appropriate
+ //_context.shitlist().shitlistRouter(peer, "Unable to contact");
+ //_context.netDb().fail(peer);
}
// this removes the _pending block on the address and
diff --git a/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java b/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java
index 42f2d173b..7bf39523f 100644
--- a/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java
@@ -783,12 +783,21 @@ public class TCPTransport extends TransportImpl {
/** Make this stuff pretty (only used in the old console) */
public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(1024);
+ int outbound = 0;
+ int inbound = 0;
synchronized (_connectionLock) {
long offsetTotal = 0;
buf.append("Connections (").append(_connectionsByIdent.size()).append("):\n");
for (Iterator iter = _connectionsByIdent.values().iterator(); iter.hasNext(); ) {
TCPConnection con = (TCPConnection)iter.next();
buf.append("- ");
+ if (con.getIsOutbound()) {
+ outbound++;
+ buf.append("Outbound to ");
+ } else {
+ inbound++;
+ buf.append("Inbound from ");
+ }
buf.append(con.getRemoteRouterIdentity().getHash().toBase64().substring(0,6));
buf.append(": up for ").append(DataHelper.formatDuration(con.getLifetime()));
buf.append(" transferring at ");
@@ -817,6 +826,7 @@ public class TCPTransport extends TransportImpl {
buf.append("
\n");
}
buf.append(" \n");
+ buf.append("Inbound: ").append(inbound).append(", Outbound: ").append(outbound).append(" \n");
}
buf.append("Most recent connection errors:");
diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
index 567b0d35b..1f7505244 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -126,19 +126,26 @@ public class EstablishmentManager {
return;
}
UDPAddress addr = new UDPAddress(ra);
+ RemoteHostId to = null;
InetAddress remAddr = addr.getHostAddress();
int port = addr.getPort();
- RemoteHostId to = new RemoteHostId(remAddr.getAddress(), port);
-
- if (!_transport.isValid(to.getIP())) {
- _transport.failed(msg);
- _context.shitlist().shitlistRouter(msg.getTarget().getIdentity().calculateHash(), "Invalid SSU address");
- return;
+ if ( (remAddr != null) && (port > 0) ) {
+ to = new RemoteHostId(remAddr.getAddress(), port);
+
+ if (!_transport.isValid(to.getIP())) {
+ _transport.failed(msg);
+ _context.shitlist().shitlistRouter(msg.getTarget().getIdentity().calculateHash(), "Invalid SSU address");
+ return;
+ }
+
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("Add outbound establish state to: " + to);
+ } else {
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("Add indirect outbound establish state to: " + addr);
+ to = new RemoteHostId(msg.getTarget().getIdentity().calculateHash().getData());
}
- if (_log.shouldLog(Log.DEBUG))
- _log.debug("Add outobund establish state to: " + to);
-
OutboundEstablishState state = null;
int deferred = 0;
synchronized (_outboundStates) {
@@ -465,12 +472,18 @@ public class EstablishmentManager {
long now = _context.clock().now();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Send request to: " + state.getRemoteHostId().toString());
- _transport.send(_builder.buildSessionRequestPacket(state));
+ UDPPacket packet = _builder.buildSessionRequestPacket(state);
+ if (packet != null) {
+ _transport.send(packet);
+ } else {
+ if (_log.shouldLog(Log.WARN))
+ _log.warn("Unable to build a session request packet for " + state.getRemoteHostId());
+ }
state.requestSent();
}
private static final long MAX_NONCE = 0xFFFFFFFFl;
- /** if we don't get a relayResponse in 3 seconds, try again with another intro peer */
+ /** if we don't get a relayResponse in 3 seconds, try again */
private static final int INTRO_ATTEMPT_TIMEOUT = 3*1000;
private void handlePendingIntro(OutboundEstablishState state) {
@@ -488,7 +501,11 @@ public class EstablishmentManager {
SimpleTimer.getInstance().addEvent(new FailIntroduction(state, nonce), INTRO_ATTEMPT_TIMEOUT);
state.setIntroNonce(nonce);
_context.statManager().addRateData("udp.sendIntroRelayRequest", 1, 0);
- _transport.send(_builder.buildRelayRequest(_transport, state, _transport.getIntroKey()));
+ UDPPacket requests[] = _builder.buildRelayRequest(_transport, state, _transport.getIntroKey());
+ for (int i = 0; i < requests.length; i++) {
+ if (requests[i] != null)
+ _transport.send(requests[i]);
+ }
if (_log.shouldLog(Log.DEBUG))
_log.debug("Send intro for " + state.getRemoteHostId().toString() + " with our intro key as " + _transport.getIntroKey().toBase64());
state.introSent();
@@ -542,7 +559,15 @@ public class EstablishmentManager {
}
_context.statManager().addRateData("udp.receiveIntroRelayResponse", state.getLifetime(), 0);
int port = reader.getRelayResponseReader().readCharliePort();
+ if (_log.shouldLog(Log.INFO))
+ _log.info("Received relay intro for " + state.getRemoteIdentity().calculateHash().toBase64() + " - they are on "
+ + addr.toString() + ":" + port + " (according to " + bob.toString(true) + ")");
+ RemoteHostId oldId = state.getRemoteHostId();
state.introduced(addr, ip, port);
+ synchronized (_outboundStates) {
+ _outboundStates.remove(oldId);
+ _outboundStates.put(state.getRemoteHostId(), state);
+ }
notifyActivity();
}
diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java
index b160b4ceb..23f311c50 100644
--- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java
+++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java
@@ -77,9 +77,15 @@ public class OutboundEstablishState {
RouterIdentity remotePeer, SessionKey introKey, UDPAddress addr) {
_context = ctx;
_log = ctx.logManager().getLog(OutboundEstablishState.class);
- _bobIP = (remoteHost != null ? remoteHost.getAddress() : null);
- _bobPort = remotePort;
- _remoteHostId = new RemoteHostId(_bobIP, _bobPort);
+ if ( (remoteHost != null) && (remotePort > 0) ) {
+ _bobIP = remoteHost.getAddress();
+ _bobPort = remotePort;
+ _remoteHostId = new RemoteHostId(_bobIP, _bobPort);
+ } else {
+ _bobIP = null;
+ _bobPort = -1;
+ _remoteHostId = new RemoteHostId(remotePeer.calculateHash().getData());
+ }
_remotePeer = remotePeer;
_introKey = introKey;
_keyBuilder = null;
@@ -387,6 +393,8 @@ public class OutboundEstablishState {
_bobIP = bobIP;
_bobPort = bobPort;
_remoteHostId = new RemoteHostId(bobIP, bobPort);
+ if (_log.shouldLog(Log.INFO))
+ _log.info("Introduced to " + _remoteHostId + ", now lets get on with establishing");
}
/** how long have we been trying to establish this session? */
diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
index 19608a2ec..a56a540ac 100644
--- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
+++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java
@@ -746,28 +746,28 @@ public class PacketBuilder {
private byte[] getOurExplicitIP() { return null; }
private int getOurExplicitPort() { return 0; }
- public UDPPacket buildRelayRequest(UDPTransport transport, OutboundEstablishState state, SessionKey ourIntroKey) {
+ /** build intro packets for each of the published introducers */
+ public UDPPacket[] buildRelayRequest(UDPTransport transport, OutboundEstablishState state, SessionKey ourIntroKey) {
UDPAddress addr = state.getRemoteAddress();
int count = addr.getIntroducerCount();
if (count <= 0)
- return null;
- int index = _context.random().nextInt(count);
+ return new UDPPacket[0];
+ UDPPacket rv[] = new UDPPacket[count];
for (int i = 0; i < count; i++) {
- int cur = (i + index) % count;
- InetAddress iaddr = addr.getIntroducerHost(cur);
- int iport = addr.getIntroducerPort(cur);
- byte ikey[] = addr.getIntroducerKey(cur);
- long tag = addr.getIntroducerTag(cur);
+ InetAddress iaddr = addr.getIntroducerHost(i);
+ int iport = addr.getIntroducerPort(i);
+ byte ikey[] = addr.getIntroducerKey(i);
+ long tag = addr.getIntroducerTag(i);
if ( (ikey == null) || (iport <= 0) || (iaddr == null) || (tag <= 0) ) {
if (_log.shouldLog(_log.WARN))
_log.warn("Cannot build a relay request to " + state.getRemoteIdentity().calculateHash().toBase64()
- + ", as their UDP address is invalid: addr=" + addr + " index=" + cur);
+ + ", as their UDP address is invalid: addr=" + addr + " index=" + i);
continue;
}
if (transport.isValid(iaddr.getAddress()))
- return buildRelayRequest(iaddr, iport, ikey, tag, ourIntroKey, state.getIntroNonce(), true);
+ rv[i] = buildRelayRequest(iaddr, iport, ikey, tag, ourIntroKey, state.getIntroNonce(), true);
}
- return null;
+ return rv;
}
public UDPPacket buildRelayRequest(InetAddress introHost, int introPort, byte introKey[], long introTag, SessionKey ourIntroKey, long introNonce, boolean encrypt) {
diff --git a/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java b/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java
index 3f0e8cc2d..117f8c563 100644
--- a/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java
+++ b/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java
@@ -1,28 +1,37 @@
package net.i2p.router.transport.udp;
+import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
/**
* Unique ID for a peer - its IP + port, all bundled into a tidy obj.
- * Aint it cute?
+ * If the remote peer is not reachabe through an IP+port, this contains
+ * the hash of their identity.
*
*/
final class RemoteHostId {
private byte _ip[];
private int _port;
+ private byte _peerHash[];
public RemoteHostId(byte ip[], int port) {
_ip = ip;
_port = port;
}
+ public RemoteHostId(byte peerHash[]) {
+ _peerHash = peerHash;
+ }
public byte[] getIP() { return _ip; }
public int getPort() { return _port; }
+ public byte[] getPeerHash() { return _peerHash; }
public int hashCode() {
int rv = 0;
- for (int i = 0; i < _ip.length; i++)
+ for (int i = 0; _ip != null && i < _ip.length; i++)
rv += _ip[i] << i;
+ for (int i = 0; _peerHash != null && i < _peerHash.length; i++)
+ rv += _peerHash[i] << i;
rv += _port;
return rv;
}
@@ -33,15 +42,19 @@ final class RemoteHostId {
if (!(obj instanceof RemoteHostId))
throw new ClassCastException("obj is a " + obj.getClass().getName());
RemoteHostId id = (RemoteHostId)obj;
- return (_port == id.getPort()) && DataHelper.eq(_ip, id.getIP());
+ return (_port == id.getPort()) && DataHelper.eq(_ip, id.getIP()) && DataHelper.eq(_peerHash, id.getPeerHash());
}
public String toString() { return toString(true); }
public String toString(boolean includePort) {
- if (includePort)
- return toString(_ip) + ':' + _port;
- else
- return toString(_ip);
+ if (_ip != null) {
+ if (includePort)
+ return toString(_ip) + ':' + _port;
+ else
+ return toString(_ip);
+ } else {
+ return Base64.encode(_peerHash);
+ }
}
public static String toString(byte ip[]) {
StringBuffer buf = new StringBuffer(ip.length+5);
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
index 95cf752e8..949f17c2e 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -97,6 +97,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/** do we require introducers, regardless of our status? */
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
+ /** do we allow direct SSU connections, sans introducers? */
+ public static final String PROP_ALLOW_DIRECT = "i2np.udp.allowDirect";
/** how many relays offered to us will we use at a time? */
public static final int PUBLIC_RELAY_COUNT = 3;
@@ -797,8 +799,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_log.info("Picked peers: " + found);
_introducersSelectedOn = _context.clock().now();
}
- }
- if ( (_externalListenPort > 0) && (_externalListenHost != null) && (isValid(_externalListenHost.getAddress())) ) {
+ }
+ if ( allowDirectUDP() && (_externalListenPort > 0) && (_externalListenHost != null) && (isValid(_externalListenHost.getAddress())) ) {
options.setProperty(UDPAddress.PROP_PORT, String.valueOf(_externalListenPort));
options.setProperty(UDPAddress.PROP_HOST, _externalListenHost.getHostAddress());
// if we have explicit external addresses, they had better be reachable
@@ -866,6 +868,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
}
+ private boolean allowDirectUDP() {
+ String allowDirect = _context.getProperty(PROP_ALLOW_DIRECT);
+ return ( (allowDirect == null) || (Boolean.valueOf(allowDirect).booleanValue()) );
+ }
+
String getPacketHandlerStatus() {
PacketHandler handler = _handler;
if (handler != null)
|