package NET.worlds.network; import NET.worlds.console.Console; import NET.worlds.console.Main; import NET.worlds.console.MainCallback; import NET.worlds.console.MainTerminalCallback; import NET.worlds.core.Std; import NET.worlds.scape.Drone; import NET.worlds.scape.WObject; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.text.MessageFormat; import java.util.Enumeration; import java.util.Vector; public class WorldServer implements MainCallback, MainTerminalCallback, NetworkObject { protected int _serverProtocolVersion; protected ServerURL _serverURL = null; protected String _clientVersion = Std.getClientVersion(); protected WSConnecting _connectThread; protected OutputStream _ostr = null; protected Socket _sock = null; protected netPacketReader _reader = null; private WaitList _waiters; protected int _refCnt = 0; protected int _tmpRefCnt = 0; protected boolean _isMainRegistered = false; protected ObjectMgr _objTable = null; protected Galaxy _galaxy = null; protected SMState _state; protected boolean _firstLogon = false; protected boolean _requestOffline = false; private int _lastAccessTime = 0; protected int _retriesLeft = 5; protected VarErrorException _lastError = null; protected int _retryTimeout = 60000; private int _lastMsgProcCnt = 5; protected PropertyList _propList = null; protected int _updateTime = 2000; Vector _backupServers; String _currentBackupServer; private static final int STATE_DEAD = -1; protected static final int STATE_PRECONNECTED = 0; private static final int STATE_AUTHPROMPT = 1; private static final int STATE_AUTHREPLY = 2; protected static final int STATE_INITIALIZING = 3; private static final int STATE_CONNECTING = 4; private static final int STATE_XMIT_PROPREQ = 5; private static final int STATE_RCV_PROPS = 6; protected static final int STATE_XMIT_SI = 7; static final int STATE_RCV_SI_ACK = 8; static final int STATE_XMIT_AI = 9; static final int STATE_RCV_AI_ACK = 10; static final int STATE_XMIT_PROPS = 11; static final int STATE_MAINLOOP = 12; private static final int STATE_XMIT_AE = 13; private static final int STATE_RCV_AE_ACK = 14; private static final int STATE_XMIT_SE = 15; static final int STATE_RCV_SE_ACK = 16; static final int STATE_DETACHING = 17; static final int STATE_DISCONNECTED = 18; static final int STATE_SLEEPING = 19; private Vector _referrerList = new Vector(); private String _scriptServer; private String _smtpServer; private String _mailDomain; private int _lastWhisperTick = 0; private int _whisperCnt = 0; private Vector zombies; protected WorldServer() { this._serverProtocolVersion = 24; this._state = new SMState(this, 0); this._currentBackupServer = null; this._backupServers = new Vector(); } public void regShortID(int shortObjID, String longObjID) { assert shortObjID < 253; this._objTable.regShortID(shortObjID, longObjID); } public NetworkObject getObject(ObjID objID) { return this._objTable.getObject(objID); } public void delObject(ObjID objID) { this._objTable.delObject(objID); } public void regObject(ObjID objID, NetworkObject obj) { this._objTable.regObject(objID, obj); } public void regObject(String longid, NetworkObject obj) { this._objTable.regObject(new ObjID(longid), obj); } public String getLongID(ObjID objID) { return this._objTable.getLongID(objID); } public InetAddress getLocalAddress() { return this._sock != null ? this._sock.getLocalAddress() : null; } public Galaxy getGalaxy() { return this._galaxy; } ServerURL getServerURL() { return this._serverURL; } void initInstance(Galaxy galaxy, ServerURL serverURL) { this._galaxy = galaxy; this._serverURL = serverURL; this._objTable = new ObjectMgr(this._galaxy); this._waiters = new WaitList(this); } public net2Property getProperty(int propID) { return this._propList.getProperty(propID); } public int getUpdateTime() { return this._updateTime; } void setUsername(String newUsername) { if ((getDebugLevel() & 4) > 0) { System.out.println(this + ": Server requested username change to " + newUsername); } this._galaxy.setChatname(newUsername); this.regShortID(1, newUsername); } public synchronized void printReferrers() { System.out.println("[" + Std.getRealTime() + "] " + this + ": Referrer list -"); for (int i = this._referrerList.size() - 1; i >= 0; i--) { Object ref = this._referrerList.elementAt(i); System.out.println("\t" + ref); } System.out.println(this + ": Referrer list complete."); } public synchronized Vector printDroneReferrers() { Vector list = new Vector(); for (int i = this._referrerList.size() - 1; i >= 0; i--) { Object ref = this._referrerList.elementAt(i); if (ref.toString().startsWith("!")) { list.addElement(ref.toString()); } } return list; } public synchronized void incRefCnt(Object referrer) { if (this._refCnt == 0 && !this._isMainRegistered) { Main.register(this); this._isMainRegistered = true; } this._lastAccessTime = Std.getFastTime(); this._refCnt++; assert !this._referrerList.removeElement(referrer); this._referrerList.addElement(referrer); if ((getDebugLevel() & 4096) > 0) { System.out.println(this + ": incRefCnt to " + this._refCnt + " by " + referrer); } } public synchronized void tmpRefCnt(Object referrer) { this._tmpRefCnt++; boolean existed = this._referrerList.removeElement(referrer); assert existed; } public synchronized void decRefCnt(Object referrer) { this._refCnt--; boolean existed = this._referrerList.removeElement(referrer); assert existed; if ((getDebugLevel() & 4096) > 0) { System.out.println(this + ": decRefCnt to " + this._refCnt + " by " + referrer); } assert this._refCnt >= 0; } int getRefCnt() { return this._refCnt; } public int getVersion() { return this._serverProtocolVersion; } public void setVersion(int ver) { this._galaxy.setProtocol(ver); this._serverProtocolVersion = ver; if (this._reader != null) { this._reader.setVersion(ver); } if (ver < 18) { System.out.println(this + ": WARNING: Old server running protocol #17!"); } } public static int getDebugLevel() { return Galaxy.getDebugLevel(); } public void sendNetworkMsg(netPacket msg) throws InfiniteWaitException, PacketTooLargeException { synchronized (this._state) { assert this._refCnt != 0 || this._state.getState() != -1; if (this._state.getState() != 12) { throw new InfiniteWaitException(); } else { this.sendNetMsg(msg); } } } public int getServerType() { if (this._propList == null) { return 1; } else { net2Property stProp = this._propList.getProperty(15); int servType = 0; try { servType = Integer.parseInt(stProp.value()); } catch (NumberFormatException var4) { assert false; } return servType; } } private void setScriptServer(String server) { if (!server.endsWith("/")) { server = server + "/"; } this._scriptServer = server; } public String getScriptServer() { return this._scriptServer; } private void setSmtpServer(String server) { this._smtpServer = server; } public String getSmtpServer() { return this._smtpServer; } private void setMailDomain(String domain) { this._mailDomain = domain; } public String getMailDomain() { return this._mailDomain; } void sendNetMsg(netPacket msg) throws PacketTooLargeException { assert msg != null; if ((getDebugLevel() & 128) > 0) { System.out.println("[" + Std.getRealTime() + "] " + this + ": send(" + msg.toString(this) + ")"); } if (this._ostr != null) { try { ByteArrayOutputStream rostr = new ByteArrayOutputStream(256); ServerOutputStream ostr = new ServerOutputStream(rostr, this.getVersion()); msg.send(ostr); if ((getDebugLevel() & 1024) > 0) { byte[] byteArray = rostr.toByteArray(); int size = byteArray[0] & 255; synchronized (System.out) { System.out.print(this + ": send["); for (int i = 0; i < size; i++) { System.out.print(Integer.toString(byteArray[i] & 255, 16) + " "); } System.out.println("]"); } } synchronized (this._ostr) { rostr.writeTo(this._ostr); } this._lastAccessTime = Std.getFastTime(); } catch (PacketTooLargeException var10) { throw var10; } catch (IOException var11) { VarErrorException ve = new VarErrorException(101); if (this._lastError == null) { this._lastError = ve; } assert this._connectThread == null; this._state.setState(17); } } } public void sendText(String input) { this.sendText(null, input); } private void _sendText(String who, String msg) { if (msg.length() > 200) { Object[] arguments = new Object[]{new Integer(msg.length())}; Console.println(MessageFormat.format(Console.message("msg-too-long"), arguments)); msg = msg.substring(0, 199); } msg.trim(); if (msg.length() >= 1) { if (who == null) { try { this.sendNetworkMsg(new textCmd(msg)); } catch (InfiniteWaitException var4) { if (!msg.startsWith("&|+")) { Console.println(Console.message("not-connected")); } } catch (PacketTooLargeException var5) { assert false; } } else { if (!msg.startsWith("&|+")) { Console.printOwnWhisper(who, msg); } if (!msg.startsWith("&|+trade>") && !who.equalsIgnoreCase("trade")) { int timeNow = Std.getRealTime(); if (timeNow - this._lastWhisperTick > 60000) { this._whisperCnt = 0; this._lastWhisperTick = timeNow; } this._whisperCnt++; if (this._whisperCnt > 15) { Console.println(Console.message("whisper-too-fast")); return; } } try { this.sendNetworkMsg(new whisperCmd(who, msg)); } catch (PacketTooLargeException var6) { assert false; } catch (InfiniteWaitException var7) { if (!msg.startsWith("&|+")) { Console.println(Console.message("not-connected")); } } } } } public void sendText(String who, String msg) { if ((getDebugLevel() & 1) > 0) { System.out.println("[" + Std.getRealTime() + "] " + this + ": sendText(" + msg + ")"); } msg = msg.trim(); if (msg.length() > 200) { Console.println(Console.message("converting-long")); int i1 = 0; int i2 = 0; while (msg.length() - i1 > 200) { i2 = msg.lastIndexOf(32, i1 + 200); if (i2 <= i1) { i2 = i1 + 200; } this._sendText(who, msg.substring(i1, i2)); i1 = i2 + 1; } this._sendText(who, msg.substring(i1)); } else { this._sendText(who, msg); } } public int getState() { return this._state.getState(); } void setState(int state) { this._state.setState(state); } public void waitForConnection() throws InfiniteWaitException { this._state.waitForState(12); } public void requestRoomID(String roomName, NetworkRoom room) { this._galaxy.addRoomRequest(roomName, room); if (this._state.getState() == 12) { try { this.sendNetworkMsg(new roomIDReqCmd(roomName)); } catch (PacketTooLargeException var4) { assert false; } catch (InfiniteWaitException var5) { } } } public void delRoomRequest(String roomName) { this._galaxy.delRoomRequest(roomName); } public void delRoomID(int roomID, NetworkRoom room) { this._galaxy.delRoomID(roomID, room); } void regRoomID(int roomID, String roomName, boolean willRedirect) { NetworkRoom room = this._galaxy.regRoomID(roomID, roomName); if (room != null) { room.setRoomID(this, roomID, roomName, willRedirect); } } public void redirectRoom(String roomName, ServerURL serverURL) { NetworkRoom room = (NetworkRoom)this._galaxy.getObject(roomName); if (room != null) { room.serverRedirect(this, roomName, serverURL); } } NetworkRoom getNetworkRoom(int roomID) { return this._galaxy.getRoom(roomID); } public final boolean isConnected() { return this._state.getState() == 12; } void startConnect() { synchronized (this._state) { int state = this._state.getState(); switch (state) { case 0: assert this._connectThread == null; this._state.setState(3); break; case 18: this._retriesLeft = 5; assert this._connectThread == null; this._state.setState(3); case 19: } } this._lastAccessTime = Std.getFastTime(); } void forceOffline() { this._retriesLeft = 0; this._lastError = new VarErrorException(205); this._requestOffline = true; } void goOnline() { this._requestOffline = false; this.startConnect(); } protected void perFrame(int timeNow) { synchronized (this._state) { int ServerState = this._state.getState(); switch (ServerState) { case -1: this.state_Dead(timeNow); case 0: case 4: default: break; case 1: case 2: assert false; break; case 3: this.state_Initializing(); break; case 5: this.state_XMIT_PROPREQ(); break; case 6: case 8: case 16: if (timeNow - this._lastAccessTime > 30000) { if (getDebugLevel() > 0) { System.out.println("[" + timeNow + "] " + this + ": Messaging timeout. (state=" + ServerState + ")"); } if (this._lastError == null) { this._lastError = new VarErrorException(106); } switch (ServerState) { case 6: case 16: this._state.setState(17); return; case 8: this._state.setState(15); } } else { try { this.processMsgs(ServerState, timeNow); } catch (VarErrorException var10) { if (getDebugLevel() > 0) { System.out.println("[" + timeNow + "] " + this + ": VarError#" + var10.getErrorNum()); System.out.println(this + ": " + var10.getMsg()); } if (this._lastError == null) { this._lastError = var10; } this._state.setState(17); } catch (EOFException var11) { EOFException e = var11; VarErrorException ve = new VarErrorException(100); if (this._lastError == null) { this._lastError = ve; } if (getDebugLevel() > 0) { synchronized (System.out) { e.printStackTrace(System.out); } } this._state.setState(17); } catch (IOException var12) { IOException ex = var12; VarErrorException vex = new VarErrorException(102); if (this._lastError == null) { this._lastError = vex; } synchronized (System.out) { System.out.println("[" + timeNow + "] " + this + ": Read error:"); if (getDebugLevel() > 0) { ex.printStackTrace(System.out); } } this._state.setState(17); } catch (Exception var13) { Exception ex = var13; VarErrorException vex = new VarErrorException(103); if (this._lastError == null) { this._lastError = vex; } synchronized (System.out) { System.out.println("[" + timeNow + "] " + this + ": Unexpected error:"); ex.printStackTrace(System.out); } this._state.setState(17); } } break; case 7: this.state_XMIT_SI(); break; case 9: this.state_XMIT_AI(); break; case 10: assert false; break; case 11: this.state_XMIT_Props(); break; case 12: this.state_Mainloop(timeNow); break; case 13: this.state_XMIT_AE(); break; case 14: assert false; break; case 15: this.state_XMIT_SE(); break; case 17: this.state_Detaching(); break; case 18: this.state_Disconnected(timeNow); break; case 19: this.state_Sleeping(timeNow); } } } private void processMsgs(int state, int timeNow) throws Exception { int msgsInQueue = this._reader.count(); if (msgsInQueue > 0) { int msgsToProcess = (int)Math.sqrt(this._lastMsgProcCnt * msgsInQueue); if ((getDebugLevel() & 2) > 0 && msgsInQueue > 30) { synchronized (System.out) { System.out.println(this + ": msgs on incoming queue = " + msgsInQueue); System.out.println(" processed approx " + this._lastMsgProcCnt + " messages on last round."); System.out.println(" processing " + msgsToProcess + " messages."); } } if (5 > msgsToProcess) { this._lastMsgProcCnt = 5; } else { this._lastMsgProcCnt = msgsToProcess; } if (msgsInQueue < msgsToProcess) { msgsToProcess = msgsInQueue; } msgsToProcess = Math.min(msgsToProcess, msgsInQueue); while (this._state.getState() == state && msgsToProcess-- != 0) { receivedNetPacket p = this._reader.get(); assert p != null; if ((getDebugLevel() & 64) > 0) { System.out.println(this + ": recv(" + p.toString(this) + ")"); } p.process(this); } this._lastAccessTime = timeNow; } } protected void state_Initializing() { if (this._requestOffline) { this._state.setState(-1); } else if (this._serverURL.getHost().equals("0.0.0.0:0")) { System.out.println(this + ": DOA"); this._state.setState(-1); } else { this._objTable.regShortID(255, this.getLongID()); this._objTable.regObject(this.getLongID(), this); this._lastError = null; this._firstLogon = false; String host = this._serverURL.getHost(); int port = 5100; assert host != null; int cindx = this._serverURL.getHost().lastIndexOf(58); if (cindx >= 0) { try { port = Integer.parseInt(this._serverURL.getHost().substring(cindx + 1)); } catch (NumberFormatException var8) { NumberFormatException e = var8; synchronized (System.out) { System.out.println("######DEBUGGING######"); System.out.println(" server: " + this._serverURL.getHost()); System.out.println(" message: " + e.getMessage()); e.printStackTrace(System.out); System.out.println("#####################"); } VarErrorException ve = new VarErrorException(103); if (this._lastError == null) { this._lastError = ve; } System.out.println("Error in server URL format: " + this._serverURL.getHost()); this._state.setState(17); return; } host = this._serverURL.getHost().substring(0, cindx); } this._lastAccessTime = Std.getFastTime(); if (this._currentBackupServer != null) { if (this._sock != null) { try { this._sock.close(); } catch (Exception var7) { } this._sock = null; } host = this._currentBackupServer; } if (this._sock == null) { this._state.setState(4); assert this._connectThread == null; this._connectThread = new WSConnecting(this, host, port, 15); } else if (this._propList == null) { this._state.setState(5); } else { this._state.setState(7); } } } protected void setSocket(Socket sock, VarErrorException ve, String host) { Vector resolvedHosts = this._connectThread.getBackupHosts(); Enumeration en = resolvedHosts.elements(); while (en.hasMoreElements()) { WorldServer.BackupServer bs = new WorldServer.BackupServer(en.nextElement()); Enumeration en2 = this._backupServers.elements(); boolean unique = true; while (en2.hasMoreElements()) { if (en2.nextElement().GetHost().equals(bs.GetHost())) { unique = false; break; } } if (unique) { this._backupServers.addElement(bs); } if (host != null && host.equals(bs.GetHost())) { bs.IncTries(); } } this._connectThread = null; if (this._state.getState() == 4) { if (sock != null) { this._sock = sock; try { this._ostr = this._sock.getOutputStream(); this._reader = new netPacketReader(this, new ServerInputStream(this._sock.getInputStream())); this._reader.setVersion(this.getVersion()); } catch (Exception var9) { ve = new VarErrorException(105); if (this._lastError == null) { this._lastError = ve; } System.out.println(this + ": Error opening I/O streams."); this._state.setState(17); return; } this._reader.setDaemon(true); this._reader.start(); this._state.setState(5); } else { assert ve != null; if (this._lastError == null) { this._lastError = ve; } this._state.setState(17); } } } protected void state_XMIT_PROPREQ() { if (this._requestOffline) { this._state.setState(17); } else { propReqCmd propReq = new propReqCmd(new ObjID(255)); if (NetUpdate.isInternalVersion()) { propReq.addProp(1); propReq.addProp(3); propReq.addProp(15); propReq.addProp(29); propReq.addProp(25); propReq.addProp(26); propReq.addProp(27); } try { this.sendNetMsg(propReq); } catch (PacketTooLargeException var3) { assert false; } this._state.setState(6); } } protected void state_XMIT_SI() { assert false; if (this._requestOffline) { this._state.setState(17); } else { this._galaxy.addPendingServer(this); this._state.setState(8); } } protected void state_XMIT_AI() { assert false; if (this._requestOffline) { this._state.setState(17); } else { this._state.setState(11); } } protected void state_XMIT_Props() { if (this._requestOffline) { this._state.setState(15); } else { this._state.setState(12); this._galaxy.addActiveServer(this); } } protected void state_Mainloop(int timeNow) { this.killZombies(); if (this._requestOffline) { this._state.setState(15); } else if (timeNow - this._lastAccessTime > 120000) { if (getDebugLevel() > 0) { System.out.println(this + ": Timeout during connection."); } System.out.println("[" + timeNow + "] " + this + ": Timeout during connection."); System.out.println("\t_lastAccessTime = " + this._lastAccessTime); System.out.println("\t timeNow = " + timeNow); this._retriesLeft = 0; this._state.setState(15); } else { this._waiters.notify(true); try { this.processMsgs(12, timeNow); } catch (VarErrorException var8) { assert false; this._state.setState(17); } catch (EOFException var9) { EOFException e = var9; VarErrorException ve = new VarErrorException(100); if (this._lastError == null) { this._lastError = ve; } synchronized (System.out) { System.out.println("[" + timeNow + "] " + this + ": Server has shut down connection."); if (getDebugLevel() > 0) { e.printStackTrace(System.out); } } this._state.setState(17); } catch (IOException var10) { IOException e = var10; VarErrorException ve = new VarErrorException(100); if (this._lastError == null) { this._lastError = ve; } synchronized (System.out) { System.out.println("[" + timeNow + "] " + this + ": Error reading from network."); if (getDebugLevel() > 0) { e.printStackTrace(System.out); } } this._state.setState(17); } catch (Exception var11) { Exception e = var11; VarErrorException ve = new VarErrorException(103); if (this._lastError == null) { this._lastError = ve; } synchronized (System.out) { System.out.println("[" + timeNow + "] " + this + ": Unexpected error."); e.printStackTrace(System.out); } this._state.setState(17); } } } protected void state_XMIT_AE() { assert false; this._state.setState(14); this._state.setState(15); } protected void state_XMIT_SE() { boolean sendVAR_LOGONOFF = this._galaxy.addClosingServer(this); OldPropertyList propList = new OldPropertyList(); if (sendVAR_LOGONOFF) { propList.addProperty(new netProperty(12, "1")); } try { this.sendNetMsg(new sessionExitCmd(propList)); } catch (PacketTooLargeException var4) { assert false; } this._state.setState(16); } protected void reuseConnection(WorldServer src) { this._reader = src._reader; src._reader = null; this._ostr = src._ostr; src._ostr = null; this._sock = src._sock; src._sock = null; this._backupServers = (Vector)src._backupServers.clone(); } public boolean useBackupServer() { Enumeration enums = this._backupServers.elements(); while (enums.hasMoreElements()) { WorldServer.BackupServer bs = enums.nextElement(); if (bs.tries == 0) { bs.IncTries(); this._currentBackupServer = bs.GetHost(); return true; } } this._currentBackupServer = null; return false; } private void addZombies() { Enumeration enums = this._objTable.objects(); while (enums.hasMoreElements()) { NetworkObject no = enums.nextElement(); if (no instanceof WObject) { if (this.zombies == null) { this.zombies = new Vector(); } this.zombies.addElement(no); } else if (no instanceof Drone) { ((Drone)no).disappear(); } } this._objTable.clear(); } public void killZombies() { if (this.zombies != null) { int i = this.zombies.size(); while (--i >= 0) { NetworkObject no = this.zombies.elementAt(i); this._objTable.regObject(no.getLongID(), no); if (no instanceof Drone) { ((Drone)no).disappear(); } } this.zombies = null; } } private void cleanup() { assert this._objTable != null; if (this._lastError != null && !this._lastError.getStatusFlag()) { this.addZombies(); } else { this.killZombies(); Enumeration enums = this._objTable.objects(); while (enums.hasMoreElements()) { NetworkObject no = enums.nextElement(); if (no instanceof Drone) { ((Drone)no).disappear(); } } this._objTable.clear(); } if (this._reader != null) { if (this._reader.isAlive()) { this._reader.stop(); } this._reader = null; } if (this._ostr != null) { try { this._ostr.close(); } catch (Exception var4) { } this._ostr = null; } if (this._sock != null) { try { this._sock.close(); } catch (Exception var3) { } this._sock = null; } assert this._connectThread == null; } protected void state_Detaching_helper() { if (this._galaxy != null) { this._galaxy.addClosingServer(this); this._galaxy.markClosedServer(this); } this.cleanup(); this._retryTimeout = 60000; if (this._galaxy != null) { this._galaxy.noteServerDeath(this._lastError); } } protected void state_Detaching() { this._state.setState(18); this.state_Detaching_helper(); if (this._lastError != null) { System.out.println("[" + Std.getRealTime() + "] " + this + ": lastError=" + this._lastError); this._lastError = null; this._galaxy.reacquireServer(this); } else if (this._refCnt - this._tmpRefCnt > 0) { this.startConnect(); } } protected void state_Sleeping(int timeNow) { if (this._requestOffline) { this._state.setState(-1); } else { if (timeNow - this._lastAccessTime > this._retryTimeout) { if (this._refCnt == 0) { this._state.setState(18); } else { this._state.setState(3); } } } } protected void state_Disconnected(int timeNow) { this._waiters.notify(false); if (timeNow - this._lastAccessTime > 1800000) { synchronized (this) { if (this._refCnt == 0) { assert this._isMainRegistered; Main.unregister(this); this._isMainRegistered = false; if (this._galaxy != null) { this._galaxy.killServer(this); } } } } else { this._lastAccessTime = timeNow; } } protected void state_Dead(int timeNow) { this.killZombies(); this.state_Disconnected(timeNow); } @Override public void mainCallback() { int t = Std.getRealTime(); this.perFrame(t); if ((getDebugLevel() & 4096) > 0 && this._tmpRefCnt > 0) { System.out.println(this + ": tmpRefCnt cleanup of " + this._tmpRefCnt + " refs."); } synchronized (this) { this._refCnt = this._refCnt - this._tmpRefCnt; this._tmpRefCnt = 0; } assert this._refCnt >= 0; } @Override public void terminalCallback() { synchronized (this) { if (this._isMainRegistered) { Main.unregister(this); } Galaxy.forceOffline(false); if (this._lastError == null) { this._lastError = new VarErrorException(201); } this._retriesLeft = 0; int state = this._state.getState(); this._state.setState(-1); switch (state) { case 4: this._connectThread = null; case 7: case 16: case 17: if ((getDebugLevel() & 512) > 0) { System.out.println(this + ": terminalCallback(): Detach"); } this.state_Detaching(); break; case 5: case 6: case 13: case 14: default: if ((getDebugLevel() & 512) > 0) { System.out.println(this + ": terminalCallback(): no operation"); } break; case 8: case 9: case 10: case 11: case 12: case 15: if ((getDebugLevel() & 512) > 0) { System.out.println(this + ": terminalCallback(): XMIT_SE, Detach"); } this.state_XMIT_SE(); this.state_Detaching(); } } } public void waitForConnection(ConnectionWaiter cw) { this._waiters.addWaiter(cw); } public void abortWaitForConnection(ConnectionWaiter cw) { this._waiters.abortWait(cw); } @Override public String toString() { return this.getLongID(); } @Override public void property(OldPropertyList propList) { assert false; } @Override public void propertyUpdate(PropertyList propList) { this._propList = propList; net2Property protocol = this._propList.getProperty(3); if (protocol != null) { int ver; try { ver = Integer.parseInt(protocol.value()); } catch (NumberFormatException var9) { System.err.println(this + ": Error converting protocol value: " + protocol.value()); ver = 18; } int oldVer = this.getVersion(); this.setVersion(ver < oldVer ? ver : oldVer); } net2Property update = this._propList.getProperty(8); if (update != null) { try { this._updateTime = Integer.parseInt(update.value()); this._updateTime /= 1000; } catch (NumberFormatException var8) { System.err.println(this + ": Error converting update value: " + update.value()); } } net2Property http = this._propList.getProperty(24); if (http == null) { http = this._propList.getProperty(29); } if (http != null) { NetUpdate.setUpgradeServerURL(http.value()); } net2Property script = this._propList.getProperty(25); if (script != null) { this.setScriptServer(script.value()); } net2Property smtp = this._propList.getProperty(26); if (smtp != null) { this.setSmtpServer(smtp.value()); } net2Property domain = this._propList.getProperty(27); if (domain != null) { this.setMailDomain(domain.value()); } if (this._state.getState() == 6) { this._state.setState(7); } } @Override public WorldServer getServer() { return this; } @Override public String getLongID() { return this._serverURL.getHost(); } @Override public void register() { assert false; } @Override public void galaxyDisconnected() { assert false; } @Override public void reacquireServer(WorldServer oldServer) { } @Override public void changeChannel(Galaxy g, String oldChannel, String newChannel) { } protected class BackupServer { protected String hostName; protected int tries; public BackupServer() { this.hostName = ""; this.tries = 0; } public BackupServer(String host) { this.hostName = host; this.tries = 0; } public String GetHost() { return this.hostName; } public void IncTries() { this.tries++; } } }