Search in sources :

Example 1 with I2CPMessageReader

use of net.i2p.data.i2cp.I2CPMessageReader in project i2p.i2p by i2p.

the class I2PSessionImpl method connect.

/**
 * Connect to the router and establish a session.  This call blocks until
 * a session is granted.
 *
 * Should be threadsafe, other threads will block until complete.
 * Disconnect / destroy from another thread may be called simultaneously and
 * will (should?) interrupt the connect.
 *
 * Connecting a primary session will not automatically connect subsessions.
 * Connecting a subsession will automatically connect the primary session
 * if not previously connected.
 *
 * @throws I2PSessionException if there is a configuration error or the router is
 *                             not reachable
 */
public void connect() throws I2PSessionException {
    synchronized (_stateLock) {
        boolean wasOpening = false;
        boolean loop = true;
        while (loop) {
            switch(_state) {
                case INIT:
                    loop = false;
                    break;
                case CLOSED:
                    if (wasOpening)
                        throw new I2PSessionException("connect by other thread failed");
                    loop = false;
                    break;
                case OPENING:
                case GOTDATE:
                    wasOpening = true;
                    try {
                        _stateLock.wait(10 * 1000);
                    } catch (InterruptedException ie) {
                        throw new I2PSessionException("Interrupted", ie);
                    }
                    break;
                case CLOSING:
                    throw new I2PSessionException("close in progress");
                case OPEN:
                    return;
            }
        }
        changeState(State.OPENING);
    }
    _availabilityNotifier.stopNotifying();
    if ((_options != null) && (I2PClient.PROP_RELIABILITY_GUARANTEED.equals(_options.getProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT)))) {
        if (_log.shouldLog(Log.ERROR))
            _log.error("I2CP guaranteed delivery mode has been removed, using best effort.");
    }
    boolean success = false;
    long startConnect = _context.clock().now();
    try {
        // protect w/ closeSocket()
        synchronized (_stateLock) {
            // If we are in the router JVM, connect using the internal queue
            if (_context.isRouterContext()) {
                // _socket and _writer remain null
                InternalClientManager mgr = _context.internalClientManager();
                if (mgr == null)
                    throw new I2PSessionException("Router is not ready for connections");
                // the following may throw an I2PSessionException
                _queue = mgr.connect();
                _reader = new QueuedI2CPMessageReader(_queue, this);
            } else {
                if (SystemVersion.isAndroid() && _options.getProperty(PROP_DOMAIN_SOCKET) != null) {
                    try {
                        Class<?> clazz = Class.forName("net.i2p.client.DomainSocketFactory");
                        Constructor<?> ctor = clazz.getDeclaredConstructor(I2PAppContext.class);
                        Object fact = ctor.newInstance(_context);
                        Method createSocket = clazz.getDeclaredMethod("createSocket", String.class);
                        try {
                            _socket = (Socket) createSocket.invoke(fact, _options.getProperty(PROP_DOMAIN_SOCKET));
                        } catch (InvocationTargetException e) {
                            throw new I2PSessionException("Cannot create domain socket", e);
                        }
                    } catch (ClassNotFoundException e) {
                        throw new I2PSessionException("Cannot load DomainSocketFactory", e);
                    } catch (NoSuchMethodException e) {
                        throw new I2PSessionException("Cannot load DomainSocketFactory", e);
                    } catch (InstantiationException e) {
                        throw new I2PSessionException("Cannot load DomainSocketFactory", e);
                    } catch (IllegalAccessException e) {
                        throw new I2PSessionException("Cannot load DomainSocketFactory", e);
                    } catch (InvocationTargetException e) {
                        throw new I2PSessionException("Cannot load DomainSocketFactory", e);
                    }
                } else if (Boolean.parseBoolean(_options.getProperty(PROP_ENABLE_SSL))) {
                    try {
                        I2PSSLSocketFactory fact = new I2PSSLSocketFactory(_context, false, "certificates/i2cp");
                        _socket = fact.createSocket(_hostname, _portNum);
                        _socket.setKeepAlive(true);
                    } catch (GeneralSecurityException gse) {
                        IOException ioe = new IOException("SSL Fail");
                        ioe.initCause(gse);
                        throw ioe;
                    }
                } else {
                    _socket = new Socket(_hostname, _portNum);
                    _socket.setKeepAlive(true);
                }
                // _socket.setSoTimeout(1000000); // Uhmmm we could really-really use a real timeout, and handle it.
                OutputStream out = _socket.getOutputStream();
                out.write(I2PClient.PROTOCOL_BYTE);
                out.flush();
                _writer = new ClientWriterRunner(out, this);
                _writer.startWriting();
                InputStream in = new BufferedInputStream(_socket.getInputStream(), BUF_SIZE);
                _reader = new I2CPMessageReader(in, this);
            }
        }
        if (_log.shouldLog(Log.DEBUG))
            _log.debug(getPrefix() + "before startReading");
        _reader.startReading();
        if (_log.shouldLog(Log.DEBUG))
            _log.debug(getPrefix() + "Before getDate");
        Properties auth = null;
        if ((!_context.isRouterContext()) && _options.containsKey(PROP_USER) && _options.containsKey(PROP_PW)) {
            // Only supported by routers 0.9.11 or higher, but we don't know the version yet.
            // Auth will also be sent in the SessionConfig.
            auth = new OrderedProperties();
            auth.setProperty(PROP_USER, _options.getProperty(PROP_USER));
            auth.setProperty(PROP_PW, _options.getProperty(PROP_PW));
        }
        sendMessage_unchecked(new GetDateMessage(CoreVersion.VERSION, auth));
        waitForDate();
        if (_log.shouldLog(Log.DEBUG))
            _log.debug(getPrefix() + "Before producer.connect()");
        _producer.connect(this);
        if (_log.shouldLog(Log.DEBUG))
            _log.debug(getPrefix() + "After producer.connect()");
        // wait until we have created a lease set
        int waitcount = 0;
        while (_leaseSet == null) {
            if (waitcount++ > 5 * 60) {
                throw new IOException("No tunnels built after waiting 5 minutes. Your network connection may be down, or there is severe network congestion.");
            }
            synchronized (_leaseSetWait) {
                // InterruptedException caught below
                _leaseSetWait.wait(1000);
            }
            // if we got a disconnect message while waiting
            if (isClosed())
                throw new IOException("Disconnected from router while waiting for tunnels");
        }
        if (_log.shouldLog(Log.INFO)) {
            long connected = _context.clock().now();
            _log.info(getPrefix() + "Lease set created with inbound tunnels after " + (connected - startConnect) + "ms - ready to participate in the network!");
        }
        Thread notifier = new I2PAppThread(_availabilityNotifier, "ClientNotifier " + getPrefix(), true);
        notifier.start();
        startIdleMonitor();
        startVerifyUsage();
        success = true;
        // now send CreateSessionMessages for all subsessions, one at a time, must wait for each response
        synchronized (_subsessionLock) {
            for (SubSession ss : _subsessions) {
                if (_log.shouldLog(Log.INFO))
                    _log.info(getPrefix() + "Connecting subsession " + ss);
                _producer.connect(ss);
            }
        }
    } catch (InterruptedException ie) {
        throw new I2PSessionException("Interrupted", ie);
    } catch (UnknownHostException uhe) {
        throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, uhe);
    } catch (IOException ioe) {
        // Generate the best error message as this will be logged
        String msg;
        if (_context.isRouterContext())
            msg = "Failed to build tunnels";
        else if (SystemVersion.isAndroid() && _options.getProperty(PROP_DOMAIN_SOCKET) != null)
            msg = "Failed to bind to the router on " + _options.getProperty(PROP_DOMAIN_SOCKET) + " and build tunnels";
        else
            msg = "Cannot connect to the router on " + _hostname + ':' + _portNum + " and build tunnels";
        throw new I2PSessionException(getPrefix() + msg, ioe);
    } finally {
        if (success) {
            changeState(State.OPEN);
        } else {
            _availabilityNotifier.stopNotifying();
            synchronized (_stateLock) {
                changeState(State.CLOSING);
                try {
                    _producer.disconnect(this);
                } catch (I2PSessionException ipe) {
                }
                closeSocket();
            }
        }
    }
}
Also used : OutputStream(java.io.OutputStream) OrderedProperties(net.i2p.util.OrderedProperties) Properties(java.util.Properties) I2PAppThread(net.i2p.util.I2PAppThread) BufferedInputStream(java.io.BufferedInputStream) OrderedProperties(net.i2p.util.OrderedProperties) QueuedI2CPMessageReader(net.i2p.internal.QueuedI2CPMessageReader) GetDateMessage(net.i2p.data.i2cp.GetDateMessage) InternalClientManager(net.i2p.internal.InternalClientManager) UnknownHostException(java.net.UnknownHostException) BufferedInputStream(java.io.BufferedInputStream) InputStream(java.io.InputStream) GeneralSecurityException(java.security.GeneralSecurityException) Method(java.lang.reflect.Method) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) I2PAppThread(net.i2p.util.I2PAppThread) I2PSSLSocketFactory(net.i2p.util.I2PSSLSocketFactory) I2PSessionException(net.i2p.client.I2PSessionException) QueuedI2CPMessageReader(net.i2p.internal.QueuedI2CPMessageReader) I2CPMessageReader(net.i2p.data.i2cp.I2CPMessageReader) Socket(java.net.Socket)

Example 2 with I2CPMessageReader

use of net.i2p.data.i2cp.I2CPMessageReader in project i2p.i2p by i2p.

the class I2PSimpleSession method connect.

/**
 * Connect to the router and establish a session.  This call blocks until
 * a session is granted.
 *
 * NOT threadsafe, do not call from multiple threads.
 *
 * @throws I2PSessionException if there is a configuration error or the router is
 *                             not reachable
 */
@Override
public void connect() throws I2PSessionException {
    changeState(State.OPENING);
    boolean success = false;
    try {
        // protect w/ closeSocket()
        synchronized (_stateLock) {
            // If we are in the router JVM, connect using the interal queue
            if (_context.isRouterContext()) {
                // _socket and _writer remain null
                InternalClientManager mgr = _context.internalClientManager();
                if (mgr == null)
                    throw new I2PSessionException("Router is not ready for connections");
                // the following may throw an I2PSessionException
                _queue = mgr.connect();
                _reader = new QueuedI2CPMessageReader(_queue, this);
                _reader.startReading();
            } else {
                if (Boolean.parseBoolean(getOptions().getProperty(PROP_ENABLE_SSL))) {
                    try {
                        I2PSSLSocketFactory fact = new I2PSSLSocketFactory(_context, false, "certificates/i2cp");
                        _socket = fact.createSocket(_hostname, _portNum);
                    } catch (GeneralSecurityException gse) {
                        IOException ioe = new IOException("SSL Fail");
                        ioe.initCause(gse);
                        throw ioe;
                    }
                } else {
                    _socket = new Socket(_hostname, _portNum);
                }
                _socket.setKeepAlive(true);
                OutputStream out = _socket.getOutputStream();
                out.write(I2PClient.PROTOCOL_BYTE);
                out.flush();
                _writer = new ClientWriterRunner(out, this);
                _writer.startWriting();
                InputStream in = new BufferedInputStream(_socket.getInputStream(), BUF_SIZE);
                _reader = new I2CPMessageReader(in, this);
                _reader.startReading();
            }
        }
        // must be out of synch block for writer to get unblocked
        if (!_context.isRouterContext()) {
            Properties opts = getOptions();
            // support the AuthMessage
            if ((!opts.containsKey(PROP_USER)) && (!opts.containsKey(PROP_PW))) {
                // auto-add auth if not set in the options
                String configUser = _context.getProperty(PROP_USER);
                String configPW = _context.getProperty(PROP_PW);
                if (configUser != null && configPW != null) {
                    opts.setProperty(PROP_USER, configUser);
                    opts.setProperty(PROP_PW, configPW);
                }
            }
            if (opts.containsKey(PROP_USER) && opts.containsKey(PROP_PW)) {
                Properties auth = new OrderedProperties();
                auth.setProperty(PROP_USER, opts.getProperty(PROP_USER));
                auth.setProperty(PROP_PW, opts.getProperty(PROP_PW));
                sendMessage_unchecked(new GetDateMessage(CoreVersion.VERSION, auth));
            } else {
                // we must now send a GetDate even in SimpleSession, or we won't know
                // what version we are talking with and cannot use HostLookup
                sendMessage_unchecked(new GetDateMessage(CoreVersion.VERSION));
            }
            waitForDate();
        }
        // we do not receive payload messages, so we do not need an AvailabilityNotifier
        // ... or an Idle timer, or a VerifyUsage
        success = true;
        if (_log.shouldLog(Log.INFO))
            _log.info(getPrefix() + " simple session connected");
    } catch (InterruptedException ie) {
        throw new I2PSessionException("Interrupted", ie);
    } catch (UnknownHostException uhe) {
        throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, uhe);
    } catch (IOException ioe) {
        // Generate the best error message as this will be logged
        String msg;
        if (_context.isRouterContext())
            msg = "Failed internal router binding";
        else if (SystemVersion.isAndroid() && Boolean.parseBoolean(getOptions().getProperty(PROP_DOMAIN_SOCKET)))
            msg = "Failed to bind to the router";
        else
            msg = "Cannot connect to the router on " + _hostname + ':' + _portNum;
        throw new I2PSessionException(getPrefix() + msg, ioe);
    } finally {
        changeState(success ? State.OPEN : State.CLOSED);
    }
}
Also used : GetDateMessage(net.i2p.data.i2cp.GetDateMessage) InternalClientManager(net.i2p.internal.InternalClientManager) UnknownHostException(java.net.UnknownHostException) BufferedInputStream(java.io.BufferedInputStream) InputStream(java.io.InputStream) GeneralSecurityException(java.security.GeneralSecurityException) OutputStream(java.io.OutputStream) IOException(java.io.IOException) OrderedProperties(net.i2p.util.OrderedProperties) Properties(java.util.Properties) I2PSSLSocketFactory(net.i2p.util.I2PSSLSocketFactory) BufferedInputStream(java.io.BufferedInputStream) I2PSessionException(net.i2p.client.I2PSessionException) OrderedProperties(net.i2p.util.OrderedProperties) I2CPMessageReader(net.i2p.data.i2cp.I2CPMessageReader) QueuedI2CPMessageReader(net.i2p.internal.QueuedI2CPMessageReader) Socket(java.net.Socket) QueuedI2CPMessageReader(net.i2p.internal.QueuedI2CPMessageReader)

