order canditates by priority before attempting to connect
This commit is contained in:
parent
7d6bd540d9
commit
783ed53d3a
|
@ -11,6 +11,7 @@ import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -303,7 +304,7 @@ public class JingleConnection implements Transferable {
|
||||||
if (this.initialTransport == Transport.IBB) {
|
if (this.initialTransport == Transport.IBB) {
|
||||||
this.sendInitRequest();
|
this.sendInitRequest();
|
||||||
} else if (this.candidates.size() > 0) {
|
} else if (this.candidates.size() > 0) {
|
||||||
this.sendInitRequest();
|
this.sendInitRequest(); //TODO we will never get here? Can probably be removed
|
||||||
} else {
|
} else {
|
||||||
this.mJingleConnectionManager.getPrimaryCandidate(account, (success, candidate) -> {
|
this.mJingleConnectionManager.getPrimaryCandidate(account, (success, candidate) -> {
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -635,7 +636,7 @@ public class JingleConnection implements Transferable {
|
||||||
|
|
||||||
private boolean receiveAccept(JinglePacket packet) {
|
private boolean receiveAccept(JinglePacket packet) {
|
||||||
if (this.mJingleStatus != JINGLE_STATUS_INITIATED) {
|
if (this.mJingleStatus != JINGLE_STATUS_INITIATED) {
|
||||||
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": received out of order session-accept");
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received out of order session-accept");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.mJingleStatus = JINGLE_STATUS_ACCEPTED;
|
this.mJingleStatus = JINGLE_STATUS_ACCEPTED;
|
||||||
|
@ -654,7 +655,7 @@ public class JingleConnection implements Transferable {
|
||||||
this.ibbBlockSize = bs;
|
this.ibbBlockSize = bs;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to parse block size in session-accept");
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to parse block size in session-accept");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
|
this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
|
||||||
|
@ -850,7 +851,7 @@ public class JingleConnection implements Transferable {
|
||||||
this.ibbBlockSize = bs;
|
this.ibbBlockSize = bs;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to parse block size in transport-replace");
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to parse block size in transport-replace");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.transportId = packet.getJingleContent().getTransportId();
|
this.transportId = packet.getJingleContent().getTransportId();
|
||||||
|
@ -889,7 +890,7 @@ public class JingleConnection implements Transferable {
|
||||||
this.ibbBlockSize = bs;
|
this.ibbBlockSize = bs;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
Log.d(Config.LOGTAG, account.getJid().asBareJid()+": unable to parse block size in transport-accept");
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to parse block size in transport-accept");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
|
this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
|
||||||
|
@ -1087,6 +1088,7 @@ public class JingleConnection implements Transferable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mergeCandidates(List<JingleCandidate> candidates) {
|
private void mergeCandidates(List<JingleCandidate> candidates) {
|
||||||
|
Collections.sort(candidates, (a, b) -> Integer.compare(b.getPriority(), a.getPriority()));
|
||||||
for (JingleCandidate c : candidates) {
|
for (JingleCandidate c : candidates) {
|
||||||
mergeCandidate(c);
|
mergeCandidate(c);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,177 +22,177 @@ import eu.siacs.conversations.utils.WakeLockHelper;
|
||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
|
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
|
||||||
|
|
||||||
public class JingleSocks5Transport extends JingleTransport {
|
public class JingleSocks5Transport extends JingleTransport {
|
||||||
private JingleCandidate candidate;
|
private final JingleCandidate candidate;
|
||||||
private JingleConnection connection;
|
private final JingleConnection connection;
|
||||||
private String destination;
|
private final String destination;
|
||||||
private OutputStream outputStream;
|
private OutputStream outputStream;
|
||||||
private InputStream inputStream;
|
private InputStream inputStream;
|
||||||
private boolean isEstablished = false;
|
private boolean isEstablished = false;
|
||||||
private boolean activated = false;
|
private boolean activated = false;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
|
||||||
JingleSocks5Transport(JingleConnection jingleConnection, JingleCandidate candidate) {
|
JingleSocks5Transport(JingleConnection jingleConnection, JingleCandidate candidate) {
|
||||||
this.candidate = candidate;
|
final MessageDigest messageDigest;
|
||||||
this.connection = jingleConnection;
|
try {
|
||||||
try {
|
messageDigest = MessageDigest.getInstance("SHA-1");
|
||||||
MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
|
} catch (NoSuchAlgorithmException e) {
|
||||||
StringBuilder destBuilder = new StringBuilder();
|
throw new AssertionError(e);
|
||||||
if (jingleConnection.getFtVersion() == Content.Version.FT_3) {
|
}
|
||||||
Log.d(Config.LOGTAG, this.connection.getAccount().getJid().asBareJid() + ": using session Id instead of transport Id for proxy destination");
|
this.candidate = candidate;
|
||||||
destBuilder.append(jingleConnection.getSessionId());
|
this.connection = jingleConnection;
|
||||||
} else {
|
final StringBuilder destBuilder = new StringBuilder();
|
||||||
destBuilder.append(jingleConnection.getTransportId());
|
if (jingleConnection.getFtVersion() == Content.Version.FT_3) {
|
||||||
}
|
Log.d(Config.LOGTAG, this.connection.getAccount().getJid().asBareJid() + ": using session Id instead of transport Id for proxy destination");
|
||||||
if (candidate.isOurs()) {
|
destBuilder.append(jingleConnection.getSessionId());
|
||||||
destBuilder.append(jingleConnection.getAccount().getJid());
|
} else {
|
||||||
destBuilder.append(jingleConnection.getCounterPart());
|
destBuilder.append(jingleConnection.getTransportId());
|
||||||
} else {
|
}
|
||||||
destBuilder.append(jingleConnection.getCounterPart());
|
if (candidate.isOurs()) {
|
||||||
destBuilder.append(jingleConnection.getAccount().getJid());
|
destBuilder.append(jingleConnection.getAccount().getJid());
|
||||||
}
|
destBuilder.append(jingleConnection.getCounterPart());
|
||||||
mDigest.reset();
|
} else {
|
||||||
this.destination = CryptoHelper.bytesToHex(mDigest
|
destBuilder.append(jingleConnection.getCounterPart());
|
||||||
.digest(destBuilder.toString().getBytes()));
|
destBuilder.append(jingleConnection.getAccount().getJid());
|
||||||
} catch (NoSuchAlgorithmException e) {
|
}
|
||||||
|
messageDigest.reset();
|
||||||
|
this.destination = CryptoHelper.bytesToHex(messageDigest.digest(destBuilder.toString().getBytes()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public void connect(final OnTransportConnected callback) {
|
||||||
}
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
final boolean useTor = connection.getAccount().isOnion() || connection.getConnectionManager().getXmppConnectionService().useTorToConnect();
|
||||||
|
if (useTor) {
|
||||||
|
socket = SocksSocketFactory.createSocketOverTor(candidate.getHost(), candidate.getPort());
|
||||||
|
} else {
|
||||||
|
socket = new Socket();
|
||||||
|
SocketAddress address = new InetSocketAddress(candidate.getHost(), candidate.getPort());
|
||||||
|
socket.connect(address, Config.SOCKET_TIMEOUT * 1000);
|
||||||
|
}
|
||||||
|
inputStream = socket.getInputStream();
|
||||||
|
outputStream = socket.getOutputStream();
|
||||||
|
SocksSocketFactory.createSocksConnection(socket, destination, 0);
|
||||||
|
isEstablished = true;
|
||||||
|
callback.established();
|
||||||
|
} catch (IOException e) {
|
||||||
|
callback.failed();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
public void connect(final OnTransportConnected callback) {
|
}
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
final boolean useTor = connection.getAccount().isOnion() || connection.getConnectionManager().getXmppConnectionService().useTorToConnect();
|
|
||||||
if (useTor) {
|
|
||||||
socket = SocksSocketFactory.createSocketOverTor(candidate.getHost(), candidate.getPort());
|
|
||||||
} else {
|
|
||||||
socket = new Socket();
|
|
||||||
SocketAddress address = new InetSocketAddress(candidate.getHost(), candidate.getPort());
|
|
||||||
socket.connect(address, Config.SOCKET_TIMEOUT * 1000);
|
|
||||||
}
|
|
||||||
inputStream = socket.getInputStream();
|
|
||||||
outputStream = socket.getOutputStream();
|
|
||||||
SocksSocketFactory.createSocksConnection(socket, destination, 0);
|
|
||||||
isEstablished = true;
|
|
||||||
callback.established();
|
|
||||||
} catch (IOException e) {
|
|
||||||
callback.failed();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
}
|
public void send(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
|
||||||
|
new Thread(() -> {
|
||||||
|
InputStream fileInputStream = null;
|
||||||
|
final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_" + connection.getSessionId());
|
||||||
|
try {
|
||||||
|
wakeLock.acquire();
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
digest.reset();
|
||||||
|
fileInputStream = connection.getFileInputStream();
|
||||||
|
if (fileInputStream == null) {
|
||||||
|
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create input stream");
|
||||||
|
callback.onFileTransferAborted();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final InputStream innerInputStream = AbstractConnectionManager.upgrade(file, fileInputStream);
|
||||||
|
long size = file.getExpectedSize();
|
||||||
|
long transmitted = 0;
|
||||||
|
int count;
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
while ((count = innerInputStream.read(buffer)) > 0) {
|
||||||
|
outputStream.write(buffer, 0, count);
|
||||||
|
digest.update(buffer, 0, count);
|
||||||
|
transmitted += count;
|
||||||
|
connection.updateProgress((int) ((((double) transmitted) / size) * 100));
|
||||||
|
}
|
||||||
|
outputStream.flush();
|
||||||
|
file.setSha1Sum(digest.digest());
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onFileTransmitted(file);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage());
|
||||||
|
callback.onFileTransferAborted();
|
||||||
|
} finally {
|
||||||
|
FileBackend.close(fileInputStream);
|
||||||
|
WakeLockHelper.release(wakeLock);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
public void send(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
|
}
|
||||||
new Thread(() -> {
|
|
||||||
InputStream fileInputStream = null;
|
|
||||||
final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_" + connection.getSessionId());
|
|
||||||
try {
|
|
||||||
wakeLock.acquire();
|
|
||||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
|
||||||
digest.reset();
|
|
||||||
fileInputStream = connection.getFileInputStream();
|
|
||||||
if (fileInputStream == null) {
|
|
||||||
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create input stream");
|
|
||||||
callback.onFileTransferAborted();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final InputStream innerInputStream = AbstractConnectionManager.upgrade(file, fileInputStream);
|
|
||||||
long size = file.getExpectedSize();
|
|
||||||
long transmitted = 0;
|
|
||||||
int count;
|
|
||||||
byte[] buffer = new byte[8192];
|
|
||||||
while ((count = innerInputStream.read(buffer)) > 0) {
|
|
||||||
outputStream.write(buffer, 0, count);
|
|
||||||
digest.update(buffer, 0, count);
|
|
||||||
transmitted += count;
|
|
||||||
connection.updateProgress((int) ((((double) transmitted) / size) * 100));
|
|
||||||
}
|
|
||||||
outputStream.flush();
|
|
||||||
file.setSha1Sum(digest.digest());
|
|
||||||
if (callback != null) {
|
|
||||||
callback.onFileTransmitted(file);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage());
|
|
||||||
callback.onFileTransferAborted();
|
|
||||||
} finally {
|
|
||||||
FileBackend.close(fileInputStream);
|
|
||||||
WakeLockHelper.release(wakeLock);
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
}
|
public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
|
||||||
|
new Thread(() -> {
|
||||||
|
OutputStream fileOutputStream = null;
|
||||||
|
final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_receive_" + connection.getSessionId());
|
||||||
|
try {
|
||||||
|
wakeLock.acquire();
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
digest.reset();
|
||||||
|
//inputStream.skip(45);
|
||||||
|
socket.setSoTimeout(30000);
|
||||||
|
fileOutputStream = connection.getFileOutputStream();
|
||||||
|
if (fileOutputStream == null) {
|
||||||
|
callback.onFileTransferAborted();
|
||||||
|
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create output stream");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double size = file.getExpectedSize();
|
||||||
|
long remainingSize = file.getExpectedSize();
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int count;
|
||||||
|
while (remainingSize > 0) {
|
||||||
|
count = inputStream.read(buffer);
|
||||||
|
if (count == -1) {
|
||||||
|
callback.onFileTransferAborted();
|
||||||
|
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": file ended prematurely with " + remainingSize + " bytes remaining");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
fileOutputStream.write(buffer, 0, count);
|
||||||
|
digest.update(buffer, 0, count);
|
||||||
|
remainingSize -= count;
|
||||||
|
}
|
||||||
|
connection.updateProgress((int) (((size - remainingSize) / size) * 100));
|
||||||
|
}
|
||||||
|
fileOutputStream.flush();
|
||||||
|
fileOutputStream.close();
|
||||||
|
file.setSha1Sum(digest.digest());
|
||||||
|
callback.onFileTransmitted(file);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage());
|
||||||
|
callback.onFileTransferAborted();
|
||||||
|
} finally {
|
||||||
|
WakeLockHelper.release(wakeLock);
|
||||||
|
FileBackend.close(fileOutputStream);
|
||||||
|
FileBackend.close(inputStream);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
|
public boolean isProxy() {
|
||||||
new Thread(() -> {
|
return this.candidate.getType() == JingleCandidate.TYPE_PROXY;
|
||||||
OutputStream fileOutputStream = null;
|
}
|
||||||
final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_receive_" + connection.getSessionId());
|
|
||||||
try {
|
|
||||||
wakeLock.acquire();
|
|
||||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
|
||||||
digest.reset();
|
|
||||||
//inputStream.skip(45);
|
|
||||||
socket.setSoTimeout(30000);
|
|
||||||
fileOutputStream = connection.getFileOutputStream();
|
|
||||||
if (fileOutputStream == null) {
|
|
||||||
callback.onFileTransferAborted();
|
|
||||||
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create output stream");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double size = file.getExpectedSize();
|
|
||||||
long remainingSize = file.getExpectedSize();
|
|
||||||
byte[] buffer = new byte[8192];
|
|
||||||
int count;
|
|
||||||
while (remainingSize > 0) {
|
|
||||||
count = inputStream.read(buffer);
|
|
||||||
if (count == -1) {
|
|
||||||
callback.onFileTransferAborted();
|
|
||||||
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": file ended prematurely with " + remainingSize + " bytes remaining");
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
fileOutputStream.write(buffer, 0, count);
|
|
||||||
digest.update(buffer, 0, count);
|
|
||||||
remainingSize -= count;
|
|
||||||
}
|
|
||||||
connection.updateProgress((int) (((size - remainingSize) / size) * 100));
|
|
||||||
}
|
|
||||||
fileOutputStream.flush();
|
|
||||||
fileOutputStream.close();
|
|
||||||
file.setSha1Sum(digest.digest());
|
|
||||||
callback.onFileTransmitted(file);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage());
|
|
||||||
callback.onFileTransferAborted();
|
|
||||||
} finally {
|
|
||||||
WakeLockHelper.release(wakeLock);
|
|
||||||
FileBackend.close(fileOutputStream);
|
|
||||||
FileBackend.close(inputStream);
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isProxy() {
|
public boolean needsActivation() {
|
||||||
return this.candidate.getType() == JingleCandidate.TYPE_PROXY;
|
return (this.isProxy() && !this.activated);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean needsActivation() {
|
public void disconnect() {
|
||||||
return (this.isProxy() && !this.activated);
|
FileBackend.close(inputStream);
|
||||||
}
|
FileBackend.close(outputStream);
|
||||||
|
FileBackend.close(socket);
|
||||||
|
}
|
||||||
|
|
||||||
public void disconnect() {
|
public boolean isEstablished() {
|
||||||
FileBackend.close(inputStream);
|
return this.isEstablished;
|
||||||
FileBackend.close(outputStream);
|
}
|
||||||
FileBackend.close(socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEstablished() {
|
public JingleCandidate getCandidate() {
|
||||||
return this.isEstablished;
|
return this.candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JingleCandidate getCandidate() {
|
public void setActivated(boolean activated) {
|
||||||
return this.candidate;
|
this.activated = activated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActivated(boolean activated) {
|
|
||||||
this.activated = activated;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue