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:
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
14
history.txt
14
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.
|
||||
|
@ -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);
|
||||
|
@ -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()))
|
||||
|
@ -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) ){
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>");
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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? */
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user