Search in sources :

Example 1 with SendMessageOptions

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);
}
Also used : Destination(net.i2p.data.Destination) SendMessageOptions(net.i2p.client.SendMessageOptions)

Example 2 with SendMessageOptions

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;
    }
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) I2PDatagramMaker(net.i2p.client.datagram.I2PDatagramMaker) SendMessageOptions(net.i2p.client.SendMessageOptions) I2PSessionException(net.i2p.client.I2PSessionException) IOException(java.io.IOException)

Example 3 with SendMessageOptions

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;
}
Also used : SendMessageOptions(net.i2p.client.SendMessageOptions) ByteArray(net.i2p.data.ByteArray) I2PSession(net.i2p.client.I2PSession) I2PSessionException(net.i2p.client.I2PSessionException)

Aggregations

SendMessageOptions (net.i2p.client.SendMessageOptions)3 I2PSessionException (net.i2p.client.I2PSessionException)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 IOException (java.io.IOException)1 I2PSession (net.i2p.client.I2PSession)1 I2PDatagramMaker (net.i2p.client.datagram.I2PDatagramMaker)1 ByteArray (net.i2p.data.ByteArray)1 Destination (net.i2p.data.Destination)1