Search in sources :

Example 6 with Destination

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

the class SAMv3StreamSession method connect.

/**
 * Connect the SAM STREAM session to the specified Destination
 * for a single connection, using the socket stolen from the handler.
 *
 * @param handler The handler that communicates with the requesting client
 * @param dest Base64-encoded Destination to connect to
 * @param props Options to be used for connection
 *
 * @throws DataFormatException if the destination is not valid
 * @throws ConnectException if the destination refuses connections
 * @throws NoRouteToHostException if the destination can't be reached
 * @throws InterruptedIOException if the connection timeouts
 * @throws I2PException if there's another I2P-related error
 * @throws IOException
 */
public void connect(SAMv3Handler handler, String dest, Properties props) throws I2PException, ConnectException, NoRouteToHostException, DataFormatException, InterruptedIOException, IOException {
    boolean verbose = !Boolean.parseBoolean(props.getProperty("SILENT"));
    Destination d = SAMUtils.getDest(dest);
    I2PSocketOptions opts = socketMgr.buildOptions(props);
    if (props.getProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT) == null)
        opts.setConnectTimeout(60 * 1000);
    String fromPort = props.getProperty("FROM_PORT");
    if (fromPort != null) {
        try {
            opts.setLocalPort(Integer.parseInt(fromPort));
        } catch (NumberFormatException nfe) {
            throw new I2PException("Bad port " + fromPort);
        }
    }
    String toPort = props.getProperty("TO_PORT");
    if (toPort != null) {
        try {
            opts.setPort(Integer.parseInt(toPort));
        } catch (NumberFormatException nfe) {
            throw new I2PException("Bad port " + toPort);
        }
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Connecting new I2PSocket...");
    // blocking connection (SAMv3)
    I2PSocket i2ps = socketMgr.connect(d, opts);
    SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
    if (rec == null)
        throw new InterruptedIOException();
    handler.notifyStreamResult(verbose, "OK", null);
    handler.stealSocket();
    ReadableByteChannel fromClient = handler.getClientSocket();
    ReadableByteChannel fromI2P = Channels.newChannel(i2ps.getInputStream());
    WritableByteChannel toClient = handler.getClientSocket();
    WritableByteChannel toI2P = Channels.newChannel(i2ps.getOutputStream());
    SAMBridge bridge = handler.getBridge();
    (new I2PAppThread(rec.getThreadGroup(), new Pipe(fromClient, toI2P, bridge), "ConnectV3 SAMPipeClientToI2P")).start();
    (new I2PAppThread(rec.getThreadGroup(), new Pipe(fromI2P, toClient, bridge), "ConnectV3 SAMPipeI2PToClient")).start();
}
Also used : I2PException(net.i2p.I2PException) Destination(net.i2p.data.Destination) InterruptedIOException(java.io.InterruptedIOException) ReadableByteChannel(java.nio.channels.ReadableByteChannel) I2PSocket(net.i2p.client.streaming.I2PSocket) WritableByteChannel(java.nio.channels.WritableByteChannel) I2PSocketOptions(net.i2p.client.streaming.I2PSocketOptions) I2PAppThread(net.i2p.util.I2PAppThread)

Example 7 with Destination

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

the class ConnectionHandler method accept.

/**
 * Receive an incoming connection (built from a received SYN)
 * Non-SYN packets with a zero SendStreamID may also be queued here so
 * that they don't get thrown away while the SYN packet before it is queued.
 *
 * @param timeoutMs max amount of time to wait for a connection (if less
 *                  than 1ms, wait indefinitely)
 * @return connection received. Prior to 0.9.17, or null if there was a timeout or the
 *                  handler was shut down. As of 0.9.17, never null.
 * @throws RouterRestartException (extends I2PException) if the router is apparently restarting, since 0.9.34
 * @throws ConnectException since 0.9.17, returned null before;
 *                  if the I2PServerSocket is closed, or if interrupted.
 * @throws SocketTimeoutException since 0.9.17, returned null before;
 *                  if a timeout was previously set with setSoTimeout and the timeout has been reached.
 */
