Search in sources :

Example 6 with Socks5BytestreamSession

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession in project Smack by igniterealtime.

the class Socks5BytestreamRequest method accept.

/**
 * Accepts the SOCKS5 Bytestream initialization request and returns the socket to send/receive
 * data.
 * <p>
 * Before accepting the SOCKS5 Bytestream request you can set timeouts by invoking
 * {@link #setTotalConnectTimeout(int)} and {@link #setMinimumConnectTimeout(int)}.
 *
 * @return the socket to send/receive data
 * @throws InterruptedException if the current thread was interrupted while waiting
 * @throws XMPPErrorException if there was an XMPP error returned.
 * @throws NotConnectedException if the XMPP connection is not connected.
 * @throws CouldNotConnectToAnyProvidedSocks5Host if no connection to any provided stream host could be established
 * @throws NoSocks5StreamHostsProvided if no stream host was provided.
 */
@Override
public Socks5BytestreamSession accept() throws InterruptedException, XMPPErrorException, CouldNotConnectToAnyProvidedSocks5Host, NotConnectedException, NoSocks5StreamHostsProvided {
    Collection<StreamHost> streamHosts = this.bytestreamRequest.getStreamHosts();
    Map<StreamHost, Exception> streamHostsExceptions = new HashMap<>();
    // throw exceptions if request contains no stream hosts
    if (streamHosts.size() == 0) {
        cancelRequest(streamHostsExceptions);
    }
    StreamHost selectedHost = null;
    Socket socket = null;
    String digest = Socks5Utils.createDigest(this.bytestreamRequest.getSessionID(), this.bytestreamRequest.getFrom(), this.manager.getConnection().getUser());
    /*
         * determine timeout for each connection attempt; each SOCKS5 proxy has the same amount of
         * time so that the first does not consume the whole timeout
         */
    int timeout = Math.max(getTotalConnectTimeout() / streamHosts.size(), getMinimumConnectTimeout());
    for (StreamHost streamHost : streamHosts) {
        String address = streamHost.getAddress() + ":" + streamHost.getPort();
        // check to see if this address has been blacklisted
        int failures = getConnectionFailures(address);
        if (connectionFailureThreshold > 0 && failures >= connectionFailureThreshold) {
            continue;
        }
        // establish socket
        try {
            // build SOCKS5 client
            final Socks5Client socks5Client = new Socks5Client(streamHost, digest);
            // connect to SOCKS5 proxy with a timeout
            socket = socks5Client.getSocket(timeout);
            // set selected host
            selectedHost = streamHost;
            break;
        } catch (TimeoutException | IOException | SmackException | XMPPException e) {
            streamHostsExceptions.put(streamHost, e);
            incrementConnectionFailures(address);
        }
    }
    // throw exception if connecting to all SOCKS5 proxies failed
    if (selectedHost == null || socket == null) {
        cancelRequest(streamHostsExceptions);
    }
    // send used-host confirmation
    Bytestream response = createUsedHostResponse(selectedHost);
    this.manager.getConnection().sendStanza(response);
    return new Socks5BytestreamSession(socket, selectedHost.getJID().equals(this.bytestreamRequest.getFrom()));
}
Also used : HashMap(java.util.HashMap) SmackException(org.jivesoftware.smack.SmackException) IOException(java.io.IOException) SmackException(org.jivesoftware.smack.SmackException) NotConnectedException(org.jivesoftware.smack.SmackException.NotConnectedException) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) XMPPErrorException(org.jivesoftware.smack.XMPPException.XMPPErrorException) XMPPException(org.jivesoftware.smack.XMPPException) Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) XMPPException(org.jivesoftware.smack.XMPPException) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Socket(java.net.Socket) TimeoutException(java.util.concurrent.TimeoutException)

Example 7 with Socks5BytestreamSession

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession in project ecf by eclipse.

the class Socks5BytestreamRequest method accept.

/**
 * Accepts the SOCKS5 Bytestream initialization request and returns the socket to send/receive
 * data.
 * <p>
 * Before accepting the SOCKS5 Bytestream request you can set timeouts by invoking
 * {@link #setTotalConnectTimeout(int)} and {@link #setMinimumConnectTimeout(int)}.
 *
 * @return the socket to send/receive data
 * @throws XMPPException if connection to all SOCKS5 proxies failed or if stream is invalid.
 * @throws InterruptedException if the current thread was interrupted while waiting
 */
