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 ;
2013-07-01 13:03:00 +02:00
import java.io.DataOutput ;
2011-03-27 22:12:39 +02:00
import java.io.DataOutputStream ;
2012-11-06 13:05:28 +01:00
import java.io.InputStream ;
2011-03-27 22:12:39 +02:00
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 ;
2013-07-09 01:43:37 +02:00
import java.util.Queue ;
import java.util.concurrent.ConcurrentLinkedQueue ;
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 ( ) ;
2013-03-13 23:33:27 +01:00
private final Object h = new Object ( ) ;
private final IConsoleLogManager i ;
2011-05-14 16:29:42 +02:00
public Socket socket ; // CraftBukkit - private -> public
2013-03-13 23:33:27 +01:00
private final SocketAddress k ;
2012-07-29 09:33:13 +02:00
private volatile DataInputStream input ;
private volatile DataOutputStream output ;
2013-03-13 23:33:27 +01:00
private volatile boolean n = true ;
2013-07-01 13:03:00 +02:00
private volatile boolean o ;
2013-07-09 01:43:37 +02:00
private Queue inboundQueue = new ConcurrentLinkedQueue ( ) ;
2011-06-27 00:25:01 +02:00
private List highPriorityQueue = Collections . synchronizedList ( new ArrayList ( ) ) ;
private List lowPriorityQueue = Collections . synchronizedList ( new ArrayList ( ) ) ;
2012-12-20 05:03:52 +01:00
private Connection connection ;
2013-07-01 13:03:00 +02:00
private boolean t ;
2012-07-29 09:33:13 +02:00
private Thread u ;
2013-03-13 23:33:27 +01:00
private Thread v ;
private String w = " " ;
private Object [ ] x ;
2013-07-01 13:03:00 +02:00
private int y ;
private int z ;
2012-07-29 09:33:13 +02:00
public static int [ ] c = new int [ 256 ] ;
2011-05-26 14:48:22 +02:00
public static int [ ] d = new int [ 256 ] ;
2013-07-01 13:03:00 +02:00
public int e ;
boolean f ;
boolean g ;
private SecretKey A ;
private PrivateKey B ;
2011-06-27 00:25:01 +02:00
private int lowPriorityQueueDelay = 50 ;
2011-03-27 22:12:39 +02:00
2013-03-13 23:33:27 +01:00
public NetworkManager ( IConsoleLogManager iconsolelogmanager , Socket socket , String s , Connection connection , PrivateKey privatekey ) throws IOException { // CraftBukkit - throws IOException
this . B = privatekey ;
2011-04-20 19:05:14 +02:00
this . socket = socket ;
2013-03-13 23:33:27 +01:00
this . i = iconsolelogmanager ;
this . k = socket . getRemoteSocketAddress ( ) ;
2012-12-20 05:03:52 +01:00
this . connection = connection ;
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 ) ) ;
2013-03-13 23:33:27 +01:00
this . v = new NetworkReaderThread ( this , s + " read thread " ) ;
this . u = new NetworkWriterThread ( this , s + " write thread " ) ;
this . v . start ( ) ;
2012-07-29 09:33:13 +02:00
this . u . start ( ) ;
2011-03-27 22:12:39 +02:00
}
2012-12-20 05:03:52 +01:00
public void a ( Connection connection ) {
this . connection = connection ;
2011-03-27 22:12:39 +02:00
}
2011-06-27 00:25:01 +02:00
public void queue ( Packet packet ) {
2013-03-13 23:33:27 +01:00
if ( ! this . t ) {
2012-07-29 09:33:13 +02:00
Object object = this . h ;
2011-03-27 22:12:39 +02:00
2012-07-29 09:33:13 +02:00
synchronized ( this . h ) {
2013-03-13 23:33:27 +01:00
this . z + = packet . a ( ) + 1 ;
2012-11-06 13:05:28 +01: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 ;
2013-07-01 13:03:00 +02:00
if ( this . e = = 0 | | ! this . highPriorityQueue . isEmpty ( ) & & MinecraftServer . aq ( ) - ( ( Packet ) this . highPriorityQueue . get ( 0 ) ) . timestamp > = ( long ) this . e ) {
2012-07-29 09:33:13 +02:00
packet = this . a ( false ) ;
if ( packet ! = null ) {
2013-07-01 13:03:00 +02:00
Packet . a ( packet , ( DataOutput ) this . output ) ;
2012-07-29 09:33:13 +02:00
if ( packet instanceof Packet252KeyResponse & & ! this . g ) {
2012-12-20 05:03:52 +01:00
if ( ! this . connection . a ( ) ) {
2013-03-13 23:33:27 +01:00
this . A = ( ( Packet252KeyResponse ) packet ) . d ( ) ;
2012-07-29 09:33:13 +02:00
}
this . k ( ) ;
}
aint = d ;
2013-03-13 23:33:27 +01:00
i = packet . n ( ) ;
2012-07-29 09:33:13 +02:00
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 ) {
2013-07-01 13:03:00 +02:00
Packet . a ( packet , ( DataOutput ) this . output ) ;
2012-07-29 09:33:13 +02:00
aint = d ;
2013-03-13 23:33:27 +01:00
i = packet . n ( ) ;
2012-07-29 09:33:13 +02:00
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 ) {
2013-03-13 23:33:27 +01:00
if ( ! this . o ) {
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 ) ;
2013-03-13 23:33:27 +01:00
this . z - = packet . a ( ) + 1 ;
2012-07-29 09:33:13 +02:00
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 ( ) ;
2013-03-13 23:33:27 +01:00
} while ( packet1 . n ( ) ! = packet . n ( ) ) ;
2012-07-29 09:33:13 +02:00
return packet . a ( packet1 ) ;
}
}
2011-05-26 14:48:22 +02:00
public void a ( ) {
2013-03-13 23:33:27 +01:00
if ( this . v ! = null ) {
this . v . interrupt ( ) ;
2012-07-29 09:33:13 +02:00
}
2013-03-13 23:33:27 +01:00
if ( this . u ! = null ) {
this . u . interrupt ( ) ;
2012-07-29 09:33:13 +02:00
}
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 {
2013-03-13 23:33:27 +01:00
Packet packet = Packet . a ( this . i , this . input , this . connection . a ( ) , this . socket ) ;
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 ) {
2012-12-20 05:03:52 +01:00
if ( this . connection . a ( ) ) {
2013-03-13 23:33:27 +01:00
this . A = ( ( Packet252KeyResponse ) packet ) . a ( this . B ) ;
2012-07-29 09:33:13 +02:00
}
this . j ( ) ;
}
int [ ] aint = c ;
2013-03-13 23:33:27 +01:00
int i = packet . n ( ) ;
2011-05-26 14:48:22 +02:00
2011-05-28 22:50:08 +02:00
aint [ i ] + = packet . a ( ) + 1 ;
2013-03-13 23:33:27 +01:00
if ( ! this . t ) {
2012-12-20 05:03:52 +01:00
if ( packet . a_ ( ) & & this . connection . b ( ) ) {
2013-03-13 23:33:27 +01:00
this . y = 0 ;
2012-12-20 05:03:52 +01:00
packet . handle ( this . connection ) ;
2012-07-29 09:33:13 +02:00
} 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 ) {
2013-03-13 23:33:27 +01:00
if ( ! this . o ) {
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 ) {
2013-03-13 23:33:27 +01:00
if ( this . n ) {
this . o = true ;
this . w = s ;
this . x = aobject ;
this . n = 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 ( ) ;
2012-11-06 13:05:28 +01:00
} catch ( Throwable throwable ) {
;
}
try {
2011-04-20 19:05:14 +02:00
this . output . close ( ) ;
2012-11-06 13:05:28 +01:00
} catch ( Throwable throwable1 ) {
;
}
try {
2011-04-20 19:05:14 +02:00
this . socket . close ( ) ;
2012-11-06 13:05:28 +01:00
} catch ( Throwable throwable2 ) {
2011-03-27 22:12:39 +02:00
;
}
2012-11-06 13:05:28 +01:00
this . input = null ;
this . output = null ;
this . socket = null ;
2011-03-27 22:12:39 +02:00
}
}
2011-05-26 14:48:22 +02:00
public void b ( ) {
2013-03-13 23:33:27 +01:00
if ( this . z > 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 ( ) ) {
2013-03-13 23:33:27 +01:00
if ( this . y + + = = 1200 ) {
2011-03-27 22:12:39 +02:00
this . a ( " disconnect.timeout " , new Object [ 0 ] ) ;
}
} else {
2013-03-13 23:33:27 +01:00
this . y = 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 ) {
2013-07-09 01:43:37 +02:00
Packet packet = ( Packet ) this . inboundQueue . poll ( ) ;
2011-03-27 22:12:39 +02:00
2012-09-10 06:19:28 +02:00
// CraftBukkit start
2013-03-13 23:33:27 +01:00
if ( this . connection instanceof PendingConnection ? ( ( PendingConnection ) this . connection ) . b : ( ( PlayerConnection ) this . connection ) . disconnected ) {
2012-09-10 06:19:28 +02:00
continue ;
}
// CraftBukkit end
2013-07-09 01:43:37 +02:00
if ( packet ! = null & & ! this . connection . c ( ) ) {
packet . handle ( this . connection ) ;
}
2011-03-27 22:12:39 +02:00
}
2011-05-28 22:50:08 +02:00
this . a ( ) ;
2013-03-13 23:33:27 +01:00
if ( this . o & & this . inboundQueue . isEmpty ( ) ) {
this . connection . a ( this . w , this . x ) ;
2011-03-27 22:12:39 +02:00
}
}
2011-04-20 19:05:14 +02:00
public SocketAddress getSocketAddress ( ) {
2013-03-13 23:33:27 +01:00
return this . k ;
2011-03-27 22:12:39 +02:00
}
2011-05-26 14:48:22 +02:00
public void d ( ) {
2013-03-13 23:33:27 +01:00
if ( ! this . t ) {
2012-01-12 23:10:13 +01:00
this . a ( ) ;
2013-03-13 23:33:27 +01:00
this . t = true ;
this . v . 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 ;
2012-11-06 13:05:28 +01:00
InputStream inputstream = this . socket . getInputStream ( ) ;
2013-03-13 23:33:27 +01:00
this . input = new DataInputStream ( MinecraftEncryption . a ( this . A , inputstream ) ) ;
2012-07-29 09:33:13 +02:00
}
private void k ( ) throws IOException { // CraftBukkit - throws IOException
this . output . flush ( ) ;
this . g = true ;
2013-03-13 23:33:27 +01:00
BufferedOutputStream bufferedoutputstream = new BufferedOutputStream ( MinecraftEncryption . a ( this . A , this . socket . getOutputStream ( ) ) , 5120 ) ;
2012-11-06 13:05:28 +01:00
this . output = new DataOutputStream ( bufferedoutputstream ) ;
2012-07-29 09:33:13 +02:00
}
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 ) {
2013-03-13 23:33:27 +01:00
return networkmanager . n ;
2011-03-27 22:12:39 +02:00
}
static boolean b ( NetworkManager networkmanager ) {
2013-03-13 23:33:27 +01:00
return networkmanager . t ;
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 ) {
2013-03-13 23:33:27 +01:00
return networkmanager . o ;
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 ) {
2013-03-13 23:33:27 +01:00
return networkmanager . v ;
2011-03-27 22:12:39 +02:00
}
2011-05-26 14:48:22 +02:00
static Thread h ( NetworkManager networkmanager ) {
2013-03-13 23:33:27 +01:00
return networkmanager . u ;
2011-03-27 22:12:39 +02:00
}
}