00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.scripts;
00023
00024 import com.realtime.crossfire.jxclient.server.crossfire.CrossfireServerConnection;
00025 import com.realtime.crossfire.jxclient.server.server.ReceivedPacketListener;
00026 import java.nio.ByteBuffer;
00027 import java.util.Collection;
00028 import java.util.HashSet;
00029 import java.util.regex.Pattern;
00030 import org.jetbrains.annotations.NotNull;
00031 import org.jetbrains.annotations.Nullable;
00032
00037 public class PacketWatcher {
00038
00042 @NotNull
00043 private final Collection<String> commands = new HashSet<String>();
00044
00048 @NotNull
00049 private final CrossfireServerConnection crossfireServerConnection;
00050
00054 @NotNull
00055 private final ScriptProcess scriptProcess;
00056
00061 @Nullable
00062 private Pattern pattern = null;
00063
00069 @NotNull
00070 private final ReceivedPacketListener receivedPacketListener = new ReceivedPacketListener() {
00071
00072 @Override
00073 public void processEmpty(@NotNull final String command) {
00074 if (matchesCommand(command)) {
00075 scriptProcess.commandSent("watch "+command);
00076 }
00077 }
00078
00079 @Override
00080 public void processAscii(@NotNull final String command, @NotNull final ByteBuffer packet) {
00081 if (matchesCommand(command)) {
00082 final byte[] data = new byte[packet.remaining()];
00083 packet.get(data);
00084 scriptProcess.commandSent("watch "+command+" "+new String(data));
00085 }
00086 }
00087
00088 @Override
00089 public void processShortArray(@NotNull final String command, @NotNull final ByteBuffer packet) {
00090 if (matchesCommand(command)) {
00091 final StringBuilder sb = new StringBuilder("watch ");
00092 sb.append(command);
00093 for (int i = 0; i < 100 && packet.remaining() >= 2; i++) {
00094 sb.append(' ');
00095 sb.append(getShort(packet));
00096 }
00097 scriptProcess.commandSent(sb.toString());
00098 }
00099 }
00100
00101 @Override
00102 public void processIntArray(@NotNull final String command, @NotNull final ByteBuffer packet) {
00103 if (matchesCommand(command)) {
00104 final StringBuilder sb = new StringBuilder("watch ");
00105 sb.append(command);
00106 while (packet.remaining() >= 4) {
00107 sb.append(' ');
00108 sb.append(getInt(packet));
00109 }
00110 scriptProcess.commandSent(sb.toString());
00111 }
00112 }
00113
00114 @Override
00115 public void processShortInt(@NotNull final String command, @NotNull final ByteBuffer packet) {
00116 if (packet.remaining() == 6 && matchesCommand(command)) {
00117 scriptProcess.commandSent("watch "+command+" "+getShort(packet)+" "+getInt(packet));
00118 }
00119 }
00120
00121 @Override
00122 public void processMixed(@NotNull final String command, @NotNull final ByteBuffer packet) {
00123 if (matchesCommand(command)) {
00124 final StringBuilder sb = new StringBuilder("watch ");
00125 sb.append(command);
00126 sb.append(' ');
00127 sb.append(packet.remaining());
00128 scriptProcess.commandSent(sb.toString());
00129 }
00130 }
00131
00132 @Override
00133 public void processStats(@NotNull final String command, final int stat, @NotNull final Object[] args) {
00134 if (matchesCommand(command)) {
00135 final StringBuilder sb = new StringBuilder("watch ");
00136 sb.append(command);
00137 sb.append(' ');
00138 sb.append(StatUtils.getStatNames(stat));
00139 for (final Object arg : args) {
00140 sb.append(' ');
00141 sb.append(arg);
00142 }
00143 scriptProcess.commandSent(sb.toString());
00144 }
00145 }
00146
00147 @Override
00148 public void processNoData(@NotNull final String command, @NotNull final ByteBuffer packet) {
00149 processMixed(command, packet);
00150 }
00151
00157 private int getShort(@NotNull final ByteBuffer packet) {
00158 return packet.getShort()&0xFFFF;
00159 }
00160
00166 private int getInt(@NotNull final ByteBuffer packet) {
00167 return packet.getInt();
00168 }
00169
00170 };
00171
00177 public PacketWatcher(@NotNull final CrossfireServerConnection crossfireServerConnection, @NotNull final ScriptProcess scriptProcess) {
00178 this.crossfireServerConnection = crossfireServerConnection;
00179 this.scriptProcess = scriptProcess;
00180 rebuildPattern();
00181 }
00182
00187 public void destroy() {
00188 if (pattern != null) {
00189 pattern = null;
00190 crossfireServerConnection.removePacketWatcherListener(receivedPacketListener);
00191 }
00192 }
00193
00197 private void rebuildPattern() {
00198 final StringBuilder sb = new StringBuilder();
00199 for (final String command : commands) {
00200 sb.append(Pattern.quote(command));
00201 sb.append(".*|");
00202 }
00203 final int length = sb.length();
00204 if (length <= 0) {
00205 if (pattern != null) {
00206 pattern = null;
00207 crossfireServerConnection.removePacketWatcherListener(receivedPacketListener);
00208 }
00209 } else {
00210 if (pattern == null) {
00211 crossfireServerConnection.addPacketWatcherListener(receivedPacketListener);
00212 }
00213 sb.setLength(length-1);
00214 pattern = Pattern.compile(sb.toString());
00215 }
00216 }
00217
00222 public void addCommand(@NotNull final String command) {
00223 if (commands.add(command)) {
00224 rebuildPattern();
00225 }
00226 }
00227
00232 public void removeCommand(@NotNull final String command) {
00233 if (commands.remove(command)) {
00234 rebuildPattern();
00235 }
00236 }
00237
00243 private boolean matchesCommand(@NotNull final CharSequence command) {
00244 return pattern != null && pattern.matcher(command).matches();
00245 }
00246
00247 }