2011-03-27 22:12:39 +02:00
package net.minecraft.server ;
2011-04-20 22:47:26 +02:00
import java.io.BufferedOutputStream ;
2011-03-27 22:12:39 +02:00
import java.io.DataInputStream ;
import java.io.DataOutputStream ;
import java.net.Socket ;
import java.net.SocketAddress ;
2012-08-08 13:54:28 +02:00
import java.net.SocketException ;
2012-07-29 09:33:13 +02:00
import java.security.PrivateKey ;
2011-03-27 22:12:39 +02:00
import java.util.ArrayList ;
import java.util.Collections ;
2012-07-29 09:33:13 +02:00
import java.util.Iterator ;
2011-03-27 22:12:39 +02:00
import java.util.List ;
2012-07-29 09:33:13 +02:00
import java.util.concurrent.atomic.AtomicInteger ;
import javax.crypto.SecretKey ;
2011-06-07 07:29:55 +02:00
2012-07-29 09:33:13 +02:00
import java.io.IOException ; // CraftBukkit
2011-03-27 22:12:39 +02:00
2012-07-29 09:33:13 +02:00
public class NetworkManager implements INetworkManager {
public static AtomicInteger a = new AtomicInteger ( ) ;
public static AtomicInteger b = new AtomicInteger ( ) ;
private Object h = new Object ( ) ;
2011-05-14 16:29:42 +02:00
public Socket socket ; // CraftBukkit - private -> public
2012-07-29 09:33:13 +02:00
private final SocketAddress j ;
private volatile DataInputStream input ;
private volatile DataOutputStream output ;
private volatile boolean m = true ;
private volatile boolean n = false ;
private java . util . Queue inboundQueue = new java . util . concurrent . ConcurrentLinkedQueue ( ) ; // CraftBukkit - Concurrent linked queue
2011-06-27 00:25:01 +02:00
private List highPriorityQueue = Collections . synchronizedList ( new ArrayList ( ) ) ;
private List lowPriorityQueue = Collections . synchronizedList ( new ArrayList ( ) ) ;
2012-01-14 21:03:48 +01:00
private NetHandler packetListener ;
2012-07-29 09:33:13 +02:00
private boolean s = false ;
private Thread t ;
private Thread u ;
private String v = " " ;
private Object [ ] w ;
2011-05-26 14:48:22 +02:00
private int x = 0 ;
2012-07-29 09:33:13 +02:00
private int y = 0 ;
public static int [ ] c = new int [ 256 ] ;
2011-05-26 14:48:22 +02:00
public static int [ ] d = new int [ 256 ] ;
2012-07-29 09:33:13 +02:00
public int e = 0 ;
boolean f = false ;
boolean g = false ;
private SecretKey z = null ;
private PrivateKey A = null ;
2011-06-27 00:25:01 +02:00
private int lowPriorityQueueDelay = 50 ;
2011-03-27 22:12:39 +02:00
2012-08-08 13:54:28 +02:00
public NetworkManager ( Socket socket , String s , NetHandler nethandler , PrivateKey privatekey ) throws IOException { // CraftBukkit - throws IOException
2012-07-29 09:33:13 +02:00
this . A = privatekey ;
2011-04-20 19:05:14 +02:00
this . socket = socket ;
2012-07-29 09:33:13 +02:00
this . j = socket . getRemoteSocketAddress ( ) ;
2012-01-14 21:03:48 +01:00
this . packetListener = nethandler ;
2011-03-27 22:12:39 +02:00
2011-06-07 07:29:55 +02:00
try {
socket . setSoTimeout ( 30000 ) ;
2012-07-29 09:33:13 +02:00
socket . setTrafficClass ( 24 ) ;
2012-08-08 13:54:28 +02:00
} catch ( SocketException socketexception ) {
2011-03-31 22:40:00 +02:00
System . err . println ( socketexception . getMessage ( ) ) ;
}
2011-03-27 22:12:39 +02:00
2011-06-27 00:25:01 +02:00
this . input = new DataInputStream ( socket . getInputStream ( ) ) ;
this . output = new DataOutputStream ( new BufferedOutputStream ( socket . getOutputStream ( ) , 5120 ) ) ;
2012-07-29 09:33:13 +02:00
this . u = new NetworkReaderThread ( this , s + " read thread " ) ;
this . t = new NetworkWriterThread ( this , s + " write thread " ) ;
this . u . start ( ) ;
this . t . start ( ) ;
2011-03-27 22:12:39 +02:00
}
public void a ( NetHandler nethandler ) {
2012-01-14 21:03:48 +01:00
this . packetListener = nethandler ;
2011-03-27 22:12:39 +02:00
}
2011-06-27 00:25:01 +02:00
public void queue ( Packet packet ) {
2012-07-29 09:33:13 +02:00
if ( ! this . s ) {
Object object = this . h ;
2011-03-27 22:12:39 +02:00
2012-07-29 09:33:13 +02:00
synchronized ( this . h ) {
this . y + = packet . a ( ) + 1 ;
2012-01-14 21:03:48 +01:00
if ( packet . lowPriority ) {
2011-06-27 00:25:01 +02:00
this . lowPriorityQueue . add ( packet ) ;
2011-03-27 22:12:39 +02:00
} else {
2011-06-27 00:25:01 +02:00
this . highPriorityQueue . add ( packet ) ;
2011-03-27 22:12:39 +02:00
}
}
}
}
2012-07-29 09:33:13 +02:00
private boolean h ( ) {
2011-05-26 16:20:11 +02:00
boolean flag = false ;
2011-03-27 22:12:39 +02:00
try {
2011-06-10 09:42:36 +02:00
Packet packet ;
2011-05-26 14:48:22 +02:00
int i ;
int [ ] aint ;
2012-07-29 09:33:13 +02:00
if ( this . e = = 0 | | System . currentTimeMillis ( ) - ( ( Packet ) this . highPriorityQueue . get ( 0 ) ) . timestamp > = ( long ) this . e ) {
packet = this . a ( false ) ;
if ( packet ! = null ) {
Packet . a ( packet , this . output ) ;
if ( packet instanceof Packet252KeyResponse & & ! this . g ) {
if ( ! this . packetListener . a ( ) ) {
this . z = ( ( Packet252KeyResponse ) packet ) . d ( ) ;
}
this . k ( ) ;
}
aint = d ;
i = packet . k ( ) ;
aint [ i ] + = packet . a ( ) + 1 ;
flag = true ;
2011-06-10 09:42:36 +02:00
}
}
2012-07-29 09:33:13 +02:00
// 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 TODO: is this still right?
2011-06-27 00:25:01 +02:00
if ( ( flag | | this . lowPriorityQueueDelay - - < = 0 ) & & ! this . lowPriorityQueue . isEmpty ( ) & & ( this . highPriorityQueue . isEmpty ( ) | | ( ( Packet ) this . highPriorityQueue . get ( 0 ) ) . timestamp > ( ( Packet ) this . lowPriorityQueue . get ( 0 ) ) . timestamp ) ) {
2012-07-29 09:33:13 +02:00
packet = this . a ( true ) ;
if ( packet ! = null ) {
Packet . a ( packet , this . output ) ;
aint = d ;
i = packet . k ( ) ;
aint [ i ] + = packet . a ( ) + 1 ;
this . lowPriorityQueueDelay = 0 ;
flag = true ;
2011-03-27 22:12:39 +02:00
}
}
2011-05-28 22:50:08 +02:00
return flag ;
2011-03-27 22:12:39 +02:00
} catch ( Exception exception ) {
2012-07-29 09:33:13 +02:00
if ( ! this . n ) {
2011-03-27 22:12:39 +02:00
this . a ( exception ) ;
}
2011-05-26 16:20:11 +02:00
2011-05-28 22:50:08 +02:00
return false ;
}
2011-03-27 22:12:39 +02:00
}
2012-07-29 09:33:13 +02:00
private Packet a ( boolean flag ) {
Packet packet = null ;
List list = flag ? this . lowPriorityQueue : this . highPriorityQueue ;
Object object = this . h ;
synchronized ( this . h ) {
while ( ! list . isEmpty ( ) & & packet = = null ) {
packet = ( Packet ) list . remove ( 0 ) ;
this . y - = packet . a ( ) + 1 ;
if ( this . a ( packet , flag ) ) {
packet = null ;
}
}
return packet ;
}
}
private boolean a ( Packet packet , boolean flag ) {
if ( ! packet . e ( ) ) {
return false ;
} else {
List list = flag ? this . lowPriorityQueue : this . highPriorityQueue ;
Iterator iterator = list . iterator ( ) ;
Packet packet1 ;
do {
if ( ! iterator . hasNext ( ) ) {
return false ;
}
packet1 = ( Packet ) iterator . next ( ) ;
} while ( packet1 . k ( ) ! = packet . k ( ) ) ;
return packet . a ( packet1 ) ;
}
}
2011-05-26 14:48:22 +02:00
public void a ( ) {
2012-07-29 09:33:13 +02:00
if ( this . u ! = null ) {
this . u . interrupt ( ) ;
}
if ( this . t ! = null ) {
this . t . interrupt ( ) ;
}
2011-05-26 14:48:22 +02:00
}
2012-07-29 09:33:13 +02:00
private boolean i ( ) {
2011-05-26 16:20:11 +02:00
boolean flag = false ;
2011-03-27 22:12:39 +02:00
try {
2012-07-29 09:33:13 +02:00
Packet packet = Packet . a ( this . input , this . packetListener . a ( ) ) ;
2011-03-27 22:12:39 +02:00
if ( packet ! = null ) {
2012-07-29 09:33:13 +02:00
if ( packet instanceof Packet252KeyResponse & & ! this . f ) {
if ( this . packetListener . a ( ) ) {
this . z = ( ( Packet252KeyResponse ) packet ) . a ( this . A ) ;
}
this . j ( ) ;
}
int [ ] aint = c ;
int i = packet . k ( ) ;
2011-05-26 14:48:22 +02:00
2011-05-28 22:50:08 +02:00
aint [ i ] + = packet . a ( ) + 1 ;
2012-07-29 09:33:13 +02:00
if ( ! this . s ) {
if ( packet . a_ ( ) & & this . packetListener . b ( ) ) {
this . x = 0 ;
packet . handle ( this . packetListener ) ;
} else {
this . inboundQueue . add ( packet ) ;
}
2012-03-01 11:49:23 +01:00
}
2011-05-26 16:20:11 +02:00
flag = true ;
2011-03-27 22:12:39 +02:00
} else {
this . a ( " disconnect.endOfStream " , new Object [ 0 ] ) ;
}
2011-05-28 22:50:08 +02:00
return flag ;
2011-03-27 22:12:39 +02:00
} catch ( Exception exception ) {
2012-07-29 09:33:13 +02:00
if ( ! this . n ) {
2011-03-27 22:12:39 +02:00
this . a ( exception ) ;
}
2011-05-26 16:20:11 +02:00
2011-05-28 22:50:08 +02:00
return false ;
}
2011-03-27 22:12:39 +02:00
}
private void a ( Exception exception ) {
2012-05-13 01:44:32 +02:00
// exception.printStackTrace(); // CraftBukkit - Remove console spam
2011-03-27 22:12:39 +02:00
this . a ( " disconnect.genericReason " , new Object [ ] { " Internal exception: " + exception . toString ( ) } ) ;
}
public void a ( String s , Object . . . aobject ) {
2012-07-29 09:33:13 +02:00
if ( this . m ) {
this . n = true ;
this . v = s ;
this . w = aobject ;
this . m = false ;
2011-03-27 22:12:39 +02:00
( new NetworkMasterThread ( this ) ) . start ( ) ;
try {
2011-04-20 19:05:14 +02:00
this . input . close ( ) ;
this . input = null ;
this . output . close ( ) ;
this . output = null ;
this . socket . close ( ) ;
this . socket = null ;
2012-07-29 09:33:13 +02:00
} catch ( Throwable throwable ) {
2011-03-27 22:12:39 +02:00
;
}
}
}
2011-05-26 14:48:22 +02:00
public void b ( ) {
2012-07-29 09:33:13 +02:00
if ( this . y > 2097152 ) {
2011-03-27 22:12:39 +02:00
this . a ( " disconnect.overflow " , new Object [ 0 ] ) ;
}
2012-07-29 09:33:13 +02:00
if ( this . inboundQueue . isEmpty ( ) ) {
if ( this . x + + = = 1200 ) {
2011-03-27 22:12:39 +02:00
this . a ( " disconnect.timeout " , new Object [ 0 ] ) ;
}
} else {
2012-07-29 09:33:13 +02:00
this . x = 0 ;
2011-03-27 22:12:39 +02:00
}
2011-09-15 02:23:52 +02:00
int i = 1000 ;
2011-03-27 22:12:39 +02:00
2012-07-29 09:33:13 +02:00
while ( ! this . inboundQueue . isEmpty ( ) & & i - - > = 0 ) {
Packet packet = ( Packet ) this . inboundQueue . poll ( ) ; // CraftBukkit - remove -> poll
2011-03-27 22:12:39 +02:00
2012-09-10 06:19:28 +02:00
// CraftBukkit start
if ( this . packetListener instanceof NetLoginHandler ? ( ( NetLoginHandler ) this . packetListener ) . c : ( ( NetServerHandler ) this . packetListener ) . disconnected ) {
continue ;
}
// CraftBukkit end
2012-07-29 09:33:13 +02:00
packet . handle ( this . packetListener ) ;
2011-03-27 22:12:39 +02:00
}
2011-05-28 22:50:08 +02:00
this . a ( ) ;
2012-07-29 09:33:13 +02:00
if ( this . n & & this . inboundQueue . isEmpty ( ) ) {
this . packetListener . a ( this . v , this . w ) ;
2011-03-27 22:12:39 +02:00
}
}
2011-04-20 19:05:14 +02:00
public SocketAddress getSocketAddress ( ) {
2012-07-29 09:33:13 +02:00
return this . j ;
2011-03-27 22:12:39 +02:00
}
2011-05-26 14:48:22 +02:00
public void d ( ) {
2012-07-29 09:33:13 +02:00
if ( ! this . s ) {
2012-01-12 23:10:13 +01:00
this . a ( ) ;
2012-07-29 09:33:13 +02:00
this . s = true ;
this . u . interrupt ( ) ;
2012-01-12 23:10:13 +01:00
( new NetworkMonitorThread ( this ) ) . start ( ) ;
}
2011-03-27 22:12:39 +02:00
}
2012-07-29 09:33:13 +02:00
private void j ( ) throws IOException { // CraftBukkit - throws IOException
this . f = true ;
this . input = new DataInputStream ( MinecraftEncryption . a ( this . z , this . socket . getInputStream ( ) ) ) ;
}
private void k ( ) throws IOException { // CraftBukkit - throws IOException
this . output . flush ( ) ;
this . g = true ;
this . output = new DataOutputStream ( new BufferedOutputStream ( MinecraftEncryption . a ( this . z , this . socket . getOutputStream ( ) ) , 5120 ) ) ;
}
2011-05-26 14:48:22 +02:00
public int e ( ) {
2011-06-27 00:25:01 +02:00
return this . lowPriorityQueue . size ( ) ;
2011-03-27 22:12:39 +02:00
}
2012-01-14 21:03:48 +01:00
public Socket getSocket ( ) {
2011-09-15 02:23:52 +02:00
return this . socket ;
}
2011-03-27 22:12:39 +02:00
static boolean a ( NetworkManager networkmanager ) {
2012-07-29 09:33:13 +02:00
return networkmanager . m ;
2011-03-27 22:12:39 +02:00
}
static boolean b ( NetworkManager networkmanager ) {
2012-07-29 09:33:13 +02:00
return networkmanager . s ;
2011-03-27 22:12:39 +02:00
}
2011-05-26 16:20:11 +02:00
static boolean c ( NetworkManager networkmanager ) {
2012-07-29 09:33:13 +02:00
return networkmanager . i ( ) ;
2011-03-27 22:12:39 +02:00
}
2011-05-26 16:20:11 +02:00
static boolean d ( NetworkManager networkmanager ) {
2012-07-29 09:33:13 +02:00
return networkmanager . h ( ) ;
2011-03-27 22:12:39 +02:00
}
2011-05-28 22:50:08 +02:00
static DataOutputStream e ( NetworkManager networkmanager ) {
return networkmanager . output ;
2011-05-26 14:48:22 +02:00
}
2011-05-28 22:50:08 +02:00
static boolean f ( NetworkManager networkmanager ) {
2012-07-29 09:33:13 +02:00
return networkmanager . n ;
2011-05-26 14:48:22 +02:00
}
2011-05-28 22:50:08 +02:00
static void a ( NetworkManager networkmanager , Exception exception ) {
networkmanager . a ( exception ) ;
2011-05-26 14:48:22 +02:00
}
static Thread g ( NetworkManager networkmanager ) {
2012-07-29 09:33:13 +02:00
return networkmanager . u ;
2011-03-27 22:12:39 +02:00
}
2011-05-26 14:48:22 +02:00
static Thread h ( NetworkManager networkmanager ) {
2012-07-29 09:33:13 +02:00
return networkmanager . t ;
2011-03-27 22:12:39 +02:00
}
}