Search in sources :

Example 1 with I2PSession

use of net.i2p.client.I2PSession in project i2p.i2p by i2p.

the class I2PSocketManagerFull method connect.

/**
 * Create a new connected socket. Blocks until the socket is created,
 * unless the connectDelay option (i2p.streaming.connectDelay) is
 * set and greater than zero. If so this will return immediately,
 * and the client may quickly write initial data to the socket and
 * this data will be bundled in the SYN packet.
 *
 * @param peer Destination to connect to
 * @param options I2P socket options to be used for connecting, may be null
 *
 * @return I2PSocket if successful
 * @throws NoRouteToHostException if the peer is not found or not reachable
 * @throws I2PException if there is some other I2P-related problem
 */
public I2PSocket connect(Destination peer, I2PSocketOptions options) throws I2PException, NoRouteToHostException {
    if (peer == null)
        throw new NullPointerException();
    if (options == null)
        options = _defaultOptions;
    ConnectionOptions opts = null;
    if (options instanceof ConnectionOptions)
        opts = new ConnectionOptions((ConnectionOptions) options);
    else
        opts = new ConnectionOptions(options);
    if (_log.shouldLog(Log.INFO))
        _log.info("Connecting to " + peer.calculateHash().toBase64().substring(0, 6) + " with options: " + opts);
    // pick the subsession here
    I2PSession session = _session;
    if (!_subsessions.isEmpty()) {
        updateUserDsaList();
        Hash h = peer.calculateHash();
        SigAlgo myAlgo = session.getMyDestination().getSigType().getBaseAlgorithm();
        if ((myAlgo == SigAlgo.EC && _ecUnsupported.contains(h)) || (myAlgo == SigAlgo.EdDSA && _edUnsupported.contains(h)) || (!_userDsaOnly.isEmpty() && _userDsaOnly.contains(h))) {
            // FIXME just taking the first one for now
            for (I2PSession sess : _subsessions) {
                if (sess.getMyDestination().getSigType() == SigType.DSA_SHA1) {
                    session = sess;
                    break;
                }
            }
        }
    }
    verifySession(session);
    // the following blocks unless connect delay > 0
    Connection con = _connectionManager.connect(peer, opts, session);
    if (con == null)
        throw new TooManyStreamsException("Too many streams, max " + _defaultOptions.getMaxConns());
    I2PSocketFull socket = new I2PSocketFull(con, _context);
    con.setSocket(socket);
    if (con.getConnectionError() != null) {
        con.disconnect(false);
        throw new NoRouteToHostException(con.getConnectionError());
    }
    return socket;
}
Also used : SigAlgo(net.i2p.crypto.SigAlgo) I2PSession(net.i2p.client.I2PSession) Hash(net.i2p.data.Hash) ConvertToHash(net.i2p.util.ConvertToHash) NoRouteToHostException(java.net.NoRouteToHostException)

Example 2 with I2PSession

use of net.i2p.client.I2PSession in project i2p.i2p by i2p.

the class I2PSocketManagerFull method addSubsession.

/**
 *  For a server, you must call connect() on the returned object.
 *  Connecting the primary session does NOT connect any subsessions.
 *  If the primary session is not connected, connecting a subsession will connect the primary session first.
 *
 *  @return a new subsession, non-null
 *  @param privateKeyStream null for transient, if non-null must have same encryption keys as primary session
 *                          and different signing keys
 *  @param opts subsession options if any, may be null
 *  @since 0.9.21
 */
public I2PSession addSubsession(InputStream privateKeyStream, Properties opts) throws I2PSessionException {
    if (privateKeyStream == null) {
        // We don't actually need the same pubkey in the dest, just in the LS.
        // The dest one is unused. But this is how we find the LS keys
        // to reuse in RequestLeaseSetMessageHandler.
        ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
        try {
            SigType type = getSigType(opts);
            if (type != SigType.DSA_SHA1) {
                // hassle, have to set up the padding and cert, see I2PClientImpl
                throw new I2PSessionException("type " + type + " unsupported");
            }
            PublicKey pub = _session.getMyDestination().getPublicKey();
            PrivateKey priv = _session.getDecryptionKey();
            SimpleDataStructure[] keys = _context.keyGenerator().generateSigningKeys(type);
            pub.writeBytes(keyStream);
            // signing pub
            keys[0].writeBytes(keyStream);
            Certificate.NULL_CERT.writeBytes(keyStream);
            priv.writeBytes(keyStream);
            // signing priv
            keys[1].writeBytes(keyStream);
        } catch (GeneralSecurityException e) {
            throw new I2PSessionException("Error creating keys", e);
        } catch (I2PException e) {
            throw new I2PSessionException("Error creating keys", e);
        } catch (IOException e) {
            throw new I2PSessionException("Error creating keys", e);
        } catch (RuntimeException e) {
            throw new I2PSessionException("Error creating keys", e);
        }
        privateKeyStream = new ByteArrayInputStream(keyStream.toByteArray());
    }
    I2PSession rv = _session.addSubsession(privateKeyStream, opts);
    boolean added = _subsessions.add(rv);
    if (!added) {
        // shouldn't happen
        _session.removeSubsession(rv);
        throw new I2PSessionException("dup");
    }
    ConnectionOptions defaultOptions = new ConnectionOptions(opts);
    int protocol = defaultOptions.getEnforceProtocol() ? I2PSession.PROTO_STREAMING : I2PSession.PROTO_ANY;
    rv.addMuxedSessionListener(_connectionManager.getMessageHandler(), protocol, defaultOptions.getLocalPort());
    if (_log.shouldLog(Log.WARN))
        _log.warn("Added subsession " + rv);
    return rv;
}
Also used : I2PException(net.i2p.I2PException) PrivateKey(net.i2p.data.PrivateKey) PublicKey(net.i2p.data.PublicKey) GeneralSecurityException(java.security.GeneralSecurityException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) SigType(net.i2p.crypto.SigType) ByteArrayInputStream(java.io.ByteArrayInputStream) I2PSessionException(net.i2p.client.I2PSessionException) I2PSession(net.i2p.client.I2PSession) SimpleDataStructure(net.i2p.data.SimpleDataStructure)

Example 3 with I2PSession

use of net.i2p.client.I2PSession in project i2p.i2p by i2p.

the class I2PTunnelClientBase method verifySocketManager.

/**
 * Create the manager if it doesn't exist, AND connect it to the router and
 * build tunnels.
 *
 * Sets the this.sockMgr field if it is null, or if we want a new one.
 * This may take a LONG time if building a new manager.
 *
 * We need a socket manager before getDefaultOptions() and most other things
 * @throws IllegalArgumentException if the I2CP configuration is b0rked so
 *                                  badly that we cant create a socketManager
 */
protected void verifySocketManager() {
    synchronized (sockLock) {
        boolean newManager = false;
        // other shared client could have destroyed it
        if (this.sockMgr == null || this.sockMgr.isDestroyed()) {
            newManager = true;
        } else {
            I2PSession sess = sockMgr.getSession();
            if (sess.isClosed() && Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.closeOnIdle")) && Boolean.parseBoolean(getTunnel().getClientOptions().getProperty("i2cp.newDestOnResume"))) {
                // build a new socket manager and a new dest if the session is closed.
                getTunnel().removeSession(sess);
                if (_log.shouldLog(Log.WARN))
                    _log.warn(getTunnel().getClientOptions().getProperty("inbound.nickname") + ": Built a new destination on resume");
                // make sure the old one is closed
                // if it's shared client, it will be destroyed in getSocketManager()
                // with the correct locking
                boolean shouldDestroy;
                synchronized (I2PTunnelClientBase.class) {
                    shouldDestroy = sockMgr != socketManager;
                }
                if (shouldDestroy)
                    sockMgr.destroySocketManager();
                newManager = true;
            }
        // else the old socket manager will reconnect the old session if necessary
        }
        if (newManager) {
            if (_ownDest)
                this.sockMgr = buildSocketManager();
            else
                this.sockMgr = getSocketManager();
        }
    }
    connectManager();
}
Also used : I2PSession(net.i2p.client.I2PSession)

Example 4 with I2PSession

use of net.i2p.client.I2PSession in project i2p.i2p by i2p.

the class I2PTunnelClientBase method close.

/**
 *  Note that the tunnel can be reopened after this by calling startRunning().
 *  This may not release all resources. In particular, the I2PSocketManager remains
 *  and it may have timer threads that continue running.
 *
 *  To release all resources permanently, call destroy().
 *
 *  Does nothing if open is already false.
 *  Sets open = false but does not notifyAll().
 *
 *  @return success
 */
public boolean close(boolean forced) {
    if (_log.shouldLog(Log.INFO))
        _log.info("close() called: forced = " + forced + " open = " + open + " sockMgr = " + sockMgr);
    if (!open)
        return true;
    // to return with an error in that situation quickly.
    synchronized (sockLock) {
        if (sockMgr != null) {
            mySockets.retainAll(sockMgr.listSockets());
            if ((!forced) && (!mySockets.isEmpty())) {
                l.log("Not closing, there are still active connections!");
                _log.debug("can't close: there are still active connections!");
                for (I2PSocket s : mySockets) {
                    l.log("  -> " + s.toString());
                }
                return false;
            }
            if (!chained) {
                I2PSession session = sockMgr.getSession();
                getTunnel().removeSession(session);
                if (_ownDest) {
                    try {
                        session.destroySession();
                    } catch (I2PException ex) {
                    }
                }
            // TCG will try to destroy it too
            }
        // else the app chaining to this one closes it!
        }
        l.log("Stopping client " + toString());
        open = false;
        try {
            if (ss != null)
                ss.close();
        } catch (IOException ex) {
            if (_log.shouldDebug())
                _log.debug("error closing", ex);
            return false;
        }
    // l.log("Client closed.");
    }
    return true;
}
Also used : I2PException(net.i2p.I2PException) I2PSocket(net.i2p.client.streaming.I2PSocket) I2PSession(net.i2p.client.I2PSession) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException)

Example 5 with I2PSession

use of net.i2p.client.I2PSession in project i2p.i2p by i2p.

the class I2PTunnelHTTPClient method clientConnectionRun.

/**
 *  Note: This does not handle RFC 2616 header line splitting,
 *  which is obsoleted in RFC 7230.
 */
