aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/pixart/messenger/services
diff options
context:
space:
mode:
authorChristian Schneppe <christian.schneppe@pix-art.de>2019-11-03 19:41:16 +0100
committerChristian Schneppe <christian.schneppe@pix-art.de>2019-11-03 19:41:16 +0100
commitad75ab3f683391c26c2a99242210747c0bf881c2 (patch)
tree03cb3f2d2eb80e5a19a72315e09da0619f322316 /src/main/java/de/pixart/messenger/services
parent6a672b4aacfd62fcbbbe3ea031bf53c0daace132 (diff)
optionally search local muc rooms instead of jabber.network
Diffstat (limited to '')
-rw-r--r--src/main/java/de/pixart/messenger/services/AvatarService.java15
-rw-r--r--src/main/java/de/pixart/messenger/services/ChannelDiscoveryService.java172
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java13
3 files changed, 149 insertions, 51 deletions
diff --git a/src/main/java/de/pixart/messenger/services/AvatarService.java b/src/main/java/de/pixart/messenger/services/AvatarService.java
index 469de2599..0ae6f7099 100644
--- a/src/main/java/de/pixart/messenger/services/AvatarService.java
+++ b/src/main/java/de/pixart/messenger/services/AvatarService.java
@@ -13,14 +13,15 @@ import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import androidx.annotation.ColorInt;
-import androidx.annotation.Nullable;
-import androidx.core.content.res.ResourcesCompat;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LruCache;
+import androidx.annotation.ColorInt;
+import androidx.annotation.Nullable;
+import androidx.core.content.res.ResourcesCompat;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -39,7 +40,7 @@ import de.pixart.messenger.entities.ListItem;
import de.pixart.messenger.entities.Message;
import de.pixart.messenger.entities.MucOptions;
import de.pixart.messenger.entities.RawBlockable;
-import de.pixart.messenger.http.services.MuclumbusService;
+import de.pixart.messenger.entities.Room;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.xmpp.OnAdvancedStreamFeaturesLoaded;
import de.pixart.messenger.xmpp.XmppConnection;
@@ -84,13 +85,13 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
return get((ListItem) avatarable, size, cachedOnly);
} else if (avatarable instanceof MucOptions.User) {
return get((MucOptions.User) avatarable, size, cachedOnly);
- } else if (avatarable instanceof MuclumbusService.Room) {
- return get((MuclumbusService.Room) avatarable, size, cachedOnly);
+ } else if (avatarable instanceof Room) {
+ return get((Room) avatarable, size, cachedOnly);
}
throw new AssertionError("AvatarService does not know how to generate avatar from " + avatarable.getClass().getName());
}
- private Bitmap get(final MuclumbusService.Room result, final int size, boolean cacheOnly) {
+ private Bitmap get(final Room result, final int size, boolean cacheOnly) {
final Jid room = result.getRoom();
Conversation conversation = room != null ? mXmppConnectionService.findFirstMuc(room) : null;
if (conversation != null) {
diff --git a/src/main/java/de/pixart/messenger/services/ChannelDiscoveryService.java b/src/main/java/de/pixart/messenger/services/ChannelDiscoveryService.java
index bd92c886d..81668cb92 100644
--- a/src/main/java/de/pixart/messenger/services/ChannelDiscoveryService.java
+++ b/src/main/java/de/pixart/messenger/services/ChannelDiscoveryService.java
@@ -1,39 +1,48 @@
package de.pixart.messenger.services;
-import androidx.annotation.NonNull;
import android.util.Log;
+import androidx.annotation.NonNull;
+
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
-import org.jetbrains.annotations.NotNull;
-
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import de.pixart.messenger.Config;
+import de.pixart.messenger.entities.Account;
+import de.pixart.messenger.entities.Room;
import de.pixart.messenger.http.HttpConnectionManager;
import de.pixart.messenger.http.services.MuclumbusService;
-import okhttp3.Interceptor;
+import de.pixart.messenger.parser.IqParser;
+import de.pixart.messenger.xmpp.OnIqPacketReceived;
+import de.pixart.messenger.xmpp.XmppConnection;
+import de.pixart.messenger.xmpp.stanzas.IqPacket;
import okhttp3.OkHttpClient;
-import okhttp3.Request;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
+import rocks.xmpp.addr.Jid;
public class ChannelDiscoveryService {
private final XmppConnectionService service;
+
private MuclumbusService muclumbusService;
- private final Cache<String, List<MuclumbusService.Room>> cache;
+ private final Cache<String, List<Room>> cache;
ChannelDiscoveryService(XmppConnectionService service) {
this.service = service;
@@ -42,6 +51,7 @@ public class ChannelDiscoveryService {
void initializeMuclumbusService() {
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
+
if (service.useTorToConnect()) {
try {
builder.proxy(HttpConnectionManager.getProxy());
@@ -49,11 +59,6 @@ public class ChannelDiscoveryService {
throw new RuntimeException("Unable to use Tor proxy", e);
}
}
- try {
- builder.networkInterceptors().add(new UserAgentInterceptor(service.getIqGenerator().getUserAgent()));
- } catch (Exception e) {
- e.printStackTrace();
- }
Retrofit retrofit = new Retrofit.Builder()
.client(builder.build())
.baseUrl(Config.CHANNEL_DISCOVERY)
@@ -63,21 +68,28 @@ public class ChannelDiscoveryService {
this.muclumbusService = retrofit.create(MuclumbusService.class);
}
- void discover(String query, OnChannelSearchResultsFound onChannelSearchResultsFound) {
- final boolean all = query == null || query.trim().isEmpty();
- List<MuclumbusService.Room> result = cache.getIfPresent(all ? "" : query);
+ void cleanCache() {
+ cache.invalidateAll();
+ }
+
+ void discover(@NonNull final String query, Method method, OnChannelSearchResultsFound onChannelSearchResultsFound) {
+ List<Room> result = cache.getIfPresent(key(method, query));
if (result != null) {
onChannelSearchResultsFound.onChannelSearchResultsFound(result);
return;
}
- if (all) {
- discoverChannels(onChannelSearchResultsFound);
+ if (method == Method.LOCAL_SERVER) {
+ discoverChannelsLocalServers(query, onChannelSearchResultsFound);
} else {
- discoverChannels(query, onChannelSearchResultsFound);
+ if (query.isEmpty()) {
+ discoverChannelsJabberNetwork(onChannelSearchResultsFound);
+ } else {
+ discoverChannelsJabberNetwork(query, onChannelSearchResultsFound);
+ }
}
}
- private void discoverChannels(OnChannelSearchResultsFound listener) {
+ private void discoverChannelsJabberNetwork(OnChannelSearchResultsFound listener) {
Call<MuclumbusService.Rooms> call = muclumbusService.getRooms(1);
try {
call.enqueue(new Callback<MuclumbusService.Rooms>() {
@@ -89,7 +101,7 @@ public class ChannelDiscoveryService {
logError(response);
return;
}
- cache.put("", body.items);
+ cache.put(key(Method.JABBER_NETWORK, ""), body.items);
listener.onChannelSearchResultsFound(body.items);
}
@@ -104,9 +116,10 @@ public class ChannelDiscoveryService {
}
}
- private void discoverChannels(final String query, OnChannelSearchResultsFound listener) {
+ private void discoverChannelsJabberNetwork(final String query, OnChannelSearchResultsFound listener) {
MuclumbusService.SearchRequest searchRequest = new MuclumbusService.SearchRequest(query);
Call<MuclumbusService.SearchResult> searchResultCall = muclumbusService.search(searchRequest);
+
searchResultCall.enqueue(new Callback<MuclumbusService.SearchResult>() {
@Override
public void onResponse(@NonNull Call<MuclumbusService.SearchResult> call, @NonNull Response<MuclumbusService.SearchResult> response) {
@@ -116,7 +129,7 @@ public class ChannelDiscoveryService {
logError(response);
return;
}
- cache.put(query, body.result.items);
+ cache.put(key(Method.JABBER_NETWORK, query), body.result.items);
listener.onChannelSearchResultsFound(body.result.items);
}
@@ -128,6 +141,102 @@ public class ChannelDiscoveryService {
});
}
+ private void discoverChannelsLocalServers(final String query, final OnChannelSearchResultsFound listener) {
+ final Map<Jid, Account> localMucService = getLocalMucServices();
+ Log.d(Config.LOGTAG, "checking with " + localMucService.size() + " muc services");
+ if (localMucService.size() == 0) {
+ listener.onChannelSearchResultsFound(Collections.emptyList());
+ return;
+ }
+ if (!query.isEmpty()) {
+ final List<Room> cached = cache.getIfPresent(key(Method.LOCAL_SERVER, ""));
+ if (cached != null) {
+ final List<Room> results = copyMatching(cached, query);
+ cache.put(key(Method.LOCAL_SERVER, query), results);
+ listener.onChannelSearchResultsFound(results);
+ }
+ }
+ final AtomicInteger queriesInFlight = new AtomicInteger();
+ final List<Room> rooms = new ArrayList<>();
+ for (Map.Entry<Jid, Account> entry : localMucService.entrySet()) {
+ IqPacket itemsRequest = service.getIqGenerator().queryDiscoItems(entry.getKey());
+ queriesInFlight.incrementAndGet();
+ service.sendIqPacket(entry.getValue(), itemsRequest, (account, itemsResponse) -> {
+ if (itemsResponse.getType() == IqPacket.TYPE.RESULT) {
+ final List<Jid> items = IqParser.items(itemsResponse);
+ for (Jid item : items) {
+ IqPacket infoRequest = service.getIqGenerator().queryDiscoInfo(item);
+ queriesInFlight.incrementAndGet();
+ service.sendIqPacket(account, infoRequest, new OnIqPacketReceived() {
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket infoResponse) {
+ if (infoResponse.getType() == IqPacket.TYPE.RESULT) {
+ final Room room = IqParser.parseRoom(infoResponse);
+ if (room != null) {
+ rooms.add(room);
+ }
+ if (queriesInFlight.decrementAndGet() <= 0) {
+ finishDiscoSearch(rooms, query, listener);
+ }
+ } else {
+ queriesInFlight.decrementAndGet();
+ }
+ }
+ });
+ }
+ }
+ if (queriesInFlight.decrementAndGet() <= 0) {
+ finishDiscoSearch(rooms, query, listener);
+ }
+ });
+ }
+ }
+
+ private void finishDiscoSearch(List<Room> rooms, String query, OnChannelSearchResultsFound listener) {
+ Collections.sort(rooms);
+ cache.put(key(Method.LOCAL_SERVER, ""), rooms);
+ if (query.isEmpty()) {
+ listener.onChannelSearchResultsFound(rooms);
+ } else {
+ List<Room> results = copyMatching(rooms, query);
+ cache.put(key(Method.LOCAL_SERVER, query), results);
+ listener.onChannelSearchResultsFound(rooms);
+ }
+ }
+
+ private static List<Room> copyMatching(List<Room> haystack, String needle) {
+ ArrayList<Room> result = new ArrayList<>();
+ for (Room room : haystack) {
+ if (room.contains(needle)) {
+ result.add(room);
+ }
+ }
+ return result;
+ }
+
+ private Map<Jid, Account> getLocalMucServices() {
+ final HashMap<Jid, Account> localMucServices = new HashMap<>();
+ for (Account account : service.getAccounts()) {
+ if (account.isEnabled()) {
+ final XmppConnection xmppConnection = account.getXmppConnection();
+ if (xmppConnection == null) {
+ continue;
+ }
+ for (final String mucService : xmppConnection.getMucServers()) {
+ Jid jid = Jid.of(mucService);
+ if (!localMucServices.containsKey(jid)) {
+ localMucServices.put(jid, account);
+ }
+ }
+ }
+ }
+ return localMucServices;
+ }
+
+ private static String key(Method method, String query) {
+ return String.format("%s\00%s", method, query);
+ }
+
private static void logError(final Response response) {
final ResponseBody errorBody = response.errorBody();
Log.d(Config.LOGTAG, "code from muclumbus=" + response.code());
@@ -142,24 +251,11 @@ public class ChannelDiscoveryService {
}
public interface OnChannelSearchResultsFound {
- void onChannelSearchResultsFound(List<MuclumbusService.Room> results);
+ void onChannelSearchResultsFound(List<Room> results);
}
- private class UserAgentInterceptor implements Interceptor {
- private final String userAgent;
-
- UserAgentInterceptor(String userAgent) {
- this.userAgent = userAgent;
- }
-
- @NotNull
- @Override
- public okhttp3.Response intercept(Chain chain) throws IOException {
- Request originalRequest = chain.request();
- Request requestWithUserAgent = originalRequest.newBuilder()
- .header("User-Agent", userAgent)
- .build();
- return chain.proceed(requestWithUserAgent);
- }
+ public enum Method {
+ JABBER_NETWORK,
+ LOCAL_SERVER
}
} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index e7c587107..5de4c79b9 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -44,6 +44,8 @@ import androidx.annotation.IntegerRes;
import androidx.core.app.RemoteInput;
import androidx.core.content.ContextCompat;
+import com.google.common.base.Strings;
+
import net.java.otr4j.OtrException;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionID;
@@ -928,8 +930,8 @@ public class XmppConnectionService extends Service {
mChannelDiscoveryService.initializeMuclumbusService();
}
- public void discoverChannels(String query, ChannelDiscoveryService.OnChannelSearchResultsFound onChannelSearchResultsFound) {
- mChannelDiscoveryService.discover(query, onChannelSearchResultsFound);
+ public void discoverChannels(String query, ChannelDiscoveryService.Method method, ChannelDiscoveryService.OnChannelSearchResultsFound onChannelSearchResultsFound) {
+ mChannelDiscoveryService.discover(Strings.nullToEmpty(query).trim(), method, onChannelSearchResultsFound);
}
public boolean isDataSaverDisabled() {
@@ -2536,6 +2538,7 @@ public class XmppConnectionService extends Service {
getNotificationService().updateErrorNotification();
toggleForegroundService();
syncEnabledAccountSetting();
+ mChannelDiscoveryService.cleanCache();
return true;
} else {
return false;
@@ -3379,9 +3382,7 @@ public class XmppConnectionService extends Service {
}
public void fetchConferenceConfiguration(final Conversation conversation, final OnConferenceConfigurationFetched callback) {
- IqPacket request = new IqPacket(IqPacket.TYPE.GET);
- request.setTo(conversation.getJid().asBareJid());
- request.query("http://jabber.org/protocol/disco#info");
+ IqPacket request = mIqGenerator.queryDiscoInfo(conversation.getJid().asBareJid());
sendIqPacket(conversation.getAccount(), request, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
@@ -4831,7 +4832,7 @@ public class XmppConnectionService extends Service {
request.setTo(jid);
final String node = presence.getNode();
final String ver = presence.getVer();
- final Element query = request.query("http://jabber.org/protocol/disco#info");
+ final Element query = request.query(Namespace.DISCO_INFO);
if (node != null && ver != null) {
query.setAttribute("node", node + "#" + ver);
}