use of net.i2p.client.I2PSession in project i2p.i2p by i2p.
the class PacketQueue method enqueue.
/**
* Add a new packet to be sent out ASAP.
* This updates the acks.
*
* keys and tags disabled since dropped in I2PSession
* @return true if sent
*/
public boolean enqueue(PacketLocal packet) {
if (_dead)
return false;
if (packet.getAckTime() > 0) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Not resending " + packet);
return false;
}
Connection con = packet.getConnection();
if (con != null) {
// this updates the ack/nack fields
con.getInputStream().updateAcks(packet);
}
ByteArray ba = _cache.acquire();
byte[] buf = ba.getData();
long begin = 0;
long end = 0;
boolean sent = false;
try {
int size = 0;
// long beforeWrite = System.currentTimeMillis();
if (packet.shouldSign())
size = packet.writeSignedPacket(buf, 0);
else
size = packet.writePacket(buf, 0);
// last chance to short circuit...
if (packet.getAckTime() > 0)
return false;
// this should not block!
begin = _context.clock().now();
long expires = 0;
Connection.ResendPacketEvent rpe = (Connection.ResendPacketEvent) packet.getResendEvent();
if (rpe != null)
// we want the router to expire it a little before we do,
// so if we retransmit it will use a new tunnel/lease combo
expires = rpe.getNextSendTime() - 500;
SendMessageOptions options = new SendMessageOptions();
if (expires > 0)
options.setDate(expires);
boolean listenForStatus = false;
// FINAL trumps INITIAL, in the case of SYN+CLOSE
if (packet.isFlagSet(FLAGS_FINAL_TAGS)) {
if (packet.isFlagSet(Packet.FLAG_ECHO)) {
// Send LS for PING, not for PONG
if (// pong
packet.getSendStreamId() <= 0)
options.setSendLeaseSet(false);
} else {
options.setSendLeaseSet(false);
}
int sendTags = FINAL_TAGS_TO_SEND;
int tagThresh = FINAL_TAG_THRESHOLD;
if (con != null) {
ConnectionOptions copts = con.getOptions();
int cSendTags = copts.getTagsToSend();
int cTagThresh = copts.getTagThreshold();
if (cSendTags < sendTags)
sendTags = cSendTags;
if (cTagThresh < tagThresh)
tagThresh = cTagThresh;
}
options.setTagsToSend(sendTags);
options.setTagThreshold(tagThresh);
} else if (packet.isFlagSet(FLAGS_INITIAL_TAGS)) {
if (con != null) {
if (con.isInbound())
options.setSendLeaseSet(false);
else if (ENABLE_STATUS_LISTEN)
listenForStatus = true;
}
int sendTags = INITIAL_TAGS_TO_SEND;
int tagThresh = MIN_TAG_THRESHOLD;
if (con != null) {
ConnectionOptions copts = con.getOptions();
int cSendTags = copts.getTagsToSend();
int cTagThresh = copts.getTagThreshold();
if (cSendTags < sendTags)
sendTags = cSendTags;
if (cTagThresh < tagThresh)
tagThresh = cTagThresh;
}
options.setTagsToSend(sendTags);
options.setTagThreshold(tagThresh);
} else {
if (con != null) {
if (con.isInbound() && con.getLifetime() < 2 * 60 * 1000)
options.setSendLeaseSet(false);
// increase threshold with higher window sizes to prevent stalls
// after tag delivery failure
ConnectionOptions copts = con.getOptions();
int wdw = copts.getWindowSize();
int thresh = Math.max(MIN_TAG_THRESHOLD, wdw * TAG_WINDOW_FACTOR);
int cTagThresh = copts.getTagThreshold();
if (cTagThresh < thresh)
thresh = cTagThresh;
options.setTagThreshold(thresh);
}
}
I2PSession session = packet.getSession();
if (listenForStatus) {
long id = session.sendMessage(packet.getTo(), buf, 0, size, I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort(), options, this);
_messageStatusMap.put(Long.valueOf(id), con);
sent = true;
} else {
sent = session.sendMessage(packet.getTo(), buf, 0, size, I2PSession.PROTO_STREAMING, packet.getLocalPort(), packet.getRemotePort(), options);
}
end = _context.clock().now();
if ((end - begin > 1000) && (_log.shouldLog(Log.WARN)))
_log.warn("Took " + (end - begin) + "ms to sendMessage(...) " + packet);
_context.statManager().addRateData("stream.con.sendMessageSize", size, packet.getLifetime());
if (packet.getNumSends() > 1)
_context.statManager().addRateData("stream.con.sendDuplicateSize", size, packet.getLifetime());
if (con != null) {
con.incrementBytesSent(size);
if (packet.getNumSends() > 1)
con.incrementDupMessagesSent(1);
}
} catch (I2PSessionException ise) {
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to send the packet " + packet, ise);
}
_cache.release(ba);
if (!sent) {
if (_log.shouldLog(Log.WARN))
_log.warn("Send failed for " + packet);
if (// handle race on b0rk
con != null)
con.disconnect(false);
} else {
// packet.setKeyUsed(keyUsed);
// packet.setTagsSent(tagsSent);
packet.incrementSends();
if (con != null && _log.shouldDebug()) {
String suffix = "wsize " + con.getOptions().getWindowSize() + " rto " + con.getOptions().getRTO();
con.getConnectionManager().getPacketHandler().displayPacket(packet, "SEND", suffix);
}
if (I2PSocketManagerFull.pcapWriter != null && _context.getBooleanProperty(I2PSocketManagerFull.PROP_PCAP))
packet.logTCPDump();
}
if ((packet.getSequenceNum() == 0) && (!packet.isFlagSet(Packet.FLAG_SYNCHRONIZE))) {
// ack only, so release it asap
packet.releasePayload();
} else if (packet.isFlagSet(Packet.FLAG_ECHO) && !packet.isFlagSet(Packet.FLAG_SIGNATURE_INCLUDED)) {
// pong
packet.releasePayload();
} else if (packet.isFlagSet(Packet.FLAG_RESET)) {
// reset
packet.releasePayload();
}
return sent;
}
use of net.i2p.client.I2PSession in project i2p.i2p by i2p.
the class PingIT method test.
@Test
public void test() throws Exception {
I2PAppContext context = I2PAppContext.getGlobalContext();
I2PSession session = createSession();
ConnectionManager mgr = new ConnectionManager(context, session, new ConnectionOptions());
for (int i = 0; i < 10; i++) {
boolean ponged = mgr.ping(session.getMyDestination(), 2 * 1000);
assertTrue(ponged);
}
}
use of net.i2p.client.I2PSession in project i2p.i2p by i2p.
the class I2PTunnel method destFromName.
/**
* @param i2cpHost may be null
* @param i2cpPort may be null
* @param user may be null
* @param pw may be null
* @since 0.9.11
*/
private static Destination destFromName(String name, String i2cpHost, String i2cpPort, boolean isSSL, String user, String pw) throws DataFormatException {
if ((name == null) || (name.trim().length() <= 0))
throw new DataFormatException("Empty destination provided");
I2PAppContext ctx = I2PAppContext.getGlobalContext();
Log log = ctx.logManager().getLog(I2PTunnel.class);
if (name.startsWith("file:")) {
Destination result = new Destination();
byte[] content = null;
FileInputStream in = null;
try {
in = new FileInputStream(name.substring("file:".length()));
byte[] buf = new byte[1024];
int read = DataHelper.read(in, buf);
content = new byte[read];
System.arraycopy(buf, 0, content, 0, read);
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
return null;
} finally {
if (in != null)
try {
in.close();
} catch (IOException io) {
}
}
try {
result.fromByteArray(content);
return result;
} catch (RuntimeException ex) {
if (log.shouldLog(Log.INFO))
log.info("File is not a binary destination - trying base64");
try {
byte[] decoded = Base64.decode(new String(content));
result.fromByteArray(decoded);
return result;
} catch (DataFormatException dfe) {
if (log.shouldLog(Log.WARN))
log.warn("File is not a base64 destination either - failing!");
return null;
}
}
} else {
// ask naming service
name = name.trim();
NamingService inst = ctx.namingService();
boolean b32 = name.length() == 60 && name.toLowerCase(Locale.US).endsWith(".b32.i2p");
Destination d = null;
if (ctx.isRouterContext() || !b32) {
// Local lookup.
// Even though we could do b32 outside router ctx here,
// we do it below instead so we can set the host and port,
// which we can't do with lookup()
d = inst.lookup(name);
if (d != null || ctx.isRouterContext() || name.length() >= 516)
return d;
}
// Outside router context only,
// try simple session to ask the router.
I2PClient client = new I2PSimpleClient();
Properties opts = new Properties();
if (i2cpHost != null)
opts.put(I2PClient.PROP_TCP_HOST, i2cpHost);
if (i2cpPort != null)
opts.put(I2PClient.PROP_TCP_PORT, i2cpPort);
opts.put("i2cp.SSL", Boolean.toString(isSSL));
if (user != null)
opts.put("i2cp.username", user);
if (pw != null)
opts.put("i2cp.password", pw);
I2PSession session = null;
try {
session = client.createSession(null, opts);
session.connect();
d = session.lookupDest(name);
} catch (I2PSessionException ise) {
if (log.shouldLog(Log.WARN))
log.warn("Lookup via router failed", ise);
} finally {
if (session != null) {
try {
session.destroySession();
} catch (I2PSessionException ise) {
}
}
}
return d;
}
}
use of net.i2p.client.I2PSession in project i2p.i2p by i2p.
the class I2PTunnelClientBase method getSocketManager.
/**
* This is ONLY for shared clients.
* As of 0.9.20 this is fast, and does NOT connect the manager to the router.
* Call verifySocketManager() for that.
*
* @return non-null
* @throws IllegalArgumentException if the I2CP configuration is b0rked so
* badly that we cant create a socketManager
*/
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
// shadows instance _log
Log _log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
if (socketManager != null && !socketManager.isDestroyed()) {
I2PSession s = socketManager.getSession();
if (s.isClosed() && _socketManagerState != SocketManagerState.INIT) {
if (_log.shouldLog(Log.INFO))
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since the old one closed [s=" + s + "]");
tunnel.removeSession(s);
// make sure the old one is closed
socketManager.destroySocketManager();
_socketManagerState = SocketManagerState.INIT;
// We could be here a LONG time, holding the lock
socketManager = buildSocketManager(tunnel, pkf);
// FIXME may not be the right place for this
I2PSession sub = addSubsession(tunnel);
if (sub != null && _log.shouldLog(Log.WARN))
_log.warn("Added subsession " + sub);
} else {
if (_log.shouldLog(Log.INFO))
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Not building a new socket manager since the old one is open [s=" + s + "]");
// If some other tunnel created the session, we need to add it
// as our session too.
// It's a Set in I2PTunnel
tunnel.addSession(s);
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since there is no other one");
socketManager = buildSocketManager(tunnel, pkf);
I2PSession sub = addSubsession(tunnel);
if (sub != null && _log.shouldLog(Log.WARN))
_log.warn("Added subsession " + sub);
}
return socketManager;
}
use of net.i2p.client.I2PSession in project i2p.i2p by i2p.
the class I2PTunnelClientBase method addSubsession.
/**
* Add a DSA_SHA1 subsession to the shared client if necessary.
*
* @return subsession, or null if none was added
* @since 0.9.20
*/
protected static synchronized I2PSession addSubsession(I2PTunnel tunnel) {
I2PSession sess = socketManager.getSession();
if (sess.getMyDestination().getSigType() == SigType.DSA_SHA1)
return null;
Properties props = new Properties();
props.putAll(tunnel.getClientOptions());
String name = props.getProperty("inbound.nickname");
if (name != null)
props.setProperty("inbound.nickname", name + " (DSA)");
name = props.getProperty("outbound.nickname");
if (name != null)
props.setProperty("outbound.nickname", name + " (DSA)");
props.setProperty(I2PClient.PROP_SIGTYPE, "DSA_SHA1");
try {
return socketManager.addSubsession(null, props);
} catch (I2PSessionException ise) {
Log log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
if (log.shouldLog(Log.WARN))
log.warn("Failed to add subssession", ise);
return null;
}
}
Aggregations