package net.sf.l2j.gameserver; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.ByteOrder; import net.sf.l2j.gameserver.serverpackets.ServerBasePacket; import net.sf.l2j.util.Util; import com.ibm.io.async.AsyncServerSocketChannel; import com.ibm.io.async.AsyncSocketChannel; import com.ibm.io.async.IAbstractAsyncFuture; import com.ibm.io.async.IAsyncFuture; import com.ibm.io.async.ICompletionListener; /** * @author zabbix * Lets drink to code! */ public class AIOThread extends Thread implements ICompletionListener { private static AIOThread _instance; private static int _pendingWrite=0; private static int _usersConnected=0; public static AIOThread getInstance() { if(_instance == null) _instance = new AIOThread("localhost",7777); return _instance; } public AIOThread(String hostname, int port) { } public void run() { AsyncServerSocketChannel ssChannel = null; try { ssChannel = AsyncServerSocketChannel.open(); ServerSocket serverSocket = ssChannel.socket(); InetSocketAddress isa = new InetSocketAddress( 7777 ); serverSocket.bind( isa ); } catch( IOException ex ) { ex.printStackTrace(); return; } while(true) { try { AsyncSocketChannel clientChannel = ssChannel.accept(); System.out.println("Conn from "+ clientChannel.socket()); _usersConnected++; AIOOverlapped lpovl = new AIOOverlapped(new ClientThread(clientChannel),0,clientChannel); ByteBuffer read = ByteBuffer.allocateDirect(8192); clientChannel.read( read ).addCompletionListener( this, lpovl); } catch(Exception e) { e.printStackTrace(); } } } public void sendPacket(ServerBasePacket pkt) { ByteBuffer buf = ByteBuffer.allocateDirect(8192); buf.position(0); buf.order(ByteOrder.LITTLE_ENDIAN); //System.err.println("OB1 pos: "+buf.position()+" sz: "+buf.limit()+" rm: "+buf.remaining()+" order: "+buf.order()); pkt.write(buf); //byte[] tmp = new byte[buf.limit()]; //buf.get(tmp,0,buf.limit()); //System.err.println(Util.printData(tmp)); //buf.position(0); //System.err.println("OB2 pos: "+buf.position()+" sz: "+buf.limit()+" rm: "+buf.remaining()+" order: "+buf.order()); try { _pendingWrite += buf.remaining(); pkt.getConnection().getChannel().write(buf).addCompletionListener(this,new AIOOverlapped(pkt.getClient(),1,pkt.getConnection().getChannel())); } catch(Exception e) { e.printStackTrace(); } } public void futureCompleted( IAbstractAsyncFuture f, Object state ) { IAsyncFuture future = ( IAsyncFuture ) f; AIOOverlapped ovl = (AIOOverlapped)state; try { //System.out.println("AsyncIO Completed, state: "+ovl._state+" bytes: "+future.getByteCount()); if((future.isCompleted() && future.getByteCount() == 0 && ovl._state == 0) || !ovl._chan.isOpen()) { if(ovl._chan.isOpen()) ovl._chan.close(); future.cancel(); _usersConnected--; System.out.println("client disconnected"); return; } } catch(Exception e) { e.printStackTrace(); } if(ovl._state == 0) //read { try { future.getBuffer().flip(); future.getBuffer().order(ByteOrder.LITTLE_ENDIAN); int sz = future.getBuffer().getShort() & 0xffff; sz -= 2; if(sz > 0) { ByteBuffer b = future.getBuffer(); b.order(ByteOrder.LITTLE_ENDIAN); b.position(2); ovl._client.getConnection().decript(b); ovl._client.getConnection().addReceivedMsg(b); } ovl._chan.read(future.getBuffer()).addCompletionListener(this,ovl,true); } catch(Exception e) { e.printStackTrace(); } } else if(ovl._state == 1) //write { try { _pendingWrite -= future.getByteCount(); System.err.println("Bytes written: "+future.getByteCount()+", pending write: "+_pendingWrite); } catch(Exception e) { e.printStackTrace(); } } } private class AIOOverlapped { public ClientThread _client; public int _state; AsyncSocketChannel _chan; public AIOOverlapped(ClientThread c,int s,AsyncSocketChannel ch) { _client = c; _state = s; _chan = ch; } } }