protected void clientConnectionRun(Socket s) {
    OutputStream out = null;
    /**
     * The URL after fixup, always starting with http:// or https://
     */
    String targetRequest = null;
    // in-net outproxy
    boolean usingWWWProxy = false;
    // local outproxy plugin
    boolean usingInternalOutproxy = false;
    Outproxy outproxy = null;
    boolean usingInternalServer = false;
    String internalPath = null;
    String internalRawQuery = null;
    String currentProxy = null;
    long requestId = __requestId.incrementAndGet();
    boolean shout = false;
    I2PSocket i2ps = null;
    try {
        s.setSoTimeout(INITIAL_SO_TIMEOUT);
        out = s.getOutputStream();
        InputReader reader = new InputReader(s.getInputStream());
        String line, method = null, protocol = null, host = null, destination = null;
        StringBuilder newRequest = new StringBuilder();
        boolean ahelperPresent = false;
        boolean ahelperNew = false;
        String ahelperKey = null;
        String userAgent = null;
        String authorization = null;
        int remotePort = 0;
        String referer = null;
        URI origRequestURI = null;
        while ((line = reader.readLine(method)) != null) {
            line = line.trim();
            if (_log.shouldLog(Log.DEBUG)) {
                _log.debug(getPrefix(requestId) + "Line=[" + line + "]");
            }
            String lowercaseLine = line.toLowerCase(Locale.US);
            if (lowercaseLine.startsWith("connection: ") || lowercaseLine.startsWith("keep-alive: ") || lowercaseLine.startsWith("proxy-connection: ")) {
                continue;
            }
            if (method == null) {
                // first line (GET /base64/realaddr)
                if (_log.shouldLog(Log.DEBUG)) {
                    _log.debug(getPrefix(requestId) + "First line [" + line + "]");
                }
                String[] params = DataHelper.split(line, " ", 3);
                if (params.length != 3) {
                    break;
                }
                String request = params[1];
                // various obscure fixups
                if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
                    // what is this for ???
                    request = "http://i2p" + request;
                } else if (request.startsWith("/eepproxy/")) {
                    // Deprecated
                    // /eepproxy/foo.i2p/bar/baz.html
                    String subRequest = request.substring("/eepproxy/".length());
                    if (subRequest.indexOf('/') == -1) {
                        subRequest += '/';
                    }
                    request = "http://" + subRequest;
                /**
                 **
                 *                    } else if (request.toLowerCase(Locale.US).startsWith("http://i2p/")) {
                 *                    // http://i2p/b64key/bar/baz.html
                 *                    // we can't do this now by setting the URI host to the b64key, as
                 *                    // it probably contains '=' and '~' which are illegal,
                 *                    // and a host may not include escaped octets
                 *                    // This will get undone below.
                 *                    String subRequest = request.substring("http://i2p/".length());
                 *                    if (subRequest.indexOf("/") == -1)
                 *                    subRequest += "/";
                 *                    "http://" + "b64key/bar/baz.html"
                 *                    request = "http://" + subRequest;
                 *                    } else if (request.toLowerCase(Locale.US).startsWith("http://")) {
                 *                    // Unsupported
                 *                    // http://$b64key/...
                 *                    // This probably used to work, rewrite it so that
                 *                    // we can create a URI without illegal characters
                 *                    // This will get undone below.
                 *                    String  oldPath = request.substring(7);
                 *                    int slash = oldPath.indexOf("/");
                 *                    if (slash < 0)
                 *                    slash = oldPath.length();
                 *                    if (slash >= 516 && !oldPath.substring(0, slash).contains("."))
                 *                    request = "http://i2p/" + oldPath;
                 ***
                 */
                }
                method = params[0];
                if (method.toUpperCase(Locale.US).equals("CONNECT")) {
                    // this makes things easier later, by spoofing a
                    // protocol so the URI parser find the host and port
                    // For in-net outproxy, will be fixed up below
                    request = "https://" + request + '/';
                }
                // Now use the Java URI parser
                // This will be the incoming URI but will then get modified
                // to be the outgoing URI (with http:// if going to outproxy, otherwise without)
                URI requestURI = null;
                try {
                    try {
                        requestURI = new URI(request);
                    } catch (URISyntaxException use) {
                        // fixup []| in path/query not escaped by browsers, see ticket #2130
                        boolean error = true;
                        // find 3rd /
                        int idx = 0;
                        for (int i = 0; i < 2; i++) {
                            idx = request.indexOf('/', idx);
                            if (idx < 0)
                                break;
                            idx++;
                        }
                        if (idx > 0) {
                            String schemeHostPort = request.substring(0, idx);
                            String rest = request.substring(idx);
                            rest = rest.replace("[", "%5B");
                            rest = rest.replace("]", "%5D");
                            rest = rest.replace("|", "%7C");
                            String testRequest = schemeHostPort + rest;
                            if (!testRequest.equals(request)) {
                                try {
                                    requestURI = new URI(testRequest);
                                    request = testRequest;
                                    error = false;
                                } catch (URISyntaxException use2) {
                                // didn't work, give up
                                }
                            }
                        }
                        // guess it wasn't []|
                        if (error)
                            throw use;
                    }
                    origRequestURI = requestURI;
                    if (requestURI.getRawUserInfo() != null || requestURI.getRawFragment() != null) {
                        // these should never be sent to the proxy in the request line
                        if (_log.shouldLog(Log.WARN)) {
                            _log.warn(getPrefix(requestId) + "Removing userinfo or fragment [" + request + "]");
                        }
                        requestURI = changeURI(requestURI, null, 0, null);
                    }
                    if (requestURI.getPath() == null || requestURI.getPath().length() <= 0) {
                        // Add a path
                        if (_log.shouldLog(Log.WARN)) {
                            _log.warn(getPrefix(requestId) + "Adding / path to [" + request + "]");
                        }
                        requestURI = changeURI(requestURI, null, 0, "/");
                    }
                } catch (URISyntaxException use) {
                    if (_log.shouldLog(Log.WARN)) {
                        _log.warn(getPrefix(requestId) + "Bad request [" + request + "]", use);
                    }
                    try {
                        out.write(getErrorPage("baduri", ERR_BAD_URI).getBytes("UTF-8"));
                        String msg = use.getLocalizedMessage();
                        if (msg != null) {
                            out.write(DataHelper.getASCII("<p>\n"));
                            out.write(DataHelper.getUTF8(DataHelper.escapeHTML(msg)));
                            out.write(DataHelper.getASCII("</p>\n"));
                        }
                        out.write(DataHelper.getASCII("</div>\n"));
                        writeFooter(out);
                        reader.drain();
                    } catch (IOException ioe) {
                    // ignore
                    }
                    return;
                }
                String protocolVersion = params[2];
                protocol = requestURI.getScheme();
                host = requestURI.getHost();
                if (protocol == null || host == null) {
                    _log.warn("Null protocol or host: " + request + ' ' + protocol + ' ' + host);
                    method = null;
                    break;
                }
                int port = requestURI.getPort();
                // Go through the various types of host names, set
                // the host and destination variables accordingly,
                // and transform the first line.
                // For all i2p network hosts, ensure that the host is a
                // Base 32 hostname so that we do not reveal our name for it
                // in our addressbook (all naming is local),
                // and it is removed from the request line.
                String hostLowerCase = host.toLowerCase(Locale.US);
                if (hostLowerCase.equals(LOCAL_SERVER)) {
                    // so we don't do any naming service lookups
                    destination = host;
                    usingInternalServer = true;
                    internalPath = requestURI.getPath();
                    internalRawQuery = requestURI.getRawQuery();
                } else if (hostLowerCase.equals("i2p")) {
                    // pull the b64 _dest out of the first path element
                    String oldPath = requestURI.getPath().substring(1);
                    int slash = oldPath.indexOf('/');
                    if (slash < 0) {
                        slash = oldPath.length();
                        oldPath += '/';
                    }
                    String _dest = oldPath.substring(0, slash);
                    if (slash >= 516 && !_dest.contains(".")) {
                        // possible alternative:
                        // redirect to b32
                        destination = _dest;
                        host = getHostName(destination);
                        targetRequest = requestURI.toASCIIString();
                        String newURI = oldPath.substring(slash);
                        String query = requestURI.getRawQuery();
                        if (query != null) {
                            newURI += '?' + query;
                        }
                        try {
                            requestURI = new URI(newURI);
                        } catch (URISyntaxException use) {
                            // shouldnt happen
                            _log.warn(request, use);
                            method = null;
                            break;
                        }
                    } else {
                        _log.warn("Bad http://i2p/b64dest " + request);
                        host = null;
                        break;
                    }
                } else if (hostLowerCase.endsWith(".i2p")) {
                    // Destination gets the host name
                    destination = host;
                    // Host becomes the destination's "{b32}.b32.i2p" string, or "i2p" on lookup failure
                    host = getHostName(destination);
                    int rPort = requestURI.getPort();
                    if (rPort > 0) {
                        // Save it to put in the I2PSocketOptions,
                        remotePort = rPort;
                    /**
                     ******
                     *                            // but strip it from the URL
                     *                            if(_log.shouldLog(Log.WARN)) {
                     *                                _log.warn(getPrefix(requestId) + "Removing port from [" + request + "]");
                     *                            }
                     *                            try {
                     *                                requestURI = changeURI(requestURI, null, -1, null);
                     *                            } catch(URISyntaxException use) {
                     *                                _log.warn(request, use);
                     *                                method = null;
                     *                                break;
                     *                            }
                     *****
                     */
                    } else if ("https".equals(protocol) || method.toUpperCase(Locale.US).equals("CONNECT")) {
                        remotePort = 443;
                    } else {
                        remotePort = 80;
                    }
                    String query = requestURI.getRawQuery();
                    if (query != null) {
                        boolean ahelperConflict = false;
                        // Try to find an address helper in the query
                        String[] helperStrings = removeHelper(query);
                        if (helperStrings != null && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) {
                            query = helperStrings[0];
                            if (query.equals("")) {
                                query = null;
                            }
                            try {
                                requestURI = replaceQuery(requestURI, query);
                            } catch (URISyntaxException use) {
                                // shouldn't happen
                                _log.warn(request, use);
                                method = null;
                                break;
                            }
                            ahelperKey = helperStrings[1];
                            // Key contains data, lets not ignore it
                            if (ahelperKey.length() > 0) {
                                if (ahelperKey.endsWith(".i2p")) {
                                    // allow i2paddresshelper=<b32>.b32.i2p syntax.
                                    /*
                                        also i2paddresshelper=name.i2p for aliases
                                        i.e. on your eepsite put
                                        <a href="?i2paddresshelper=name.i2p">This is the name I want to be called.</a>
                                         */
                                    Destination _dest = _context.namingService().lookup(ahelperKey);
                                    if (_dest == null) {
                                        if (_log.shouldLog(Log.WARN)) {
                                            _log.warn(getPrefix(requestId) + "Could not find destination for " + ahelperKey);
                                        }
                                        String header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
                                        try {
                                            out.write(header.getBytes("UTF-8"));
                                            out.write(("<p>" + _t("This seems to be a bad destination:") + " " + ahelperKey + " " + _t("i2paddresshelper cannot help you with a destination like that!") + "</p>").getBytes("UTF-8"));
                                            writeFooter(out);
                                            reader.drain();
                                        } catch (IOException ioe) {
                                        // ignore
                                        }
                                        return;
                                    }
                                    ahelperKey = _dest.toBase64();
                                }
                                ahelperPresent = true;
                                // ahelperKey will be validated later
                                if (host == null || "i2p".equals(host)) {
                                    // Host lookup failed - resolvable only with addresshelper
                                    // Store in local HashMap unless there is conflict
                                    String old = addressHelpers.putIfAbsent(destination.toLowerCase(Locale.US), ahelperKey);
                                    ahelperNew = old == null;
                                    // inr address helper links without trailing '=', so omit from comparison
                                    if ((!ahelperNew) && !old.replace("=", "").equals(ahelperKey.replace("=", ""))) {
                                        // Conflict: handle when URL reconstruction done
                                        ahelperConflict = true;
                                        if (_log.shouldLog(Log.WARN)) {
                                            _log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination + "], trusted key [" + old + "], specified key [" + ahelperKey + "].");
                                        }
                                    }
                                } else {
                                    // If the host is resolvable from database, verify addresshelper key
                                    // Silently bypass correct keys, otherwise alert
                                    Destination hostDest = _context.namingService().lookup(destination);
                                    if (hostDest != null) {
                                        String destB64 = hostDest.toBase64();
                                        if (destB64 != null && !destB64.equals(ahelperKey)) {
                                            // Conflict: handle when URL reconstruction done
                                            ahelperConflict = true;
                                            if (_log.shouldLog(Log.WARN)) {
                                                _log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination + "], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
                                            }
                                        }
                                    }
                                }
                            }
                        // ahelperKey
                        }
                        // Did addresshelper key conflict?
                        if (ahelperConflict) {
                            try {
                                // convert ahelperKey to b32
                                String alias = getHostName(ahelperKey);
                                if (alias.equals("i2p")) {
                                    // bad ahelperKey
                                    String header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
                                    writeErrorMessage(header, out, targetRequest, false, destination);
                                } else {
                                    String trustedURL = requestURI.toASCIIString();
                                    URI conflictURI;
                                    try {
                                        conflictURI = changeURI(requestURI, alias, 0, null);
                                    } catch (URISyntaxException use) {
                                        // shouldn't happen
                                        _log.warn(request, use);
                                        method = null;
                                        break;
                                    }
                                    String conflictURL = conflictURI.toASCIIString();
                                    String header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
                                    out.write(header.getBytes("UTF-8"));
                                    out.write("<p>".getBytes("UTF-8"));
                                    out.write(_t("To visit the destination in your address book, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, click <a href=\"{1}\">here</a>.", trustedURL, conflictURL).getBytes("UTF-8"));
                                    out.write("</p>".getBytes("UTF-8"));
                                    Hash h1 = ConvertToHash.getHash(requestURI.getHost());
                                    Hash h2 = ConvertToHash.getHash(ahelperKey);
                                    if (h1 != null && h2 != null) {
                                        String conURL = _context.portMapper().getConsoleURL();
                                        out.write(("\n<table class=\"conflict\"><tr><th align=\"center\">" + "<a href=\"" + trustedURL + "\">").getBytes("UTF-8"));
                                        out.write(_t("Destination for {0} in address book", requestURI.getHost()).getBytes("UTF-8"));
                                        out.write(("</a></th>\n<th align=\"center\">" + "<a href=\"" + conflictURL + "\">").getBytes("UTF-8"));
                                        out.write(_t("Conflicting address helper destination").getBytes("UTF-8"));
                                        out.write(("</a></th></tr>\n").getBytes("UTF-8"));
                                        if (_context.portMapper().getPort(PortMapper.SVC_IMAGEGEN) > 0) {
                                            out.write(("<tr><td align=\"center\">" + "<a href=\"" + trustedURL + "\">" + "<img src=\"" + conURL + "imagegen/id?s=160&amp;c=" + h1.toBase64().replace("=", "%3d") + "\" width=\"160\" height=\"160\"></a>\n" + "</td>\n<td align=\"center\">" + "<a href=\"" + conflictURL + "\">" + "<img src=\"" + conURL + "imagegen/id?s=160&amp;c=" + h2.toBase64().replace("=", "%3d") + "\" width=\"160\" height=\"160\"></a>\n" + "</td></tr>").getBytes("UTF-8"));
                                        }
                                        out.write("</table>".getBytes("UTF-8"));
                                    }
                                    out.write("</div>".getBytes("UTF-8"));
                                    writeFooter(out);
                                }
                                reader.drain();
                            } catch (IOException ioe) {
                            // ignore
                            }
                            return;
                        }
                    }
                    // end query processing
                    String addressHelper = addressHelpers.get(destination);
                    if (addressHelper != null) {
                        host = getHostName(addressHelper);
                    }
                    // now strip everything but path and query from URI
                    targetRequest = requestURI.toASCIIString();
                    String newURI = requestURI.getRawPath();
                    if (query != null) {
                        newURI += '?' + query;
                    }
                    try {
                        requestURI = new URI(newURI);
                    } catch (URISyntaxException use) {
                        // shouldnt happen
                        _log.warn(request, use);
                        method = null;
                        break;
                    }
                // end of (host endsWith(".i2p"))
                } else if (hostLowerCase.equals("localhost") || host.equals("127.0.0.1") || host.startsWith("192.168.") || host.equals("[::1]")) {
                    // if somebody is trying to get to 192.168.example.com, oh well
                    try {
                        out.write(getErrorPage("localhost", ERR_LOCALHOST).getBytes("UTF-8"));
                        writeFooter(out);
                        reader.drain();
                    } catch (IOException ioe) {
                    // ignore
                    }
                    return;
                } else if (host.contains(".") || host.startsWith("[")) {
                    if (Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USE_OUTPROXY_PLUGIN, "true"))) {
                        ClientAppManager mgr = _context.clientAppManager();
                        if (mgr != null) {
                            ClientApp op = mgr.getRegisteredApp(Outproxy.NAME);
                            if (op != null) {
                                outproxy = (Outproxy) op;
                                int rPort = requestURI.getPort();
                                if (rPort > 0)
                                    remotePort = rPort;
                                else if ("https".equals(protocol) || method.toUpperCase(Locale.US).equals("CONNECT"))
                                    remotePort = 443;
                                else
                                    remotePort = 80;
                                usingInternalOutproxy = true;
                                targetRequest = requestURI.toASCIIString();
                                if (_log.shouldLog(Log.DEBUG))
                                    _log.debug(getPrefix(requestId) + " [" + host + "]: outproxy!");
                            }
                        }
                    }
                    if (!usingInternalOutproxy) {
                        if (port >= 0) {
                            host = host + ':' + port;
                        }
                        // The request must be forwarded to a WWW proxy
                        if (_log.shouldLog(Log.DEBUG)) {
                            _log.debug("Before selecting outproxy for " + host);
                        }
                        if ("https".equals(protocol) || method.toUpperCase(Locale.US).equals("CONNECT"))
                            currentProxy = selectSSLProxy();
                        else
                            currentProxy = selectProxy();
                        if (_log.shouldLog(Log.DEBUG)) {
                            _log.debug("After selecting outproxy for " + host + ": " + currentProxy);
                        }
                        if (currentProxy == null) {
                            if (_log.shouldLog(Log.WARN)) {
                                _log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
                            }
                            l.log("No outproxy found for the request.");
                            try {
                                out.write(getErrorPage("noproxy", ERR_NO_OUTPROXY).getBytes("UTF-8"));
                                writeFooter(out);
                                reader.drain();
                            } catch (IOException ioe) {
                            // ignore
                            }
                            return;
                        }
                        destination = currentProxy;
                        usingWWWProxy = true;
                        targetRequest = requestURI.toASCIIString();
                        if (_log.shouldLog(Log.DEBUG)) {
                            _log.debug(getPrefix(requestId) + " [" + host + "]: wwwProxy!");
                        }
                    }
                } else {
                    // Rather than look it up, just bail out.
                    if (_log.shouldLog(Log.WARN)) {
                        _log.warn("NODOTS, NOI2P: " + request);
                    }
                    try {
                        out.write(getErrorPage("denied", ERR_REQUEST_DENIED).getBytes("UTF-8"));
                        writeFooter(out);
                        reader.drain();
                    } catch (IOException ioe) {
                    // ignore
                    }
                    return;
                }
                // end host name processing
                boolean isValid = usingInternalOutproxy || usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
                if (!isValid) {
                    if (_log.shouldLog(Log.INFO)) {
                        _log.info(getPrefix(requestId) + "notValid(" + host + ")");
                    }
                    method = null;
                    destination = null;
                    break;
                }
                if (method.toUpperCase(Locale.US).equals("CONNECT")) {
                    // fix up the change to requestURI above to get back to the original host:port
                    line = method + ' ' + requestURI.getHost() + ':' + requestURI.getPort() + ' ' + protocolVersion;
                } else {
                    line = method + ' ' + requestURI.toASCIIString() + ' ' + protocolVersion;
                }
                if (_log.shouldLog(Log.DEBUG)) {
                    _log.debug(getPrefix(requestId) + "NEWREQ: \"" + line + "\"");
                    _log.debug(getPrefix(requestId) + "HOST  : \"" + host + "\"");
                    _log.debug(getPrefix(requestId) + "DEST  : \"" + destination + "\"");
                }
            // end first line processing
            } else {
                if (lowercaseLine.startsWith("host: ") && !usingWWWProxy && !usingInternalOutproxy) {
                    // Note that we only pass the original Host: line through to the outproxy
                    // But we don't create a Host: line if it wasn't sent to us
                    line = "Host: " + host;
                    if (_log.shouldLog(Log.INFO)) {
                        _log.info(getPrefix(requestId) + "Setting host = " + host);
                    }
                } else if (lowercaseLine.startsWith("user-agent: ")) {
                    // save for deciding whether to offer address book form
                    userAgent = lowercaseLine.substring(12);
                    if (!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT))) {
                        line = null;
                        continue;
                    }
                } else if (lowercaseLine.startsWith("accept: ")) {
                    if (!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_ACCEPT))) {
                        // Replace with a standard one if possible
                        boolean html = lowercaseLine.indexOf("text/html") > 0;
                        boolean css = lowercaseLine.indexOf("text/css") > 0;
                        boolean img = lowercaseLine.indexOf("image") > 0;
                        if (html && !img && !css) {
                            // firefox, tor browser
                            line = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                        } else if (img && !html && !css) {
                            // chrome
                            line = "Accept: image/webp,image/apng,image/*,*/*;q=0.8";
                        } else if (css && !html && !img) {
                            // chrome, firefox
                            line = "Accept: text/css,*/*;q=0.1";
                        }
                    // else allow as-is
                    }
                } else if (lowercaseLine.startsWith("accept")) {
                    // But allow Accept-Encoding: gzip, deflate
                    if (!lowercaseLine.startsWith("accept-encoding: ") && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_ACCEPT))) {
                        line = null;
                        continue;
                    }
                } else if (lowercaseLine.startsWith("referer: ")) {
                    // save for address helper form below
                    referer = line.substring(9);
                    if (!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_REFERER))) {
                        try {
                            // Either strip or rewrite the referer line
                            URI refererURI = new URI(referer);
                            String refererHost = refererURI.getHost();
                            if (refererHost != null) {
                                String origHost = origRequestURI.getHost();
                                if (!refererHost.equals(origHost) || refererURI.getPort() != origRequestURI.getPort() || !DataHelper.eq(refererURI.getScheme(), origRequestURI.getScheme())) {
                                    line = null;
                                    // completely strip the line if everything doesn't match
                                    continue;
                                }
                                // Strip to a relative URI, to hide the original host name
                                StringBuilder buf = new StringBuilder();
                                buf.append("Referer: ");
                                String refererPath = refererURI.getRawPath();
                                buf.append(refererPath != null ? refererPath : "/");
                                String refererQuery = refererURI.getRawQuery();
                                if (refererQuery != null)
                                    buf.append('?').append(refererQuery);
                                line = buf.toString();
                            }
                        // else relative URI, leave in
                        } catch (URISyntaxException use) {
                            line = null;
                            // completely strip the line
                            continue;
                        }
                    }
                // else allow
                } else if (lowercaseLine.startsWith("via: ") && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_VIA))) {
                    // line = "Via: i2p";
                    line = null;
                    // completely strip the line
                    continue;
                } else if (lowercaseLine.startsWith("from: ")) {
                    // line = "From: i2p";
                    line = null;
                    // completely strip the line
                    continue;
                } else if (lowercaseLine.startsWith("authorization: ntlm ")) {
                    // Block Windows NTLM after 401
                    line = null;
                    continue;
                } else if (lowercaseLine.startsWith("proxy-authorization: ")) {
                    // This should be for us. It is a
                    // hop-by-hop header, and we definitely want to block Windows NTLM after a far-end 407.
                    // Response to far-end shouldn't happen, as we
                    // strip Proxy-Authenticate from the response in HTTPResponseOutputStream
                    // "proxy-authorization: ".length()
                    authorization = line.substring(21);
                    line = null;
                    continue;
                } else if (lowercaseLine.startsWith("icy")) {
                    // icecast/shoutcast, We need to leave the user-agent alone.
                    shout = true;
                }
            }
            if (line.length() == 0) {
                // No more headers, add our own and break out of the loop
                String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
                boolean gzip = DEFAULT_GZIP;
                if (ok != null) {
                    gzip = Boolean.parseBoolean(ok);
                }
                if (gzip && !usingInternalServer && !method.toUpperCase(Locale.US).equals("CONNECT")) {
                    // newRequest.append("Accept-Encoding: \r\n");
                    if (!usingInternalOutproxy)
                        newRequest.append("X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n");
                }
                if (!shout && !method.toUpperCase(Locale.US).equals("CONNECT")) {
                    if (!Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT))) {
                        // let's not advertise to external sites that we are from I2P
                        if (usingWWWProxy || usingInternalOutproxy) {
                            newRequest.append(UA_CLEARNET);
                        } else {
                            newRequest.append(UA_I2P);
                        }
                    }
                }
                // Add Proxy-Authentication header for next hop (outproxy)
                if (usingWWWProxy && Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_AUTH))) {
                    // specific for this proxy
                    String user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER_PREFIX + currentProxy);
                    String pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW_PREFIX + currentProxy);
                    if (user == null || pw == null) {
                        // if not, look at default user and pw
                        user = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_USER);
                        pw = getTunnel().getClientOptions().getProperty(PROP_OUTPROXY_PW);
                    }
                    if (user != null && pw != null) {
                        newRequest.append("Proxy-Authorization: Basic ").append(// true = use standard alphabet
                        Base64.encode((user + ':' + pw).getBytes("UTF-8"), true)).append("\r\n");
                    }
                }
                newRequest.append("Connection: close\r\n\r\n");
                s.setSoTimeout(0);
                break;
            } else {
                // HTTP spec
                newRequest.append(line).append("\r\n");
            }
        }
        if (_log.shouldLog(Log.DEBUG)) {
            _log.debug(getPrefix(requestId) + "NewRequest header: [" + newRequest.toString() + "]");
        }
        if (method == null || (destination == null && !usingInternalOutproxy)) {
            // l.log("No HTTP method found in the request.");
            try {
                if (protocol != null && "http".equals(protocol.toLowerCase(Locale.US))) {
                    out.write(getErrorPage("denied", ERR_REQUEST_DENIED).getBytes("UTF-8"));
                } else {
                    out.write(getErrorPage("protocol", ERR_BAD_PROTOCOL).getBytes("UTF-8"));
                }
                writeFooter(out);
            } catch (IOException ioe) {
            // ignore
            }
            return;
        }
        if (_log.shouldLog(Log.DEBUG)) {
            _log.debug(getPrefix(requestId) + "Destination: " + destination);
        }
        // Authorization
        AuthResult result = authorize(s, requestId, method, authorization);
        if (result != AuthResult.AUTH_GOOD) {
            if (_log.shouldLog(Log.WARN)) {
                if (authorization != null) {
                    _log.warn(getPrefix(requestId) + "Auth failed, sending 407 again");
                } else {
                    _log.warn(getPrefix(requestId) + "Auth required, sending 407");
                }
            }
            try {
                out.write(getAuthError(result == AuthResult.AUTH_STALE).getBytes("UTF-8"));
                writeFooter(out);
            } catch (IOException ioe) {
            // ignore
            }
            return;
        }
        // Ignore all the headers
        if (usingInternalServer) {
            try {
                // disable the add form if address helper is disabled
                if (internalPath.equals("/add") && Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) {
                    out.write(ERR_HELPER_DISABLED.getBytes("UTF-8"));
                } else {
                    LocalHTTPServer.serveLocalFile(out, method, internalPath, internalRawQuery, _proxyNonce);
                }
            } catch (IOException ioe) {
            // ignore
            }
            return;
        }
        // no destination, going to outproxy plugin
        if (usingInternalOutproxy) {
            Socket outSocket = outproxy.connect(host, remotePort);
            OnTimeout onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
            byte[] data;
            byte[] response;
            if (method.toUpperCase(Locale.US).equals("CONNECT")) {
                data = null;
                response = SUCCESS_RESPONSE.getBytes("UTF-8");
            } else {
                data = newRequest.toString().getBytes("ISO-8859-1");
                response = null;
            }
            Thread t = new I2PTunnelOutproxyRunner(s, outSocket, sockLock, data, response, onTimeout);
            // we are called from an unlimited thread pool, so run inline
            // t.start();
            t.run();
            return;
        }
        // LOOKUP
        // If the host is "i2p", the getHostName() lookup failed, don't try to
        // look it up again as the naming service does not do negative caching
        // so it will be slow.
        Destination clientDest = null;
        String addressHelper = addressHelpers.get(destination.toLowerCase(Locale.US));
        if (addressHelper != null) {
            clientDest = _context.namingService().lookup(addressHelper);
            if (clientDest == null) {
                // remove bad entries
                addressHelpers.remove(destination.toLowerCase(Locale.US));
                if (_log.shouldLog(Log.WARN)) {
                    _log.warn(getPrefix(requestId) + "Could not find destination for " + addressHelper);
                }
                String header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
                try {
                    writeErrorMessage(header, out, targetRequest, false, destination);
                } catch (IOException ioe) {
                // ignore
                }
                return;
            }
        } else if ("i2p".equals(host)) {
            clientDest = null;
        } else if (destination.length() == 60 && destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
            // use existing session to look up for efficiency
            verifySocketManager();
            I2PSession sess = sockMgr.getSession();
            if (!sess.isClosed()) {
                byte[] hData = Base32.decode(destination.substring(0, 52));
                if (hData != null) {
                    if (_log.shouldLog(Log.INFO)) {
                        _log.info("lookup in-session " + destination);
                    }
                    Hash hash = Hash.create(hData);
                    clientDest = sess.lookupDest(hash, 20 * 1000);
                }
            } else {
                clientDest = _context.namingService().lookup(destination);
            }
        } else {
            clientDest = _context.namingService().lookup(destination);
        }
        if (clientDest == null) {
            // l.log("Could not resolve " + destination + ".");
            if (_log.shouldLog(Log.WARN)) {
                _log.warn("Unable to resolve " + destination + " (proxy? " + usingWWWProxy + ", request: " + targetRequest);
            }
            String header;
            String jumpServers = null;
            String extraMessage = null;
            if (usingWWWProxy) {
                header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN);
            } else if (ahelperPresent) {
                header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
            } else if (destination.length() == 60 && destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
                header = getErrorPage("nols", ERR_DESTINATION_UNKNOWN);
                extraMessage = _t("Destination lease set not found");
            } else {
                header = getErrorPage("dnfh", ERR_DESTINATION_UNKNOWN);
                jumpServers = getTunnel().getClientOptions().getProperty(PROP_JUMP_SERVERS);
                if (jumpServers == null) {
                    jumpServers = DEFAULT_JUMP_SERVERS;
                }
                int jumpDelay = 400 + _context.random().nextInt(256);
                try {
                    Thread.sleep(jumpDelay);
                } catch (InterruptedException ie) {
                }
            }
            try {
                writeErrorMessage(header, extraMessage, out, targetRequest, usingWWWProxy, destination, jumpServers);
            } catch (IOException ioe) {
            // ignore
            }
            return;
        }
        if (method.toUpperCase(Locale.US).equals("CONNECT") && !usingWWWProxy && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_INTERNAL_SSL))) {
            try {
                writeErrorMessage(ERR_INTERNAL_SSL, out, targetRequest, false, destination);
            } catch (IOException ioe) {
            // ignore
            }
            if (_log.shouldLog(Log.WARN))
                _log.warn("SSL to i2p destinations denied by configuration: " + targetRequest);
            return;
        }
        // Don't do this for eepget, which uses a user-agent of "Wget"
        if (ahelperNew && "GET".equals(method) && (userAgent == null || !userAgent.startsWith("Wget")) && !Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER))) {
            try {
                writeHelperSaveForm(out, destination, ahelperKey, targetRequest, referer);
            } catch (IOException ioe) {
            // ignore
            }
            return;
        }
        // Syndie can't handle a redirect of a POST
        if (ahelperPresent && !"POST".equals(method)) {
            String uri = targetRequest;
            if (_log.shouldLog(Log.DEBUG)) {
                _log.debug("Auto redirecting to " + uri);
            }
            try {
                out.write(("HTTP/1.1 301 Address Helper Accepted\r\n" + "Location: " + uri + "\r\n" + "Connection: close\r\n" + "Proxy-Connection: close\r\n" + "\r\n").getBytes("UTF-8"));
            } catch (IOException ioe) {
            // ignore
            }
            return;
        }
        Properties opts = new Properties();
        // opts.setProperty("i2p.streaming.inactivityTimeout", ""+120*1000);
        // 1 == disconnect.  see ConnectionOptions in the new streaming lib, which i
        // dont want to hard link to here
        // opts.setProperty("i2p.streaming.inactivityTimeoutAction", ""+1);
        I2PSocketOptions sktOpts = getDefaultOptions(opts);
        if (remotePort > 0)
            sktOpts.setPort(remotePort);
        i2ps = createI2PSocket(clientDest, sktOpts);
        OnTimeout onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
        Thread t;
        if (method.toUpperCase(Locale.US).equals("CONNECT")) {
            byte[] data;
            byte[] response;
            if (usingWWWProxy) {
                data = newRequest.toString().getBytes("ISO-8859-1");
                response = null;
            } else {
                data = null;
                response = SUCCESS_RESPONSE.getBytes("UTF-8");
            }
            t = new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout);
        } else {
            byte[] data = newRequest.toString().getBytes("ISO-8859-1");
            t = new I2PTunnelHTTPClientRunner(s, i2ps, sockLock, data, mySockets, onTimeout);
        }
        // we are called from an unlimited thread pool, so run inline
        // t.start();
        t.run();
    } catch (IOException ex) {
        if (_log.shouldLog(Log.INFO)) {
            _log.info(getPrefix(requestId) + "Error trying to connect", ex);
        }
        handleClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
    } catch (I2PException ex) {
        if (_log.shouldLog(Log.INFO)) {
            _log.info("getPrefix(requestId) + Error trying to connect", ex);
        }
        handleClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
    } catch (OutOfMemoryError oom) {
        IOException ex = new IOException("OOM");
        _log.error("getPrefix(requestId) + Error trying to connect", oom);
        handleClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
    } finally {
        // only because we are running it inline
        closeSocket(s);
        if (i2ps != null)
            try {
                i2ps.close();
            } catch (IOException ioe) {
            }
    }
}
Also used : Destination(net.i2p.data.Destination) ClientApp(net.i2p.app.ClientApp) OutputStream(java.io.OutputStream) Outproxy(net.i2p.app.Outproxy) URISyntaxException(java.net.URISyntaxException) Hash(net.i2p.data.Hash) ConvertToHash(net.i2p.util.ConvertToHash) Properties(java.util.Properties) URI(java.net.URI) I2PSession(net.i2p.client.I2PSession) I2PException(net.i2p.I2PException) I2PSocket(net.i2p.client.streaming.I2PSocket) I2PSocketOptions(net.i2p.client.streaming.I2PSocketOptions) IOException(java.io.IOException) ClientAppManager(net.i2p.app.ClientAppManager) Socket(java.net.Socket) I2PSocket(net.i2p.client.streaming.I2PSocket)

Aggregations

I2PSession (net.i2p.client.I2PSession)37 Properties (java.util.Properties)13 I2PSessionException (net.i2p.client.I2PSessionException)12 ByteArrayInputStream (java.io.ByteArrayInputStream)10 Destination (net.i2p.data.Destination)10 I2PClient (net.i2p.client.I2PClient)9 ByteArrayOutputStream (java.io.ByteArrayOutputStream)8 IOException (java.io.IOException)8 I2PException (net.i2p.I2PException)5 Hash (net.i2p.data.Hash)4 File (java.io.File)3 FileInputStream (java.io.FileInputStream)3 I2PSimpleClient (net.i2p.client.I2PSimpleClient)3 I2PSocket (net.i2p.client.streaming.I2PSocket)3 DataFormatException (net.i2p.data.DataFormatException)3 Log (net.i2p.util.Log)3 InterruptedIOException (java.io.InterruptedIOException)2 URI (java.net.URI)2 URISyntaxException (java.net.URISyntaxException)2 GeneralSecurityException (java.security.GeneralSecurityException)2