Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
at develop 378 lines 12 kB view raw
1package net.minecraft.server; 2 3import java.io.BufferedOutputStream; 4import java.io.DataInputStream; 5import java.io.DataOutputStream; 6import java.net.InetSocketAddress; 7import java.net.Socket; 8import java.net.SocketAddress; 9import java.net.SocketException; 10import java.util.ArrayList; 11import java.util.Collections; 12import java.util.List; 13 14import org.bukkit.Bukkit; 15import org.bukkit.ChatColor; 16 17import com.legacyminecraft.poseidon.PoseidonConfig; 18import com.legacyminecraft.poseidon.event.PlayerReceivePacketEvent; 19 20import uk.betacraft.uberbukkit.Uberbukkit; 21import uk.betacraft.uberbukkit.protocol.Protocol; 22 23public class NetworkManager { 24 25 public static final Object a = new Object(); 26 public static int b; 27 public static int c; 28 private Object g = new Object(); 29 public Socket socket; // CraftBukkit - private -> public 30 private SocketAddress i; //Project Poseidon - remove final statement 31 private DataInputStream input; 32 private DataOutputStream output; 33 private boolean l = true; 34 private List m = Collections.synchronizedList(new ArrayList()); 35 private List highPriorityQueue = Collections.synchronizedList(new ArrayList()); 36 private List lowPriorityQueue = Collections.synchronizedList(new ArrayList()); 37 private NetHandler p; 38 private boolean q = false; 39 private Thread r; 40 private Thread s; 41 private boolean t = false; 42 private String u = ""; 43 private Object[] v; 44 private int w = 0; 45 private int x = 0; 46 public static int[] d = new int[256]; 47 public static int[] e = new int[256]; 48 public int f = 0; 49 private int lowPriorityQueueDelay = 50; 50 private final boolean firePacketEvents; 51 52 private final boolean spamDetection; 53 54 private final int threshold; 55 56 // uberbukkit 57 public int pvn = 0; 58 public Protocol protocol = null; 59 60 public NetworkManager(Socket socket, String s, NetHandler nethandler) { 61 this.socket = socket; 62 this.i = socket.getRemoteSocketAddress(); 63 this.p = nethandler; 64 65 //Poseidon 66 this.firePacketEvents = PoseidonConfig.getInstance().getBoolean("settings.packet-events.enabled", false); 67 this.spamDetection = PoseidonConfig.getInstance().getBoolean("settings.packet-spam-detection.enabled", true); 68 this.threshold = PoseidonConfig.getInstance().getInt("settings.packet-spam-detection.threshold", 1000); 69 70 //Debug for packet spam detection 71// System.out.println("[Poseidon] Packet spam detection is " + (this.spamDetection ? "enabled" : "disabled") + " with a threshold of " + this.threshold + " packets"); 72 73 // CraftBukkit start - IPv6 stack in Java on BSD/OSX doesn't support setTrafficClass 74 try { 75 socket.setTrafficClass(24); 76 } catch (SocketException e) { 77 } 78 // CraftBukkit end 79 80 try { 81 // CraftBukkit start - cant compile these outside the try 82 socket.setSoTimeout(30000); 83 if (PoseidonConfig.getEmptyNode().getBoolean("settings.enable-tpc-nodelay", false)) { 84 socket.setTcpNoDelay(true); 85 } 86 87 // uberbukkit 88 if (Uberbukkit.getTargetPVN() >= 11) { 89 this.input = new DataInputStream(socket.getInputStream()); 90 this.output = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), 5120)); 91 } else { 92 this.input = new DataInputStream(socket.getInputStream()); 93 this.output = new DataOutputStream(socket.getOutputStream()); 94 } 95 } catch (java.io.IOException socketexception) { 96 // CraftBukkit end 97 System.err.println(socketexception.getMessage()); 98 } 99 100 /* CraftBukkit start - moved up 101 this.input = new DataInputStream(socket.getInputStream()); 102 this.output = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), 5120)); 103 // CraftBukkit end */ 104 this.s = new NetworkReaderThread(this, s + " read thread"); 105 this.r = new NetworkWriterThread(this, s + " write thread"); 106 this.s.start(); 107 this.r.start(); 108 } 109 110 //Project Poseidon Start 111 public void setSocketAddress(SocketAddress socketAddress) { 112 this.i = socketAddress; 113 } 114 115 public SocketAddress generateSocketAddress(String hostname, int port) { 116 return new InetSocketAddress(hostname, port); 117 } 118 119 //Project Poseidon End 120 121 public void a(NetHandler nethandler) { 122 this.p = nethandler; 123 } 124 125 public void queue(Packet packet) { 126 if (!this.q) { 127 Object object = this.g; 128 129 // uberbukkit 130 if (this.protocol != null && !this.protocol.canReceivePacket(packet.b())) return; 131 132 // uberbukkit 133 if (this.pvn != 0) packet.pvn = this.pvn; 134 135 synchronized (this.g) { 136 this.x += packet.a() + 1; 137 if (packet.k) { 138 this.lowPriorityQueue.add(packet); 139 } else { 140 this.highPriorityQueue.add(packet); 141 } 142 } 143 } 144 } 145 146 private boolean f() { 147 boolean flag = false; 148 149 try { 150 Object object; 151 Packet packet; 152 int i; 153 int[] aint; 154 155 if (!this.highPriorityQueue.isEmpty() && (this.f == 0 || System.currentTimeMillis() - ((Packet) this.highPriorityQueue.get(0)).timestamp >= (long) this.f)) { 156 object = this.g; 157 synchronized (this.g) { 158 packet = (Packet) this.highPriorityQueue.remove(0); 159 this.x -= packet.a() + 1; 160 } 161 162 Packet.a(packet, this.output); 163 aint = e; 164 i = packet.b(); 165 aint[i] += packet.a() + 1; 166 flag = true; 167 } 168 169 // CraftBukkit - don't allow low priority packet to be sent unless it was placed in the queue before the first packet on the high priority queue 170 if ((flag || this.lowPriorityQueueDelay-- <= 0) && !this.lowPriorityQueue.isEmpty() && (this.highPriorityQueue.isEmpty() || ((Packet) this.highPriorityQueue.get(0)).timestamp > ((Packet) this.lowPriorityQueue.get(0)).timestamp)) { 171 object = this.g; 172 synchronized (this.g) { 173 packet = (Packet) this.lowPriorityQueue.remove(0); 174 this.x -= packet.a() + 1; 175 } 176 177 Packet.a(packet, this.output); 178 aint = e; 179 i = packet.b(); 180 aint[i] += packet.a() + 1; 181 this.lowPriorityQueueDelay = 0; 182 flag = true; 183 } 184 185 return flag; 186 } catch (Exception exception) { 187 if (!this.t) { 188 this.a(exception); 189 } 190 191 return false; 192 } 193 } 194 195 public void a() { 196 this.s.interrupt(); 197 this.r.interrupt(); 198 } 199 200 private boolean g() { 201 boolean flag = false; 202 203 try { 204 Packet packet = Packet.a(this.input, this.p.c(), this.pvn); // uberbukkit - allows packets to be read accordingly to client version 205 206 if (packet != null) { 207 int[] aint = d; 208 int i = packet.b(); 209 210 aint[i] += packet.a() + 1; 211 this.m.add(packet); 212 flag = true; 213 } else { 214 this.a("disconnect.endOfStream", new Object[0]); 215 } 216 217 return flag; 218 } catch (Exception exception) { 219 if (!this.t) { 220 this.a(exception); 221 } 222 223 return false; 224 } 225 } 226 227 private void a(Exception exception) { 228 exception.printStackTrace(); 229 this.a("disconnect.genericReason", new Object[] { "Internal exception: " + exception.toString() }); 230 } 231 232 public void a(String s, Object... aobject) { 233 if (this.l) { 234 this.t = true; 235 this.u = s; 236 this.v = aobject; 237 (new NetworkMasterThread(this)).start(); 238 this.l = false; 239 240 try { 241 this.input.close(); 242 this.input = null; 243 } catch (Throwable throwable) { 244 ; 245 } 246 247 try { 248 this.output.close(); 249 this.output = null; 250 } catch (Throwable throwable1) { 251 ; 252 } 253 254 try { 255 this.socket.close(); 256 this.socket = null; 257 } catch (Throwable throwable2) { 258 ; 259 } 260 } 261 } 262 263 public void b() { 264 boolean fast = PoseidonConfig.getInstance().getBoolean("settings.faster-packets.enabled", true); 265 if (this.x > (fast ? 2097152 : 1048576)) { 266 this.a("disconnect.overflow", new Object[0]); 267 } 268 269 if (this.m.isEmpty()) { 270 if (this.w++ == 1200) { 271 this.a("disconnect.timeout", new Object[0]); 272 } 273 } else { 274 this.w = 0; 275 } 276 277 int i = (fast ? 1000 : 100); 278 279 //Poseidon - Packet spam detection 280 if (spamDetection) { 281 if (this.m.size() > threshold) { 282 String playerUsername = "Unknown"; 283 if (this.p instanceof NetServerHandler) { 284 playerUsername = ((NetServerHandler) this.p).player.name; 285 ((NetServerHandler) this.p).disconnect(ChatColor.RED + "[Poseidon] You have been kicked for packet spamming."); 286 } else { 287 this.a("disconnect.spam", new Object[0]); 288 } 289 System.out.println("[Poseidon] Player " + playerUsername + " has been kicked for packet spamming. The queue size was " + this.m.size() + " and the threshold was " + threshold + "."); 290 } 291 } 292 293// if(this.m.size() > 1000) { 294// String playerUsername = "Unknown"; 295// if (this.p instanceof NetServerHandler) { 296// System.out.println("The packet queue size is " + this.m.size() + " for player " + ((NetServerHandler) this.p).player.name + "."); 297// } 298// } 299 300 301 while (!this.m.isEmpty() && i-- >= 0) { 302 Packet packet = (Packet) this.m.remove(0); 303 304 //Poseidon Start - Packet Receive Event 305 if (firePacketEvents && this.p instanceof NetServerHandler) { 306 PlayerReceivePacketEvent event = new PlayerReceivePacketEvent(((NetServerHandler) this.p).player.name, packet); 307 Bukkit.getPluginManager().callEvent(event); 308 packet = event.getPacket(); 309 if (!event.isCancelled()) { 310 packet.a(this.p); 311 } 312 313 } else { 314 packet.a(this.p); 315 } 316 317 //Poseidon End 318 319 // packet.a(this.p); 320 } 321 322 this.a(); 323 if (this.t && this.m.isEmpty()) { 324 this.p.a(this.u, this.v); 325 } 326 } 327 328 public SocketAddress getSocketAddress() { 329 return this.i; 330 } 331 332 public void d() { 333 this.a(); 334 this.q = true; 335 this.s.interrupt(); 336 (new ThreadMonitorConnection(this)).start(); 337 } 338 339 public int e() { 340 return this.lowPriorityQueue.size(); 341 } 342 343 static boolean a(NetworkManager networkmanager) { 344 return networkmanager.l; 345 } 346 347 static boolean b(NetworkManager networkmanager) { 348 return networkmanager.q; 349 } 350 351 static boolean c(NetworkManager networkmanager) { 352 return networkmanager.g(); 353 } 354 355 static boolean d(NetworkManager networkmanager) { 356 return networkmanager.f(); 357 } 358 359 static DataOutputStream e(NetworkManager networkmanager) { 360 return networkmanager.output; 361 } 362 363 static boolean f(NetworkManager networkmanager) { 364 return networkmanager.t; 365 } 366 367 static void a(NetworkManager networkmanager, Exception exception) { 368 networkmanager.a(exception); 369 } 370 371 static Thread g(NetworkManager networkmanager) { 372 return networkmanager.s; 373 } 374 375 static Thread h(NetworkManager networkmanager) { 376 return networkmanager.r; 377 } 378}