package net.yura.lobby.quickserver;
import java.io.ByteArrayOutputStream;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import net.yura.lobby.model.Message;
import net.yura.lobby.server.LobbyServer;
import net.yura.lobby.server.LobbySession;
import net.yura.lobby.server.SocketServer;
import org.quickserver.net.server.ClientHandler;
import org.quickserver.net.server.DataMode;
import org.quickserver.net.server.DataType;
import org.quickserver.net.server.QuickServer;
import org.quickserver.util.xmlreader.BasicServerConfig;
import org.quickserver.util.xmlreader.ServerMode;
public class Server extends QuickServer implements QuickServerMXBean,SocketServer {
public static final Logger logger = Logger.getLogger(Server.class.getName());
@Override
public void send(LobbySession key, Message message) {
ClientHandler ch = getClientHandler(key);
if (ch!=null) {
try {
// TODO we do not give the ByteArrayOutputStream a size, even though we can work it out
ByteArrayOutputStream out = new ByteArrayOutputStream();
lobbyServer.encode(out, message);
byte[] data = out.toByteArray();
// synchronized does NOT fix the "toNotify object was already set!",
// and does not really solve any problem or help anything
//synchronized(ch) {
ch.sendClientBinary(data);
//}
}
catch (Exception ex) {
logger.log(Level.WARNING,"Failed to send "+key+" "+message,ex);
}
}
else {
logger.warning("LobbySession: "+key+" NOT FOUND! can not send "+message);
}
}
@Override
public void kick(LobbySession key) {
ClientHandler ch = getClientHandler(key);
if (ch!=null) {
ch.closeConnection();
}
else {
logger.warning("LobbySession: "+key+" NOT FOUND! can not kick");
}
}
@Override
public boolean isConnected(LobbySession key) {
ClientHandler ch = getClientHandler(key);
if (ch!=null) {
return ch.isOpen();
}
else {
return false;
}
}
@Override
public List<LobbySession> getLobbySession(String username) {
if (isClosed()) return Collections.EMPTY_LIST;
List<LobbySession> sessions = new ArrayList();
Iterator<ClientHandler> chit = username==null?findAllClient():findAllClientById( Pattern.quote(username) );
while (chit.hasNext()) {
sessions.add( ((Session)chit.next().getClientData()).lobbySession );
}
return sessions;
}
private ClientHandler getClientHandler(LobbySession key) {
return findClientByKey( key.getSessionUID().toString() );
}
public LobbyServer lobbyServer;
public static void main(String s[]) {
try {
LobbyServer.args = s;
LobbyServer.setupLogging();
ServerMode serverMode = new ServerMode();
serverMode.setBlocking(false);
Server myServer = new Server();
myServer.lobbyServer = new LobbyServer(myServer);
//myServer.findFirstClientById(null); // username
//myServer.findClientByKey(null); // uuid
//QuickServerConfig config = new QuickServerConfig();
//config.setServerMode(serverMode);
//myServer.setConfig(config);
BasicServerConfig basicServerConfig = new BasicServerConfig();
basicServerConfig.setServerMode(serverMode);
myServer.setBasicConfig(basicServerConfig);
myServer.setPort( 1964 );
myServer.setName("Lobby Server");
myServer.setClientEventHandler( EventHandler.class.getName() );
myServer.setClientBinaryHandler( BinaryHandler.class.getName() );
myServer.setClientData( Session.class.getName() );
myServer.setDefaultDataMode(DataMode.BINARY, DataType.OUT);
myServer.setDefaultDataMode(DataMode.BINARY, DataType.IN);
myServer.setTimeout(Integer.MAX_VALUE);
// quickserver logging
//myServer.getAppLogger().setLevel(Level.FINEST); // this will give me LOADS of QuickServer debug info
//myServer.setAppLogger( Logger.getLogger("lobbyserver") ); // dont really think this is needed unless i want a different level for AppLogger (next line)
//myServer.getAppLogger().setLevel(Level.FINEST); // this will give me stuff like "Got BINARY [127.0.0.1] : 80.00 B"
// this is to change the java.util.logging.ConsoleHandler that outputs through the Console, we do not use this
//myServer.setConsoleLoggingToMini(); // "org.quickserver.util.logging.MiniFormatter"
// OR
//myServer.setConsoleLoggingToMicro(); // "org.quickserver.util.logging.MicroFormatter"
// OR
//myServer.setConsoleLoggingFormatter("org.quickserver.util.logging.SimpleTextFormatter");
//reduce info to Console, info is default, unless we change the global default
//myServer.setConsoleLoggingLevel(Level.INFO);
//end of logger code
//QSAdminServerConfig adminConfig = new QSAdminServerConfig();
//adminConfig.setMaxConnection(Integer.MAX_VALUE);
//adminConfig.setTimeout(Integer.MAX_VALUE);
//myServer.configQuickServer(adminConfig);
myServer.setQSAdminServerPort(9876);
myServer.setQSAdminServerAuthenticator(Authenticator.class.getName());
myServer.getQSAdminServer().setCommandPlugin(QSAdminCommandPlugin.class.getName());
//myServer.getQSAdminServer().setShellEnable(true);
//myServer.startQSAdminServer();
// not sure why this is needed
org.quickserver.net.server.impl.NonBlockingClientHandler.setMaxThreadAccessCount(-1);
myServer.startServer();
/*
for (int c=0;c<20;c++) {
new Thread() {
@Override
public void run() {
while (true) {
Iterator it = myServer.findAllClient();
while (it.hasNext()) {
ClientHandler ch = (ClientHandler)it.next();
Session session = (Session)ch.getClientData();
send(session.lobbySession.getUUID(), ProtoAccess.PING , new byte[2000] );
}
try {
Thread.sleep(10);
}
catch (Exception ex) { }
}
}
}.start();
}
*/
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.registerMBean(myServer, new ObjectName("net.yura.lobby:type=QuickServer") );
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}