propagate from branch 'i2p.i2p.zzz.test' (head b1e81b14fbaafdc188ae4d312f843c38b65cc310)
to branch 'i2p.i2p' (head 010351f9470b0e699e17447c87daf6c67e5e5dcc)
This commit is contained in:
@ -16,9 +16,9 @@ net.i2p.client.streaming.I2PServerSocket#accept} method, which will provide an
|
|||||||
application wants to create a new stream to a peer, it should do so with the
|
application wants to create a new stream to a peer, it should do so with the
|
||||||
appropriate {@link net.i2p.client.streaming.I2PSocketManager#connect} call.</p>
|
appropriate {@link net.i2p.client.streaming.I2PSocketManager#connect} call.</p>
|
||||||
|
|
||||||
<p>There is a simple pair of demo applications available as well - {@link
|
<p>There is a simple pair of demo applications available as well -
|
||||||
net.i2p.client.streaming.StreamSinkServer} listens to a destination and dumps
|
net.i2p.client.streaming.StreamSinkServer listens to a destination and dumps
|
||||||
the data from all sockets it accepts to individual files, while {@link
|
the data from all sockets it accepts to individual files, while
|
||||||
net.i2p.client.streaming.StreamSinkClient} connects to a particular destination
|
net.i2p.client.streaming.StreamSinkClient connects to a particular destination
|
||||||
and sends a specific amount of random data then disconnects.</p>
|
and sends a specific amount of random data then disconnects.</p>
|
||||||
</body></html>
|
</body></html>
|
||||||
|
30
apps/routerconsole/jsp/debug.jsp
Normal file
30
apps/routerconsole/jsp/debug.jsp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<%@page contentType="text/html"%>
|
||||||
|
<%@page pageEncoding="UTF-8"%>
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html><head><title>DEBUG</title>
|
||||||
|
<%@include file="css.jsp" %>
|
||||||
|
</head><body>
|
||||||
|
<%@include file="summary.jsp" %>
|
||||||
|
<div class="main" id="main">
|
||||||
|
<%
|
||||||
|
/*
|
||||||
|
* Quick and easy place to put debugging stuff
|
||||||
|
*/
|
||||||
|
net.i2p.router.RouterContext ctx = (net.i2p.router.RouterContext) net.i2p.I2PAppContext.getGlobalContext();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print out the status for all the SessionKeyManagers
|
||||||
|
*/
|
||||||
|
out.print("<h1>Router SKM</h1>");
|
||||||
|
ctx.sessionKeyManager().renderStatusHTML(out);
|
||||||
|
java.util.Set<net.i2p.data.Destination> clients = ctx.clientManager().listClients();
|
||||||
|
for (net.i2p.data.Destination dest : clients) {
|
||||||
|
net.i2p.data.Hash h = dest.calculateHash();
|
||||||
|
net.i2p.crypto.SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(h);
|
||||||
|
if (skm != null) {
|
||||||
|
out.print("<h1>" + h.toBase64().substring(0,6) + " SKM</h1>");
|
||||||
|
skm.renderStatusHTML(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
</div></body></html>
|
@ -354,6 +354,7 @@ public class Connection {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********
|
||||||
private class PingNotifier implements ConnectionManager.PingNotifier {
|
private class PingNotifier implements ConnectionManager.PingNotifier {
|
||||||
private long _startedPingOn;
|
private long _startedPingOn;
|
||||||
public PingNotifier() {
|
public PingNotifier() {
|
||||||
@ -367,6 +368,7 @@ public class Connection {
|
|||||||
_options.updateRTT((int)time*2);
|
_options.updateRTT((int)time*2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*********/
|
||||||
|
|
||||||
List ackPackets(long ackThrough, long nacks[]) {
|
List ackPackets(long ackThrough, long nacks[]) {
|
||||||
if (ackThrough < _highestAckedThrough) {
|
if (ackThrough < _highestAckedThrough) {
|
||||||
@ -548,20 +550,21 @@ public class Connection {
|
|||||||
killOutstandingPackets();
|
killOutstandingPackets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** ignore tag issues */
|
||||||
private void killOutstandingPackets() {
|
private void killOutstandingPackets() {
|
||||||
boolean tagsCancelled = false;
|
//boolean tagsCancelled = false;
|
||||||
synchronized (_outboundPackets) {
|
synchronized (_outboundPackets) {
|
||||||
for (Iterator iter = _outboundPackets.values().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = _outboundPackets.values().iterator(); iter.hasNext(); ) {
|
||||||
PacketLocal pl = (PacketLocal)iter.next();
|
PacketLocal pl = (PacketLocal)iter.next();
|
||||||
if ( (pl.getTagsSent() != null) && (pl.getTagsSent().size() > 0) )
|
//if ( (pl.getTagsSent() != null) && (pl.getTagsSent().size() > 0) )
|
||||||
tagsCancelled = true;
|
// tagsCancelled = true;
|
||||||
pl.cancelled();
|
pl.cancelled();
|
||||||
}
|
}
|
||||||
_outboundPackets.clear();
|
_outboundPackets.clear();
|
||||||
_outboundPackets.notifyAll();
|
_outboundPackets.notifyAll();
|
||||||
}
|
}
|
||||||
if (tagsCancelled)
|
//if (tagsCancelled)
|
||||||
_context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
|
// _context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DisconnectEvent implements SimpleTimer.TimedEvent {
|
private class DisconnectEvent implements SimpleTimer.TimedEvent {
|
||||||
@ -1140,12 +1143,12 @@ public class Connection {
|
|||||||
|
|
||||||
// in case things really suck, the other side may have lost thier
|
// in case things really suck, the other side may have lost thier
|
||||||
// session tags (e.g. they restarted), so jump back to ElGamal.
|
// session tags (e.g. they restarted), so jump back to ElGamal.
|
||||||
int failTagsAt = _options.getMaxResends() - 2;
|
//int failTagsAt = _options.getMaxResends() - 2;
|
||||||
if ( (newWindowSize == 1) && (numSends == failTagsAt) ) {
|
//if ( (newWindowSize == 1) && (numSends == failTagsAt) ) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
// if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Optimistically failing tags at resend " + numSends);
|
// _log.warn("Optimistically failing tags at resend " + numSends);
|
||||||
_context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
|
// _context.sessionKeyManager().failTags(_remotePeer.getPublicKey());
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (numSends - 1 > _options.getMaxResends()) {
|
if (numSends - 1 > _options.getMaxResends()) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
@ -349,24 +349,35 @@ public class ConnectionManager {
|
|||||||
return new HashSet(_connectionByInboundId.values());
|
return new HashSet(_connectionByInboundId.values());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** blocking */
|
||||||
public boolean ping(Destination peer, long timeoutMs) {
|
public boolean ping(Destination peer, long timeoutMs) {
|
||||||
return ping(peer, timeoutMs, true);
|
return ping(peer, timeoutMs, true, null);
|
||||||
}
|
}
|
||||||
public boolean ping(Destination peer, long timeoutMs, boolean blocking) {
|
public boolean ping(Destination peer, long timeoutMs, boolean blocking) {
|
||||||
return ping(peer, timeoutMs, blocking, null, null, null);
|
return ping(peer, timeoutMs, blocking, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated I2PSession ignores tags, use non-tag variant
|
||||||
|
* @param keyToUse ignored
|
||||||
|
* @param tagsToSend ignored
|
||||||
|
*/
|
||||||
public boolean ping(Destination peer, long timeoutMs, boolean blocking, SessionKey keyToUse, Set tagsToSend, PingNotifier notifier) {
|
public boolean ping(Destination peer, long timeoutMs, boolean blocking, SessionKey keyToUse, Set tagsToSend, PingNotifier notifier) {
|
||||||
|
return ping(peer, timeoutMs, blocking, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean ping(Destination peer, long timeoutMs, boolean blocking, PingNotifier notifier) {
|
||||||
Long id = new Long(_context.random().nextLong(Packet.MAX_STREAM_ID-1)+1);
|
Long id = new Long(_context.random().nextLong(Packet.MAX_STREAM_ID-1)+1);
|
||||||
PacketLocal packet = new PacketLocal(_context, peer);
|
PacketLocal packet = new PacketLocal(_context, peer);
|
||||||
packet.setSendStreamId(id.longValue());
|
packet.setSendStreamId(id.longValue());
|
||||||
packet.setFlag(Packet.FLAG_ECHO);
|
packet.setFlag(Packet.FLAG_ECHO);
|
||||||
packet.setFlag(Packet.FLAG_SIGNATURE_INCLUDED);
|
packet.setFlag(Packet.FLAG_SIGNATURE_INCLUDED);
|
||||||
packet.setOptionalFrom(_session.getMyDestination());
|
packet.setOptionalFrom(_session.getMyDestination());
|
||||||
if ( (keyToUse != null) && (tagsToSend != null) ) {
|
//if ( (keyToUse != null) && (tagsToSend != null) ) {
|
||||||
packet.setKeyUsed(keyToUse);
|
// packet.setKeyUsed(keyToUse);
|
||||||
packet.setTagsSent(tagsToSend);
|
// packet.setTagsSent(tagsToSend);
|
||||||
}
|
//}
|
||||||
|
|
||||||
PingRequest req = new PingRequest(peer, packet, notifier);
|
PingRequest req = new PingRequest(peer, packet, notifier);
|
||||||
|
|
||||||
@ -435,7 +446,7 @@ public class ConnectionManager {
|
|||||||
}
|
}
|
||||||
public void pong() {
|
public void pong() {
|
||||||
_log.debug("Ping successful");
|
_log.debug("Ping successful");
|
||||||
_context.sessionKeyManager().tagsDelivered(_peer.getPublicKey(), _packet.getKeyUsed(), _packet.getTagsSent());
|
//_context.sessionKeyManager().tagsDelivered(_peer.getPublicKey(), _packet.getKeyUsed(), _packet.getTagsSent());
|
||||||
synchronized (ConnectionManager.PingRequest.this) {
|
synchronized (ConnectionManager.PingRequest.this) {
|
||||||
_ponged = true;
|
_ponged = true;
|
||||||
ConnectionManager.PingRequest.this.notifyAll();
|
ConnectionManager.PingRequest.this.notifyAll();
|
||||||
|
@ -263,12 +263,12 @@ public class ConnectionPacketHandler {
|
|||||||
numResends++;
|
numResends++;
|
||||||
|
|
||||||
// ACK the tags we delivered so we can use them
|
// ACK the tags we delivered so we can use them
|
||||||
if ( (p.getKeyUsed() != null) && (p.getTagsSent() != null)
|
//if ( (p.getKeyUsed() != null) && (p.getTagsSent() != null)
|
||||||
&& (p.getTagsSent().size() > 0) ) {
|
// && (p.getTagsSent().size() > 0) ) {
|
||||||
_context.sessionKeyManager().tagsDelivered(p.getTo().getPublicKey(),
|
// _context.sessionKeyManager().tagsDelivered(p.getTo().getPublicKey(),
|
||||||
p.getKeyUsed(),
|
// p.getKeyUsed(),
|
||||||
p.getTagsSent());
|
// p.getTagsSent());
|
||||||
}
|
//}
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Packet acked after " + p.getAckTime() + "ms: " + p);
|
_log.debug("Packet acked after " + p.getAckTime() + "ms: " + p);
|
||||||
}
|
}
|
||||||
|
@ -47,11 +47,31 @@ public class PacketLocal extends Packet implements MessageOutputStream.WriteStat
|
|||||||
public Destination getTo() { return _to; }
|
public Destination getTo() { return _to; }
|
||||||
public void setTo(Destination to) { _to = to; }
|
public void setTo(Destination to) { _to = to; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated should always return null
|
||||||
|
*/
|
||||||
public SessionKey getKeyUsed() { return _keyUsed; }
|
public SessionKey getKeyUsed() { return _keyUsed; }
|
||||||
public void setKeyUsed(SessionKey key) { _keyUsed = key; }
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated I2PSession throws out the tags
|
||||||
|
*/
|
||||||
|
public void setKeyUsed(SessionKey key) {
|
||||||
|
if (key != null)
|
||||||
|
_log.error("Who is sending tags thru the streaming lib?");
|
||||||
|
_keyUsed = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated should always return null or an empty set
|
||||||
|
*/
|
||||||
public Set getTagsSent() { return _tagsSent; }
|
public Set getTagsSent() { return _tagsSent; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated I2PSession throws out the tags
|
||||||
|
*/
|
||||||
public void setTagsSent(Set tags) {
|
public void setTagsSent(Set tags) {
|
||||||
|
if (tags != null && tags.size() > 0)
|
||||||
|
_log.error("Who is sending tags thru the streaming lib? " + tags.size());
|
||||||
if ( (_tagsSent != null) && (_tagsSent.size() > 0) && (tags.size() > 0) ) {
|
if ( (_tagsSent != null) && (_tagsSent.size() > 0) && (tags.size() > 0) ) {
|
||||||
//int old = _tagsSent.size();
|
//int old = _tagsSent.size();
|
||||||
//_tagsSent.addAll(tags);
|
//_tagsSent.addAll(tags);
|
||||||
|
@ -36,16 +36,18 @@ public class PacketQueue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new packet to be sent out ASAP
|
* Add a new packet to be sent out ASAP
|
||||||
|
*
|
||||||
|
* keys and tags disabled since dropped in I2PSession
|
||||||
*/
|
*/
|
||||||
public void enqueue(PacketLocal packet) {
|
public void enqueue(PacketLocal packet) {
|
||||||
packet.prepare();
|
packet.prepare();
|
||||||
|
|
||||||
SessionKey keyUsed = packet.getKeyUsed();
|
//SessionKey keyUsed = packet.getKeyUsed();
|
||||||
if (keyUsed == null)
|
//if (keyUsed == null)
|
||||||
keyUsed = new SessionKey();
|
// keyUsed = new SessionKey();
|
||||||
Set tagsSent = packet.getTagsSent();
|
//Set tagsSent = packet.getTagsSent();
|
||||||
if (tagsSent == null)
|
//if (tagsSent == null)
|
||||||
tagsSent = new HashSet(0);
|
// tagsSent = new HashSet(0);
|
||||||
|
|
||||||
// cache this from before sendMessage
|
// cache this from before sendMessage
|
||||||
String conStr = null;
|
String conStr = null;
|
||||||
@ -92,13 +94,19 @@ public class PacketQueue {
|
|||||||
// I2PSessionImpl2
|
// I2PSessionImpl2
|
||||||
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires);
|
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires);
|
||||||
// I2PSessionMuxedImpl
|
// I2PSessionMuxedImpl
|
||||||
sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires,
|
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, expires,
|
||||||
|
// I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
|
||||||
|
// I2PSessionMuxedImpl no tags
|
||||||
|
sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null, expires,
|
||||||
I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
|
I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
|
||||||
else
|
else
|
||||||
// I2PSessionImpl2
|
// I2PSessionImpl2
|
||||||
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, 0);
|
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent, 0);
|
||||||
// I2PSessionMuxedImpl
|
// I2PSessionMuxedImpl
|
||||||
sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent,
|
//sent = _session.sendMessage(packet.getTo(), buf, 0, size, keyUsed, tagsSent,
|
||||||
|
// I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
|
||||||
|
// I2PSessionMuxedImpl no tags
|
||||||
|
sent = _session.sendMessage(packet.getTo(), buf, 0, size, null, null,
|
||||||
I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
|
I2PSession.PROTO_STREAMING, I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED);
|
||||||
end = _context.clock().now();
|
end = _context.clock().now();
|
||||||
|
|
||||||
@ -129,13 +137,11 @@ public class PacketQueue {
|
|||||||
if (c != null) // handle race on b0rk
|
if (c != null) // handle race on b0rk
|
||||||
c.disconnect(false);
|
c.disconnect(false);
|
||||||
} else {
|
} else {
|
||||||
packet.setKeyUsed(keyUsed);
|
//packet.setKeyUsed(keyUsed);
|
||||||
packet.setTagsSent(tagsSent);
|
//packet.setTagsSent(tagsSent);
|
||||||
packet.incrementSends();
|
packet.incrementSends();
|
||||||
if (_log.shouldLog(Log.DEBUG)) {
|
if (_log.shouldLog(Log.DEBUG)) {
|
||||||
String msg = "SEND " + packet + (tagsSent.size() > 0
|
String msg = "SEND " + packet
|
||||||
? " with " + tagsSent.size() + " tags"
|
|
||||||
: "")
|
|
||||||
+ " send # " + packet.getNumSends()
|
+ " send # " + packet.getNumSends()
|
||||||
+ " sendTime: " + (end-begin)
|
+ " sendTime: " + (end-begin)
|
||||||
+ " con: " + conStr;
|
+ " con: " + conStr;
|
||||||
|
@ -93,6 +93,10 @@ class I2CPMessageProducer {
|
|||||||
/**
|
/**
|
||||||
* Package up and send the payload to the router for delivery
|
* Package up and send the payload to the router for delivery
|
||||||
*
|
*
|
||||||
|
* @param tag unused - no end-to-end crypto
|
||||||
|
* @param tags unused - no end-to-end crypto
|
||||||
|
* @param key unused - no end-to-end crypto
|
||||||
|
* @param newKey unused - no end-to-end crypto
|
||||||
*/
|
*/
|
||||||
public void sendMessage(I2PSessionImpl session, Destination dest, long nonce, byte[] payload, SessionTag tag,
|
public void sendMessage(I2PSessionImpl session, Destination dest, long nonce, byte[] payload, SessionTag tag,
|
||||||
SessionKey key, Set tags, SessionKey newKey, long expires) throws I2PSessionException {
|
SessionKey key, Set tags, SessionKey newKey, long expires) throws I2PSessionException {
|
||||||
@ -135,6 +139,10 @@ class I2CPMessageProducer {
|
|||||||
/**
|
/**
|
||||||
* Create a new signed payload and send it off to the destination
|
* Create a new signed payload and send it off to the destination
|
||||||
*
|
*
|
||||||
|
* @param tag unused - no end-to-end crypto
|
||||||
|
* @param tags unused - no end-to-end crypto
|
||||||
|
* @param key unused - no end-to-end crypto
|
||||||
|
* @param newKey unused - no end-to-end crypto
|
||||||
*/
|
*/
|
||||||
private Payload createPayload(Destination dest, byte[] payload, SessionTag tag, SessionKey key, Set tags,
|
private Payload createPayload(Destination dest, byte[] payload, SessionTag tag, SessionKey key, Set tags,
|
||||||
SessionKey newKey) throws I2PSessionException {
|
SessionKey newKey) throws I2PSessionException {
|
||||||
|
@ -355,17 +355,23 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
|
|||||||
*/
|
*/
|
||||||
public abstract boolean sendMessage(Destination dest, byte[] payload) throws I2PSessionException;
|
public abstract boolean sendMessage(Destination dest, byte[] payload) throws I2PSessionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
|
*/
|
||||||
public abstract boolean sendMessage(Destination dest, byte[] payload, SessionKey keyUsed,
|
public abstract boolean sendMessage(Destination dest, byte[] payload, SessionKey keyUsed,
|
||||||
Set tagsSent) throws I2PSessionException;
|
Set tagsSent) throws I2PSessionException;
|
||||||
|
|
||||||
public abstract void receiveStatus(int msgId, long nonce, int status);
|
public abstract void receiveStatus(int msgId, long nonce, int status);
|
||||||
|
|
||||||
|
/****** no end-to-end crypto
|
||||||
protected static final Set createNewTags(int num) {
|
protected static final Set createNewTags(int num) {
|
||||||
Set tags = new HashSet();
|
Set tags = new HashSet();
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
tags.add(new SessionTag(true));
|
tags.add(new SessionTag(true));
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
*******/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recieve a payload message and let the app know its available
|
* Recieve a payload message and let the app know its available
|
||||||
|
@ -133,14 +133,28 @@ class I2PSessionImpl2 extends I2PSessionImpl {
|
|||||||
return sendMessage(dest, payload, offset, size, null, null, 0);
|
return sendMessage(dest, payload, offset, size, null, null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean sendMessage(Destination dest, byte[] payload, SessionKey keyUsed, Set tagsSent) throws I2PSessionException {
|
public boolean sendMessage(Destination dest, byte[] payload, SessionKey keyUsed, Set tagsSent) throws I2PSessionException {
|
||||||
return sendMessage(dest, payload, 0, payload.length, keyUsed, tagsSent, 0);
|
return sendMessage(dest, payload, 0, payload.length, keyUsed, tagsSent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
|
*/
|
||||||
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent)
|
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent)
|
||||||
throws I2PSessionException {
|
throws I2PSessionException {
|
||||||
return sendMessage(dest, payload, offset, size, keyUsed, tagsSent, 0);
|
return sendMessage(dest, payload, offset, size, keyUsed, tagsSent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
|
*/
|
||||||
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, long expires)
|
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, long expires)
|
||||||
throws I2PSessionException {
|
throws I2PSessionException {
|
||||||
if (_log.shouldLog(Log.DEBUG)) _log.debug("sending message");
|
if (_log.shouldLog(Log.DEBUG)) _log.debug("sending message");
|
||||||
@ -196,13 +210,17 @@ class I2PSessionImpl2 extends I2PSessionImpl {
|
|||||||
|
|
||||||
private static final int NUM_TAGS = 50;
|
private static final int NUM_TAGS = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
|
*/
|
||||||
protected boolean sendBestEffort(Destination dest, byte payload[], SessionKey keyUsed, Set tagsSent, long expires)
|
protected boolean sendBestEffort(Destination dest, byte payload[], SessionKey keyUsed, Set tagsSent, long expires)
|
||||||
throws I2PSessionException {
|
throws I2PSessionException {
|
||||||
SessionKey key = null;
|
//SessionKey key = null;
|
||||||
SessionKey newKey = null;
|
//SessionKey newKey = null;
|
||||||
SessionTag tag = null;
|
//SessionTag tag = null;
|
||||||
Set sentTags = null;
|
//Set sentTags = null;
|
||||||
int oldTags = 0;
|
//int oldTags = 0;
|
||||||
long begin = _context.clock().now();
|
long begin = _context.clock().now();
|
||||||
/***********
|
/***********
|
||||||
if (I2CPMessageProducer.END_TO_END_CRYPTO) {
|
if (I2CPMessageProducer.END_TO_END_CRYPTO) {
|
||||||
@ -256,27 +274,27 @@ class I2PSessionImpl2 extends I2PSessionImpl {
|
|||||||
long nonce = _context.random().nextInt(Integer.MAX_VALUE);
|
long nonce = _context.random().nextInt(Integer.MAX_VALUE);
|
||||||
if (_log.shouldLog(Log.DEBUG)) _log.debug("before sync state");
|
if (_log.shouldLog(Log.DEBUG)) _log.debug("before sync state");
|
||||||
MessageState state = new MessageState(_context, nonce, getPrefix());
|
MessageState state = new MessageState(_context, nonce, getPrefix());
|
||||||
state.setKey(key);
|
//state.setKey(key);
|
||||||
state.setTags(sentTags);
|
//state.setTags(sentTags);
|
||||||
state.setNewKey(newKey);
|
//state.setNewKey(newKey);
|
||||||
state.setTo(dest);
|
state.setTo(dest);
|
||||||
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Setting key = " + key);
|
//if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Setting key = " + key);
|
||||||
|
|
||||||
if (keyUsed != null) {
|
//if (keyUsed != null) {
|
||||||
//if (I2CPMessageProducer.END_TO_END_CRYPTO) {
|
//if (I2CPMessageProducer.END_TO_END_CRYPTO) {
|
||||||
// if (newKey != null)
|
// if (newKey != null)
|
||||||
// keyUsed.setData(newKey.getData());
|
// keyUsed.setData(newKey.getData());
|
||||||
// else
|
// else
|
||||||
// keyUsed.setData(key.getData());
|
// keyUsed.setData(key.getData());
|
||||||
//} else {
|
//} else {
|
||||||
keyUsed.setData(SessionKey.INVALID_KEY.getData());
|
// keyUsed.setData(SessionKey.INVALID_KEY.getData());
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//if (tagsSent != null) {
|
||||||
|
// if (sentTags != null) {
|
||||||
|
// tagsSent.addAll(sentTags);
|
||||||
|
// }
|
||||||
//}
|
//}
|
||||||
}
|
|
||||||
if (tagsSent != null) {
|
|
||||||
if (sentTags != null) {
|
|
||||||
tagsSent.addAll(sentTags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_log.shouldLog(Log.DEBUG)) _log.debug("before sync state");
|
if (_log.shouldLog(Log.DEBUG)) _log.debug("before sync state");
|
||||||
long beforeSendingSync = _context.clock().now();
|
long beforeSendingSync = _context.clock().now();
|
||||||
@ -291,7 +309,8 @@ class I2PSessionImpl2 extends I2PSessionImpl {
|
|||||||
+ state.getNonce() + " for best effort "
|
+ state.getNonce() + " for best effort "
|
||||||
+ " sync took " + (inSendingSync-beforeSendingSync)
|
+ " sync took " + (inSendingSync-beforeSendingSync)
|
||||||
+ " add took " + (afterSendingSync-inSendingSync));
|
+ " add took " + (afterSendingSync-inSendingSync));
|
||||||
_producer.sendMessage(this, dest, nonce, payload, tag, key, sentTags, newKey, expires);
|
//_producer.sendMessage(this, dest, nonce, payload, tag, key, sentTags, newKey, expires);
|
||||||
|
_producer.sendMessage(this, dest, nonce, payload, null, null, null, null, expires);
|
||||||
|
|
||||||
// since this is 'best effort', all we're waiting for is a status update
|
// since this is 'best effort', all we're waiting for is a status update
|
||||||
// saying that the router received it - in theory, that should come back
|
// saying that the router received it - in theory, that should come back
|
||||||
|
@ -128,6 +128,10 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession {
|
|||||||
return sendMessage(dest, payload, 0, payload.length, null, null, 0, proto, fromport, toport);
|
return sendMessage(dest, payload, 0, payload.length, null, null, 0, proto, fromport, toport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size,
|
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size,
|
||||||
SessionKey keyUsed, Set tagsSent, long expires)
|
SessionKey keyUsed, Set tagsSent, long expires)
|
||||||
@ -135,6 +139,10 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession {
|
|||||||
return sendMessage(dest, payload, offset, size, keyUsed, tagsSent, 0, PROTO_UNSPECIFIED, PORT_UNSPECIFIED, PORT_UNSPECIFIED);
|
return sendMessage(dest, payload, offset, size, keyUsed, tagsSent, 0, PROTO_UNSPECIFIED, PORT_UNSPECIFIED, PORT_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent,
|
public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent,
|
||||||
int proto, int fromport, int toport) throws I2PSessionException {
|
int proto, int fromport, int toport) throws I2PSessionException {
|
||||||
@ -142,6 +150,8 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param keyUsed unused - no end-to-end crypto
|
||||||
|
* @param tagsSent unused - no end-to-end crypto
|
||||||
* @param proto 1-254 or 0 for unset; recommended:
|
* @param proto 1-254 or 0 for unset; recommended:
|
||||||
* I2PSession.PROTO_UNSPECIFIED
|
* I2PSession.PROTO_UNSPECIFIED
|
||||||
* I2PSession.PROTO_STREAMING
|
* I2PSession.PROTO_STREAMING
|
||||||
|
@ -22,6 +22,8 @@ import net.i2p.util.Log;
|
|||||||
* of a message by accepting it, decrypting the payload, adding it to the set of
|
* of a message by accepting it, decrypting the payload, adding it to the set of
|
||||||
* recieved messages, and telling the router that it has been recieved correctly.
|
* recieved messages, and telling the router that it has been recieved correctly.
|
||||||
*
|
*
|
||||||
|
* We don't really decrypt (no more end-to-end crypto)
|
||||||
|
*
|
||||||
* @author jrandom
|
* @author jrandom
|
||||||
*/
|
*/
|
||||||
class MessagePayloadMessageHandler extends HandlerImpl {
|
class MessagePayloadMessageHandler extends HandlerImpl {
|
||||||
@ -51,21 +53,24 @@ class MessagePayloadMessageHandler extends HandlerImpl {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt the payload
|
* Decrypt the payload
|
||||||
|
*
|
||||||
|
* We don't really decrypt (no more end-to-end crypto)
|
||||||
|
* If we do, we need to use the correct key manager in the decrypt() call below
|
||||||
*/
|
*/
|
||||||
private Payload decryptPayload(MessagePayloadMessage msg, I2PSessionImpl session) throws DataFormatException {
|
private Payload decryptPayload(MessagePayloadMessage msg, I2PSessionImpl session) throws DataFormatException {
|
||||||
Payload payload = msg.getPayload();
|
Payload payload = msg.getPayload();
|
||||||
if (!I2CPMessageProducer.END_TO_END_CRYPTO) {
|
//if (!I2CPMessageProducer.END_TO_END_CRYPTO) {
|
||||||
payload.setUnencryptedData(payload.getEncryptedData());
|
payload.setUnencryptedData(payload.getEncryptedData());
|
||||||
return payload;
|
return payload;
|
||||||
}
|
//}
|
||||||
|
|
||||||
byte[] data = _context.elGamalAESEngine().decrypt(payload.getEncryptedData(), session.getDecryptionKey());
|
//byte[] data = _context.elGamalAESEngine().decrypt(payload.getEncryptedData(), session.getDecryptionKey());
|
||||||
if (data == null) {
|
//if (data == null) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
// if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Error decrypting the payload");
|
// _log.warn("Error decrypting the payload");
|
||||||
throw new DataFormatException("Unable to decrypt the payload");
|
// throw new DataFormatException("Unable to decrypt the payload");
|
||||||
}
|
//}
|
||||||
payload.setUnencryptedData(data);
|
//payload.setUnencryptedData(data);
|
||||||
return payload;
|
//return payload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import org.bouncycastle.crypto.macs.I2PHMac;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the HMAC-SHA256 of a key+message. All the good stuff occurs
|
* Calculate the HMAC-SHA256 of a key+message. All the good stuff occurs
|
||||||
* in {@link org.bouncycastle.crypto.macs.HMac} and
|
* in {@link org.bouncycastle.crypto.macs.I2PHMac} and
|
||||||
* {@link org.bouncycastle.crypto.digests.MD5Digest}.
|
* {@link org.bouncycastle.crypto.digests.MD5Digest}.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,7 @@ import org.bouncycastle.crypto.macs.I2PHMac;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the HMAC-MD5 of a key+message. All the good stuff occurs
|
* Calculate the HMAC-MD5 of a key+message. All the good stuff occurs
|
||||||
* in {@link org.bouncycastle.crypto.macs.HMac} and
|
* in {@link org.bouncycastle.crypto.macs.I2PHMac} and
|
||||||
* {@link org.bouncycastle.crypto.digests.MD5Digest}.
|
* {@link org.bouncycastle.crypto.digests.MD5Digest}.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -9,6 +9,8 @@ package net.i2p.crypto;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
@ -130,4 +132,6 @@ public class SessionKeyManager {
|
|||||||
*/
|
*/
|
||||||
public void shutdown() { // nop
|
public void shutdown() { // nop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void renderStatusHTML(Writer out) throws IOException {}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,10 @@ package net.i2p.crypto;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -17,6 +20,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
@ -503,57 +507,83 @@ public class TransientSessionKeyManager extends SessionKeyManager {
|
|||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String renderStatusHTML() {
|
@Override
|
||||||
|
public void renderStatusHTML(Writer out) throws IOException {
|
||||||
StringBuilder buf = new StringBuilder(1024);
|
StringBuilder buf = new StringBuilder(1024);
|
||||||
buf.append("<h2>Inbound sessions</h2>");
|
buf.append("<h2>Inbound sessions</h2>" +
|
||||||
buf.append("<table>");
|
"<table>");
|
||||||
Set<TagSet> inbound = getInboundTagSets();
|
Set<TagSet> inbound = getInboundTagSets();
|
||||||
Map<SessionKey, Set<TagSet>> inboundSets = new HashMap(inbound.size());
|
Map<SessionKey, Set<TagSet>> inboundSets = new HashMap(inbound.size());
|
||||||
|
// Build a map of the inbound tag sets, grouped by SessionKey
|
||||||
for (Iterator<TagSet> iter = inbound.iterator(); iter.hasNext();) {
|
for (Iterator<TagSet> iter = inbound.iterator(); iter.hasNext();) {
|
||||||
TagSet ts = iter.next();
|
TagSet ts = iter.next();
|
||||||
if (!inboundSets.containsKey(ts.getAssociatedKey())) inboundSets.put(ts.getAssociatedKey(), new HashSet());
|
if (!inboundSets.containsKey(ts.getAssociatedKey())) inboundSets.put(ts.getAssociatedKey(), new HashSet());
|
||||||
Set<TagSet> sets = inboundSets.get(ts.getAssociatedKey());
|
Set<TagSet> sets = inboundSets.get(ts.getAssociatedKey());
|
||||||
sets.add(ts);
|
sets.add(ts);
|
||||||
}
|
}
|
||||||
|
int total = 0;
|
||||||
|
long now = _context.clock().now();
|
||||||
for (Iterator<SessionKey> iter = inboundSets.keySet().iterator(); iter.hasNext();) {
|
for (Iterator<SessionKey> iter = inboundSets.keySet().iterator(); iter.hasNext();) {
|
||||||
SessionKey skey = iter.next();
|
SessionKey skey = iter.next();
|
||||||
Set<TagSet> sets = inboundSets.get(skey);
|
Set<TagSet> sets = new TreeSet(new TagSetComparator());
|
||||||
buf.append("<tr><td><b>Session key</b>: ").append(skey.toBase64()).append("</td>");
|
sets.addAll(inboundSets.get(skey));
|
||||||
buf.append("<td><b># Sets:</b> ").append(sets.size()).append("</td></tr>");
|
buf.append("<tr><td><b>Session key</b>: ").append(skey.toBase64()).append("</td>" +
|
||||||
buf.append("<tr><td colspan=\"2\"><ul>");
|
"<td><b># Sets:</b> ").append(sets.size()).append("</td></tr>" +
|
||||||
|
"<tr><td colspan=\"2\"><ul>");
|
||||||
for (Iterator<TagSet> siter = sets.iterator(); siter.hasNext();) {
|
for (Iterator<TagSet> siter = sets.iterator(); siter.hasNext();) {
|
||||||
TagSet ts = siter.next();
|
TagSet ts = siter.next();
|
||||||
buf.append("<li><b>Received on:</b> ").append(new Date(ts.getDate())).append(" with ")
|
int size = ts.getTags().size();
|
||||||
.append(ts.getTags().size()).append(" tags remaining</li>");
|
total += size;
|
||||||
|
buf.append("<li><b>Received:</b> ").append(DataHelper.formatDuration(now - ts.getDate())).append(" ago with ");
|
||||||
|
buf.append(size).append(" tags remaining</li>");
|
||||||
}
|
}
|
||||||
buf.append("</ul></td></tr>");
|
buf.append("</ul></td></tr>\n");
|
||||||
|
out.write(buf.toString());
|
||||||
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
buf.append("</table>");
|
buf.append("<tr><th colspan=\"2\">Total tags: ").append(total).append(" (");
|
||||||
|
buf.append(DataHelper.formatSize(32*total)).append("B)</th></tr>\n" +
|
||||||
buf.append("<h2><b>Outbound sessions</b></h2>");
|
"</table>" +
|
||||||
|
"<h2><b>Outbound sessions</b></h2>" +
|
||||||
buf.append("<table>");
|
"<table>");
|
||||||
|
total = 0;
|
||||||
Set<OutboundSession> outbound = getOutboundSessions();
|
Set<OutboundSession> outbound = getOutboundSessions();
|
||||||
for (Iterator<OutboundSession> iter = outbound.iterator(); iter.hasNext();) {
|
for (Iterator<OutboundSession> iter = outbound.iterator(); iter.hasNext();) {
|
||||||
OutboundSession sess = iter.next();
|
OutboundSession sess = iter.next();
|
||||||
buf.append("<tr><td><b>Target key:</b> ").append(sess.getTarget().toString()).append("<br>");
|
Set<TagSet> sets = new TreeSet(new TagSetComparator());
|
||||||
buf.append("<b>Established:</b> ").append(new Date(sess.getEstablishedDate())).append("<br>");
|
sets.addAll(sess.getTagSets());
|
||||||
buf.append("<b>Last Used:</b> ").append(new Date(sess.getLastUsedDate())).append("<br>");
|
buf.append("<tr><td><b>Target key:</b> ").append(sess.getTarget().toBase64().substring(0, 64)).append("<br>" +
|
||||||
buf.append("<b># Sets:</b> ").append(sess.getTagSets().size()).append("</td></tr>");
|
"<b>Established:</b> ").append(DataHelper.formatDuration(now - sess.getEstablishedDate())).append(" ago<br>" +
|
||||||
buf.append("<tr><td><b>Session key:</b> ").append(sess.getCurrentKey().toBase64()).append("</td></tr>");
|
"<b>Last Used:</b> ").append(DataHelper.formatDuration(now - sess.getLastUsedDate())).append(" ago<br>" +
|
||||||
buf.append("<tr><td><ul>");
|
"<b>Session key:</b> ").append(sess.getCurrentKey().toBase64()).append("</td>" +
|
||||||
for (Iterator<TagSet> siter = sess.getTagSets().iterator(); siter.hasNext();) {
|
"<td><b># Sets:</b> ").append(sess.getTagSets().size()).append("</td></tr>" +
|
||||||
|
"<tr><td colspan=\"2\"><ul>");
|
||||||
|
for (Iterator<TagSet> siter = sets.iterator(); siter.hasNext();) {
|
||||||
TagSet ts = siter.next();
|
TagSet ts = siter.next();
|
||||||
buf.append("<li><b>Sent on:</b> ").append(new Date(ts.getDate())).append(" with ").append(
|
int size = ts.getTags().size();
|
||||||
ts.getTags()
|
total += size;
|
||||||
.size())
|
buf.append("<li><b>Sent:</b> ").append(DataHelper.formatDuration(now - ts.getDate())).append(" ago with ");
|
||||||
.append(" tags remaining</li>");
|
buf.append(size).append(" tags remaining</li>");
|
||||||
}
|
}
|
||||||
buf.append("</ul></td></tr>");
|
buf.append("</ul></td></tr>\n");
|
||||||
|
out.write(buf.toString());
|
||||||
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
buf.append("</table>");
|
buf.append("<tr><th colspan=\"2\">Total tags: ").append(total).append(" (");
|
||||||
|
buf.append(DataHelper.formatSize(32*total)).append("B)</th></tr>\n" +
|
||||||
|
"</table>");
|
||||||
|
|
||||||
return buf.toString();
|
out.write(buf.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just for the HTML method above so we can see what's going on easier
|
||||||
|
* Earliest first
|
||||||
|
*/
|
||||||
|
private class TagSetComparator implements Comparator {
|
||||||
|
public int compare(Object l, Object r) {
|
||||||
|
return (int) (((TagSet)l).getDate() - ((TagSet)r).getDate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OutboundSession {
|
class OutboundSession {
|
||||||
@ -760,7 +790,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
long rv = 0;
|
long rv = 0;
|
||||||
if (_key != null) rv = rv * 7 + _key.hashCode();
|
if (_key != null) rv = _key.hashCode();
|
||||||
rv = rv * 7 + _date;
|
rv = rv * 7 + _date;
|
||||||
// no need to hashCode the tags, key + date should be enough
|
// no need to hashCode the tags, key + date should be enough
|
||||||
return (int) rv;
|
return (int) rv;
|
||||||
|
@ -85,13 +85,13 @@ public abstract class ClientManagerFacade implements Service {
|
|||||||
*
|
*
|
||||||
* @return set of Destination objects
|
* @return set of Destination objects
|
||||||
*/
|
*/
|
||||||
public Set listClients() { return Collections.EMPTY_SET; }
|
public Set<Destination> listClients() { return Collections.EMPTY_SET; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the client's current config, or null if not connected
|
* Return the client's current config, or null if not connected
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract SessionConfig getClientSessionConfig(Destination dest);
|
public abstract SessionConfig getClientSessionConfig(Destination dest);
|
||||||
public abstract SessionKeyManager getClientSessionKeyManager(Destination dest);
|
public abstract SessionKeyManager getClientSessionKeyManager(Hash dest);
|
||||||
public void renderStatusHTML(Writer out) throws IOException { }
|
public void renderStatusHTML(Writer out) throws IOException { }
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ public class DummyClientManagerFacade extends ClientManagerFacade {
|
|||||||
public void messageDeliveryStatusUpdate(Destination fromDest, MessageId id, boolean delivered) {}
|
public void messageDeliveryStatusUpdate(Destination fromDest, MessageId id, boolean delivered) {}
|
||||||
|
|
||||||
public SessionConfig getClientSessionConfig(Destination _dest) { return null; }
|
public SessionConfig getClientSessionConfig(Destination _dest) { return null; }
|
||||||
public SessionKeyManager getClientSessionKeyManager(Destination _dest) { return null; }
|
public SessionKeyManager getClientSessionKeyManager(Hash _dest) { return null; }
|
||||||
|
|
||||||
public void requestLeaseSet(Hash dest, LeaseSet set) {}
|
public void requestLeaseSet(Hash dest, LeaseSet set) {}
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ import net.i2p.util.Log;
|
|||||||
public class ClientManager {
|
public class ClientManager {
|
||||||
private Log _log;
|
private Log _log;
|
||||||
private ClientListenerRunner _listener;
|
private ClientListenerRunner _listener;
|
||||||
private final HashMap _runners; // Destination --> ClientConnectionRunner
|
private final HashMap<Destination, ClientConnectionRunner> _runners; // Destination --> ClientConnectionRunner
|
||||||
private final Set _pendingRunners; // ClientConnectionRunner for clients w/out a Dest yet
|
private final Set<ClientConnectionRunner> _pendingRunners; // ClientConnectionRunner for clients w/out a Dest yet
|
||||||
private RouterContext _ctx;
|
private RouterContext _ctx;
|
||||||
|
|
||||||
/** ms to wait before rechecking for inbound messages to deliver to clients */
|
/** ms to wait before rechecking for inbound messages to deliver to clients */
|
||||||
@ -90,21 +90,21 @@ public class ClientManager {
|
|||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
_log.info("Shutting down the ClientManager");
|
_log.info("Shutting down the ClientManager");
|
||||||
_listener.stopListening();
|
_listener.stopListening();
|
||||||
Set runners = new HashSet();
|
Set<ClientConnectionRunner> runners = new HashSet();
|
||||||
synchronized (_runners) {
|
synchronized (_runners) {
|
||||||
for (Iterator iter = _runners.values().iterator(); iter.hasNext();) {
|
for (Iterator<ClientConnectionRunner> iter = _runners.values().iterator(); iter.hasNext();) {
|
||||||
ClientConnectionRunner runner = (ClientConnectionRunner)iter.next();
|
ClientConnectionRunner runner = iter.next();
|
||||||
runners.add(runner);
|
runners.add(runner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
synchronized (_pendingRunners) {
|
synchronized (_pendingRunners) {
|
||||||
for (Iterator iter = _pendingRunners.iterator(); iter.hasNext();) {
|
for (Iterator<ClientConnectionRunner> iter = _pendingRunners.iterator(); iter.hasNext();) {
|
||||||
ClientConnectionRunner runner = (ClientConnectionRunner)iter.next();
|
ClientConnectionRunner runner = iter.next();
|
||||||
runners.add(runner);
|
runners.add(runner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Iterator iter = runners.iterator(); iter.hasNext(); ) {
|
for (Iterator<ClientConnectionRunner> iter = runners.iterator(); iter.hasNext(); ) {
|
||||||
ClientConnectionRunner runner = (ClientConnectionRunner)iter.next();
|
ClientConnectionRunner runner = iter.next();
|
||||||
runner.stopRunning();
|
runner.stopRunning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,15 +131,26 @@ public class ClientManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add to the clients list. Check for a dup destination.
|
||||||
|
*/
|
||||||
public void destinationEstablished(ClientConnectionRunner runner) {
|
public void destinationEstablished(ClientConnectionRunner runner) {
|
||||||
|
Destination dest = runner.getConfig().getDestination();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("DestinationEstablished called for destination " + runner.getConfig().getDestination().calculateHash().toBase64());
|
_log.debug("DestinationEstablished called for destination " + dest.calculateHash().toBase64());
|
||||||
|
|
||||||
synchronized (_pendingRunners) {
|
synchronized (_pendingRunners) {
|
||||||
_pendingRunners.remove(runner);
|
_pendingRunners.remove(runner);
|
||||||
}
|
}
|
||||||
|
boolean fail = false;
|
||||||
synchronized (_runners) {
|
synchronized (_runners) {
|
||||||
_runners.put(runner.getConfig().getDestination(), runner);
|
fail = _runners.containsKey(dest);
|
||||||
|
if (!fail)
|
||||||
|
_runners.put(dest, runner);
|
||||||
|
}
|
||||||
|
if (fail) {
|
||||||
|
_log.log(Log.CRIT, "Client attempted to register duplicate destination " + dest.calculateHash().toBase64());
|
||||||
|
runner.disconnectClient("Duplicate destination");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,8 +289,8 @@ public class ClientManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set listClients() {
|
public Set<Destination> listClients() {
|
||||||
Set rv = new HashSet();
|
Set<Destination> rv = new HashSet();
|
||||||
synchronized (_runners) {
|
synchronized (_runners) {
|
||||||
rv.addAll(_runners.keySet());
|
rv.addAll(_runners.keySet());
|
||||||
}
|
}
|
||||||
@ -293,7 +304,7 @@ public class ClientManager {
|
|||||||
long inLock = 0;
|
long inLock = 0;
|
||||||
synchronized (_runners) {
|
synchronized (_runners) {
|
||||||
inLock = _ctx.clock().now();
|
inLock = _ctx.clock().now();
|
||||||
rv = (ClientConnectionRunner)_runners.get(dest);
|
rv = _runners.get(dest);
|
||||||
}
|
}
|
||||||
long afterLock = _ctx.clock().now();
|
long afterLock = _ctx.clock().now();
|
||||||
if (afterLock - beforeLock > 50) {
|
if (afterLock - beforeLock > 50) {
|
||||||
@ -317,9 +328,10 @@ public class ClientManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the client's SessionKeyManager
|
* Return the client's SessionKeyManager
|
||||||
*
|
* Use this instead of the RouterContext.sessionKeyManager()
|
||||||
|
* to prevent correlation attacks across destinations
|
||||||
*/
|
*/
|
||||||
public SessionKeyManager getClientSessionKeyManager(Destination dest) {
|
public SessionKeyManager getClientSessionKeyManager(Hash dest) {
|
||||||
ClientConnectionRunner runner = getRunner(dest);
|
ClientConnectionRunner runner = getRunner(dest);
|
||||||
if (runner != null)
|
if (runner != null)
|
||||||
return runner.getSessionKeyManager();
|
return runner.getSessionKeyManager();
|
||||||
@ -331,8 +343,8 @@ public class ClientManager {
|
|||||||
if (destHash == null)
|
if (destHash == null)
|
||||||
return null;
|
return null;
|
||||||
synchronized (_runners) {
|
synchronized (_runners) {
|
||||||
for (Iterator iter = _runners.values().iterator(); iter.hasNext(); ) {
|
for (Iterator<ClientConnectionRunner> iter = _runners.values().iterator(); iter.hasNext(); ) {
|
||||||
ClientConnectionRunner cur = (ClientConnectionRunner)iter.next();
|
ClientConnectionRunner cur = iter.next();
|
||||||
if (cur.getDestHash().equals(destHash))
|
if (cur.getDestHash().equals(destHash))
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
@ -354,8 +366,8 @@ public class ClientManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set getRunnerDestinations() {
|
Set<Destination> getRunnerDestinations() {
|
||||||
Set dests = new HashSet();
|
Set<Destination> dests = new HashSet();
|
||||||
long beforeLock = _ctx.clock().now();
|
long beforeLock = _ctx.clock().now();
|
||||||
long inLock = 0;
|
long inLock = 0;
|
||||||
synchronized (_runners) {
|
synchronized (_runners) {
|
||||||
@ -390,13 +402,13 @@ public class ClientManager {
|
|||||||
StringBuilder buf = new StringBuilder(8*1024);
|
StringBuilder buf = new StringBuilder(8*1024);
|
||||||
buf.append("<u><b>Local destinations</b></u><br>");
|
buf.append("<u><b>Local destinations</b></u><br>");
|
||||||
|
|
||||||
Map runners = null;
|
Map<Destination, ClientConnectionRunner> runners = null;
|
||||||
synchronized (_runners) {
|
synchronized (_runners) {
|
||||||
runners = (Map)_runners.clone();
|
runners = (Map)_runners.clone();
|
||||||
}
|
}
|
||||||
for (Iterator iter = runners.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator<Destination> iter = runners.keySet().iterator(); iter.hasNext(); ) {
|
||||||
Destination dest = (Destination)iter.next();
|
Destination dest = iter.next();
|
||||||
ClientConnectionRunner runner = (ClientConnectionRunner)runners.get(dest);
|
ClientConnectionRunner runner = runners.get(dest);
|
||||||
buf.append("<b>*</b> ").append(dest.calculateHash().toBase64().substring(0,6)).append("<br>\n");
|
buf.append("<b>*</b> ").append(dest.calculateHash().toBase64().substring(0,6)).append("<br>\n");
|
||||||
LeaseSet ls = runner.getLeaseSet();
|
LeaseSet ls = runner.getLeaseSet();
|
||||||
if (ls == null) {
|
if (ls == null) {
|
||||||
|
@ -194,7 +194,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade {
|
|||||||
* Return the client's current manager or null if not connected
|
* Return the client's current manager or null if not connected
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public SessionKeyManager getClientSessionKeyManager(Destination dest) {
|
public SessionKeyManager getClientSessionKeyManager(Hash dest) {
|
||||||
if (_manager != null)
|
if (_manager != null)
|
||||||
return _manager.getClientSessionKeyManager(dest);
|
return _manager.getClientSessionKeyManager(dest);
|
||||||
else {
|
else {
|
||||||
@ -215,7 +215,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade {
|
|||||||
* @return set of Destination objects
|
* @return set of Destination objects
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set listClients() {
|
public Set<Destination> listClients() {
|
||||||
if (_manager != null)
|
if (_manager != null)
|
||||||
return _manager.listClients();
|
return _manager.listClients();
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user