public Socks5BytestreamSession accept() throws XMPPException, InterruptedException {
    Collection<StreamHost> streamHosts = this.bytestreamRequest.getStreamHosts();
    // throw exceptions if request contains no stream hosts
    if (streamHosts.size() == 0) {
        cancelRequest();
    }
    StreamHost selectedHost = null;
    Socket socket = null;
    String digest = Socks5Utils.createDigest(this.bytestreamRequest.getSessionID(), this.bytestreamRequest.getFrom(), this.manager.getConnection().getUser());
    /*
         * determine timeout for each connection attempt; each SOCKS5 proxy has the same amount of
         * time so that the first does not consume the whole timeout
         */
    int timeout = Math.max(getTotalConnectTimeout() / streamHosts.size(), getMinimumConnectTimeout());
    for (StreamHost streamHost : streamHosts) {
        String address = streamHost.getAddress() + ":" + streamHost.getPort();
        // check to see if this address has been blacklisted
        int failures = getConnectionFailures(address);
        if (CONNECTION_FAILURE_THRESHOLD > 0 && failures >= CONNECTION_FAILURE_THRESHOLD) {
            continue;
        }
        // establish socket
        try {
            // build SOCKS5 client
            final Socks5Client socks5Client = new Socks5Client(streamHost, digest);
            // connect to SOCKS5 proxy with a timeout
            socket = socks5Client.getSocket(timeout);
            // set selected host
            selectedHost = streamHost;
            break;
        } catch (TimeoutException e) {
            incrementConnectionFailures(address);
        } catch (IOException e) {
            incrementConnectionFailures(address);
        } catch (XMPPException e) {
            incrementConnectionFailures(address);
        }
    }
    // throw exception if connecting to all SOCKS5 proxies failed
    if (selectedHost == null || socket == null) {
        cancelRequest();
    }
    // send used-host confirmation
    Bytestream response = createUsedHostResponse(selectedHost);
    this.manager.getConnection().sendPacket(response);
    return new Socks5BytestreamSession(socket, selectedHost.getJID().equals(this.bytestreamRequest.getFrom()));
}
Also used : Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) IOException(java.io.IOException) XMPPException(org.jivesoftware.smack.XMPPException) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Socket(java.net.Socket) TimeoutException(java.util.concurrent.TimeoutException)

Example 8 with Socks5BytestreamSession

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession in project Smack by igniterealtime.

the class Socks5BytestreamManager method establishSession.

/**
 * Establishes a SOCKS5 Bytestream with the given user using the given session ID and returns
 * the Socket to send/receive data to/from the user.
 *
 * @param targetJID the JID of the user a SOCKS5 Bytestream should be established
 * @param sessionID the session ID for the SOCKS5 Bytestream request
 * @return the Socket to send/receive data to/from the user
 * @throws IOException if the bytestream could not be established
 * @throws InterruptedException if the current thread was interrupted while waiting
 * @throws XMPPException if an XMPP protocol error was received.
 * @throws NotConnectedException if the XMPP connection is not connected.
 * @throws NoResponseException if there was no response from the remote entity.
 * @throws SmackMessageException if there was an error.
 * @throws FeatureNotSupportedException if a requested feature is not supported by the remote entity.
 */
@Override
public Socks5BytestreamSession establishSession(Jid targetJID, String sessionID) throws IOException, InterruptedException, XMPPException, NoResponseException, NotConnectedException, SmackMessageException, FeatureNotSupportedException {
    XMPPConnection connection = connection();
    XMPPErrorException discoveryException = null;
    // check if target supports SOCKS5 Bytestream
    if (!supportsSocks5(targetJID)) {
        throw new FeatureNotSupportedException("SOCKS5 Bytestream", targetJID);
    }
    List<Jid> proxies = new ArrayList<>();
    // determine SOCKS5 proxies from XMPP-server
    try {
        proxies.addAll(determineProxies());
    } catch (XMPPErrorException e) {
        // don't abort here, just remember the exception thrown by determineProxies()
        // determineStreamHostInfos() will at least add the local Socks5 proxy (if enabled)
        discoveryException = e;
    }
    // determine address and port of each proxy
    List<StreamHost> streamHosts = determineStreamHostInfos(proxies);
    if (streamHosts.isEmpty()) {
        if (discoveryException != null) {
            throw discoveryException;
        } else {
            throw new SmackException.SmackMessageException("no SOCKS5 proxies available");
        }
    }
    // compute digest
    String digest = Socks5Utils.createDigest(sessionID, connection.getUser(), targetJID);
    // prioritize last working SOCKS5 proxy if exists
    if (this.proxyPrioritizationEnabled && this.lastWorkingProxy != null) {
        StreamHost selectedStreamHost = null;
        for (StreamHost streamHost : streamHosts) {
            if (streamHost.getJID().equals(this.lastWorkingProxy)) {
                selectedStreamHost = streamHost;
                break;
            }
        }
        if (selectedStreamHost != null) {
            streamHosts.remove(selectedStreamHost);
            streamHosts.add(0, selectedStreamHost);
        }
    }
    Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
    try {
        // add transfer digest to local proxy to make transfer valid
        socks5Proxy.addTransfer(digest);
        // create initiation packet
        Bytestream initiation = createBytestreamInitiation(sessionID, targetJID, streamHosts);
        // send initiation packet
        Stanza response = connection.createStanzaCollectorAndSend(initiation).nextResultOrThrow(getTargetResponseTimeout());
        // extract used stream host from response
        StreamHostUsed streamHostUsed = ((Bytestream) response).getUsedHost();
        StreamHost usedStreamHost = initiation.getStreamHost(streamHostUsed.getJID());
        if (usedStreamHost == null) {
            throw new SmackException.SmackMessageException("Remote user responded with unknown host");
        }
        // build SOCKS5 client
        Socks5Client socks5Client = new Socks5ClientForInitiator(usedStreamHost, digest, connection, sessionID, targetJID);
        // establish connection to proxy
        Socket socket = socks5Client.getSocket(getProxyConnectionTimeout());
        // remember last working SOCKS5 proxy to prioritize it for next request
        this.lastWorkingProxy = usedStreamHost.getJID();
        // negotiation successful, return the output stream
        return new Socks5BytestreamSession(socket, usedStreamHost.getJID().equals(connection.getUser()));
    } catch (TimeoutException e) {
        throw new IOException("Timeout while connecting to SOCKS5 proxy", e);
    } finally {
        // remove transfer digest if output stream is returned or an exception
        // occurred
        socks5Proxy.removeTransfer(digest);
    }
}
Also used : StreamHostUsed(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHostUsed) SmackMessageException(org.jivesoftware.smack.SmackException.SmackMessageException) XMPPErrorException(org.jivesoftware.smack.XMPPException.XMPPErrorException) Jid(org.jxmpp.jid.Jid) EntityFullJid(org.jxmpp.jid.EntityFullJid) Stanza(org.jivesoftware.smack.packet.Stanza) FeatureNotSupportedException(org.jivesoftware.smack.SmackException.FeatureNotSupportedException) ArrayList(java.util.ArrayList) XMPPConnection(org.jivesoftware.smack.XMPPConnection) IOException(java.io.IOException) Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Socket(java.net.Socket) TimeoutException(java.util.concurrent.TimeoutException)

Example 9 with Socks5BytestreamSession

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession in project Smack by igniterealtime.

the class JingleS5BTransportSession method handleCandidateActivate.

public IQ handleCandidateActivate(Jingle jingle) {
    LOGGER.log(Level.INFO, "handleCandidateActivate");
    Socks5BytestreamSession bs = new Socks5BytestreamSession(ourChoice.socket, ourChoice.candidate.getJid().asBareJid().equals(jingleSession.getRemote().asBareJid()));
    callback.onSessionInitiated(bs);
    return IQ.createResultIQ(jingle);
}
Also used : Socks5BytestreamSession(org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession)

Example 10 with Socks5BytestreamSession

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession in project Smack by igniterealtime.

the class JingleS5BTransportSession method connectIfReady.

/**
 * Determine, which candidate (ours/theirs) is the nominated one.
 * Connect to this candidate. If it is a proxy and it is ours, activate it and connect.
 * If its a proxy and it is theirs, wait for activation.
 * If it is not a proxy, just connect.
 */
private void connectIfReady() {
    JingleContent content = jingleSession.getContents().get(0);
    if (ourChoice == null || theirChoice == null) {
        // Not yet ready.
        LOGGER.log(Level.INFO, "Not ready.");
        return;
    }
    if (ourChoice == CANDIDATE_FAILURE && theirChoice == CANDIDATE_FAILURE) {
        LOGGER.log(Level.INFO, "Failure.");
        jingleSession.onTransportMethodFailed(getNamespace());
        return;
    }
    LOGGER.log(Level.INFO, "Ready.");
    // Determine nominated candidate.
    UsedCandidate nominated;
    if (ourChoice != CANDIDATE_FAILURE && theirChoice != CANDIDATE_FAILURE) {
        if (ourChoice.candidate.getPriority() > theirChoice.candidate.getPriority()) {
            nominated = ourChoice;
        } else if (ourChoice.candidate.getPriority() < theirChoice.candidate.getPriority()) {
            nominated = theirChoice;
        } else {
            nominated = jingleSession.isInitiator() ? ourChoice : theirChoice;
        }
    } else if (ourChoice != CANDIDATE_FAILURE) {
        nominated = ourChoice;
    } else {
        nominated = theirChoice;
    }
    if (nominated == theirChoice) {
        LOGGER.log(Level.INFO, "Their choice, so our proposed candidate is used.");
        boolean isProxy = nominated.candidate.getType() == JingleS5BTransportCandidate.Type.proxy;
        try {
            nominated = connectToOurCandidate(nominated.candidate);
        } catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
            LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
            // TODO: Proxy-Error
            return;
        }
        if (isProxy) {
            LOGGER.log(Level.INFO, "Is external proxy. Activate it.");
            Bytestream activate = new Bytestream(ourProposal.getStreamId());
            activate.setMode(null);
            activate.setType(IQ.Type.set);
            activate.setTo(nominated.candidate.getJid());
            activate.setToActivate(jingleSession.getRemote());
            activate.setFrom(jingleSession.getLocal());
            try {
                jingleSession.getConnection().sendIqRequestAndWaitForResponse(activate);
            } catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
                LOGGER.log(Level.WARNING, "Could not activate proxy.", e);
                return;
            }
            LOGGER.log(Level.INFO, "Send candidate-activate.");
            Jingle candidateActivate = transportManager().createCandidateActivated(jingleSession.getRemote(), jingleSession.getInitiator(), jingleSession.getSessionId(), content.getSenders(), content.getCreator(), content.getName(), nominated.transport.getStreamId(), nominated.candidate.getCandidateId());
            try {
                jingleSession.getConnection().sendIqRequestAndWaitForResponse(candidateActivate);
            } catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
                LOGGER.log(Level.WARNING, "Could not send candidate-activated", e);
                return;
            }
        }
        LOGGER.log(Level.INFO, "Start transmission.");
        Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.socket, !isProxy);
        callback.onSessionInitiated(bs);
    } else // Our choice
    {
        LOGGER.log(Level.INFO, "Our choice, so their candidate was used.");
        boolean isProxy = nominated.candidate.getType() == JingleS5BTransportCandidate.Type.proxy;
        if (!isProxy) {
            LOGGER.log(Level.INFO, "Direct connection.");
            Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.socket, true);
            callback.onSessionInitiated(bs);
        } else {
            LOGGER.log(Level.INFO, "Our choice was their external proxy. wait for candidate-activate.");
        }
    }
}
Also used : SmackException(org.jivesoftware.smack.SmackException) IOException(java.io.IOException) Socks5BytestreamSession(org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession) Jingle(org.jivesoftware.smackx.jingle.element.Jingle) Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) JingleContent(org.jivesoftware.smackx.jingle.element.JingleContent) XMPPException(org.jivesoftware.smack.XMPPException) TimeoutException(java.util.concurrent.TimeoutException)

Aggregations

TimeoutException (java.util.concurrent.TimeoutException)8 XMPPException (org.jivesoftware.smack.XMPPException)8 IOException (java.io.IOException)7 Socks5BytestreamSession (org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession)7 Socks5BytestreamRequest (org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest)5 Bytestream (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream)5 Socket (java.net.Socket)4 XMPPConnection (org.jivesoftware.smack.XMPPConnection)4 StreamHost (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost)4 InputStream (java.io.InputStream)3 OutputStream (java.io.OutputStream)3 SynchronousQueue (java.util.concurrent.SynchronousQueue)3 SmackException (org.jivesoftware.smack.SmackException)3 Socks5BytestreamListener (org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamListener)3 Socks5BytestreamManager (org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager)3 PushbackInputStream (java.io.PushbackInputStream)2 ArrayList (java.util.ArrayList)2 XMPPErrorException (org.jivesoftware.smack.XMPPException.XMPPErrorException)2 StreamHostUsed (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHostUsed)2 HashMap (java.util.HashMap)1