Search in sources :

Example 6 with ByteArray

use of net.i2p.data.ByteArray in project i2p.i2p by i2p.

the class ConnectionDataReceiver method buildPacket.

/**
 * Compose a packet.
 * Most flags are set here; however, some are set in Connection.sendPacket()
 * and Connection.ResendPacketEvent.retransmit().
 * Take care not to set the same options both here and in Connection.
 *
 * @param buf data to be sent - may be null
 * @param off offset into the buffer to start writing from
 * @param size how many bytes of the buffer to write (may be 0)
 * @param forceIncrement even if the buffer is empty, increment the packetId
 *                       so we get an ACK back
 * @return the packet to be sent
 */
private PacketLocal buildPacket(byte[] buf, int off, int size, boolean forceIncrement) {
    if (size > Packet.MAX_PAYLOAD_SIZE)
        throw new IllegalArgumentException("size is too large (" + size + ")");
    boolean ackOnly = isAckOnly(_connection, size);
    boolean isFirst = (_connection.getAckedPackets() <= 0) && (_connection.getUnackedPacketsSent() <= 0);
    PacketLocal packet = new PacketLocal(_context, _connection.getRemotePeer(), _connection);
    // ByteArray data = packet.acquirePayload();
    ByteArray data = new ByteArray(new byte[size]);
    if (size > 0)
        System.arraycopy(buf, off, data.getData(), 0, size);
    data.setValid(size);
    data.setOffset(0);
    packet.setPayload(data);
    if ((ackOnly && !forceIncrement) && (!isFirst))
        packet.setSequenceNum(0);
    else
        packet.setSequenceNum(_connection.getNextOutboundPacketNum());
    packet.setSendStreamId(_connection.getSendStreamId());
    packet.setReceiveStreamId(_connection.getReceiveStreamId());
    // not needed here, handled in PacketQueue.enqueue()
    // con.getInputStream().updateAcks(packet);
    // Do not set optional delay here, set in Connection.sendPacket()
    // bugfix release 0.7.8, we weren't dividing by 1000
    packet.setResendDelay(_connection.getOptions().getResendDelay() / 1000);
    if (_connection.getOptions().getProfile() == ConnectionOptions.PROFILE_INTERACTIVE)
        packet.setFlag(Packet.FLAG_PROFILE_INTERACTIVE, true);
    else
        packet.setFlag(Packet.FLAG_PROFILE_INTERACTIVE, false);
    // if ( (!ackOnly) && (packet.getSequenceNum() <= 0) ) {
    if (isFirst) {
        packet.setFlag(Packet.FLAG_SYNCHRONIZE);
        packet.setOptionalFrom();
        packet.setOptionalMaxSize(_connection.getOptions().getMaxMessageSize());
    }
    packet.setLocalPort(_connection.getLocalPort());
    packet.setRemotePort(_connection.getPort());
    if (_connection.getSendStreamId() == Packet.STREAM_ID_UNKNOWN) {
        packet.setFlag(Packet.FLAG_NO_ACK);
    }
    // 
    if (_connection.getOutputStream().getClosed() && ((size > 0) || (_connection.getUnackedPacketsSent() <= 0) || (packet.getSequenceNum() > 0))) {
        packet.setFlag(Packet.FLAG_CLOSE);
        _connection.notifyCloseSent();
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("New OB pkt (acks not yet filled in): " + packet + " on " + _connection);
    return packet;
}
Also used : ByteArray(net.i2p.data.ByteArray)

Example 7 with ByteArray

use of net.i2p.data.ByteArray in project i2p.i2p by i2p.

the class ConnectionManager method receiveConnection.

/**
 * Create a new connection based on the SYN packet we received.
 *
 * @param synPacket SYN packet to process
 * @return created Connection with the packet's data already delivered to
 *         it, or null if the syn's streamId was already taken
 */
public Connection receiveConnection(Packet synPacket) {
    ConnectionOptions opts = new ConnectionOptions(_defaultOptions);
    opts.setPort(synPacket.getRemotePort());
    opts.setLocalPort(synPacket.getLocalPort());
    boolean reject = false;
    int active = 0;
    int total = 0;
    // }
    if (locked_tooManyStreams()) {
        if ((!_defaultOptions.getDisableRejectLogging()) || _log.shouldLog(Log.WARN))
            _log.logAlways(Log.WARN, "Refusing connection since we have exceeded our max of " + _defaultOptions.getMaxConns() + " connections");
        reject = true;
    } else {
        // this may not be right if more than one is enabled
        String why = shouldRejectConnection(synPacket);
        if (why != null) {
            if ((!_defaultOptions.getDisableRejectLogging()) || _log.shouldLog(Log.WARN))
                _log.logAlways(Log.WARN, "Refusing connection since peer is " + why + (synPacket.getOptionalFrom() == null ? "" : ": " + synPacket.getOptionalFrom().toBase32()));
            reject = true;
        }
    }
    _context.statManager().addRateData("stream.receiveActive", active, total);
    if (reject) {
        Destination from = synPacket.getOptionalFrom();
        if (from == null)
            return null;
        String resp = _defaultOptions.getLimitAction();
        if ("drop".equals(resp)) {
            // always drop
            return null;
        }
        Hash h = from.calculateHash();
        if (_globalBlacklist.contains(h) || (_defaultOptions.isAccessListEnabled() && !_defaultOptions.getAccessList().contains(h)) || (_defaultOptions.isBlacklistEnabled() && _defaultOptions.getBlacklist().contains(h))) {
            // always drop these regardless of setting
            return null;
        }
        if ((_minuteThrottler != null && _minuteThrottler.isOverBy(h, DROP_OVER_LIMIT)) || (_hourThrottler != null && _hourThrottler.isOverBy(h, DROP_OVER_LIMIT)) || (_dayThrottler != null && _dayThrottler.isOverBy(h, DROP_OVER_LIMIT))) {
            // thus more inbound, but let's not spend several KB on the outbound.
            if (_log.shouldLog(Log.INFO))
                _log.info("Dropping limit response to " + from.toBase32());
            return null;
        }
        boolean reset = resp == null || resp.equals("reset") || resp.length() <= 0;
        boolean http = !reset && "http".equals(resp);
        boolean custom = !(reset || http);
        String sendResponse;
        if (http) {
            sendResponse = LIMIT_HTTP_RESPONSE;
        } else if (custom) {
            sendResponse = resp.replace("\\r", "\r").replace("\\n", "\n");
        } else {
            sendResponse = null;
        }
        PacketLocal reply = new PacketLocal(_context, from, synPacket.getSession());
        if (sendResponse != null) {
            reply.setFlag(Packet.FLAG_SYNCHRONIZE | Packet.FLAG_CLOSE | Packet.FLAG_SIGNATURE_INCLUDED);
            reply.setSequenceNum(0);
            ByteArray payload = new ByteArray(DataHelper.getUTF8(sendResponse));
            reply.setPayload(payload);
        } else {
            reply.setFlag(Packet.FLAG_RESET | Packet.FLAG_SIGNATURE_INCLUDED);
        }
        reply.setAckThrough(synPacket.getSequenceNum());
        reply.setSendStreamId(synPacket.getReceiveStreamId());
        long rcvStreamId = assignRejectId();
        reply.setReceiveStreamId(rcvStreamId);
        reply.setOptionalFrom();
        reply.setLocalPort(synPacket.getLocalPort());
        reply.setRemotePort(synPacket.getRemotePort());
        if (_log.shouldInfo())
            // _log.info("Over limit, sending " + (sendResponse != null ? "configured response" : "reset") + " to " + from.toBase32());
            _log.info("Over limit, sending " + reply + " to " + from.toBase32());
        // this just sends the packet - no retries or whatnot
        _outboundQueue.enqueue(reply);
        return null;
    }
    Connection con = new Connection(_context, this, synPacket.getSession(), _schedulerChooser, _timer, _outboundQueue, _conPacketHandler, opts, true);
    _tcbShare.updateOptsFromShare(con);
    assignReceiveStreamId(con);
    // finally, we know enough that we can log the packet with the conn filled in
    if (I2PSocketManagerFull.pcapWriter != null && _context.getBooleanProperty(I2PSocketManagerFull.PROP_PCAP))
        synPacket.logTCPDump(con);
    try {
        // This validates the packet, and sets the con's SendStreamID and RemotePeer
        con.getPacketHandler().receivePacket(synPacket, con);
    } catch (I2PException ie) {
        _connectionByInboundId.remove(Long.valueOf(con.getReceiveStreamId()));
        return null;
    }
    _context.statManager().addRateData("stream.connectionReceived", 1);
    return con;
}
Also used : I2PException(net.i2p.I2PException) Destination(net.i2p.data.Destination) ByteArray(net.i2p.data.ByteArray) Hash(net.i2p.data.Hash) ConvertToHash(net.i2p.util.ConvertToHash)

Example 8 with ByteArray

use of net.i2p.data.ByteArray in project i2p.i2p by i2p.

the class ConnectionManager method receivePing.

/**
 *  Process a ping by checking for throttling, etc., then sending a pong.
 *
 *  @param con null if unknown
 *  @param ping Ping packet to process, must have From and Sig fields,
 *              with signature already verified, only if answerPings() returned true
 *  @return true if we sent a pong
 *  @since 0.9.12 from PacketHandler.receivePing()
 */
public boolean receivePing(Connection con, Packet ping) {
    Destination dest = ping.getOptionalFrom();
    if (dest == null)
        return false;
    if (con == null) {
        // Use the same throttling as for connections
        String why = shouldRejectConnection(ping);
        if (why != null) {
            if ((!_defaultOptions.getDisableRejectLogging()) || _log.shouldLog(Log.WARN))
                _log.logAlways(Log.WARN, "Dropping ping since peer is " + why + ": " + dest.calculateHash());
            return false;
        }
    } else {
        // in-connection ping to a 3rd party ???
        if (!dest.equals(con.getRemotePeer())) {
            _log.logAlways(Log.WARN, "Dropping ping from " + con.getRemotePeer().calculateHash() + " to " + dest.calculateHash());
            return false;
        }
    }
    PacketLocal pong = new PacketLocal(_context, dest, ping.getSession());
    pong.setFlag(Packet.FLAG_ECHO | Packet.FLAG_NO_ACK);
    pong.setReceiveStreamId(ping.getSendStreamId());
    pong.setLocalPort(ping.getLocalPort());
    pong.setRemotePort(ping.getRemotePort());
    // as of 0.9.18, return the payload
    ByteArray payload = ping.getPayload();
    if (payload != null) {
        if (payload.getValid() > MAX_PONG_PAYLOAD)
            payload.setValid(MAX_PONG_PAYLOAD);
        pong.setPayload(payload);
    }
    _outboundQueue.enqueue(pong);
    return true;
}
Also used : Destination(net.i2p.data.Destination) ByteArray(net.i2p.data.ByteArray)

Example 9 with ByteArray

use of net.i2p.data.ByteArray in project i2p.i2p by i2p.

the class HTTPResponseOutputStream method ensureCapacity.

/**
 *  grow (and free) the buffer as necessary
 *  @throws IOException if the headers are too big
 */
private void ensureCapacity() throws IOException {
    if (_headerBuffer.getValid() >= MAX_HEADER_SIZE)
        throw new IOException("Max header size exceeded: " + MAX_HEADER_SIZE);
    if (_headerBuffer.getValid() + 1 >= _headerBuffer.getData().length) {
        int newSize = (int) (_headerBuffer.getData().length * 1.5);
        ByteArray newBuf = new ByteArray(new byte[newSize]);
        System.arraycopy(_headerBuffer.getData(), 0, newBuf.getData(), 0, _headerBuffer.getValid());
        newBuf.setValid(_headerBuffer.getValid());
        newBuf.setOffset(0);
        // if we changed the ByteArray size, don't put it back in the cache
        if (_headerBuffer.getData().length == CACHE_SIZE)
            _cache.release(_headerBuffer);
        _headerBuffer = newBuf;
    }
}
Also used : ByteArray(net.i2p.data.ByteArray) IOException(java.io.IOException)

Example 10 with ByteArray

use of net.i2p.data.ByteArray in project i2p.i2p by i2p.

the class Message method sendMessage.

/**
 * Utility method for sending a message through a DataStream.
 */
void sendMessage(DataOutputStream dos) throws IOException {
    // KEEP_ALIVE is special.
    if (type == KEEP_ALIVE) {
        dos.writeInt(0);
        return;
    }
    ByteArray ba;
    // Get deferred data
    if (data == null && dataLoader != null) {
        ba = dataLoader.loadData(piece, begin, length);
        if (ba == null)
            // hmm will get retried, but shouldn't happen
            return;
        data = ba.getData();
    } else {
        ba = null;
    }
    // Calculate the total length in bytes
    // Type is one byte.
    int datalen = 1;
    // piece is 4 bytes.
    if (type == HAVE || type == REQUEST || type == PIECE || type == CANCEL || type == SUGGEST || type == REJECT || type == ALLOWED_FAST)
        datalen += 4;
    // begin/offset is 4 bytes
    if (type == REQUEST || type == PIECE || type == CANCEL || type == REJECT)
        datalen += 4;
    // length is 4 bytes
    if (type == REQUEST || type == CANCEL || type == REJECT)
        datalen += 4;
    else // msg type is 1 byte
    if (type == EXTENSION)
        datalen += 1;
    else if (type == PORT)
        datalen += 2;
    // add length of data for piece or bitfield array.
    if (type == BITFIELD || type == PIECE || type == EXTENSION)
        datalen += len;
    // Send length
    dos.writeInt(datalen);
    dos.writeByte(type & 0xFF);
    // Send additional info (piece number)
    if (type == HAVE || type == REQUEST || type == PIECE || type == CANCEL || type == SUGGEST || type == REJECT || type == ALLOWED_FAST)
        dos.writeInt(piece);
    // Send additional info (begin/offset)
    if (type == REQUEST || type == PIECE || type == CANCEL || type == REJECT)
        dos.writeInt(begin);
    // Send additional info (length); for PIECE this is implicit.
    if (type == REQUEST || type == CANCEL || type == REJECT)
        dos.writeInt(length);
    else if (type == EXTENSION)
        dos.writeByte((byte) piece & 0xff);
    else if (type == PORT)
        dos.writeShort(piece & 0xffff);
    // Send actual data
    if (type == BITFIELD || type == PIECE || type == EXTENSION)
        dos.write(data, off, len);
    // Was pulled from cache in Storage.getPiece() via dataLoader
    if (ba != null && ba.getData().length == BUFSIZE)
        _cache.release(ba, false);
}
Also used : ByteArray(net.i2p.data.ByteArray)

Aggregations

ByteArray (net.i2p.data.ByteArray)53 Test (org.junit.Test)14 IOException (java.io.IOException)9 ArrayList (java.util.ArrayList)3 Destination (net.i2p.data.Destination)3 InterruptedIOException (java.io.InterruptedIOException)2 SessionKey (net.i2p.data.SessionKey)2 I2NPMessage (net.i2p.data.i2np.I2NPMessage)2 I2NPMessageException (net.i2p.data.i2np.I2NPMessageException)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 InetAddress (java.net.InetAddress)1 ByteBuffer (java.nio.ByteBuffer)1 CancelledKeyException (java.nio.channels.CancelledKeyException)1 NotYetConnectedException (java.nio.channels.NotYetConnectedException)1 SelectionKey (java.nio.channels.SelectionKey)1 ServerSocketChannel (java.nio.channels.ServerSocketChannel)1 SocketChannel (java.nio.channels.SocketChannel)1 MessageDigest (java.security.MessageDigest)1 LinkedBlockingQueue (java.util.concurrent.LinkedBlockingQueue)1 I2PException (net.i2p.I2PException)1