public Connection accept(long timeoutMs) throws RouterRestartException, ConnectException, SocketTimeoutException {
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Accept(" + timeoutMs + ") called");
    long expiration = timeoutMs + _context.clock().now();
    while (true) {
        if ((timeoutMs > 0) && (expiration < _context.clock().now()))
            throw new SocketTimeoutException("accept() timed out");
        if (!_active) {
            // fail all the ones we had queued up
            while (true) {
                // fails immediately if empty
                Packet packet = _synQueue.poll();
                if (packet == null || packet.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST)
                    break;
                sendReset(packet);
            }
            if (_restartPending)
                throw new RouterRestartException();
            throw new ConnectException("ServerSocket closed");
        }
        Packet syn = null;
        while (_active && syn == null) {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Accept(" + timeoutMs + "): active=" + _active + " queue: " + _synQueue.size());
            if (timeoutMs <= 0) {
                try {
                    // waits forever
                    syn = _synQueue.take();
                } catch (InterruptedException ie) {
                    ConnectException ce = new ConnectException("Interrupted accept()");
                    ce.initCause(ie);
                    throw ce;
                }
            } else {
                long remaining = expiration - _context.clock().now();
                // and the thread simply waits until notified.
                if (remaining < 1)
                    break;
                try {
                    // waits the specified time max
                    syn = _synQueue.poll(remaining, TimeUnit.MILLISECONDS);
                } catch (InterruptedException ie) {
                    ConnectException ce = new ConnectException("Interrupted accept()");
                    ce.initCause(ie);
                    throw ce;
                }
                break;
            }
        }
        if (syn != null) {
            if (syn.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST) {
                if (_restartPending)
                    throw new RouterRestartException();
                throw new ConnectException("ServerSocket closed");
            }
            // Handle both SYN and non-SYN packets in the queue
            if (syn.isFlagSet(Packet.FLAG_SYNCHRONIZE)) {
                // We are single-threaded here, so this is
                // a good place to check for dup SYNs and drop them
                Destination from = syn.getOptionalFrom();
                if (from == null) {
                    if (_log.shouldLog(Log.WARN))
                        _log.warn("Dropping SYN packet with no FROM: " + syn);
                    // drop it
                    continue;
                }
                Connection oldcon = _manager.getConnectionByOutboundId(syn.getReceiveStreamId());
                if (oldcon != null) {
                    // only drop it on a destination match too
                    if (from.equals(oldcon.getRemotePeer())) {
                        if (_log.shouldLog(Log.WARN))
                            _log.warn("Dropping dup SYN: " + syn);
                        continue;
                    }
                }
                Connection con = _manager.receiveConnection(syn);
                if (con != null)
                    return con;
            } else {
                reReceivePacket(syn);
            // ... and keep looping
            }
        }
    // keep looping...
    }
}
Also used : Destination(net.i2p.data.Destination) SocketTimeoutException(java.net.SocketTimeoutException) RouterRestartException(net.i2p.client.streaming.RouterRestartException) ConnectException(java.net.ConnectException)

Example 8 with Destination

use of net.i2p.data.Destination 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 9 with Destination

use of net.i2p.data.Destination 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 10 with Destination

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

the class SAMDatagramSession method messageReceived.

protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) {
    byte[] payload;
    Destination sender;
    try {
        synchronized (dgramDissector) {
            dgramDissector.loadI2PDatagram(msg);
            sender = dgramDissector.getSender();
            payload = dgramDissector.extractPayload();
        }
    } catch (DataFormatException e) {
        if (_log.shouldLog(Log.DEBUG)) {
            _log.debug("Dropping ill-formatted I2P repliable datagram", e);
        }
        return;
    } catch (I2PInvalidDatagramException e) {
        if (_log.shouldLog(Log.DEBUG)) {
            _log.debug("Dropping ill-signed I2P repliable datagram", e);
        }
        return;
    }
    try {
        recv.receiveDatagramBytes(sender, payload, proto, fromPort, toPort);
    } catch (IOException e) {
        _log.error("Error forwarding message to receiver", e);
        close();
    }
}
Also used : Destination(net.i2p.data.Destination) DataFormatException(net.i2p.data.DataFormatException) IOException(java.io.IOException) I2PInvalidDatagramException(net.i2p.client.datagram.I2PInvalidDatagramException)

Aggregations

Destination (net.i2p.data.Destination)149 IOException (java.io.IOException)46 DataFormatException (net.i2p.data.DataFormatException)33 Properties (java.util.Properties)29 I2PException (net.i2p.I2PException)26 Hash (net.i2p.data.Hash)18 ArrayList (java.util.ArrayList)13 File (java.io.File)12 I2PSessionException (net.i2p.client.I2PSessionException)12 SigType (net.i2p.crypto.SigType)12 ByteArrayInputStream (java.io.ByteArrayInputStream)11 ByteArrayOutputStream (java.io.ByteArrayOutputStream)10 I2PSession (net.i2p.client.I2PSession)10 I2PSocket (net.i2p.client.streaming.I2PSocket)10 FileInputStream (java.io.FileInputStream)7 InputStream (java.io.InputStream)7 OutputStream (java.io.OutputStream)7 I2PClient (net.i2p.client.I2PClient)7 I2PSocketOptions (net.i2p.client.streaming.I2PSocketOptions)7 Test (org.junit.Test)6