use of net.i2p.client.SendMessageOptions in project i2p.i2p by i2p.
the class SAMMessageSession method sendBytesThroughMessageSession.
/**
* Actually send bytes through the SAM message-based session I2PSession,
* using per-message extended options.
* For efficiency, use the method without all the extra options if they are all defaults.
*
* @param dest Destination
* @param data Bytes to be sent
* @param proto I2CP protocol
* @param fromPort I2CP from port
* @param toPort I2CP to port
* @param sendLeaseSet true is the usual setting and the I2CP default
* @param sendTags 0 to leave as default
* @param tagThreshold 0 to leave as default
* @param expiration SECONDS from now, NOT absolute time, 0 to leave as default
*
* @return True if the data was sent, false otherwise
* @throws DataFormatException on unknown / bad dest
* @throws I2PSessionException on serious error, probably session closed
* @since 0.9.24
*/
protected boolean sendBytesThroughMessageSession(String dest, byte[] data, int proto, int fromPort, int toPort, boolean sendLeaseSet, int sendTags, int tagThreshold, int expiration) throws DataFormatException, I2PSessionException {
Destination d = SAMUtils.getDest(dest);
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("Sending " + data.length + " bytes to " + dest);
}
SendMessageOptions opts = new SendMessageOptions();
if (!sendLeaseSet)
opts.setSendLeaseSet(false);
if (sendTags > 0)
opts.setTagsToSend(sendTags);
if (tagThreshold > 0)
opts.setTagThreshold(tagThreshold);
if (expiration > 0)
opts.setDate(I2PAppContext.getGlobalContext().clock().now() + (expiration * 1000));
return session.sendMessage(d, data, 0, data.length, proto, fromPort, toPort, opts);
}
use of net.i2p.client.SendMessageOptions in project i2p.i2p by i2p.
the class KRPC method sendMessage.
/**
* Lowest-level send message call.
* @param repliable true for all but announce
* @return success
*/
private boolean sendMessage(Destination dest, int toPort, Map<String, Object> map, boolean repliable) {
if (_session.isClosed()) {
// Don't allow DHT to open a closed session
if (_log.shouldLog(Log.WARN))
_log.warn("Not sending message, session is closed");
return false;
}
if (dest.calculateHash().equals(_myNodeInfo.getHash()))
throw new IllegalArgumentException("don't send to ourselves");
byte[] payload = BEncoder.bencode(map);
if (_log.shouldLog(Log.DEBUG)) {
ByteArrayInputStream bais = new ByteArrayInputStream(payload);
try {
_log.debug("Sending to: " + dest.calculateHash() + ' ' + BDecoder.bdecode(bais).toString());
} catch (IOException ioe) {
}
}
// Always send query port, peer will increment for unsigned replies
int fromPort = _qPort;
if (repliable) {
I2PDatagramMaker dgMaker = new I2PDatagramMaker(_session);
payload = dgMaker.makeI2PDatagram(payload);
if (payload == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("DGM fail");
return false;
}
}
SendMessageOptions opts = new SendMessageOptions();
opts.setDate(_context.clock().now() + 60 * 1000);
opts.setTagsToSend(SEND_CRYPTO_TAGS);
opts.setTagThreshold(LOW_CRYPTO_TAGS);
if (!repliable)
opts.setSendLeaseSet(false);
try {
boolean success = _session.sendMessage(dest, payload, 0, payload.length, repliable ? I2PSession.PROTO_DATAGRAM : I2PSession.PROTO_DATAGRAM_RAW, fromPort, toPort, opts);
if (success) {
_txPkts.incrementAndGet();
_txBytes.addAndGet(payload.length);
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("sendMessage fail");
}
return success;
} catch (I2PSessionException ise) {
if (_log.shouldLog(Log.WARN))
_log.warn("sendMessage fail", ise);
return false;
}
}
use of net.i2p.client.SendMessageOptions 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;
}
Aggregations