lot of cleanup in jingle part

This commit is contained in:
Daniel Gultsch 2014-04-17 14:52:10 +02:00 committed by Andreas Straub
parent 8006931f80
commit 07cf07ad58
6 changed files with 328 additions and 122 deletions

View File

@ -0,0 +1,138 @@
package eu.siacs.conversations.xmpp.jingle;
import java.util.ArrayList;
import java.util.List;
import eu.siacs.conversations.xml.Element;
public class JingleCandidate {
public static int TYPE_UNKNOWN;
public static int TYPE_DIRECT = 0;
public static int TYPE_PROXY = 1;
private boolean ours;
private boolean usedByCounterpart = false;
private String cid;
private String host;
private int port;
private int type;
private String jid;
private int priority;
public JingleCandidate(String cid,boolean ours) {
this.ours = ours;
this.cid = cid;
}
public String getCid() {
return cid;
}
public void setHost(String host) {
this.host = host;
}
public String getHost() {
return this.host;
}
public void setJid(String jid) {
this.jid = jid;
}
public String getJid() {
return this.jid;
}
public void setPort(int port) {
this.port = port;
}
public int getPort() {
return this.port;
}
public void setType(int type) {
this.type = type;
}
public void setType(String type) {
if ("proxy".equals(type)) {
this.type = TYPE_PROXY;
} else if ("direct".equals(type)) {
this.type = TYPE_DIRECT;
} else {
this.type = TYPE_UNKNOWN;
}
}
public void setPriority(int i) {
this.priority = i;
}
public int getPriority() {
return this.priority;
}
public boolean equals(JingleCandidate other) {
return this.getCid().equals(other.getCid());
}
public boolean equalValues(JingleCandidate other) {
return other.getHost().equals(this.getHost())&&(other.getPort()==this.getPort());
}
public boolean isOurs() {
return ours;
}
public int getType() {
return this.type;
}
public static List<JingleCandidate> parse(List<Element> canditates) {
List<JingleCandidate> parsedCandidates = new ArrayList<JingleCandidate>();
for(Element c : canditates) {
parsedCandidates.add(JingleCandidate.parse(c));
}
return parsedCandidates;
}
public static JingleCandidate parse(Element candidate) {
JingleCandidate parsedCandidate = new JingleCandidate(candidate.getAttribute("cid"), false);
parsedCandidate.setHost(candidate.getAttribute("host"));
parsedCandidate.setJid(candidate.getAttribute("jid"));
parsedCandidate.setType(candidate.getAttribute("type"));
parsedCandidate.setPriority(Integer.parseInt(candidate.getAttribute("priority")));
parsedCandidate.setPort(Integer.parseInt(candidate.getAttribute("port")));
return parsedCandidate;
}
public Element toElement() {
Element element = new Element("candidate");
element.setAttribute("cid", this.getCid());
element.setAttribute("host", this.getHost());
element.setAttribute("port", ""+this.getPort());
element.setAttribute("jid", this.getJid());
element.setAttribute("priority",""+this.getPriority());
if (this.getType()==TYPE_DIRECT) {
element.setAttribute("type","direct");
} else if (this.getType()==TYPE_PROXY) {
element.setAttribute("type","proxy");
}
return element;
}
public void flagAsUsedByCounterpart() {
this.usedByCounterpart = true;
}
public boolean isUsedByCounterpart() {
return this.usedByCounterpart;
}
public String toString() {
return this.getHost()+":"+this.getPort()+" (prio="+this.getPriority()+")";
}
}

View File

