Add packet logging for debugging
Dieser Commit ist enthalten in:
Ursprung
57cfbc4f81
Commit
9289825d87
@ -715,11 +715,11 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String format(Protocol protocol, Sender sender, String name) {
|
public static String format(Protocol protocol, Sender sender, String name) {
|
||||||
if (name.contains("Packet"))
|
if (name.contains("Packet"))
|
||||||
return name;
|
return name;
|
||||||
|
|
||||||
return String.format("Packet%s%s%s", protocol.getPacketName(), sender.getPacketName(), name);
|
return String.format("Packet%s%s%s", protocol.getPacketName(), sender.getPacketName(), WordUtils.capitalize(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,9 +149,19 @@ public class WirePacket {
|
|||||||
* @return The resulting WirePacket
|
* @return The resulting WirePacket
|
||||||
*/
|
*/
|
||||||
public static WirePacket fromPacket(PacketContainer packet) {
|
public static WirePacket fromPacket(PacketContainer packet) {
|
||||||
checkNotNull(packet, "packet cannot be null!");
|
|
||||||
|
|
||||||
int id = packet.getType().getCurrentId();
|
int id = packet.getType().getCurrentId();
|
||||||
|
return new WirePacket(id, getBytes(bufferFromPacket(packet)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ByteBuf from an existing PacketContainer containing all the
|
||||||
|
* bytes from that packet
|
||||||
|
*
|
||||||
|
* @param packet Existing packet
|
||||||
|
* @return The ByteBuf
|
||||||
|
*/
|
||||||
|
public static ByteBuf bufferFromPacket(PacketContainer packet) {
|
||||||
|
checkNotNull(packet, "packet cannot be null!");
|
||||||
|
|
||||||
ByteBuf buffer = PacketContainer.createPacketBuffer();
|
ByteBuf buffer = PacketContainer.createPacketBuffer();
|
||||||
Method write = MinecraftMethods.getPacketWriteByteBufMethod();
|
Method write = MinecraftMethods.getPacketWriteByteBufMethod();
|
||||||
@ -162,7 +172,7 @@ public class WirePacket {
|
|||||||
throw new RuntimeException("Failed to serialize packet contents.", ex);
|
throw new RuntimeException("Failed to serialize packet contents.", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WirePacket(id, getBytes(buffer));
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,232 @@
|
|||||||
|
/**
|
||||||
|
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||||
|
* Copyright (C) 2017 Dan Mulloy
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program;
|
||||||
|
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
* 02111-1307 USA
|
||||||
|
*/
|
||||||
|
package com.comphenix.protocol;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.FileHandler;
|
||||||
|
import java.util.logging.Formatter;
|
||||||
|
import java.util.logging.Handler;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.LogRecord;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType.Protocol;
|
||||||
|
import com.comphenix.protocol.PacketType.Sender;
|
||||||
|
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||||
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
import com.comphenix.protocol.events.PacketListener;
|
||||||
|
import com.comphenix.protocol.injector.netty.WirePacket;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs packets to a given stream
|
||||||
|
* @author dmulloy2
|
||||||
|
*/
|
||||||
|
public class PacketLogging implements CommandExecutor, PacketListener {
|
||||||
|
public static final String NAME = "packetlog";
|
||||||
|
|
||||||
|
private List<PacketType> sendingTypes = new ArrayList<>();
|
||||||
|
private List<PacketType> receivingTypes = new ArrayList<>();
|
||||||
|
|
||||||
|
private ListeningWhitelist sendingWhitelist;
|
||||||
|
private ListeningWhitelist receivingWhitelist;
|
||||||
|
|
||||||
|
private Logger fileLogger;
|
||||||
|
private LogLocation location = LogLocation.FILE;
|
||||||
|
|
||||||
|
private final ProtocolManager manager;
|
||||||
|
private final Plugin plugin;
|
||||||
|
|
||||||
|
PacketLogging(Plugin plugin, ProtocolManager manager) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
PacketType type = null;
|
||||||
|
|
||||||
|
if (args.length > 2) {
|
||||||
|
Protocol protocol;
|
||||||
|
|
||||||
|
try {
|
||||||
|
protocol = Protocol.valueOf(args[0].toUpperCase());
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Unknown protocol " + args[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sender pSender;
|
||||||
|
|
||||||
|
try {
|
||||||
|
pSender = Sender.valueOf(args[1].toUpperCase());
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Unknown sender: " + args[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
int id = Integer.parseInt(args[2]);
|
||||||
|
type = PacketType.findCurrent(protocol, pSender, id);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
type = PacketType.findCurrent(protocol, pSender, args[2]);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Unknown packet: " + PacketType.format(protocol, pSender, args[2]));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length > 3) {
|
||||||
|
if (args[3].equalsIgnoreCase("console")) {
|
||||||
|
this.location = LogLocation.CONSOLE;
|
||||||
|
} else {
|
||||||
|
this.location = LogLocation.FILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSender == Sender.CLIENT) {
|
||||||
|
if (receivingTypes.contains(type)) {
|
||||||
|
receivingTypes.remove(type);
|
||||||
|
} else {
|
||||||
|
receivingTypes.add(type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sendingTypes.contains(type)) {
|
||||||
|
sendingTypes.remove(type);
|
||||||
|
} else {
|
||||||
|
sendingTypes.add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startLogging();
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Now logging " + type.getPacketClass().getSimpleName());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(ChatColor.RED + "Invalid syntax: /packetlog <protocol> <sender> <packet> [location]");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLogging() {
|
||||||
|
manager.removePacketListener(this);
|
||||||
|
|
||||||
|
if (sendingTypes.isEmpty() && receivingTypes.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sendingWhitelist = ListeningWhitelist.newBuilder().types(sendingTypes).build();
|
||||||
|
this.receivingWhitelist = ListeningWhitelist.newBuilder().types(receivingTypes).build();
|
||||||
|
|
||||||
|
if (location == LogLocation.FILE && fileLogger == null) {
|
||||||
|
fileLogger = Logger.getLogger("ProtocolLib-FileLogging");
|
||||||
|
|
||||||
|
for (Handler handler : fileLogger.getHandlers())
|
||||||
|
fileLogger.removeHandler(handler);
|
||||||
|
fileLogger.setUseParentHandlers(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
File logFile = new File(plugin.getDataFolder(), "log.log");
|
||||||
|
FileHandler handler = new FileHandler(logFile.getAbsolutePath(), true);
|
||||||
|
handler.setFormatter(new LogFormatter());
|
||||||
|
fileLogger.addHandler(handler);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
plugin.getLogger().log(Level.SEVERE, "Failed to obtain log file:", ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
manager.addPacketListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketSending(PacketEvent event) {
|
||||||
|
log(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketReceiving(PacketEvent event) {
|
||||||
|
log(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log(PacketEvent event) {
|
||||||
|
ByteBuf buffer = WirePacket.bufferFromPacket(event.getPacket());
|
||||||
|
String hexDump = ByteBufUtil.hexDump(buffer);
|
||||||
|
|
||||||
|
if (location == LogLocation.FILE) {
|
||||||
|
fileLogger.log(Level.INFO, event.getPacketType() + ":");
|
||||||
|
fileLogger.log(Level.INFO, hexDump);
|
||||||
|
fileLogger.log(Level.INFO, "");
|
||||||
|
} else {
|
||||||
|
System.out.println(event.getPacketType() + ":");
|
||||||
|
System.out.println(hexDump);
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListeningWhitelist getSendingWhitelist() {
|
||||||
|
return sendingWhitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListeningWhitelist getReceivingWhitelist() {
|
||||||
|
return receivingWhitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Plugin getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enum LogLocation {
|
||||||
|
CONSOLE,
|
||||||
|
FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class LogFormatter extends Formatter {
|
||||||
|
private static final SimpleDateFormat DATE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||||
|
private static final String FORMAT = "[{0}] {1}";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(LogRecord record) {
|
||||||
|
String string = formatMessage(record);
|
||||||
|
if (string.isEmpty()) {
|
||||||
|
return LINE_SEPARATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder message = new StringBuilder();
|
||||||
|
message.append(MessageFormat.format(FORMAT, DATE.format(record.getMillis()), string));
|
||||||
|
message.append(LINE_SEPARATOR);
|
||||||
|
return message.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -90,7 +90,8 @@ public class ProtocolLib extends JavaPlugin {
|
|||||||
private enum ProtocolCommand {
|
private enum ProtocolCommand {
|
||||||
FILTER,
|
FILTER,
|
||||||
PACKET,
|
PACKET,
|
||||||
PROTOCOL
|
PROTOCOL,
|
||||||
|
LOGGING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,6 +144,7 @@ public class ProtocolLib extends JavaPlugin {
|
|||||||
private CommandProtocol commandProtocol;
|
private CommandProtocol commandProtocol;
|
||||||
private CommandPacket commandPacket;
|
private CommandPacket commandPacket;
|
||||||
private CommandFilter commandFilter;
|
private CommandFilter commandFilter;
|
||||||
|
private PacketLogging packetLogging;
|
||||||
|
|
||||||
// Whether or not disable is not needed
|
// Whether or not disable is not needed
|
||||||
private boolean skipDisable;
|
private boolean skipDisable;
|
||||||
@ -269,6 +271,9 @@ public class ProtocolLib extends JavaPlugin {
|
|||||||
case PACKET:
|
case PACKET:
|
||||||
commandPacket = new CommandPacket(reporter, this, logger, commandFilter, protocolManager);
|
commandPacket = new CommandPacket(reporter, this, logger, commandFilter, protocolManager);
|
||||||
break;
|
break;
|
||||||
|
case LOGGING:
|
||||||
|
packetLogging = new PacketLogging(this, protocolManager);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
throw e;
|
throw e;
|
||||||
@ -404,6 +409,7 @@ public class ProtocolLib extends JavaPlugin {
|
|||||||
registerCommand(CommandProtocol.NAME, commandProtocol);
|
registerCommand(CommandProtocol.NAME, commandProtocol);
|
||||||
registerCommand(CommandPacket.NAME, commandPacket);
|
registerCommand(CommandPacket.NAME, commandPacket);
|
||||||
registerCommand(CommandFilter.NAME, commandFilter);
|
registerCommand(CommandFilter.NAME, commandFilter);
|
||||||
|
registerCommand(PacketLogging.NAME, packetLogging);
|
||||||
|
|
||||||
// Player login and logout events
|
// Player login and logout events
|
||||||
protocolManager.registerEvents(manager, this);
|
protocolManager.registerEvents(manager, this);
|
||||||
|
@ -24,6 +24,11 @@ commands:
|
|||||||
aliases: [packet_filter]
|
aliases: [packet_filter]
|
||||||
permission: protocol.admin
|
permission: protocol.admin
|
||||||
permission-message: You don't have <permission>
|
permission-message: You don't have <permission>
|
||||||
|
packetlog:
|
||||||
|
description: Logs hex representations of packets to a file or console
|
||||||
|
usage: /<command> <protocol> <sender> <packet> [location]
|
||||||
|
permission: protocol.admin
|
||||||
|
permission-message: You don't have <permission>
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
protocol.*:
|
protocol.*:
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren