fixed service discovery by properly storing and checking identities

This commit is contained in:
Daniel Gultsch 2015-04-25 18:24:10 +02:00
parent 82daf849aa
commit 5ea1c547d5
3 changed files with 50 additions and 30 deletions

View file

@ -468,7 +468,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
} else { } else {
this.mServerInfoSm.setText(R.string.server_info_unavailable); this.mServerInfoSm.setText(R.string.server_info_unavailable);
} }
if (features.pubsub()) { if (features.pep()) {
this.mServerInfoPep.setText(R.string.server_info_available); this.mServerInfoPep.setText(R.string.server_info_available);
} else { } else {
this.mServerInfoPep.setText(R.string.server_info_unavailable); this.mServerInfoPep.setText(R.string.server_info_unavailable);

View file

@ -163,8 +163,7 @@ public class PublishProfilePictureActivity extends XmppActivity {
if (jid != null) { if (jid != null) {
this.account = xmppConnectionService.findAccountByJid(jid); this.account = xmppConnectionService.findAccountByJid(jid);
if (this.account.getXmppConnection() != null) { if (this.account.getXmppConnection() != null) {
this.support = this.account.getXmppConnection() this.support = this.account.getXmppConnection().getFeatures().pep();
.getFeatures().pubsub();
} }
if (this.avatarUri == null) { if (this.avatarUri == null) {
if (this.account.getAvatar() != null if (this.account.getAvatar() != null

View file

@ -90,7 +90,7 @@ public class XmppConnection implements Runnable {
private boolean shouldBind = true; private boolean shouldBind = true;
private boolean shouldAuthenticate = true; private boolean shouldAuthenticate = true;
private Element streamFeatures; private Element streamFeatures;
private final HashMap<String, List<String>> disco = new HashMap<>(); private final HashMap<Jid, Info> disco = new HashMap<>();
private String streamId = null; private String streamId = null;
private int smVersion = 3; private int smVersion = 3;
@ -334,6 +334,7 @@ public class XmppConnection implements Runnable {
} catch (final NumberFormatException ignored) { } catch (final NumberFormatException ignored) {
} }
sendServiceDiscoveryInfo(account.getServer()); sendServiceDiscoveryInfo(account.getServer());
sendServiceDiscoveryInfo(account.getJid().toBareJid());
sendServiceDiscoveryItems(account.getServer()); sendServiceDiscoveryItems(account.getServer());
sendInitialPing(); sendInitialPing();
} else if (nextTag.isStart("r")) { } else if (nextTag.isStart("r")) {
@ -734,6 +735,7 @@ public class XmppConnection implements Runnable {
features.blockListRequested = false; features.blockListRequested = false;
disco.clear(); disco.clear();
sendServiceDiscoveryInfo(account.getServer()); sendServiceDiscoveryInfo(account.getServer());
sendServiceDiscoveryInfo(account.getJid().toBareJid());
sendServiceDiscoveryItems(account.getServer()); sendServiceDiscoveryItems(account.getServer());
if (bindListener != null) { if (bindListener != null) {
bindListener.onBind(account); bindListener.onBind(account);
@ -741,34 +743,35 @@ public class XmppConnection implements Runnable {
sendInitialPing(); sendInitialPing();
} }
private void sendServiceDiscoveryInfo(final Jid server) { private void sendServiceDiscoveryInfo(final Jid jid) {
if (disco.containsKey(server.toDomainJid().toString())) { if (disco.containsKey(jid)) {
if (account.getServer().equals(server.toDomainJid())) { if (account.getServer().equals(jid)) {
enableAdvancedStreamFeatures(); enableAdvancedStreamFeatures();
} }
} else { } else {
final IqPacket iq = new IqPacket(IqPacket.TYPE.GET); final IqPacket iq = new IqPacket(IqPacket.TYPE.GET);
iq.setTo(server.toDomainJid()); iq.setTo(jid);
iq.query("http://jabber.org/protocol/disco#info"); iq.query("http://jabber.org/protocol/disco#info");
this.sendIqPacket(iq, new OnIqPacketReceived() { this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(final Account account, final IqPacket packet) { public void onIqPacketReceived(final Account account, final IqPacket packet) {
final List<Element> elements = packet.query().getChildren(); final List<Element> elements = packet.query().getChildren();
final List<String> features = new ArrayList<>(); final Info info = new Info();
for (final Element element : elements) { for (final Element element : elements) {
if (element.getName().equals("identity")) { if (element.getName().equals("identity")) {
if ("irc".equals(element.getAttribute("type"))) { String type = element.getAttribute("type");
//add fake feature to not confuse irc and real muc String category = element.getAttribute("category");
features.add("siacs:no:muc"); if (type != null && category != null) {
info.identities.add(new Pair<>(category,type));
} }
} else if (element.getName().equals("feature")) { } else if (element.getName().equals("feature")) {
features.add(element.getAttribute("var")); info.features.add(element.getAttribute("var"));
} }
} }
disco.put(server.toDomainJid().toString(), features); disco.put(jid, info);
if (account.getServer().equals(server.toDomainJid())) { if (account.getServer().equals(jid)) {
enableAdvancedStreamFeatures(); enableAdvancedStreamFeatures();
for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) { for (final OnAdvancedStreamFeaturesLoaded listener : advancedStreamFeaturesLoadedListeners) {
listener.onAdvancedStreamFeaturesAvailable(account); listener.onAdvancedStreamFeaturesAvailable(account);
@ -987,9 +990,9 @@ public class XmppConnection implements Runnable {
public List<String> findDiscoItemsByFeature(final String feature) { public List<String> findDiscoItemsByFeature(final String feature) {
final List<String> items = new ArrayList<>(); final List<String> items = new ArrayList<>();
for (final Entry<String, List<String>> cursor : disco.entrySet()) { for (final Entry<Jid, Info> cursor : disco.entrySet()) {
if (cursor.getValue().contains(feature)) { if (cursor.getValue().features.contains(feature)) {
items.add(cursor.getKey()); items.add(cursor.getKey().toString());
} }
} }
return items; return items;
@ -1008,10 +1011,12 @@ public class XmppConnection implements Runnable {
} }
public String getMucServer() { public String getMucServer() {
for (final Entry<String, List<String>> cursor : disco.entrySet()) { for (final Entry<Jid, Info> cursor : disco.entrySet()) {
final List<String> value = cursor.getValue(); final Info value = cursor.getValue();
if (value.contains("http://jabber.org/protocol/muc") && !value.contains("jabber:iq:gateway") && !value.contains("siacs:no:muc")) { if (value.features.contains("http://jabber.org/protocol/muc")
return cursor.getKey(); && !value.features.contains("jabber:iq:gateway")
&& !value.identities.contains(new Pair<>("conference","irc"))) {
return cursor.getKey().toString();
} }
} }
return null; return null;
@ -1066,6 +1071,11 @@ public class XmppConnection implements Runnable {
this.lastConnect = 0; this.lastConnect = 0;
} }
private class Info {
public final ArrayList<String> features = new ArrayList<>();
public final ArrayList<Pair<String,String>> identities = new ArrayList<>();
}
public class Features { public class Features {
XmppConnection connection; XmppConnection connection;
private boolean carbonsEnabled = false; private boolean carbonsEnabled = false;
@ -1077,8 +1087,8 @@ public class XmppConnection implements Runnable {
} }
private boolean hasDiscoFeature(final Jid server, final String feature) { private boolean hasDiscoFeature(final Jid server, final String feature) {
return connection.disco.containsKey(server.toDomainJid().toString()) && return connection.disco.containsKey(server) &&
connection.disco.get(server.toDomainJid().toString()).contains(feature); connection.disco.get(server).features.contains(feature);
} }
public boolean carbons() { public boolean carbons() {
@ -1094,24 +1104,35 @@ public class XmppConnection implements Runnable {
} }
public boolean sm() { public boolean sm() {
return streamId != null; return streamId != null
|| (connection.streamFeatures != null && connection.streamFeatures.hasChild("sm"));
} }
public boolean csi() { public boolean csi() {
return connection.streamFeatures != null && connection.streamFeatures.hasChild("csi", "urn:xmpp:csi:0"); return connection.streamFeatures != null && connection.streamFeatures.hasChild("csi", "urn:xmpp:csi:0");
} }
public boolean pubsub() { public boolean pep() {
return hasDiscoFeature(account.getServer(), final Pair<String,String> needle = new Pair<>("pubsub","pep");
"http://jabber.org/protocol/pubsub#publish"); Info info = disco.get(account.getServer());
if (info != null && info.identities.contains(needle)) {
return true;
} else {
info = disco.get(account.getJid().toBareJid());
return info != null && info.identities.contains(needle);
}
} }
public boolean mam() { public boolean mam() {
if (hasDiscoFeature(account.getJid().toBareJid(), "urn:xmpp:mam:0")) {
return true;
} else {
return hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0"); return hasDiscoFeature(account.getServer(), "urn:xmpp:mam:0");
} }
}
public boolean advancedStreamFeaturesLoaded() { public boolean advancedStreamFeaturesLoaded() {
return disco.containsKey(account.getServer().toString()); return disco.containsKey(account.getServer());
} }
public boolean rosterVersioning() { public boolean rosterVersioning() {