// 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()));
}