disocover stream hosts (xep-0065) cleaned up disco
This commit is contained in:
parent
92dcf85701
commit
298c7adcd1
|
@ -1,50 +0,0 @@
|
|||
package eu.siacs.conversations.services;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Message;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.JingleConnection;
|
||||
import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
|
||||
|
||||
public class JingleConnectionManager {
|
||||
|
||||
private XmppConnectionService xmppConnectionService;
|
||||
|
||||
private ConcurrentHashMap<String, JingleConnection> connections = new ConcurrentHashMap<String, JingleConnection>();
|
||||
|
||||
public JingleConnectionManager(XmppConnectionService service) {
|
||||
this.xmppConnectionService = service;
|
||||
}
|
||||
|
||||
public void deliverPacket(Account account, JinglePacket packet) {
|
||||
String id = generateInternalId(account.getJid(), packet.getFrom(), packet.getSessionId());
|
||||
}
|
||||
|
||||
public JingleConnection createNewConnection(Message message) {
|
||||
Account account = message.getConversation().getAccount();
|
||||
JingleConnection connection = new JingleConnection(this,account, message.getCounterpart());
|
||||
String id = generateInternalId(account.getJid(), message.getCounterpart(), connection.getSessionId());
|
||||
connection.init(message);
|
||||
return connection;
|
||||
}
|
||||
|
||||
private String generateInternalId(String account, String counterpart, String sid) {
|
||||
return account+"#"+counterpart+"#"+sid;
|
||||
|
||||
}
|
||||
|
||||
public XmppConnectionService getXmppConnectionService() {
|
||||
return this.xmppConnectionService;
|
||||
}
|
||||
|
||||
public Element getPrimaryCanditate(String jid) {
|
||||
Element canditate = new Element("canditate");
|
||||
canditate.setAttribute("cid","122");
|
||||
canditate.setAttribute("port","1234");
|
||||
canditate.setAttribute("jid", jid);
|
||||
canditate.setAttribute("type", "assisted");
|
||||
return canditate;
|
||||
}
|
||||
}
|
|
@ -41,16 +41,17 @@ import eu.siacs.conversations.utils.UIHelper;
|
|||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.OnBindListener;
|
||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
import eu.siacs.conversations.xmpp.OnJinglePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.OnStatusChanged;
|
||||
import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
|
||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
|
||||
import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package eu.siacs.conversations.xmpp;
|
||||
|
||||
abstract interface PacketReceived {
|
||||
public abstract interface PacketReceived {
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,13 @@ import java.security.cert.CertPathValidatorException;
|
|||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
@ -44,11 +48,12 @@ import eu.siacs.conversations.xml.Element;
|
|||
import eu.siacs.conversations.xml.Tag;
|
||||
import eu.siacs.conversations.xml.TagWriter;
|
||||
import eu.siacs.conversations.xml.XmlReader;
|
||||
import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket;
|
||||
|
@ -70,8 +75,7 @@ public class XmppConnection implements Runnable {
|
|||
private boolean shouldBind = true;
|
||||
private boolean shouldAuthenticate = true;
|
||||
private Element streamFeatures;
|
||||
private HashSet<String> discoFeatures = new HashSet<String>();
|
||||
private List<String> discoItems = new ArrayList<String>();
|
||||
private HashMap<String, List<String>> disco = new HashMap<String, List<String>>();
|
||||
|
||||
private String streamId = null;
|
||||
private int smVersion = 3;
|
||||
|
@ -644,8 +648,8 @@ public class XmppConnection implements Runnable {
|
|||
tagWriter.writeStanzaAsync(enable);
|
||||
}
|
||||
sendInitialPresence();
|
||||
sendServiceDiscoveryInfo();
|
||||
sendServiceDiscoveryItems();
|
||||
sendServiceDiscoveryInfo(account.getServer());
|
||||
sendServiceDiscoveryItems(account.getServer());
|
||||
if (bindListener !=null) {
|
||||
bindListener.onBind(account);
|
||||
}
|
||||
|
@ -654,30 +658,41 @@ public class XmppConnection implements Runnable {
|
|||
});
|
||||
}
|
||||
|
||||
private void sendServiceDiscoveryInfo() {
|
||||
private void sendServiceDiscoveryInfo(final String server) {
|
||||
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
iq.setTo(account.getServer());
|
||||
iq.setTo(server);
|
||||
iq.query("http://jabber.org/protocol/disco#info");
|
||||
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
List<Element> elements = packet.query().getChildren();
|
||||
List<String> features = new ArrayList<String>();
|
||||
for (int i = 0; i < elements.size(); ++i) {
|
||||
if (elements.get(i).getName().equals("feature")) {
|
||||
discoFeatures.add(elements.get(i).getAttribute(
|
||||
features.add(elements.get(i).getAttribute(
|
||||
"var"));
|
||||
}
|
||||
}
|
||||
if (discoFeatures.contains("urn:xmpp:carbons:2")) {
|
||||
sendEnableCarbons();
|
||||
Log.d(LOGTAG,"put "+server+" "+features.toString());
|
||||
disco.put(server, features);
|
||||
|
||||
if (account.getServer().equals(server)) {
|
||||
enableAdvancedStreamFeatures();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
private void sendServiceDiscoveryItems() {
|
||||
|
||||
private void enableAdvancedStreamFeatures() {
|
||||
if (hasFeaturesCarbon()) {
|
||||
sendEnableCarbons();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendServiceDiscoveryItems(final String server) {
|
||||
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
iq.setTo(account.getServer());
|
||||
iq.setTo(server);
|
||||
iq.query("http://jabber.org/protocol/disco#items");
|
||||
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
||||
|
||||
|
@ -686,8 +701,9 @@ public class XmppConnection implements Runnable {
|
|||
List<Element> elements = packet.query().getChildren();
|
||||
for (int i = 0; i < elements.size(); ++i) {
|
||||
if (elements.get(i).getName().equals("item")) {
|
||||
discoItems.add(elements.get(i).getAttribute(
|
||||
"jid"));
|
||||
String jid = elements.get(i).getAttribute(
|
||||
"jid");
|
||||
sendServiceDiscoveryInfo(jid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -850,7 +866,26 @@ public class XmppConnection implements Runnable {
|
|||
}
|
||||
|
||||
public boolean hasFeaturesCarbon() {
|
||||
return discoFeatures.contains("urn:xmpp:carbons:2");
|
||||
return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2");
|
||||
}
|
||||
|
||||
public boolean hasDiscoFeature(String server, String feature) {
|
||||
if (!disco.containsKey(server)) {
|
||||
return false;
|
||||
}
|
||||
return disco.get(server).contains(feature);
|
||||
}
|
||||
|
||||
public String findDiscoItemByFeature(String feature) {
|
||||
Iterator<Entry<String, List<String>>> it = this.disco.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<String, List<String>> pairs = it.next();
|
||||
if (pairs.getValue().contains(feature)) {
|
||||
return pairs.getKey();
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void r() {
|
||||
|
@ -866,15 +901,6 @@ public class XmppConnection implements Runnable {
|
|||
}
|
||||
|
||||
public String getMucServer() {
|
||||
for(int i = 0; i < discoItems.size(); ++i) {
|
||||
if (discoItems.get(i).contains("conference.")) {
|
||||
return discoItems.get(i);
|
||||
} else if (discoItems.get(i).contains("conf.")) {
|
||||
return discoItems.get(i);
|
||||
} else if (discoItems.get(i).contains("muc.")) {
|
||||
return discoItems.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return findDiscoItemByFeature("http://jabber.org/protocol/muc");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package eu.siacs.conversations.xmpp;
|
||||
package eu.siacs.conversations.xmpp.jingle;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -9,30 +7,37 @@ import android.util.Log;
|
|||
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Message;
|
||||
import eu.siacs.conversations.services.JingleConnectionManager;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.stanzas.jingle.Content;
|
||||
import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
|
||||
public class JingleConnection {
|
||||
|
||||
private JingleConnectionManager mJingleConnectionManager;
|
||||
private XmppConnectionService mXmppConnectionService;
|
||||
|
||||
private Message message;
|
||||
private String sessionId;
|
||||
private Account account;
|
||||
private String counterpart;
|
||||
private String initiator;
|
||||
private String responder;
|
||||
private List<Element> canditates = new ArrayList<Element>();
|
||||
|
||||
public JingleConnection(JingleConnectionManager mJingleConnectionManager, Account account, String counterpart) {
|
||||
private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
Log.d("xmppService",packet.toString());
|
||||
}
|
||||
};
|
||||
|
||||
public JingleConnection(JingleConnectionManager mJingleConnectionManager) {
|
||||
this.mJingleConnectionManager = mJingleConnectionManager;
|
||||
this.mXmppConnectionService = mJingleConnectionManager.getXmppConnectionService();
|
||||
this.account = account;
|
||||
this.counterpart = counterpart;
|
||||
SecureRandom random = new SecureRandom();
|
||||
sessionId = new BigInteger(100, random).toString(32);
|
||||
this.canditates.add(this.mJingleConnectionManager.getPrimaryCanditate(account.getJid()));
|
||||
this.sessionId = this.mJingleConnectionManager.nextRandomId();
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
|
@ -40,26 +45,46 @@ public class JingleConnection {
|
|||
}
|
||||
|
||||
public void init(Message message) {
|
||||
this.message = message;
|
||||
this.account = message.getConversation().getAccount();
|
||||
this.initiator = this.account.getFullJid();
|
||||
if (this.canditates.size() > 0) {
|
||||
this.sendInitRequest();
|
||||
} else {
|
||||
this.mJingleConnectionManager.getPrimaryCanditate(account, new OnPrimaryCanditateFound() {
|
||||
|
||||
@Override
|
||||
public void onPrimaryCanditateFound(boolean success, Element canditate) {
|
||||
if (success) {
|
||||
canditates.add(canditate);
|
||||
}
|
||||
sendInitRequest();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sendInitRequest() {
|
||||
JinglePacket packet = this.bootstrapPacket();
|
||||
packet.setAction("session-initiate");
|
||||
packet.setInitiator(this.account.getFullJid());
|
||||
Content content = new Content();
|
||||
if (message.getType() == Message.TYPE_IMAGE) {
|
||||
//creator='initiator' name='a-file-offer'
|
||||
content.setAttribute("creator", "initiator");
|
||||
content.setAttribute("name", "a-file-offer");
|
||||
content.offerFile(this.mXmppConnectionService.getFileBackend().getImageFile(message));
|
||||
content.setCanditates(this.canditates);
|
||||
packet.setContent(content);
|
||||
Log.d("xmppService",packet.toString());
|
||||
account.getXmppConnection().sendIqPacket(packet, null);
|
||||
account.getXmppConnection().sendIqPacket(packet, this.responseListener);
|
||||
}
|
||||
}
|
||||
|
||||
private JinglePacket bootstrapPacket() {
|
||||
JinglePacket packet = new JinglePacket();
|
||||
packet.setFrom(account.getFullJid());
|
||||
packet.setTo(this.counterpart+"/Gajim");
|
||||
packet.setTo(this.message.getCounterpart()+"/Gajim"); //fixme, not right in all cases;
|
||||
packet.setSessionId(this.sessionId);
|
||||
return packet;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package eu.siacs.conversations.xmpp.jingle;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.entities.Message;
|
||||
import eu.siacs.conversations.services.XmppConnectionService;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
|
||||
public class JingleConnectionManager {
|
||||
|
||||
private XmppConnectionService xmppConnectionService;
|
||||
|
||||
private List<JingleConnection> connections = new ArrayList<JingleConnection>(); //make concurrent
|
||||
|
||||
private ConcurrentHashMap<String, Element> primaryCanditates = new ConcurrentHashMap<String, Element>();
|
||||
|
||||
private SecureRandom random = new SecureRandom();
|
||||
|
||||
public JingleConnectionManager(XmppConnectionService service) {
|
||||
this.xmppConnectionService = service;
|
||||
}
|
||||
|
||||
public void deliverPacket(Account account, JinglePacket packet) {
|
||||
String id = generateInternalId(account.getJid(), packet.getFrom(), packet.getSessionId());
|
||||
}
|
||||
|
||||
public JingleConnection createNewConnection(Message message) {
|
||||
Account account = message.getConversation().getAccount();
|
||||
JingleConnection connection = new JingleConnection(this);
|
||||
String id = generateInternalId(account.getJid(), message.getCounterpart(), connection.getSessionId());
|
||||
connection.init(message);
|
||||
return connection;
|
||||
}
|
||||
|
||||
private String generateInternalId(String account, String counterpart, String sid) {
|
||||
return account+"#"+counterpart+"#"+sid;
|
||||
|
||||
}
|
||||
|
||||
public XmppConnectionService getXmppConnectionService() {
|
||||
return this.xmppConnectionService;
|
||||
}
|
||||
|
||||
public void getPrimaryCanditate(Account account, final OnPrimaryCanditateFound listener) {
|
||||
if (!this.primaryCanditates.containsKey(account.getJid())) {
|
||||
String xmlns = "http://jabber.org/protocol/bytestreams";
|
||||
String proxy = account.getXmppConnection().findDiscoItemByFeature(xmlns);
|
||||
if (proxy!=null) {
|
||||
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||
iq.setTo(proxy);
|
||||
iq.query(xmlns);
|
||||
account.getXmppConnection().sendIqPacket(iq, new OnIqPacketReceived() {
|
||||
|
||||
@Override
|
||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||
Element streamhost = packet.query().findChild("streamhost","http://jabber.org/protocol/bytestreams");
|
||||
if (streamhost!=null) {
|
||||
Log.d("xmppService","streamhost found "+streamhost.toString());
|
||||
Element canditate = new Element("canditate");
|
||||
canditate.setAttribute("cid",nextRandomId());
|
||||
canditate.setAttribute("host", streamhost.getAttribute("host"));
|
||||
canditate.setAttribute("port",streamhost.getAttribute("port"));
|
||||
canditate.setAttribute("type", "proxy");
|
||||
primaryCanditates.put(account.getJid(), canditate);
|
||||
listener.onPrimaryCanditateFound(true, canditate);
|
||||
} else {
|
||||
listener.onPrimaryCanditateFound(false, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
listener.onPrimaryCanditateFound(false, null);
|
||||
}
|
||||
|
||||
} else {
|
||||
listener.onPrimaryCanditateFound(true, this.primaryCanditates.get(account.getJid()));
|
||||
}
|
||||
}
|
||||
|
||||
public String nextRandomId() {
|
||||
return new BigInteger(50, random).toString(32);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package eu.siacs.conversations.xmpp;
|
||||
package eu.siacs.conversations.xmpp.jingle;
|
||||
|
||||
import eu.siacs.conversations.entities.Account;
|
||||
import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.PacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
|
||||
public interface OnJinglePacketReceived extends PacketReceived {
|
||||
public void onJinglePacketReceived(Account account, JinglePacket packet);
|
|
@ -0,0 +1,7 @@
|
|||
package eu.siacs.conversations.xmpp.jingle;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
|
||||
public interface OnPrimaryCanditateFound {
|
||||
public void onPrimaryCanditateFound(boolean success, Element canditate);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package eu.siacs.conversations.xmpp.stanzas.jingle;
|
||||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package eu.siacs.conversations.xmpp.stanzas.jingle;
|
||||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
|
@ -1,4 +1,4 @@
|
|||
package eu.siacs.conversations.xmpp.stanzas.jingle;
|
||||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
|
Loading…
Reference in a new issue