📄 connection.java
字号:
//License/*** * Java TelnetD library (embeddable telnet daemon) * Copyright (c) 2000-2005 Dieter Wimberger * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. ***/package net.wimpi.telnetd.net;import net.wimpi.telnetd.io.BasicTerminalIO;import net.wimpi.telnetd.io.TerminalIO;import net.wimpi.telnetd.shell.Shell;import net.wimpi.telnetd.shell.ShellManager;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import java.util.Vector;/** * Class that implements a connection with this telnet daemon.<br> * It is derived from java.lang.Thread, which reflects the architecture * constraint of one thread per connection. This might seem a waste of * resources, but as a matter of fact sharing threads would require a * far more complex imlementation, due to the fact that telnet is not a * stateless protocol (i.e. alive throughout a session of multiple requests * and responses).<br> * Each Connection instance is created by the listeners ConnectionManager * instance, making it part of a threadgroup and passing in an associated * ConnectionData instance, that holds vital information about the connection. * Be sure to take a look at their documention.<br> * <p/> * Once the thread has started and is running, it will get a login * shell instance from the ShellManager and run passing its own reference. * * @author Dieter Wimberger * @version 2.0 (16/07/2006) * @see net.wimpi.telnetd.net.ConnectionManager * @see net.wimpi.telnetd.net.ConnectionData * @see net.wimpi.telnetd.shell.ShellManager * @see net.wimpi.telnetd.io.TerminalIO */public class Connection extends Thread { private static Log log = LogFactory.getLog(Connection.class); private static int m_Number; //unique number for a thread in the thread group private boolean m_Dead; private Vector m_Listeners; //Associations private ConnectionData m_ConnectionData; //associated information private BasicTerminalIO m_TerminalIO; //associated terminal io private Shell m_NextShell = null; //next shell to be run /** * Constructs a TelnetConnection by invoking its parent constructor * and setting of various members.<br> * Subsequently instantiates the whole i/o subsystem, negotiating * telnet protocol level options etc.<br> * * @param tcg ThreadGroup that this instance is running in. * @param cd ConnectionData instance containing all vital information * of this connection. * @see net.wimpi.telnetd.net.ConnectionData */ public Connection(ThreadGroup tcg, ConnectionData cd) { super(tcg, ("Connection" + (++m_Number))); m_ConnectionData = cd; //init the connection listeners for events //(there should actually be only one or two) m_Listeners = new Vector(3); m_TerminalIO = new TerminalIO(this); m_Dead = false; }//constructor /** * Method overloaded to implement following behaviour: * <ol> * <li> On first entry, retrieve an instance of the configured * login shell from the ShellManager and run it. * <li> Handle a shell switch or close down disgracefully when * problems (i.e. unhandled unchecked exceptions) occur in the * running shell. * </ol> */ public void run() { boolean done = false; try { Shell sh = ShellManager.getReference().getShell(m_ConnectionData.getLoginShell()); do { sh.run(this); if (m_Dead) { done = true; break; } sh = getNextShell(); if (sh == null) { done = true; } } while (!done || m_Dead); } catch (Exception ex) { log.error("run()", ex); //Handle properly } finally { //call close if not dead already if (!m_Dead) { close(); } } log.debug("run():: Returning from " + this.toString()); }//run /** * Method to access the associated connection data. * * @return ConnectionData associated with the Connection instance. * @see net.wimpi.telnetd.net.ConnectionData */ public ConnectionData getConnectionData() { return m_ConnectionData; }//getConnectionData /** * Method to access the associated terminal io. * * @return BasicTerminalIO associated with the Connection instance. * @see net.wimpi.telnetd.io.BasicTerminalIO */ public BasicTerminalIO getTerminalIO() { return m_TerminalIO; }//getTerminalIO /** * Method to prepare the Connection for a shell switch.<br> * A shell instance will be acquired from the ShellManager * according to the given name.<br> * In case of a nonexistant name the return will be false, * otherwise true. * * @param name String that should represent a valid shell name. * @return boolean flagging if the request could be carried out correctly. * @see net.wimpi.telnetd.shell.ShellManager */ public boolean setNextShell(String name) { m_NextShell = ShellManager.getReference().getShell(name); if (m_NextShell == null) { return false; } else { return true; } }//setNextShell /** * Method used internally to retrieve the next shell * to be run. Its like a one-slot stack, so that we dont * end up in a never ending story. */ private Shell getNextShell() { //get shell Shell shell = m_NextShell; if (shell != null) { //empty single queue m_NextShell = null; //return it return shell; } else { return null; } }//getNextShell /** * Closes the connection and its underlying i/o and network * resources.<br> */ public synchronized void close() { if (m_Dead) { return; } else { try { //connection dead m_Dead = true; //close i/o m_TerminalIO.close(); } catch (Exception ex) { log.error("close()", ex); //handle } try { //close socket m_ConnectionData.getSocket().close(); } catch (Exception ex) { log.error("close()", ex); //handle } try { //register closed connection in ConnectionManager m_ConnectionData.getManager().registerClosedConnection(this); } catch (Exception ex) { log.error("close()", ex); //handle } try { //try to interrupt it interrupt(); } catch (Exception ex) { log.error("close()", ex); //handle } log.debug("Closed " + this.toString() + " and inactive."); } }//close /** * Returns if a connection has been closed.<br> * * @return the state of the connection. */ public boolean isActive() { return !m_Dead; }//isClosed /****** Event handling ****************/ /** * Method that registers a ConnectionListener with the * Connection instance. * * @param cl ConnectionListener to be registered. * @see net.wimpi.telnetd.net.ConnectionListener */ public void addConnectionListener(ConnectionListener cl) { m_Listeners.addElement(cl); }//addConnectionListener /** * Method that removes a ConnectionListener from the * Connection instance. * * @param cl ConnectionListener to be removed. * @see net.wimpi.telnetd.net.ConnectionListener */ public void removeConnectionListener(ConnectionListener cl) { m_Listeners.removeElement(cl); }//removeConnectionListener /** * Method called by the io subsystem to pass on a * "low-level" event. It will be properly delegated to * all registered listeners. * * @param ce ConnectionEvent to be processed. * @see net.wimpi.telnetd.net.ConnectionEvent */ public void processConnectionEvent(ConnectionEvent ce) { for (int i = 0; i < m_Listeners.size(); i++) { ConnectionListener cl = (ConnectionListener) m_Listeners.elementAt(i); if (ce.isType(ConnectionEvent.CONNECTION_IDLE)) { cl.connectionIdle(ce); } else if (ce.isType(ConnectionEvent.CONNECTION_TIMEDOUT)) { cl.connectionTimedOut(ce); } else if (ce.isType(ConnectionEvent.CONNECTION_LOGOUTREQUEST)) { cl.connectionLogoutRequest(ce); //} //else if (ce.isType(ConnectionEvent.CONNECTION_BROKEN)) { // cl.connectionBroken(ce); } else if (ce.isType(ConnectionEvent.CONNECTION_BREAK)) { cl.connectionSentBreak(ce); } } }//processConnectionEvent}//class Connection
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -