use of org.jivesoftware.smackx.bytestreams.socks5.Socks5Exception.NoSocks5StreamHostsProvided in project Smack by igniterealtime.
the class Socks5BytestreamRequest method cancelRequest.
/**
* Cancels the SOCKS5 Bytestream request by sending an error to the initiator and building a
* XMPP exception.
*
* @param streamHostsExceptions the stream hosts and their exceptions.
* @throws NotConnectedException if the XMPP connection is not connected.
* @throws InterruptedException if the calling thread was interrupted.
* @throws CouldNotConnectToAnyProvidedSocks5Host as expected result.
* @throws NoSocks5StreamHostsProvided if no stream host was provided.
*/
private void cancelRequest(Map<StreamHost, Exception> streamHostsExceptions) throws NotConnectedException, InterruptedException, CouldNotConnectToAnyProvidedSocks5Host, NoSocks5StreamHostsProvided {
final Socks5Exception.NoSocks5StreamHostsProvided noHostsProvidedException;
final Socks5Exception.CouldNotConnectToAnyProvidedSocks5Host couldNotConnectException;
final String errorMessage;
if (streamHostsExceptions.isEmpty()) {
noHostsProvidedException = new Socks5Exception.NoSocks5StreamHostsProvided();
couldNotConnectException = null;
errorMessage = noHostsProvidedException.getMessage();
} else {
noHostsProvidedException = null;
couldNotConnectException = Socks5Exception.CouldNotConnectToAnyProvidedSocks5Host.construct(streamHostsExceptions);
errorMessage = couldNotConnectException.getMessage();
}
StanzaError error = StanzaError.from(StanzaError.Condition.item_not_found, errorMessage).build();
IQ errorIQ = IQ.createErrorResponse(this.bytestreamRequest, error);
this.manager.getConnection().sendStanza(errorIQ);
if (noHostsProvidedException != null) {
throw noHostsProvidedException;
} else {
throw couldNotConnectException;
}
}
use of org.jivesoftware.smackx.bytestreams.socks5.Socks5Exception.NoSocks5StreamHostsProvided 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()));
}
Aggregations