forked from I2P_Developers/i2p.i2p
added some stats (viewable on the router stat page when the i2ptunnel is run in the router's VM)
lots of logging
This commit is contained in:
@ -15,6 +15,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
import net.i2p.client.I2PSessionException;
|
import net.i2p.client.I2PSessionException;
|
||||||
@ -22,8 +23,10 @@ import net.i2p.client.I2PSessionListener;
|
|||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.DataFormatException;
|
import net.i2p.data.DataFormatException;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
|
import net.i2p.stat.StatManager;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Centralize the coordination and multiplexing of the local client's streaming.
|
* Centralize the coordination and multiplexing of the local client's streaming.
|
||||||
* There should be one I2PSocketManager for each I2PSession, and if an application
|
* There should be one I2PSocketManager for each I2PSession, and if an application
|
||||||
@ -33,7 +36,8 @@ import net.i2p.util.Log;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class I2PSocketManager implements I2PSessionListener {
|
public class I2PSocketManager implements I2PSessionListener {
|
||||||
private final static Log _log = new Log(I2PSocketManager.class);
|
private I2PAppContext _context;
|
||||||
|
private Log _log;
|
||||||
private I2PSession _session;
|
private I2PSession _session;
|
||||||
private I2PServerSocketImpl _serverSocket = null;
|
private I2PServerSocketImpl _serverSocket = null;
|
||||||
private Object lock = new Object(); // for locking socket lists
|
private Object lock = new Object(); // for locking socket lists
|
||||||
@ -41,6 +45,8 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
private HashMap _inSockets;
|
private HashMap _inSockets;
|
||||||
private I2PSocketOptions _defaultOptions;
|
private I2PSocketOptions _defaultOptions;
|
||||||
private long _acceptTimeout;
|
private long _acceptTimeout;
|
||||||
|
private String _name;
|
||||||
|
private static int __managerId = 0;
|
||||||
|
|
||||||
public static final short ACK = 0x51;
|
public static final short ACK = 0x51;
|
||||||
public static final short CLOSE_OUT = 0x52;
|
public static final short CLOSE_OUT = 0x52;
|
||||||
@ -57,10 +63,24 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
private static final long ACCEPT_TIMEOUT_DEFAULT = 5*1000;
|
private static final long ACCEPT_TIMEOUT_DEFAULT = 5*1000;
|
||||||
|
|
||||||
public I2PSocketManager() {
|
public I2PSocketManager() {
|
||||||
|
this("SocketManager " + (++__managerId));
|
||||||
|
}
|
||||||
|
public I2PSocketManager(String name) {
|
||||||
|
_name = name;
|
||||||
_session = null;
|
_session = null;
|
||||||
_inSockets = new HashMap(16);
|
_inSockets = new HashMap(16);
|
||||||
_outSockets = new HashMap(16);
|
_outSockets = new HashMap(16);
|
||||||
_acceptTimeout = ACCEPT_TIMEOUT_DEFAULT;
|
_acceptTimeout = ACCEPT_TIMEOUT_DEFAULT;
|
||||||
|
_context = I2PAppContext.getGlobalContext();
|
||||||
|
_log = _context.logManager().getLog(I2PSocketManager.class);
|
||||||
|
_context.statManager().createRateStat("streaming.lifetime", "How long before the socket is closed?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
|
_context.statManager().createRateStat("streaming.sent", "How many bytes are sent in the stream?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
|
_context.statManager().createRateStat("streaming.received", "How many bytes are received in the stream?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
|
_context.statManager().createRateStat("streaming.transferBalance", "How many streams send more than they receive (positive means more sent, negative means more received)?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
|
_context.statManager().createRateStat("streaming.synNoAck", "How many times have we sent a SYN but not received an ACK?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
|
_context.statManager().createRateStat("streaming.ackSendFailed", "How many times have we tried to send an ACK to a SYN and failed?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
|
_context.statManager().createRateStat("streaming.nackSent", "How many times have we refused a SYN with a NACK?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
|
_context.statManager().createRateStat("streaming.nackReceived", "How many times have we received a NACK to our SYN?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||||
}
|
}
|
||||||
|
|
||||||
public I2PSession getSession() {
|
public I2PSession getSession() {
|
||||||
@ -82,12 +102,12 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
public long getAcceptTimeout() { return _acceptTimeout; }
|
public long getAcceptTimeout() { return _acceptTimeout; }
|
||||||
|
|
||||||
public void disconnected(I2PSession session) {
|
public void disconnected(I2PSession session) {
|
||||||
_log.info("Disconnected from the session");
|
_log.info(getName() + ": Disconnected from the session");
|
||||||
destroySocketManager();
|
destroySocketManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void errorOccurred(I2PSession session, String message, Throwable error) {
|
public void errorOccurred(I2PSession session, String message, Throwable error) {
|
||||||
_log.error("Error occurred: [" + message + "]", error);
|
_log.error(getName() + ": Error occurred: [" + message + "]", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void messageAvailable(I2PSession session, int msgId, long size) {
|
public void messageAvailable(I2PSession session, int msgId, long size) {
|
||||||
@ -95,11 +115,11 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
I2PSocketImpl s;
|
I2PSocketImpl s;
|
||||||
byte msg[] = session.receiveMessage(msgId);
|
byte msg[] = session.receiveMessage(msgId);
|
||||||
if (msg.length == 1 && msg[0] == -1) {
|
if (msg.length == 1 && msg[0] == -1) {
|
||||||
_log.debug("Ping received");
|
_log.debug(getName() + ": Ping received");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg.length < 4) {
|
if (msg.length < 4) {
|
||||||
_log.error("==== packet too short ====");
|
_log.error(getName() + ": ==== packet too short ====");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int type = msg[0] & 0xff;
|
int type = msg[0] & 0xff;
|
||||||
@ -107,7 +127,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
byte[] payload = new byte[msg.length - 4];
|
byte[] payload = new byte[msg.length - 4];
|
||||||
System.arraycopy(msg, 4, payload, 0, payload.length);
|
System.arraycopy(msg, 4, payload, 0, payload.length);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Message read: type = [" + Integer.toHexString(type)
|
_log.debug(getName() + ": Message read: type = [" + Integer.toHexString(type)
|
||||||
+ "] id = [" + getReadableForm(id)
|
+ "] id = [" + getReadableForm(id)
|
||||||
+ "] payload length: [" + payload.length + "]");
|
+ "] payload length: [" + payload.length + "]");
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -136,9 +156,9 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (I2PException ise) {
|
} catch (I2PException ise) {
|
||||||
_log.error("Error processing", ise);
|
_log.error(getName() + ": Error processing", ise);
|
||||||
} catch (IllegalStateException ise) {
|
} catch (IllegalStateException ise) {
|
||||||
_log.debug("Error processing", ise);
|
_log.debug(getName() + ": Error processing", ise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,30 +170,45 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private void ackAvailable(String id, byte payload[]) {
|
private void ackAvailable(String id, byte payload[]) {
|
||||||
|
long begin = _context.clock().now();
|
||||||
I2PSocketImpl s = null;
|
I2PSocketImpl s = null;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
s = (I2PSocketImpl) _outSockets.get(id);
|
s = (I2PSocketImpl) _outSockets.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
_log.warn("No socket responsible for ACK packet");
|
_log.warn(getName() + ": No socket responsible for ACK packet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long socketRetrieved = _context.clock().now();
|
||||||
|
|
||||||
String remoteId = null;
|
String remoteId = null;
|
||||||
remoteId = s.getRemoteID(false);
|
remoteId = s.getRemoteID(false);
|
||||||
|
|
||||||
if ( (payload.length == 3) && (remoteId == null) ) {
|
if ( (payload.length == 3) && (remoteId == null) ) {
|
||||||
String newID = toString(payload);
|
String newID = toString(payload);
|
||||||
|
long beforeSetRemId = _context.clock().now();
|
||||||
s.setRemoteID(newID);
|
s.setRemoteID(newID);
|
||||||
|
if (_log.shouldLog(Log.DEBUG)) {
|
||||||
|
_log.debug(getName() + ": ackAvailable - socket retrieval took "
|
||||||
|
+ (socketRetrieved-begin) + "ms, getRemoteId took "
|
||||||
|
+ (beforeSetRemId-socketRetrieved) + "ms, setRemoteId took "
|
||||||
|
+ (_context.clock().now()-beforeSetRemId) + "ms");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// (payload.length != 3 || getRemoteId != null)
|
// (payload.length != 3 || getRemoteId != null)
|
||||||
if (_log.shouldLog(Log.WARN)) {
|
if (_log.shouldLog(Log.WARN)) {
|
||||||
if (payload.length != 3)
|
if (payload.length != 3)
|
||||||
_log.warn("Ack packet had " + payload.length + " bytes");
|
_log.warn(getName() + ": Ack packet had " + payload.length + " bytes");
|
||||||
else
|
else
|
||||||
_log.warn("Remote ID already exists? " + remoteId);
|
_log.warn(getName() + ": Remote ID already exists? " + remoteId);
|
||||||
|
}
|
||||||
|
if (_log.shouldLog(Log.DEBUG)) {
|
||||||
|
_log.debug(getName() + ": invalid ack - socket retrieval took "
|
||||||
|
+ (socketRetrieved-begin) + "ms, overall took "
|
||||||
|
+ (_context.clock().now()-begin) + "ms");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -189,11 +224,11 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
s = (I2PSocketImpl) _outSockets.get(id);
|
s = (I2PSocketImpl) _outSockets.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.debug("*Disconnect outgoing for socket " + s);
|
_log.debug(getName() + ": *Disconnect outgoing for socket " + s);
|
||||||
try {
|
try {
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
if (payload.length > 0) {
|
if (payload.length > 0) {
|
||||||
_log.debug("Disconnect packet had "
|
_log.debug(getName() + ": Disconnect packet had "
|
||||||
+ payload.length + " bytes");
|
+ payload.length + " bytes");
|
||||||
}
|
}
|
||||||
if (s.getRemoteID(false) == null) {
|
if (s.getRemoteID(false) == null) {
|
||||||
@ -207,7 +242,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} catch (Exception t) {
|
} catch (Exception t) {
|
||||||
_log.error("Ignoring error on disconnect for socket " + s, t);
|
_log.error(getName() + ": Ignoring error on disconnect for socket " + s, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,12 +260,12 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
|
|
||||||
// packet send outgoing
|
// packet send outgoing
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("*Packet send outgoing [" + payload.length + "] for socket " + s);
|
_log.debug(getName() + ": *Packet send outgoing [" + payload.length + "] for socket " + s);
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
s.queueData(payload);
|
s.queueData(payload);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
_log.error("Null socket with data available");
|
_log.error(getName() + ": Null socket with data available");
|
||||||
throw new IllegalStateException("Null socket with data available");
|
throw new IllegalStateException("Null socket with data available");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,7 +293,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
s.setRemoteID(id);
|
s.setRemoteID(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_log.debug("*Syn! for socket " + s);
|
_log.debug(getName() + ": *Syn! for socket " + s);
|
||||||
|
|
||||||
if (!acceptConnections) {
|
if (!acceptConnections) {
|
||||||
// The app did not instantiate an I2PServerSocket
|
// The app did not instantiate an I2PServerSocket
|
||||||
@ -268,10 +303,11 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
replySentOk = _session.sendMessage(d, packet);
|
replySentOk = _session.sendMessage(d, packet);
|
||||||
}
|
}
|
||||||
if (!replySentOk) {
|
if (!replySentOk) {
|
||||||
_log.error("Error sending close to " + d.calculateHash().toBase64()
|
_log.error(getName() + ": Error sending close to " + d.calculateHash().toBase64()
|
||||||
+ " in response to a new con message",
|
+ " in response to a new con message",
|
||||||
new Exception("Failed creation"));
|
new Exception("Failed creation"));
|
||||||
}
|
}
|
||||||
|
_context.statManager().addRateData("streaming.nackSent", 1, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,10 +318,11 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
replySentOk = _session.sendMessage(d, packet);
|
replySentOk = _session.sendMessage(d, packet);
|
||||||
if (!replySentOk) {
|
if (!replySentOk) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Error sending reply to " + d.calculateHash().toBase64()
|
_log.warn(getName() + ": Error sending reply to " + d.calculateHash().toBase64()
|
||||||
+ " in response to a new con message for socket " + s,
|
+ " in response to a new con message for socket " + s,
|
||||||
new Exception("Failed creation"));
|
new Exception("Failed creation"));
|
||||||
s.internalClose();
|
s.internalClose();
|
||||||
|
_context.statManager().addRateData("streaming.ackSendFailed", 1, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// timed out or serverSocket closed
|
// timed out or serverSocket closed
|
||||||
@ -293,9 +330,10 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
packet[0] = CLOSE_OUT;
|
packet[0] = CLOSE_OUT;
|
||||||
boolean nackSent = session.sendMessage(d, packet);
|
boolean nackSent = session.sendMessage(d, packet);
|
||||||
if (!nackSent) {
|
if (!nackSent) {
|
||||||
_log.warn("Error sending NACK for session creation for socket " + s);
|
_log.warn(getName() + ": Error sending NACK for session creation for socket " + s);
|
||||||
}
|
}
|
||||||
s.internalClose();
|
s.internalClose();
|
||||||
|
_context.statManager().addRateData("streaming,nackSent", 1, 1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -314,7 +352,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.debug("*Disconnect incoming for socket " + s);
|
_log.debug(getName() + ": *Disconnect incoming for socket " + s);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (payload.length == 0 && s != null) {
|
if (payload.length == 0 && s != null) {
|
||||||
@ -322,13 +360,13 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if ( (payload.length > 0) && (_log.shouldLog(Log.ERROR)) )
|
if ( (payload.length > 0) && (_log.shouldLog(Log.ERROR)) )
|
||||||
_log.error("Disconnect packet had " + payload.length + " bytes");
|
_log.error(getName() + ": Disconnect packet had " + payload.length + " bytes");
|
||||||
if (s != null)
|
if (s != null)
|
||||||
s.internalClose();
|
s.internalClose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception t) {
|
} catch (Exception t) {
|
||||||
_log.error("Ignoring error on disconnect", t);
|
_log.error(getName() + ": Ignoring error on disconnect", t);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,13 +384,13 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("*Packet send incoming [" + payload.length + "] for socket " + s);
|
_log.debug(getName() + ": *Packet send incoming [" + payload.length + "] for socket " + s);
|
||||||
|
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
s.queueData(payload);
|
s.queueData(payload);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
_log.info("Null socket with data available");
|
_log.info(getName() + ": Null socket with data available");
|
||||||
throw new IllegalStateException("Null socket with data available");
|
throw new IllegalStateException("Null socket with data available");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,7 +400,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private void handleUnknown(int type, String id, byte payload[]) {
|
private void handleUnknown(int type, String id, byte payload[]) {
|
||||||
_log.error("\n\n=============== Unknown packet! " + "============"
|
_log.error(getName() + ": \n\n=============== Unknown packet! " + "============"
|
||||||
+ "\nType: " + (int) type
|
+ "\nType: " + (int) type
|
||||||
+ "\nID: " + getReadableForm(id)
|
+ "\nID: " + getReadableForm(id)
|
||||||
+ "\nBase64'ed Data: " + Base64.encode(payload)
|
+ "\nBase64'ed Data: " + Base64.encode(payload)
|
||||||
@ -376,7 +414,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void reportAbuse(I2PSession session, int severity) {
|
public void reportAbuse(I2PSession session, int severity) {
|
||||||
_log.error("Abuse reported [" + severity + "]");
|
_log.error(getName() + ": Abuse reported [" + severity + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultOptions(I2PSocketOptions options) {
|
public void setDefaultOptions(I2PSocketOptions options) {
|
||||||
@ -424,31 +462,37 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
boolean sent = false;
|
boolean sent = false;
|
||||||
sent = _session.sendMessage(peer, packet);
|
sent = _session.sendMessage(peer, packet);
|
||||||
if (!sent) {
|
if (!sent) {
|
||||||
_log.info("Unable to send & receive ack for SYN packet for socket " + s);
|
_log.info(getName() + ": Unable to send & receive ack for SYN packet for socket " + s);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
_outSockets.remove(s.getLocalID());
|
_outSockets.remove(s.getLocalID());
|
||||||
}
|
}
|
||||||
|
_context.statManager().addRateData("streaming.synNoAck", 1, 1);
|
||||||
throw new I2PException("Error sending through I2P network");
|
throw new I2PException("Error sending through I2P network");
|
||||||
}
|
}
|
||||||
remoteID = s.getRemoteID(true, options.getConnectTimeout());
|
remoteID = s.getRemoteID(true, options.getConnectTimeout());
|
||||||
|
|
||||||
if (remoteID == null)
|
if (remoteID == null) {
|
||||||
|
_context.statManager().addRateData("streaming.nackReceived", 1, 1);
|
||||||
throw new ConnectException("Connection refused by peer for socket " + s);
|
throw new ConnectException("Connection refused by peer for socket " + s);
|
||||||
if ("".equals(remoteID))
|
}
|
||||||
|
if ("".equals(remoteID)) {
|
||||||
|
_context.statManager().addRateData("streaming.synNoAck", 1, 1);
|
||||||
throw new NoRouteToHostException("Unable to reach peer for socket " + s);
|
throw new NoRouteToHostException("Unable to reach peer for socket " + s);
|
||||||
|
}
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("TIMING: s given out for remoteID "
|
_log.debug(getName() + ": TIMING: s given out for remoteID "
|
||||||
+ getReadableForm(remoteID) + " for socket " + s);
|
+ getReadableForm(remoteID) + " for socket " + s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
} catch (InterruptedIOException ioe) {
|
} catch (InterruptedIOException ioe) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Timeout waiting for ack from syn for id "
|
_log.error(getName() + ": Timeout waiting for ack from syn for id "
|
||||||
+ getReadableForm(lcID) + " for socket " + s, ioe);
|
+ getReadableForm(lcID) + " for socket " + s, ioe);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
_outSockets.remove(s.getLocalID());
|
_outSockets.remove(s.getLocalID());
|
||||||
}
|
}
|
||||||
s.internalClose();
|
s.internalClose();
|
||||||
|
_context.statManager().addRateData("streaming.synNoAck", 1, 1);
|
||||||
throw new InterruptedIOException("Timeout waiting for ack");
|
throw new InterruptedIOException("Timeout waiting for ack");
|
||||||
} catch (ConnectException ex) {
|
} catch (ConnectException ex) {
|
||||||
s.internalClose();
|
s.internalClose();
|
||||||
@ -458,7 +502,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
throw ex;
|
throw ex;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
|
_log.error(getName() + ": Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
_outSockets.remove(s.getLocalID());
|
_outSockets.remove(s.getLocalID());
|
||||||
}
|
}
|
||||||
@ -466,7 +510,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
throw new I2PException("Unhandled IOException occurred");
|
throw new I2PException("Unhandled IOException occurred");
|
||||||
} catch (I2PException ex) {
|
} catch (I2PException ex) {
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
|
_log.info(getName() + ": Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
_outSockets.remove(s.getLocalID());
|
_outSockets.remove(s.getLocalID());
|
||||||
}
|
}
|
||||||
@ -474,7 +518,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
throw ex;
|
throw ex;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
s.internalClose();
|
s.internalClose();
|
||||||
_log.error("Unhandled error connecting", e);
|
_log.error(getName() + ": Unhandled error connecting", e);
|
||||||
throw new ConnectException("Unhandled error connecting: " + e.getMessage());
|
throw new ConnectException("Unhandled error connecting: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -515,7 +559,7 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
id = (String)iter.next();
|
id = (String)iter.next();
|
||||||
sock = (I2PSocketImpl)_inSockets.get(id);
|
sock = (I2PSocketImpl)_inSockets.get(id);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Closing inSocket \""
|
_log.debug(getName() + ": Closing inSocket \""
|
||||||
+ getReadableForm(sock.getLocalID()) + "\"");
|
+ getReadableForm(sock.getLocalID()) + "\"");
|
||||||
sock.internalClose();
|
sock.internalClose();
|
||||||
}
|
}
|
||||||
@ -525,13 +569,13 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
id = (String)iter.next();
|
id = (String)iter.next();
|
||||||
sock = (I2PSocketImpl)_outSockets.get(id);
|
sock = (I2PSocketImpl)_outSockets.get(id);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Closing outSocket \""
|
_log.debug(getName() + ": Closing outSocket \""
|
||||||
+ getReadableForm(sock.getLocalID()) + "\"");
|
+ getReadableForm(sock.getLocalID()) + "\"");
|
||||||
sock.internalClose();
|
sock.internalClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_log.debug("Waiting for all open sockets to really close...");
|
_log.debug(getName() + ": Waiting for all open sockets to really close...");
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
while ((_inSockets.size() != 0) || (_outSockets.size() != 0)) {
|
while ((_inSockets.size() != 0) || (_outSockets.size() != 0)) {
|
||||||
try {
|
try {
|
||||||
@ -541,11 +585,11 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_log.debug("Destroying I2P session...");
|
_log.debug(getName() + ": Destroying I2P session...");
|
||||||
_session.destroySession();
|
_session.destroySession();
|
||||||
_log.debug("I2P session destroyed");
|
_log.debug(getName() + ": I2P session destroyed");
|
||||||
} catch (I2PSessionException e) {
|
} catch (I2PSessionException e) {
|
||||||
_log.error("Error destroying I2P session", e);
|
_log.error(getName() + ": Error destroying I2P session", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,21 +615,47 @@ public class I2PSocketManager implements I2PSessionListener {
|
|||||||
try {
|
try {
|
||||||
return _session.sendMessage(peer, new byte[] { (byte) CHAFF});
|
return _session.sendMessage(peer, new byte[] { (byte) CHAFF});
|
||||||
} catch (I2PException ex) {
|
} catch (I2PException ex) {
|
||||||
_log.error("I2PException:", ex);
|
_log.error(getName() + ": I2PException:", ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeSocket(I2PSocketImpl sock) {
|
public void removeSocket(I2PSocketImpl sock) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
|
||||||
_log.debug("Removing socket \"" + getReadableForm(sock.getLocalID()) + "\" [" + sock + "]");
|
|
||||||
_inSockets.remove(sock.getLocalID());
|
_inSockets.remove(sock.getLocalID());
|
||||||
_outSockets.remove(sock.getLocalID());
|
_outSockets.remove(sock.getLocalID());
|
||||||
lock.notify();
|
lock.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long now = _context.clock().now();
|
||||||
|
long lifetime = now - sock.getCreatedOn();
|
||||||
|
long timeSinceClose = now - sock.getClosedOn();
|
||||||
|
long sent = sock.getBytesSent();
|
||||||
|
long recv = sock.getBytesReceived();
|
||||||
|
|
||||||
|
if (_log.shouldLog(Log.DEBUG)) {
|
||||||
|
_log.debug(getName() + ": Removing socket \"" + getReadableForm(sock.getLocalID()) + "\" [" + sock
|
||||||
|
+ ", send: " + sent + ", recv: " + recv
|
||||||
|
+ ", lifetime: " + lifetime + "ms, time since close: " + timeSinceClose + ")]",
|
||||||
|
new Exception("removeSocket called"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.statManager().addRateData("streaming.lifetime", lifetime, lifetime);
|
||||||
|
_context.statManager().addRateData("streaming.sent", sent, lifetime);
|
||||||
|
_context.statManager().addRateData("streaming.received", recv, lifetime);
|
||||||
|
|
||||||
|
if (sent > recv) {
|
||||||
|
_context.statManager().addRateData("streaming.transferBalance", 1, lifetime);
|
||||||
|
} else if (recv > sent) {
|
||||||
|
_context.statManager().addRateData("streaming.transferBalance", -1, lifetime);
|
||||||
|
} else {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() { return _name; }
|
||||||
|
public void setName(String name) { _name = name; }
|
||||||
|
|
||||||
public static String getReadableForm(String id) {
|
public static String getReadableForm(String id) {
|
||||||
if (id == null) return "(null)";
|
if (id == null) return "(null)";
|
||||||
if (id.length() != 3) return "Bogus";
|
if (id.length() != 3) return "Bogus";
|
||||||
|
Reference in New Issue
Block a user