mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-27 21:29:47 +01:00
Rewrite MessagingService message encoding, conform to new plugin message channel requirements
* This change isn't backwards compatible with previous builds, this version (& onwards) won't be able to "communicate" with old versions, and vice versa. * MC 1.13 requires plugin message channel names to be namespaced, so 'lpuc' has been changed to 'luckperms:update' * The channel names for Redis/Lily types have also changed, I've been wanting to change the encoded format to something a bit saner for a while, and this seemed like a good time. Changing the channel names a) keeps things consistent and b) means I don't have to worry about old versions interpreting the new format.
This commit is contained in:
parent
08869da96e
commit
07469599bc
@ -47,7 +47,7 @@ import javax.annotation.Nonnull;
|
|||||||
* An implementation of {@link Messenger} using the plugin messaging channels.
|
* An implementation of {@link Messenger} using the plugin messaging channels.
|
||||||
*/
|
*/
|
||||||
public class BungeeMessenger implements Messenger, PluginMessageListener {
|
public class BungeeMessenger implements Messenger, PluginMessageListener {
|
||||||
private static final String CHANNEL = "lpuc";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPBukkitPlugin plugin;
|
private final LPBukkitPlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
@ -45,7 +45,7 @@ import javax.annotation.Nonnull;
|
|||||||
* An implementation of {@link Messenger} using LilyPad.
|
* An implementation of {@link Messenger} using LilyPad.
|
||||||
*/
|
*/
|
||||||
public class LilyPadMessenger implements Messenger {
|
public class LilyPadMessenger implements Messenger {
|
||||||
private static final String CHANNEL = "lpuc";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPBukkitPlugin plugin;
|
private final LPBukkitPlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
@ -46,7 +46,7 @@ import javax.annotation.Nonnull;
|
|||||||
* An implementation of {@link Messenger} using the plugin messaging channels.
|
* An implementation of {@link Messenger} using the plugin messaging channels.
|
||||||
*/
|
*/
|
||||||
public class BungeeMessenger implements Messenger, Listener {
|
public class BungeeMessenger implements Messenger, Listener {
|
||||||
private static final String CHANNEL = "lpuc";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPBungeePlugin plugin;
|
private final LPBungeePlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
@ -43,7 +43,7 @@ import javax.annotation.Nonnull;
|
|||||||
* An implementation of {@link Messenger} using Redis, via RedisBungee's API.
|
* An implementation of {@link Messenger} using Redis, via RedisBungee's API.
|
||||||
*/
|
*/
|
||||||
public class RedisBungeeMessenger implements Messenger, Listener {
|
public class RedisBungeeMessenger implements Messenger, Listener {
|
||||||
private static final String CHANNEL = "lpuc";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPBungeePlugin plugin;
|
private final LPBungeePlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of LuckPerms, licensed under the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.common.actionlog;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class LogEntryJsonSerializer {
|
||||||
|
|
||||||
|
public static JsonObject serialize(LogEntry logEntry) {
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
data.add("actor", new JsonPrimitive(logEntry.getActor().toString()));
|
||||||
|
data.add("actorName", new JsonPrimitive(logEntry.getActorName()));
|
||||||
|
data.add("type", new JsonPrimitive(logEntry.getType().name()));
|
||||||
|
if (logEntry.getActed().isPresent()) {
|
||||||
|
data.add("acted", new JsonPrimitive(logEntry.getActed().get().toString()));
|
||||||
|
}
|
||||||
|
data.add("actedName", new JsonPrimitive(logEntry.getActedName()));
|
||||||
|
data.add("action", new JsonPrimitive(logEntry.getAction()));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedLogEntry deserialize(JsonElement element) {
|
||||||
|
Preconditions.checkArgument(element.isJsonObject());
|
||||||
|
JsonObject data = element.getAsJsonObject();
|
||||||
|
|
||||||
|
ExtendedLogEntry.Builder builder = ExtendedLogEntry.build();
|
||||||
|
|
||||||
|
builder.actor(UUID.fromString(data.get("actor").getAsString()));
|
||||||
|
builder.actorName(data.get("actorName").getAsString());
|
||||||
|
builder.type(LogEntry.Type.valueOf(data.get("type").getAsString()));
|
||||||
|
if (data.has("acted")) {
|
||||||
|
builder.actor(UUID.fromString(data.get("acted").getAsString()));
|
||||||
|
}
|
||||||
|
builder.actedName(data.get("actedName").getAsString());
|
||||||
|
builder.action(data.get("action").getAsString());
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private LogEntryJsonSerializer() {}
|
||||||
|
}
|
@ -25,6 +25,11 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.messaging;
|
package me.lucko.luckperms.common.messaging;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.LogEntry;
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
|
import me.lucko.luckperms.api.messenger.IncomingMessageConsumer;
|
||||||
import me.lucko.luckperms.api.messenger.Messenger;
|
import me.lucko.luckperms.api.messenger.Messenger;
|
||||||
@ -41,6 +46,7 @@ import me.lucko.luckperms.common.messaging.message.UpdateMessageImpl;
|
|||||||
import me.lucko.luckperms.common.messaging.message.UserUpdateMessageImpl;
|
import me.lucko.luckperms.common.messaging.message.UserUpdateMessageImpl;
|
||||||
import me.lucko.luckperms.common.model.User;
|
import me.lucko.luckperms.common.model.User;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.common.utils.gson.JObject;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -50,8 +56,11 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer {
|
public class LuckPermsMessagingService implements InternalMessagingService, IncomingMessageConsumer {
|
||||||
|
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
|
||||||
|
|
||||||
private final LuckPermsPlugin plugin;
|
private final LuckPermsPlugin plugin;
|
||||||
private final Set<UUID> receivedMessages;
|
private final Set<UUID> receivedMessages;
|
||||||
private final PushUpdateBuffer updateBuffer;
|
private final PushUpdateBuffer updateBuffer;
|
||||||
@ -137,77 +146,127 @@ public class LuckPermsMessagingService implements InternalMessagingService, Inco
|
|||||||
public boolean consumeIncomingMessage(@Nonnull Message message) {
|
public boolean consumeIncomingMessage(@Nonnull Message message) {
|
||||||
Objects.requireNonNull(message, "message");
|
Objects.requireNonNull(message, "message");
|
||||||
|
|
||||||
if (message instanceof UpdateMessage) {
|
if (!this.receivedMessages.add(message.getId())) {
|
||||||
UpdateMessage msg = (UpdateMessage) message;
|
|
||||||
if (!this.receivedMessages.add(msg.getId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plugin.getLogger().info("[" + getName() + " Messaging] Received update ping with id: " + msg.getId());
|
|
||||||
|
|
||||||
if (this.plugin.getEventFactory().handleNetworkPreSync(false, msg.getId())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plugin.getUpdateTaskBuffer().request();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (message instanceof UserUpdateMessage) {
|
|
||||||
UserUpdateMessage msg = (UserUpdateMessage) message;
|
|
||||||
if (!this.receivedMessages.add(msg.getId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
User user = this.plugin.getUserManager().getIfLoaded(msg.getUser());
|
|
||||||
if (user == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plugin.getLogger().info("[" + getName() + " Messaging] Received user update ping for '" + user.getFriendlyName() + "' with id: " + msg.getId());
|
|
||||||
|
|
||||||
if (this.plugin.getEventFactory().handleNetworkPreSync(false, msg.getId())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plugin.getStorage().loadUser(user.getUuid(), null);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else if (message instanceof LogMessage) {
|
|
||||||
LogMessage msg = (LogMessage) message;
|
|
||||||
if (!this.receivedMessages.add(msg.getId())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plugin.getEventFactory().handleLogReceive(msg.getId(), msg.getLogEntry());
|
|
||||||
this.plugin.getLogDispatcher().dispatchFromRemote((ExtendedLogEntry) msg.getLogEntry());
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.plugin.getLogger().warn("Unable to decode incoming message: " + message + " (" + message.getClass().getName() + ")");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// determine if the message can be handled by us
|
||||||
|
boolean valid = message instanceof UpdateMessage ||
|
||||||
|
message instanceof UserUpdateMessage ||
|
||||||
|
message instanceof LogMessage;
|
||||||
|
|
||||||
|
// instead of throwing an exception here, just return false
|
||||||
|
// it means an instance of LP can gracefully handle messages it doesn't
|
||||||
|
// "understand" yet. (sent from an instance running a newer version, etc)
|
||||||
|
if (!valid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
processIncomingMessage(message);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean consumeIncomingMessageAsString(@Nonnull String encodedString) {
|
public boolean consumeIncomingMessageAsString(@Nonnull String encodedString) {
|
||||||
Objects.requireNonNull(encodedString, "encodedString");
|
Objects.requireNonNull(encodedString, "encodedString");
|
||||||
|
JsonObject decodedObject = GSON.fromJson(encodedString, JsonObject.class).getAsJsonObject();
|
||||||
|
|
||||||
Message decoded = UpdateMessageImpl.decode(encodedString);
|
// extract id
|
||||||
if (decoded != null) {
|
JsonElement idElement = decodedObject.get("id");
|
||||||
return consumeIncomingMessage(decoded);
|
if (idElement == null) {
|
||||||
|
throw new IllegalStateException("Incoming message has no id argument: " + encodedString);
|
||||||
|
}
|
||||||
|
UUID id = UUID.fromString(idElement.getAsString());
|
||||||
|
|
||||||
|
// ensure the message hasn't been received already
|
||||||
|
if (!this.receivedMessages.add(id)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
decoded = UserUpdateMessageImpl.decode(encodedString);
|
// extract type
|
||||||
if (decoded != null) {
|
JsonElement typeElement = decodedObject.get("type");
|
||||||
return consumeIncomingMessage(decoded);
|
if (typeElement == null) {
|
||||||
|
throw new IllegalStateException("Incoming message has no type argument: " + encodedString);
|
||||||
|
}
|
||||||
|
String type = typeElement.getAsString();
|
||||||
|
|
||||||
|
// extract content
|
||||||
|
@Nullable JsonElement content = decodedObject.get("content");
|
||||||
|
|
||||||
|
// decode message
|
||||||
|
Message decoded;
|
||||||
|
switch (type) {
|
||||||
|
case UpdateMessageImpl.TYPE:
|
||||||
|
decoded = UpdateMessageImpl.decode(content, id);
|
||||||
|
break;
|
||||||
|
case UserUpdateMessageImpl.TYPE:
|
||||||
|
decoded = UserUpdateMessageImpl.decode(content, id);
|
||||||
|
break;
|
||||||
|
case LogMessageImpl.TYPE:
|
||||||
|
decoded = LogMessageImpl.decode(content, id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// gracefully return if we just don't recognise the type
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
decoded = LogMessageImpl.decode(encodedString);
|
// consume the message
|
||||||
return decoded != null && consumeIncomingMessage(decoded);
|
processIncomingMessage(decoded);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeMessageAsString(String type, UUID id, @Nullable JsonElement content) {
|
||||||
|
JsonObject json = new JObject()
|
||||||
|
.add("id", id.toString())
|
||||||
|
.add("type", type)
|
||||||
|
.consume(o -> {
|
||||||
|
if (content != null) {
|
||||||
|
o.add("content", content);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.toJson();
|
||||||
|
|
||||||
|
return GSON.toJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processIncomingMessage(Message message) {
|
||||||
|
if (message instanceof UpdateMessage) {
|
||||||
|
UpdateMessage msg = (UpdateMessage) message;
|
||||||
|
|
||||||
|
this.plugin.getLogger().info("[" + getName() + " Messaging] Received update ping with id: " + msg.getId());
|
||||||
|
|
||||||
|
if (this.plugin.getEventFactory().handleNetworkPreSync(false, msg.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.plugin.getUpdateTaskBuffer().request();
|
||||||
|
} else if (message instanceof UserUpdateMessage) {
|
||||||
|
UserUpdateMessage msg = (UserUpdateMessage) message;
|
||||||
|
|
||||||
|
User user = this.plugin.getUserManager().getIfLoaded(msg.getUser());
|
||||||
|
if (user == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.plugin.getLogger().info("[" + getName() + " Messaging] Received user update ping for '" + user.getFriendlyName() + "' with id: " + msg.getId());
|
||||||
|
|
||||||
|
if (this.plugin.getEventFactory().handleNetworkPreSync(false, msg.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.plugin.getStorage().loadUser(user.getUuid(), null);
|
||||||
|
} else if (message instanceof LogMessage) {
|
||||||
|
LogMessage msg = (LogMessage) message;
|
||||||
|
|
||||||
|
this.plugin.getEventFactory().handleLogReceive(msg.getId(), msg.getLogEntry());
|
||||||
|
this.plugin.getLogDispatcher().dispatchFromRemote((ExtendedLogEntry) msg.getLogEntry());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unknown message type: " + message.getClass().getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class PushUpdateBuffer extends BufferedRequest<Void> {
|
private final class PushUpdateBuffer extends BufferedRequest<Void> {
|
||||||
public PushUpdateBuffer(LuckPermsPlugin plugin) {
|
PushUpdateBuffer(LuckPermsPlugin plugin) {
|
||||||
super(2, TimeUnit.SECONDS, plugin.getBootstrap().getScheduler());
|
super(2, TimeUnit.SECONDS, plugin.getBootstrap().getScheduler());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,37 +25,27 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.messaging.message;
|
package me.lucko.luckperms.common.messaging.message;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonPrimitive;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.api.LogEntry;
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
import me.lucko.luckperms.api.messenger.message.type.LogMessage;
|
import me.lucko.luckperms.api.messenger.message.type.LogMessage;
|
||||||
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
|
import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer;
|
||||||
|
import me.lucko.luckperms.common.messaging.LuckPermsMessagingService;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class LogMessageImpl extends AbstractMessage implements LogMessage {
|
public class LogMessageImpl extends AbstractMessage implements LogMessage {
|
||||||
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
|
public static final String TYPE = "log";
|
||||||
private static final String LOG_HEADER = "log";
|
|
||||||
|
|
||||||
public static LogMessageImpl decode(String msg) {
|
public static LogMessageImpl decode(@Nullable JsonElement content, UUID id) {
|
||||||
if (msg.startsWith(LOG_HEADER) && msg.length() > LOG_HEADER.length()) {
|
if (content == null) {
|
||||||
String content = msg.substring(LOG_HEADER.length());
|
throw new IllegalStateException("Missing content");
|
||||||
|
|
||||||
try {
|
|
||||||
return decodeContent(GSON.fromJson(content, JsonObject.class));
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return new LogMessageImpl(id, LogEntryJsonSerializer.deserialize(content));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LogEntry logEntry;
|
private final LogEntry logEntry;
|
||||||
@ -74,65 +64,9 @@ public class LogMessageImpl extends AbstractMessage implements LogMessage {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String asEncodedString() {
|
public String asEncodedString() {
|
||||||
return LOG_HEADER + GSON.toJson(encodeContent(uuidToString(getId()), this.logEntry));
|
return LuckPermsMessagingService.encodeMessageAsString(
|
||||||
}
|
TYPE, getId(), LogEntryJsonSerializer.serialize(logEntry)
|
||||||
|
);
|
||||||
private static String uuidToString(UUID uuid) {
|
|
||||||
ByteBuffer buf = ByteBuffer.allocate(Long.BYTES * 2);
|
|
||||||
buf.putLong(uuid.getMostSignificantBits());
|
|
||||||
buf.putLong(uuid.getLeastSignificantBits());
|
|
||||||
return Base64.getEncoder().encodeToString(buf.array());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UUID uuidFromString(String s) {
|
|
||||||
try {
|
|
||||||
byte[] bytes = Base64.getDecoder().decode(s);
|
|
||||||
ByteBuffer buf = ByteBuffer.wrap(bytes);
|
|
||||||
return new UUID(buf.getLong(), buf.getLong());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JsonObject encodeContent(String id, LogEntry entry) {
|
|
||||||
JsonObject data = new JsonObject();
|
|
||||||
|
|
||||||
data.add("id", new JsonPrimitive(id));
|
|
||||||
data.add("actor", new JsonPrimitive(entry.getActor().toString()));
|
|
||||||
data.add("actorName", new JsonPrimitive(entry.getActorName()));
|
|
||||||
data.add("type", new JsonPrimitive(entry.getType().name()));
|
|
||||||
if (entry.getActed().isPresent()) {
|
|
||||||
data.add("acted", new JsonPrimitive(entry.getActed().get().toString()));
|
|
||||||
}
|
|
||||||
data.add("actedName", new JsonPrimitive(entry.getActedName()));
|
|
||||||
data.add("action", new JsonPrimitive(entry.getAction()));
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LogMessageImpl decodeContent(JsonObject object) {
|
|
||||||
ExtendedLogEntry.Builder builder = ExtendedLogEntry.build();
|
|
||||||
|
|
||||||
String id = object.get("id").getAsString();
|
|
||||||
if (id == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID uuid = uuidFromString(id);
|
|
||||||
if (uuid == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.actor(UUID.fromString(object.get("actor").getAsString()));
|
|
||||||
builder.actorName(object.get("actorName").getAsString());
|
|
||||||
builder.type(LogEntry.Type.valueOf(object.get("type").getAsString()));
|
|
||||||
if (object.has("acted")) {
|
|
||||||
builder.actor(UUID.fromString(object.get("acted").getAsString()));
|
|
||||||
}
|
|
||||||
builder.actedName(object.get("actedName").getAsString());
|
|
||||||
builder.action(object.get("action").getAsString());
|
|
||||||
|
|
||||||
return new LogMessageImpl(uuid, builder.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,24 +25,21 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.messaging.message;
|
package me.lucko.luckperms.common.messaging.message;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.messenger.message.type.UpdateMessage;
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.messenger.message.type.UpdateMessage;
|
||||||
|
import me.lucko.luckperms.common.messaging.LuckPermsMessagingService;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class UpdateMessageImpl extends AbstractMessage implements UpdateMessage {
|
public class UpdateMessageImpl extends AbstractMessage implements UpdateMessage {
|
||||||
private static final String UPDATE_HEADER = "update:";
|
public static final String TYPE = "update";
|
||||||
|
|
||||||
public static UpdateMessageImpl decode(String msg) {
|
public static UpdateMessageImpl decode(@Nullable JsonElement content, UUID id) {
|
||||||
if (msg.startsWith(UPDATE_HEADER) && msg.length() > UPDATE_HEADER.length()) {
|
return new UpdateMessageImpl(id);
|
||||||
String content = msg.substring(UPDATE_HEADER.length());
|
|
||||||
return decodeContent(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateMessageImpl(UUID id) {
|
public UpdateMessageImpl(UUID id) {
|
||||||
@ -52,23 +49,6 @@ public class UpdateMessageImpl extends AbstractMessage implements UpdateMessage
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String asEncodedString() {
|
public String asEncodedString() {
|
||||||
return UPDATE_HEADER + encodeContent(getId());
|
return LuckPermsMessagingService.encodeMessageAsString(TYPE, getId(), null);
|
||||||
}
|
|
||||||
|
|
||||||
private static String encodeContent(UUID uuid) {
|
|
||||||
ByteBuffer buf = ByteBuffer.allocate(Long.BYTES * 2);
|
|
||||||
buf.putLong(uuid.getMostSignificantBits());
|
|
||||||
buf.putLong(uuid.getLeastSignificantBits());
|
|
||||||
return Base64.getEncoder().encodeToString(buf.array());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UpdateMessageImpl decodeContent(String s) {
|
|
||||||
try {
|
|
||||||
byte[] bytes = Base64.getDecoder().decode(s);
|
|
||||||
ByteBuffer buf = ByteBuffer.wrap(bytes);
|
|
||||||
return new UpdateMessageImpl(new UUID(buf.getLong(), buf.getLong()));
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,24 +25,33 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.common.messaging.message;
|
package me.lucko.luckperms.common.messaging.message;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.messenger.message.type.UserUpdateMessage;
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.messenger.message.type.UserUpdateMessage;
|
||||||
|
import me.lucko.luckperms.common.messaging.LuckPermsMessagingService;
|
||||||
|
import me.lucko.luckperms.common.utils.gson.JObject;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class UserUpdateMessageImpl extends AbstractMessage implements UserUpdateMessage {
|
public class UserUpdateMessageImpl extends AbstractMessage implements UserUpdateMessage {
|
||||||
private static final String USER_UPDATE_HEADER = "userupdate:";
|
public static final String TYPE = "userupdate";
|
||||||
|
|
||||||
public static UserUpdateMessageImpl decode(String msg) {
|
public static UserUpdateMessageImpl decode(@Nullable JsonElement content, UUID id) {
|
||||||
if (msg.startsWith(USER_UPDATE_HEADER) && msg.length() > USER_UPDATE_HEADER.length()) {
|
if (content == null) {
|
||||||
String content = msg.substring(USER_UPDATE_HEADER.length());
|
throw new IllegalStateException("Missing content");
|
||||||
return decodeContent(content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
// extract user uuid
|
||||||
|
JsonElement uuidElement = content.getAsJsonObject().get("userUuid");
|
||||||
|
if (uuidElement == null) {
|
||||||
|
throw new IllegalStateException("Incoming message has no userUuid argument: " + content);
|
||||||
|
}
|
||||||
|
UUID userUuid = UUID.fromString(uuidElement.getAsString());
|
||||||
|
|
||||||
|
return new UserUpdateMessageImpl(id, userUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final UUID userUuid;
|
private final UUID userUuid;
|
||||||
@ -61,27 +70,8 @@ public class UserUpdateMessageImpl extends AbstractMessage implements UserUpdate
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String asEncodedString() {
|
public String asEncodedString() {
|
||||||
return USER_UPDATE_HEADER + encodeContent(getId(), this.userUuid);
|
return LuckPermsMessagingService.encodeMessageAsString(
|
||||||
}
|
TYPE, getId(), new JObject().add("userUuid", userUuid.toString()).toJson()
|
||||||
|
);
|
||||||
private static String encodeContent(UUID id, UUID userUuid) {
|
|
||||||
ByteBuffer buf = ByteBuffer.allocate(Long.BYTES * 4);
|
|
||||||
buf.putLong(id.getMostSignificantBits());
|
|
||||||
buf.putLong(id.getLeastSignificantBits());
|
|
||||||
buf.putLong(userUuid.getMostSignificantBits());
|
|
||||||
buf.putLong(userUuid.getLeastSignificantBits());
|
|
||||||
return Base64.getEncoder().encodeToString(buf.array());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UserUpdateMessageImpl decodeContent(String s) {
|
|
||||||
try {
|
|
||||||
byte[] bytes = Base64.getDecoder().decode(s);
|
|
||||||
ByteBuffer buf = ByteBuffer.wrap(bytes);
|
|
||||||
UUID id = new UUID(buf.getLong(), buf.getLong());
|
|
||||||
UUID userUuid = new UUID(buf.getLong(), buf.getLong());
|
|
||||||
return new UserUpdateMessageImpl(id, userUuid);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ import javax.annotation.Nonnull;
|
|||||||
* An implementation of {@link Messenger} using Redis.
|
* An implementation of {@link Messenger} using Redis.
|
||||||
*/
|
*/
|
||||||
public class RedisMessenger implements Messenger {
|
public class RedisMessenger implements Messenger {
|
||||||
private static final String CHANNEL = "lpuc";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LuckPermsPlugin plugin;
|
private final LuckPermsPlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
@ -28,24 +28,21 @@ package me.lucko.luckperms.common.storage.dao.file;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.LogEntry;
|
import me.lucko.luckperms.api.LogEntry;
|
||||||
import me.lucko.luckperms.common.actionlog.ExtendedLogEntry;
|
|
||||||
import me.lucko.luckperms.common.actionlog.Log;
|
import me.lucko.luckperms.common.actionlog.Log;
|
||||||
|
import me.lucko.luckperms.common.actionlog.LogEntryJsonSerializer;
|
||||||
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
import me.lucko.luckperms.common.buffers.BufferedRequest;
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
import me.lucko.luckperms.common.utils.gson.JObject;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
@ -109,19 +106,7 @@ public class FileActionLogger {
|
|||||||
|
|
||||||
// poll the queue for new entries
|
// poll the queue for new entries
|
||||||
for (LogEntry e; (e = this.entryQueue.poll()) != null; ) {
|
for (LogEntry e; (e = this.entryQueue.poll()) != null; ) {
|
||||||
JObject object = new JObject()
|
array.add(LogEntryJsonSerializer.serialize(e));
|
||||||
.add("timestamp", e.getTimestamp())
|
|
||||||
.add("actor", e.getActor().toString())
|
|
||||||
.add("actorName", e.getActorName())
|
|
||||||
.add("type", Character.toString(e.getType().getCode()))
|
|
||||||
.add("actedName", e.getActedName())
|
|
||||||
.add("action", e.getAction());
|
|
||||||
|
|
||||||
if (e.getActed().isPresent()) {
|
|
||||||
object.add("acted", e.getActed().get().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
array.add(object.toJson());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the full content back to the file
|
// write the full content back to the file
|
||||||
@ -142,24 +127,7 @@ public class FileActionLogger {
|
|||||||
try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) {
|
try (JsonReader reader = new JsonReader(Files.newBufferedReader(this.contentFile, StandardCharsets.UTF_8))) {
|
||||||
JsonArray array = JSON_PARSER.parse(reader).getAsJsonArray();
|
JsonArray array = JSON_PARSER.parse(reader).getAsJsonArray();
|
||||||
for (JsonElement element : array) {
|
for (JsonElement element : array) {
|
||||||
JsonObject object = element.getAsJsonObject();
|
log.add(LogEntryJsonSerializer.deserialize(element));
|
||||||
|
|
||||||
UUID actedUuid = null;
|
|
||||||
if (object.has("acted")) {
|
|
||||||
actedUuid = UUID.fromString(object.get("acted").getAsString());
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtendedLogEntry e = ExtendedLogEntry.build()
|
|
||||||
.timestamp(object.get("timestamp").getAsLong())
|
|
||||||
.actor(UUID.fromString(object.get("actor").getAsString()))
|
|
||||||
.actorName(object.get("actorName").getAsString())
|
|
||||||
.type(LogEntry.Type.valueOf(object.get("type").getAsCharacter()))
|
|
||||||
.acted(actedUuid)
|
|
||||||
.actedName(object.get("actedName").getAsString())
|
|
||||||
.action(object.get("action").getAsString())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
log.add(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return log.build();
|
return log.build();
|
||||||
|
@ -48,7 +48,7 @@ import javax.annotation.Nonnull;
|
|||||||
* An implementation of {@link Messenger} using the plugin messaging channels.
|
* An implementation of {@link Messenger} using the plugin messaging channels.
|
||||||
*/
|
*/
|
||||||
public class BungeeMessenger implements Messenger, RawDataListener {
|
public class BungeeMessenger implements Messenger, RawDataListener {
|
||||||
private static final String CHANNEL = "lpuc";
|
private static final String CHANNEL = "luckperms:update";
|
||||||
|
|
||||||
private final LPSpongePlugin plugin;
|
private final LPSpongePlugin plugin;
|
||||||
private final IncomingMessageConsumer consumer;
|
private final IncomingMessageConsumer consumer;
|
||||||
|
Loading…
Reference in New Issue
Block a user