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)
This commit is contained in:
jrandom
2005-11-30 20:48:25 +00:00
committed by zzz
parent 3d18bf870b
commit f62a6d3ce6
15 changed files with 133 additions and 46 deletions

View File

@ -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();

View File

@ -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("<tr><td colspan=\"3\">");
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;
}

View File

@ -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.

View File

@ -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);

View File

@ -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()))

View File

@ -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) ){

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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("<b>Connections (").append(_connectionsByIdent.size()).append("):</b><ul>\n");
for (Iterator iter = _connectionsByIdent.values().iterator(); iter.hasNext(); ) {
TCPConnection con = (TCPConnection)iter.next();
buf.append("<li>");
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("</li>\n");
}
buf.append("</ul>\n");
buf.append("<b>Inbound: ").append(inbound).append(", Outbound: ").append(outbound).append("</b><br />\n");
}
buf.append("<b>Most recent connection errors:</b><ul>");

View File

@ -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();
}

View File

@ -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? */

View File

@ -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) {

View File

@ -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);

View File

@ -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)