Search in sources :

Example 1 with I2PSocket

use of net.i2p.client.streaming.I2PSocket 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 2 with I2PSocket

use of net.i2p.client.streaming.I2PSocket in project i2p.i2p by i2p.

the class SAMStreamSession method connect.

/**
 * Connect the SAM STREAM session to the specified Destination
 *
 * @param id Unique id for the connection
 * @param dest Base64-encoded Destination to connect to
 * @param props Options to be used for connection
 *
 * @return true if successful
 * @throws DataFormatException if the destination is not valid
 * @throws SAMInvalidDirectionException if trying to connect through a
 *                                      receive-only session
 * @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 boolean connect(int id, String dest, Properties props) throws I2PException, ConnectException, NoRouteToHostException, DataFormatException, InterruptedIOException, SAMInvalidDirectionException, IOException {
    if (!canCreate) {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Trying to create an outgoing connection using a receive-only session");
        throw new SAMInvalidDirectionException("Trying to create connections through a receive-only session");
    }
    if (checkSocketHandlerId(id)) {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("The specified id (" + id + ") is already in use");
        return false;
    }
    Destination d = SAMUtils.getDest(dest);
    I2PSocketOptions opts = socketMgr.buildOptions(props);
    if (props.getProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT) == null)
        opts.setConnectTimeout(60 * 1000);
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Connecting new I2PSocket...");
    // blocking connection (SAMv1)
    I2PSocket i2ps = socketMgr.connect(d, opts);
    createSocketHandler(i2ps, id);
    recv.notifyStreamOutgoingConnection(id, "OK", null);
    return true;
}
Also used : Destination(net.i2p.data.Destination) I2PSocket(net.i2p.client.streaming.I2PSocket) I2PSocketOptions(net.i2p.client.streaming.I2PSocketOptions)

Example 3 with I2PSocket

use of net.i2p.client.streaming.I2PSocket in project i2p.i2p by i2p.

the class I2PTunnelClient method clientConnectionRun.

protected void clientConnectionRun(Socket s) {
    I2PSocket i2ps = null;
    try {
        I2PSocketAddress addr = pickDestination();
        if (addr == null)
            throw new UnknownHostException("No valid destination configured");
        Destination clientDest = addr.getAddress();
        if (clientDest == null)
            throw new UnknownHostException("Could not resolve " + addr.getHostName());
        int port = addr.getPort();
        i2ps = createI2PSocket(clientDest, port);
        i2ps.setReadTimeout(readTimeout);
        I2PTunnelRunner t = new I2PTunnelRunner(s, i2ps, sockLock, null, null, mySockets, (I2PTunnelRunner.FailCallback) null);
        // 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("Error connecting", ex);
    } catch (I2PException ex) {
        if (_log.shouldLog(Log.INFO))
            _log.info("Error connecting", ex);
    } finally {
        // only because we are running it inline
        closeSocket(s);
        if (i2ps != null) {
            try {
                i2ps.close();
            } catch (IOException ioe) {
            }
            synchronized (sockLock) {
                mySockets.remove(i2ps);
            }
        }
    }
}
Also used : I2PException(net.i2p.I2PException) Destination(net.i2p.data.Destination) UnknownHostException(java.net.UnknownHostException) I2PSocketAddress(net.i2p.client.streaming.I2PSocketAddress) I2PSocket(net.i2p.client.streaming.I2PSocket) IOException(java.io.IOException)

Example 4 with I2PSocket

use of net.i2p.client.streaming.I2PSocket 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 I2PSocket

use of net.i2p.client.streaming.I2PSocket in project i2p.i2p by i2p.

the class I2PTunnelConnectClient method clientConnectionRun.

protected void clientConnectionRun(Socket s) {
    InputStream in = null;
    OutputStream out = null;
    String targetRequest = null;
    boolean usingWWWProxy = false;
    String currentProxy = null;
    // local outproxy plugin
    boolean usingInternalOutproxy = false;
    Outproxy outproxy = null;
    long requestId = __requestId.incrementAndGet();
    I2PSocket i2ps = null;
    try {
        s.setSoTimeout(INITIAL_SO_TIMEOUT);
        out = s.getOutputStream();
        in = s.getInputStream();
        String line, method = null, host = null, destination = null, restofline = null;
        StringBuilder newRequest = new StringBuilder();
        String authorization = null;
        int remotePort = 443;
        while (true) {
            // Use this rather than BufferedReader because we can't have readahead,
            // since we are passing the stream on to I2PTunnelRunner
            line = DataHelper.readLine(in);
            if (line == null) {
                break;
            }
            line = line.trim();
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(getPrefix(requestId) + "Line=[" + line + "]");
            if (method == null) {
                // first line CONNECT blah.i2p:80 HTTP/1.1
                int pos = line.indexOf(' ');
                // empty first line
                if (pos == -1)
                    break;
                method = line.substring(0, pos);
                String request = line.substring(pos + 1);
                pos = request.indexOf(':');
                if (pos == -1) {
                    pos = request.indexOf(' ');
                } else {
                    int spos = request.indexOf(' ');
                    if (spos > 0) {
                        try {
                            remotePort = Integer.parseInt(request.substring(pos + 1, spos));
                        } catch (NumberFormatException nfe) {
                            break;
                        } catch (IndexOutOfBoundsException ioobe) {
                            break;
                        }
                    }
                }
                if (pos == -1) {
                    host = request;
                    restofline = "";
                } else {
                    host = request.substring(0, pos);
                    // ":80 HTTP/1.1" or " HTTP/1.1"
                    restofline = request.substring(pos);
                }
                if (host.toLowerCase(Locale.US).endsWith(".i2p")) {
                    // Destination gets the host name
                    destination = host;
                } 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;
                                usingInternalOutproxy = true;
                                if (host.startsWith("[")) {
                                    host = host.substring(1);
                                    if (host.endsWith("]"))
                                        host = host.substring(0, host.length() - 1);
                                }
                            }
                        }
                    }
                    if (!usingInternalOutproxy) {
                        // The request must be forwarded to a outproxy
                        currentProxy = selectProxy();
                        if (currentProxy == null) {
                            if (_log.shouldLog(Log.WARN))
                                _log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
                            writeErrorMessage(ERR_NO_OUTPROXY, out);
                            return;
                        }
                        destination = currentProxy;
                        usingWWWProxy = true;
                        // HTTP spec
                        newRequest.append("CONNECT ").append(host).append(restofline).append("\r\n");
                    }
                } else if (host.toLowerCase(Locale.US).equals("localhost")) {
                    writeErrorMessage(ERR_LOCALHOST, out);
                    return;
                } else {
                    // full b64 address (hopefully)
                    destination = host;
                }
                targetRequest = host;
                if (_log.shouldLog(Log.DEBUG)) {
                    _log.debug(getPrefix(requestId) + "METHOD:" + method + ":\n" + "HOST  :" + host + ":\n" + "PORT  :" + remotePort + ":\n" + "REST  :" + restofline + ":\n" + "DEST  :" + destination + ":\n" + "www proxy? " + usingWWWProxy + " internal proxy? " + usingInternalOutproxy);
                }
            } else if (line.toLowerCase(Locale.US).startsWith("proxy-authorization: ")) {
                // strip Proxy-Authenticate from the response in HTTPResponseOutputStream
                // save for auth check below
                // "proxy-authorization: ".length()
                authorization = line.substring(21);
                line = null;
            } else if (line.length() > 0) {
                // Additional lines - shouldn't be too many. Firefox sends:
                // User-Agent: blabla
                // Proxy-Connection: keep-alive
                // Host: blabla.i2p
                // 
                // We could send these (filtered like in HTTPClient) on to the outproxy,
                // but for now just chomp them all.
                line = null;
            } else {
                // 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(DataHelper.getUTF8(user + ':' + pw), true)).append("\r\n");
                    }
                }
                // HTTP spec
                newRequest.append("\r\n");
                s.setSoTimeout(0);
                // do it
                break;
            }
        }
        if (method == null || !"CONNECT".equals(method.toUpperCase(Locale.US))) {
            writeErrorMessage(ERR_BAD_PROTOCOL, out);
            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[] response = SUCCESS_RESPONSE.getBytes("UTF-8");
            Thread t = new I2PTunnelOutproxyRunner(s, outSocket, sockLock, null, response, onTimeout);
            // we are called from an unlimited thread pool, so run inline
            t.run();
            return;
        }
        if (destination == null) {
            writeErrorMessage(ERR_BAD_PROTOCOL, out);
            return;
        }
        // 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");
            }
            out.write(DataHelper.getASCII(getAuthError(result == AuthResult.AUTH_STALE)));
            return;
        }
        Destination clientDest = _context.namingService().lookup(destination);
        if (clientDest == null) {
            String header;
            if (usingWWWProxy)
                header = getErrorPage("dnfp", ERR_DESTINATION_UNKNOWN);
            else
                header = getErrorPage("dnfh", ERR_DESTINATION_UNKNOWN);
            writeErrorMessage(header, out, targetRequest, usingWWWProxy, destination);
            return;
        }
        I2PSocketOptions sktOpts = getDefaultOptions();
        if (!usingWWWProxy && remotePort > 0)
            sktOpts.setPort(remotePort);
        i2ps = createI2PSocket(clientDest, sktOpts);
        byte[] data = null;
        byte[] response = null;
        if (usingWWWProxy)
            data = newRequest.toString().getBytes("ISO-8859-1");
        else
            response = SUCCESS_RESPONSE.getBytes("UTF-8");
        OnTimeout onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
        Thread t = new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout);
        // we are called from an unlimited thread pool, so run inline
        // t.start();
        t.run();
    } catch (IOException ex) {
        _log.info(getPrefix(requestId) + "Error trying to connect", ex);
        handleClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
    } catch (I2PException ex) {
        _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.info("getPrefix(requestId) + Error trying to connect", ex);
        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) I2PException(net.i2p.I2PException) InputStream(java.io.InputStream) 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

I2PSocket (net.i2p.client.streaming.I2PSocket)28 IOException (java.io.IOException)21 I2PException (net.i2p.I2PException)15 Destination (net.i2p.data.Destination)12 Socket (java.net.Socket)8 I2PSocketOptions (net.i2p.client.streaming.I2PSocketOptions)8 I2PAppThread (net.i2p.util.I2PAppThread)7 SocketException (java.net.SocketException)6 Properties (java.util.Properties)5 SOCKSException (net.i2p.socks.SOCKSException)5 InterruptedIOException (java.io.InterruptedIOException)4 OutputStream (java.io.OutputStream)4 ConnectException (java.net.ConnectException)4 SocketTimeoutException (java.net.SocketTimeoutException)4 Outproxy (net.i2p.app.Outproxy)4 Hash (net.i2p.data.Hash)4 DataOutputStream (java.io.DataOutputStream)3 InputStream (java.io.InputStream)3 List (java.util.List)3 I2PSession (net.i2p.client.I2PSession)3