@ -38,12 +38,15 @@ public class JingleConnection {
private Account account; private Account account;
private String initiator; private String initiator;
private String responder; private String responder;
private List<Element> candidates = new ArrayList<Element>(); private List<JingleCandidate> candidates = new ArrayList<JingleCandidate>();
private List<String> candidatesUsedByCounterpart = new ArrayList<String>();
private HashMap<String, SocksConnection> connections = new HashMap<String, SocksConnection>(); private HashMap<String, SocksConnection> connections = new HashMap<String, SocksConnection>();
private Content content = new Content();
private String transportId;
private Element fileOffer;
private JingleFile file = null; private JingleFile file = null;
private boolean receivedCandidateError = false;
private OnIqPacketReceived responseListener = new OnIqPacketReceived() { private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
@Override @Override
@ -107,10 +110,11 @@ public class JingleConnection {
this.mJingleConnectionManager.getPrimaryCandidate(account, new OnPrimaryCandidateFound() { this.mJingleConnectionManager.getPrimaryCandidate(account, new OnPrimaryCandidateFound() {
@Override @Override
public void onPrimaryCandidateFound(boolean success, Element candidate) { public void onPrimaryCandidateFound(boolean success, JingleCandidate candidate) {
if (success) { if (success) {
mergeCandidate(candidate); mergeCandidate(candidate);
} }
openOurCandidates();
sendInitRequest(); sendInitRequest();
} }
}); });
@ -130,9 +134,10 @@ public class JingleConnection {
this.initiator = packet.getFrom(); this.initiator = packet.getFrom();
this.responder = this.account.getFullJid(); this.responder = this.account.getFullJid();
this.sessionId = packet.getSessionId(); this.sessionId = packet.getSessionId();
this.content = packet.getJingleContent(); Content content = packet.getJingleContent();
this.mergeCandidates(this.content.getCanditates()); this.transportId = content.getTransportId();
Element fileOffer = packet.getJingleContent().getFileOffer(); this.mergeCandidates(JingleCandidate.parse(content.getCanditates()));
this.fileOffer = packet.getJingleContent().getFileOffer();
if (fileOffer!=null) { if (fileOffer!=null) {
this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message); this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message);
Element fileSize = fileOffer.findChild("size"); Element fileSize = fileOffer.findChild("size");
@ -156,13 +161,14 @@ public class JingleConnection {
private void sendInitRequest() { private void sendInitRequest() {
JinglePacket packet = this.bootstrapPacket("session-initiate"); JinglePacket packet = this.bootstrapPacket("session-initiate");
this.content = new Content(); Content content = new Content();
if (message.getType() == Message.TYPE_IMAGE) { if (message.getType() == Message.TYPE_IMAGE) {
content.setAttribute("creator", "initiator"); content.setAttribute("creator", "initiator");
content.setAttribute("name", "a-file-offer"); content.setAttribute("name", "a-file-offer");
this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message); this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message);
content.setFileOffer(this.file); content.setFileOffer(this.file);
content.setCandidates(this.mJingleConnectionManager.nextRandomId(),this.candidates); this.transportId = this.mJingleConnectionManager.nextRandomId();
content.setCandidates(this.transportId,getCandidatesAsElements());
packet.setContent(content); packet.setContent(content);
Log.d("xmppService",packet.toString()); Log.d("xmppService",packet.toString());
account.getXmppConnection().sendIqPacket(packet, this.responseListener); account.getXmppConnection().sendIqPacket(packet, this.responseListener);
@ -170,17 +176,28 @@ public class JingleConnection {
} }
} }
private List<Element> getCandidatesAsElements() {
List<Element> elements = new ArrayList<Element>();
for(JingleCandidate c : this.candidates) {
elements.add(c.toElement());
}
return elements;
}
private void sendAccept() { private void sendAccept() {
this.mJingleConnectionManager.getPrimaryCandidate(this.account, new OnPrimaryCandidateFound() { this.mJingleConnectionManager.getPrimaryCandidate(this.account, new OnPrimaryCandidateFound() {
@Override @Override
public void onPrimaryCandidateFound(boolean success, Element candidate) { public void onPrimaryCandidateFound(boolean success, JingleCandidate candidate) {
Content content = new Content();
content.setFileOffer(fileOffer);
if (success) { if (success) {
if (!equalCandidateExists(candidate)) { if (!equalCandidateExists(candidate)) {
mergeCandidate(candidate); mergeCandidate(candidate);
content.addCandidate(candidate);
} }
} }
openOurCandidates();
content.setCandidates(transportId, getCandidatesAsElements());
JinglePacket packet = bootstrapPacket("session-accept"); JinglePacket packet = bootstrapPacket("session-accept");
packet.setContent(content); packet.setContent(content);
account.getXmppConnection().sendIqPacket(packet, new OnIqPacketReceived() { account.getXmppConnection().sendIqPacket(packet, new OnIqPacketReceived() {
@ -211,7 +228,7 @@ public class JingleConnection {
private void accept(JinglePacket packet) { private void accept(JinglePacket packet) {
Log.d("xmppService","session-accept: "+packet.toString()); Log.d("xmppService","session-accept: "+packet.toString());
Content content = packet.getJingleContent(); Content content = packet.getJingleContent();
mergeCandidates(content.getCanditates()); mergeCandidates(JingleCandidate.parse(content.getCanditates()));
this.status = STATUS_ACCEPTED; this.status = STATUS_ACCEPTED;
this.connectNextCandidate(); this.connectNextCandidate();
IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT); IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
@ -224,26 +241,25 @@ public class JingleConnection {
IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT); IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
if (cid!=null) { if (cid!=null) {
Log.d("xmppService","candidate used by counterpart:"+cid); Log.d("xmppService","candidate used by counterpart:"+cid);
this.candidatesUsedByCounterpart.add(cid); JingleCandidate candidate = getCandidate(cid);
if (this.connections.containsKey(cid)) { candidate.flagAsUsedByCounterpart();
SocksConnection connection = this.connections.get(cid); if (status == STATUS_ACCEPTED) {
if (connection.isEstablished()) { this.connect();
if (status==STATUS_ACCEPTED) {
this.connect(connection);
} else {
Log.d("xmppService","ignoring canditate used because we are already transmitting");
}
} else {
Log.d("xmppService","not yet connected. check when callback comes back");
}
} else { } else {
Log.d("xmppService","candidate not yet in list of connections"); Log.d("xmppService","ignoring because file is already in transmission");
}
} else if (content.hasCandidateError()) {
Log.d("xmppService","received candidate error");
this.receivedCandidateError = true;
if (status == STATUS_ACCEPTED) {
this.connect();
} }
} }
account.getXmppConnection().sendIqPacket(response, null); account.getXmppConnection().sendIqPacket(response, null);
} }
private void connect(final SocksConnection connection) { private void connect() {
final SocksConnection connection = chooseConnection();
this.status = STATUS_TRANSMITTING; this.status = STATUS_TRANSMITTING;
final OnFileTransmitted callback = new OnFileTransmitted() { final OnFileTransmitted callback = new OnFileTransmitted() {
@ -256,10 +272,10 @@ public class JingleConnection {
Log.d("xmppService","sucessfully transmitted file. sha1:"+file.getSha1Sum()); Log.d("xmppService","sucessfully transmitted file. sha1:"+file.getSha1Sum());
} }
}; };
if ((connection.isProxy()&&(connection.getCid().equals(mJingleConnectionManager.getPrimaryCandidateId(account))))) { if (connection.isProxy()&&(connection.getCandidate().isOurs())) {
Log.d("xmppService","candidate "+connection.getCid()+" was our proxy and needs activation"); Log.d("xmppService","candidate "+connection.getCandidate().getCid()+" was our proxy and needs activation");
IqPacket activation = new IqPacket(IqPacket.TYPE_SET); IqPacket activation = new IqPacket(IqPacket.TYPE_SET);
activation.setTo(connection.getJid()); activation.setTo(connection.getCandidate().getJid());
activation.query("http://jabber.org/protocol/bytestreams").setAttribute("sid", this.getSessionId()); activation.query("http://jabber.org/protocol/bytestreams").setAttribute("sid", this.getSessionId());
activation.query().addChild("activate").setContent(this.getCounterPart()); activation.query().addChild("activate").setContent(this.getCounterPart());
this.account.getXmppConnection().sendIqPacket(activation, new OnIqPacketReceived() { this.account.getXmppConnection().sendIqPacket(activation, new OnIqPacketReceived() {
@ -287,6 +303,41 @@ public class JingleConnection {
} }
} }
private SocksConnection chooseConnection() {
Log.d("xmppService","choosing connection from "+this.connections.size()+" possibilties");
SocksConnection connection = null;
Iterator<Entry<String, SocksConnection>> it = this.connections.entrySet().iterator();
while (it.hasNext()) {
Entry<String, SocksConnection> pairs = it.next();
SocksConnection currentConnection = pairs.getValue();
Log.d("xmppService","comparing candidate: "+currentConnection.getCandidate().toString());
if (currentConnection.isEstablished()&&(currentConnection.getCandidate().isUsedByCounterpart()||(!currentConnection.getCandidate().isOurs()))) {
Log.d("xmppService","is usable");
if (connection==null) {
connection = currentConnection;
} else {
if (connection.getCandidate().getPriority()<currentConnection.getCandidate().getPriority()) {
connection = currentConnection;
} else if (connection.getCandidate().getPriority()==currentConnection.getCandidate().getPriority()) {
Log.d("xmppService","found two candidates with same priority");
if (initiator.equals(account.getFullJid())) {
if (currentConnection.getCandidate().isOurs()) {
connection = currentConnection;
}
} else {
if (!currentConnection.getCandidate().isOurs()) {
connection = currentConnection;
}
}
}
}
}
it.remove();
}
Log.d("xmppService","chose candidate: "+connection.getCandidate().getHost());
return connection;
}
private void sendSuccess() { private void sendSuccess() {
JinglePacket packet = bootstrapPacket("session-terminate"); JinglePacket packet = bootstrapPacket("session-terminate");
Reason reason = new Reason(); Reason reason = new Reason();
@ -311,20 +362,40 @@ public class JingleConnection {
this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_REJECTED); this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_REJECTED);
} }
private void connectNextCandidate() { private void openOurCandidates() {
for(Element candidate : this.candidates) { for(JingleCandidate candidate : this.candidates) {
String cid = candidate.getAttribute("cid"); if (candidate.isOurs()) {
if (!connections.containsKey(cid)) { final SocksConnection socksConnection = new SocksConnection(this,candidate);
this.connectWithCandidate(candidate); connections.put(candidate.getCid(), socksConnection);
break; socksConnection.connect(new OnSocksConnection() {
@Override
public void failed() {
Log.d("xmppService","connection to our candidate failed");
}
@Override
public void established() {
Log.d("xmppService","connection to our candidate was successful");
}
});
} }
} }
} }
private void connectWithCandidate(Element candidate) { private void connectNextCandidate() {
boolean initating = candidate.getAttribute("cid").equals(mJingleConnectionManager.getPrimaryCandidateId(account)); for(JingleCandidate candidate : this.candidates) {
final SocksConnection socksConnection = new SocksConnection(this,candidate,initating); if ((!connections.containsKey(candidate.getCid())&&(!candidate.isOurs()))) {
connections.put(socksConnection.getCid(), socksConnection); this.connectWithCandidate(candidate);
return;
}
}
this.sendCandidateError();
}
private void connectWithCandidate(final JingleCandidate candidate) {
final SocksConnection socksConnection = new SocksConnection(this,candidate);
connections.put(candidate.getCid(), socksConnection);
socksConnection.connect(new OnSocksConnection() { socksConnection.connect(new OnSocksConnection() {
@Override @Override
@ -334,14 +405,10 @@ public class JingleConnection {
@Override @Override
public void established() { public void established() {
if (candidatesUsedByCounterpart.contains(socksConnection.getCid())) { sendCandidateUsed(candidate.getCid());
if (status==STATUS_ACCEPTED) { if ((receivedCandidateError)&&(status == STATUS_ACCEPTED)) {
connect(socksConnection); Log.d("xmppService","received candidate error before. trying to connect");
} else { connect();
Log.d("xmppService","ignoring cuz already transmitting");
}
} else {
sendCandidateUsed(socksConnection.getCid());
} }
} }
}); });
@ -359,21 +426,25 @@ public class JingleConnection {
private void sendCandidateUsed(final String cid) { private void sendCandidateUsed(final String cid) {
JinglePacket packet = bootstrapPacket("transport-info"); JinglePacket packet = bootstrapPacket("transport-info");
Content content = new Content(); Content content = new Content();
content.setUsedCandidate(this.content.getTransportId(), cid); //TODO: put these into actual variables
content.setAttribute("creator", "initiator");
content.setAttribute("name", "a-file-offer");
content.setUsedCandidate(this.transportId, cid);
packet.setContent(content); packet.setContent(content);
Log.d("xmppService","send using candidate: "+cid); Log.d("xmppService","send using candidate: "+cid);
this.account.getXmppConnection().sendIqPacket(packet, new OnIqPacketReceived() { this.account.getXmppConnection().sendIqPacket(packet,responseListener);
}
@Override private void sendCandidateError() {
public void onIqPacketReceived(Account account, IqPacket packet) { JinglePacket packet = bootstrapPacket("transport-info");
Log.d("xmppService","got ack for our candidate used"); Content content = new Content();
if (status==STATUS_ACCEPTED) { //TODO: put these into actual variables
connect(connections.get(cid)); content.setAttribute("creator", "initiator");
} else { content.setAttribute("name", "a-file-offer");
Log.d("xmppService","ignoring cuz already transmitting"); content.setCandidateError(this.transportId);
} packet.setContent(content);
} Log.d("xmppService","send candidate error");
}); this.account.getXmppConnection().sendIqPacket(packet,responseListener);
} }
public String getInitiator() { public String getInitiator() {
@ -388,33 +459,33 @@ public class JingleConnection {
return this.status; return this.status;
} }
private boolean equalCandidateExists(Element candidate) { private boolean equalCandidateExists(JingleCandidate candidate) {
for(Element c : this.candidates) { for(JingleCandidate c : this.candidates) {
if (c.getAttribute("host").equals(candidate.getAttribute("host"))&&(c.getAttribute("port").equals(candidate.getAttribute("port")))) { if (c.equalValues(candidate)) {
return true; return true;
} }
} }
return false; return false;
} }
private void mergeCandidate(Element candidate) { private void mergeCandidate(JingleCandidate candidate) {
for(Element c : this.candidates) { for(JingleCandidate c : this.candidates) {
if (c.getAttribute("cid").equals(candidate.getAttribute("cid"))) { if (c.equals(candidate)) {
return; return;
} }
} }
this.candidates.add(candidate); this.candidates.add(candidate);
} }
private void mergeCandidates(List<Element> candidates) { private void mergeCandidates(List<JingleCandidate> candidates) {
for(Element c : candidates) { for(JingleCandidate c : candidates) {
mergeCandidate(c); mergeCandidate(c);
} }
} }
private Element getCandidate(String cid) { private JingleCandidate getCandidate(String cid) {
for(Element c : this.candidates) { for(JingleCandidate c : this.candidates) {
if (c.getAttribute("cid").equals(cid)) { if (c.getCid().equals(cid)) {
return c; return c;
} }
} }

View File

@ -23,7 +23,7 @@ public class JingleConnectionManager {
private List<JingleConnection> connections = new ArrayList<JingleConnection>(); // make private List<JingleConnection> connections = new ArrayList<JingleConnection>(); // make
// concurrent // concurrent
private ConcurrentHashMap<String, Element> primaryCandidates = new ConcurrentHashMap<String, Element>(); private ConcurrentHashMap<String, JingleCandidate> primaryCandidates = new ConcurrentHashMap<String, JingleCandidate>();
private SecureRandom random = new SecureRandom(); private SecureRandom random = new SecureRandom();
@ -89,17 +89,12 @@ public class JingleConnectionManager {
if (streamhost != null) { if (streamhost != null) {
Log.d("xmppService", "streamhost found " Log.d("xmppService", "streamhost found "
+ streamhost.toString()); + streamhost.toString());
Element candidate = new Element("candidate"); JingleCandidate candidate = new JingleCandidate(nextRandomId(),true);
candidate.setAttribute("cid", candidate.setHost(streamhost.getAttribute("host"));
nextRandomId()); candidate.setPort(Integer.parseInt(streamhost.getAttribute("port")));
candidate.setAttribute("host", candidate.setType(JingleCandidate.TYPE_PROXY);
streamhost.getAttribute("host")); candidate.setJid(proxy);
candidate.setAttribute("port", candidate.setPriority(655360+65535);
streamhost.getAttribute("port"));
candidate.setAttribute("type", "proxy");
candidate.setAttribute("jid", proxy);
candidate
.setAttribute("priority", "655360");
primaryCandidates.put(account.getJid(), primaryCandidates.put(account.getJid(),
candidate); candidate);
listener.onPrimaryCandidateFound(true, listener.onPrimaryCandidateFound(true,
@ -120,14 +115,6 @@ public class JingleConnectionManager {
} }
} }
public String getPrimaryCandidateId(Account account) {
if (this.primaryCandidates.containsKey(account.getJid())) {
return this.primaryCandidates.get(account.getJid()).getAttribute("cid");
} else {
return null;
}
}
public String nextRandomId() { public String nextRandomId() {
return new BigInteger(50, random).toString(32); return new BigInteger(50, random).toString(32);
} }

View File

@ -1,7 +1,5 @@
package eu.siacs.conversations.xmpp.jingle; package eu.siacs.conversations.xmpp.jingle;
import eu.siacs.conversations.xml.Element;
public interface OnPrimaryCandidateFound { public interface OnPrimaryCandidateFound {
public void onPrimaryCandidateFound(boolean success, Element canditate); public void onPrimaryCandidateFound(boolean success, JingleCandidate canditate);
} }

View File

@ -19,29 +19,20 @@ import android.util.Log;
import android.widget.Button; import android.widget.Button;
public class SocksConnection { public class SocksConnection {
private Socket socket; private JingleCandidate candidate;
private String host;
private String jid;
private String cid;
private int port;
private boolean isProxy = false;
private String destination; private String destination;
private OutputStream outputStream; private OutputStream outputStream;
private InputStream inputStream; private InputStream inputStream;
private boolean isEstablished = false; private boolean isEstablished = false;
protected Socket socket;
public SocksConnection(JingleConnection jingleConnection, Element candidate, boolean initating) { public SocksConnection(JingleConnection jingleConnection, JingleCandidate candidate) {
this.cid = candidate.getAttribute("cid"); this.candidate = candidate;
this.host = candidate.getAttribute("host");
this.port = Integer.parseInt(candidate.getAttribute("port"));
String type = candidate.getAttribute("type");
this.jid = candidate.getAttribute("jid");
this.isProxy = "proxy".equalsIgnoreCase(type);
try { try {
MessageDigest mDigest = MessageDigest.getInstance("SHA-1"); MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
StringBuilder destBuilder = new StringBuilder(); StringBuilder destBuilder = new StringBuilder();
destBuilder.append(jingleConnection.getSessionId()); destBuilder.append(jingleConnection.getSessionId());
if (initating) { if (candidate.isOurs()) {
destBuilder.append(jingleConnection.getAccountJid()); destBuilder.append(jingleConnection.getAccountJid());
destBuilder.append(jingleConnection.getCounterPart()); destBuilder.append(jingleConnection.getCounterPart());
} else { } else {
@ -62,7 +53,7 @@ public class SocksConnection {
@Override @Override
public void run() { public void run() {
try { try {
socket = new Socket(host, port); socket = new Socket(candidate.getHost(), candidate.getPort());
inputStream = socket.getInputStream(); inputStream = socket.getInputStream();
outputStream = socket.getOutputStream(); outputStream = socket.getOutputStream();
byte[] login = { 0x05, 0x01, 0x00 }; byte[] login = { 0x05, 0x01, 0x00 };
@ -78,8 +69,7 @@ public class SocksConnection {
inputStream.read(result); inputStream.read(result);
int status = result[1]; int status = result[1];
if (status == 0) { if (status == 0) {
Log.d("xmppService", "established connection with "+host + ":" + port Log.d("xmppService", "established connection with "+candidate.getHost()+":"+candidate.getPort()+ "/" + destination);
+ "/" + destination);
isEstablished = true; isEstablished = true;
callback.established(); callback.established();
} else { } else {
@ -193,24 +183,16 @@ public class SocksConnection {
} }
public boolean isProxy() { public boolean isProxy() {
return this.isProxy; return this.candidate.getType() == JingleCandidate.TYPE_PROXY;
}
public String getJid() {
return this.jid;
}
public String getCid() {
return this.cid;
} }
public void disconnect() { public void disconnect() {
if (this.socket!=null) { if (this.socket!=null) {
try { try {
this.socket.close(); this.socket.close();
Log.d("xmppService","cloesd socket with "+this.host); Log.d("xmppService","cloesd socket with "+candidate.getHost()+":"+candidate.getPort());
} catch (IOException e) { } catch (IOException e) {
Log.d("xmppService","error closing socket with "+this.host); Log.d("xmppService","error closing socket with "+candidate.getHost()+":"+candidate.getPort());
} }
} }
} }
@ -218,4 +200,8 @@ public class SocksConnection {
public boolean isEstablished() { public boolean isEstablished() {
return this.isEstablished; return this.isEstablished;
} }
public JingleCandidate getCandidate() {
return this.candidate;
}
} }

View File

@ -77,6 +77,14 @@ public class Content extends Element {
} }
} }
public boolean hasCandidateError() {
Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");
if (transport==null) {
return false;
}
return transport.hasChild("candidate-error");
}
public void setUsedCandidate(String transportId, String cid) { public void setUsedCandidate(String transportId, String cid) {
Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1"); Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");
if (transport==null) { if (transport==null) {
@ -95,4 +103,22 @@ public class Content extends Element {
} }
transport.addChild(candidate); transport.addChild(candidate);
} }
public void setFileOffer(Element fileOffer) {
Element description = this.findChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
if (description==null) {
description = this.addChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
}
description.addChild(fileOffer);
}
public void setCandidateError(String transportId) {
Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");
if (transport==null) {
transport = this.addChild("transport", "urn:xmpp:jingle:transports:s5b:1");
}
transport.setAttribute("sid", transportId);
transport.clearChildren();
transport.addChild("candidate-error");
}
} }