blob: 1682db073423f0557883a83acf301b73bb7b5357 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/***
* Java TelnetD library (embeddable telnet daemon)
* Copyright (c) 2000-2005 Dieter Wimberger
* All rights reserved.
* <p/>
* 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.
* <p/>
* 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.
* <p/>
* 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 org.apache.felix.gogo.jline.telnet;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Class that implements a <tt>PortListener</tt>.<br>
* If available, it accepts incoming connections and passes them
* to an associated <tt>ConnectionManager</tt>.
*
* @author Dieter Wimberger
* @version 2.0 (16/07/2006)
* @see ConnectionManager
*/
public class PortListener
implements Runnable {
private static final Logger LOG = Logger.getLogger(PortListener.class.getName());
private static final String logmsg =
"Listening to Port {0,number,integer} with a connectivity queue size of {1,number,integer}.";
private String name;
private int port; //port number running on
private int floodProtection; //flooding protection
private ServerSocket serverSocket = null; //server socket
private Thread thread;
private ConnectionManager connectionManager; //connection management thread
private boolean stopping = false;
private boolean available; //Flag for availability
/**
* Constructs a PortListener instance.<br>
*
* @param port int that specifies the port number of the server socket.
* @param floodprot that specifies the server socket queue size.
*/
public PortListener(String name, int port, int floodprot) {
this.name = name;
available = false;
this.port = port;
floodProtection = floodprot;
}//constructor
/**
* Returns the name of this <tt>PortListener</tt>.
*
* @return the name as <tt>String</tt>.
*/
public String getName() {
return name;
}//getName
/**
* Tests if this <tt>PortListener</tt> is available.
*
* @return true if available, false otherwise.
*/
public boolean isAvailable() {
return available;
}//isAvailable
/**
* Sets the availability flag of this <tt>PortListener</tt>.
*
* @param b true if to be available, false otherwise.
*/
public void setAvailable(boolean b) {
available = b;
}//setAvailable
/**
* Starts this <tt>PortListener</tt>.
*/
public void start() {
LOG.log(Level.FINE, "start()");
thread = new Thread(this);
thread.start();
available = true;
}//start
/**
* Stops this <tt>PortListener</tt>, and returns
* when everything was stopped successfully.
*/
public void stop() {
LOG.log(Level.FINE, "stop()::" + this.toString());
//flag stop
stopping = true;
available = false;
//take down all connections
connectionManager.stop();
//close server socket
try {
serverSocket.close();
} catch (IOException ex) {
LOG.log(Level.SEVERE, "stop()", ex);
}
//wait for thread to die
try {
thread.join();
} catch (InterruptedException iex) {
LOG.log(Level.SEVERE, "stop()", iex);
}
LOG.info("stop()::Stopped " + this.toString());
}//stop
/**
* Listen constantly to a server socket and handles incoming connections
* through the associated {a:link ConnectionManager}.
*
* @see ConnectionManager
*/
public void run() {
try {
/*
A server socket is opened with a connectivity queue of a size specified
in int floodProtection. Concurrent login handling under normal circumstances
should be handled properly, but denial of service attacks via massive parallel
program logins should be prevented with this.
*/
serverSocket = new ServerSocket(port, floodProtection);
//log entry
LOG.info(MessageFormat.format(logmsg, port, floodProtection));
do {
try {
Socket s = serverSocket.accept();
if (available) {
connectionManager.makeConnection(s);
} else {
//just shut down the socket
s.close();
}
} catch (SocketException ex) {
if (stopping) {
//server socket was closed blocked in accept
LOG.log(Level.FINE, "run(): ServerSocket closed by stop()");
} else {
LOG.log(Level.SEVERE, "run()", ex);
}
}
} while (!stopping);
} catch (IOException e) {
LOG.log(Level.SEVERE, "run()", e);
}
LOG.log(Level.FINE, "run(): returning.");
}//run
/**
* Returns reference to ConnectionManager instance associated
* with the PortListener.
*
* @return the associated ConnectionManager.
*/
public ConnectionManager getConnectionManager() {
return connectionManager;
}//getConnectionManager
public void setConnectionManager(ConnectionManager connectionManager) {
this.connectionManager = connectionManager;
}
}//class PortListener