Example 3 with I2CPMessageReader

use of net.i2p.data.i2cp.I2CPMessageReader in project i2p.i2p by i2p.

the class ClientConnectionRunner method startRunning.

/**
 * Actually run the connection - listen for I2CP messages and respond.  This
 * is the main driver for this class, though it gets all its meat from the
 * {@link net.i2p.data.i2cp.I2CPMessageReader I2CPMessageReader}
 */
public synchronized void startRunning() throws IOException {
    if (_dead || _reader != null)
        throw new IllegalStateException();
    _reader = new I2CPMessageReader(new BufferedInputStream(_socket.getInputStream(), BUF_SIZE), createListener());
    _writer = new ClientWriterRunner(_context, this);
    I2PThread t = new I2PThread(_writer);
    t.setName("I2CP Writer " + __id.incrementAndGet());
    t.setDaemon(true);
    t.start();
    _out = new BufferedOutputStream(_socket.getOutputStream());
    _reader.startReading();
// TODO need a cleaner for unclaimed items in _messages, but we have no timestamps...
}
Also used : BufferedInputStream(java.io.BufferedInputStream) I2PThread(net.i2p.util.I2PThread) I2CPMessageReader(net.i2p.data.i2cp.I2CPMessageReader) BufferedOutputStream(java.io.BufferedOutputStream)

Aggregations

BufferedInputStream (java.io.BufferedInputStream)3 I2CPMessageReader (net.i2p.data.i2cp.I2CPMessageReader)3 IOException (java.io.IOException)2 InputStream (java.io.InputStream)2 OutputStream (java.io.OutputStream)2 Socket (java.net.Socket)2 UnknownHostException (java.net.UnknownHostException)2 GeneralSecurityException (java.security.GeneralSecurityException)2 Properties (java.util.Properties)2 I2PSessionException (net.i2p.client.I2PSessionException)2 GetDateMessage (net.i2p.data.i2cp.GetDateMessage)2 InternalClientManager (net.i2p.internal.InternalClientManager)2 QueuedI2CPMessageReader (net.i2p.internal.QueuedI2CPMessageReader)2 I2PSSLSocketFactory (net.i2p.util.I2PSSLSocketFactory)2 OrderedProperties (net.i2p.util.OrderedProperties)2 BufferedOutputStream (java.io.BufferedOutputStream)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 I2PAppThread (net.i2p.util.I2PAppThread)1 I2PThread (net.i2p.util.I2PThread)1