mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
init
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/***
|
||||
* The DatagramSocketClient provides the basic operations that are required
|
||||
* of client objects accessing datagram sockets. It is meant to be
|
||||
* subclassed to avoid having to rewrite the same code over and over again
|
||||
* to open a socket, close a socket, set timeouts, etc. Of special note
|
||||
* is the {@link #setDatagramSocketFactory setDatagramSocketFactory }
|
||||
* method, which allows you to control the type of DatagramSocket the
|
||||
* DatagramSocketClient creates for network communications. This is
|
||||
* especially useful for adding things like proxy support as well as better
|
||||
* support for applets. For
|
||||
* example, you could create a
|
||||
* {@link org.apache.commons.net.DatagramSocketFactory}
|
||||
* that
|
||||
* requests browser security capabilities before creating a socket.
|
||||
* All classes derived from DatagramSocketClient should use the
|
||||
* {@link #_socketFactory_ _socketFactory_ } member variable to
|
||||
* create DatagramSocket instances rather than instantiating
|
||||
* them by directly invoking a constructor. By honoring this contract
|
||||
* you guarantee that a user will always be able to provide his own
|
||||
* Socket implementations by substituting his own SocketFactory.
|
||||
*
|
||||
*
|
||||
* @see DatagramSocketFactory
|
||||
***/
|
||||
|
||||
public abstract class DatagramSocketClient
|
||||
{
|
||||
/***
|
||||
* The default DatagramSocketFactory shared by all DatagramSocketClient
|
||||
* instances.
|
||||
***/
|
||||
private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY =
|
||||
new DefaultDatagramSocketFactory();
|
||||
|
||||
/**
|
||||
* Charset to use for byte IO.
|
||||
*/
|
||||
private Charset charset = Charset.defaultCharset();
|
||||
|
||||
/*** The timeout to use after opening a socket. ***/
|
||||
protected int _timeout_;
|
||||
|
||||
/*** The datagram socket used for the connection. ***/
|
||||
protected DatagramSocket _socket_;
|
||||
|
||||
/***
|
||||
* A status variable indicating if the client's socket is currently open.
|
||||
***/
|
||||
protected boolean _isOpen_;
|
||||
|
||||
/*** The datagram socket's DatagramSocketFactory. ***/
|
||||
protected DatagramSocketFactory _socketFactory_;
|
||||
|
||||
/***
|
||||
* Default constructor for DatagramSocketClient. Initializes
|
||||
* _socket_ to null, _timeout_ to 0, and _isOpen_ to false.
|
||||
***/
|
||||
public DatagramSocketClient()
|
||||
{
|
||||
_socket_ = null;
|
||||
_timeout_ = 0;
|
||||
_isOpen_ = false;
|
||||
_socketFactory_ = __DEFAULT_SOCKET_FACTORY;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Opens a DatagramSocket on the local host at the first available port.
|
||||
* Also sets the timeout on the socket to the default timeout set
|
||||
* by {@link #setDefaultTimeout setDefaultTimeout() }.
|
||||
* <p>
|
||||
* _isOpen_ is set to true after calling this method and _socket_
|
||||
* is set to the newly opened socket.
|
||||
*
|
||||
* @exception SocketException If the socket could not be opened or the
|
||||
* timeout could not be set.
|
||||
***/
|
||||
public void open() throws SocketException
|
||||
{
|
||||
_socket_ = _socketFactory_.createDatagramSocket();
|
||||
_socket_.setSoTimeout(_timeout_);
|
||||
_isOpen_ = true;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Opens a DatagramSocket on the local host at a specified port.
|
||||
* Also sets the timeout on the socket to the default timeout set
|
||||
* by {@link #setDefaultTimeout setDefaultTimeout() }.
|
||||
* <p>
|
||||
* _isOpen_ is set to true after calling this method and _socket_
|
||||
* is set to the newly opened socket.
|
||||
*
|
||||
* @param port The port to use for the socket.
|
||||
* @exception SocketException If the socket could not be opened or the
|
||||
* timeout could not be set.
|
||||
***/
|
||||
public void open(int port) throws SocketException
|
||||
{
|
||||
_socket_ = _socketFactory_.createDatagramSocket(port);
|
||||
_socket_.setSoTimeout(_timeout_);
|
||||
_isOpen_ = true;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Opens a DatagramSocket at the specified address on the local host
|
||||
* at a specified port.
|
||||
* Also sets the timeout on the socket to the default timeout set
|
||||
* by {@link #setDefaultTimeout setDefaultTimeout() }.
|
||||
* <p>
|
||||
* _isOpen_ is set to true after calling this method and _socket_
|
||||
* is set to the newly opened socket.
|
||||
*
|
||||
* @param port The port to use for the socket.
|
||||
* @param laddr The local address to use.
|
||||
* @exception SocketException If the socket could not be opened or the
|
||||
* timeout could not be set.
|
||||
***/
|
||||
public void open(int port, InetAddress laddr) throws SocketException
|
||||
{
|
||||
_socket_ = _socketFactory_.createDatagramSocket(port, laddr);
|
||||
_socket_.setSoTimeout(_timeout_);
|
||||
_isOpen_ = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***
|
||||
* Closes the DatagramSocket used for the connection.
|
||||
* You should call this method after you've finished using the class
|
||||
* instance and also before you call {@link #open open() }
|
||||
* again. _isOpen_ is set to false and _socket_ is set to null.
|
||||
* If you call this method when the client socket is not open,
|
||||
* a NullPointerException is thrown.
|
||||
***/
|
||||
public void close()
|
||||
{
|
||||
if (_socket_ != null) {
|
||||
_socket_.close();
|
||||
}
|
||||
_socket_ = null;
|
||||
_isOpen_ = false;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns true if the client has a currently open socket.
|
||||
*
|
||||
* @return True if the client has a curerntly open socket, false otherwise.
|
||||
***/
|
||||
public boolean isOpen()
|
||||
{
|
||||
return _isOpen_;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Set the default timeout in milliseconds to use when opening a socket.
|
||||
* After a call to open, the timeout for the socket is set using this value.
|
||||
* This method should be used prior to a call to {@link #open open()}
|
||||
* and should not be confused with {@link #setSoTimeout setSoTimeout()}
|
||||
* which operates on the currently open socket. _timeout_ contains
|
||||
* the new timeout value.
|
||||
*
|
||||
* @param timeout The timeout in milliseconds to use for the datagram socket
|
||||
* connection.
|
||||
***/
|
||||
public void setDefaultTimeout(int timeout)
|
||||
{
|
||||
_timeout_ = timeout;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns the default timeout in milliseconds that is used when
|
||||
* opening a socket.
|
||||
*
|
||||
* @return The default timeout in milliseconds that is used when
|
||||
* opening a socket.
|
||||
***/
|
||||
public int getDefaultTimeout()
|
||||
{
|
||||
return _timeout_;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Set the timeout in milliseconds of a currently open connection.
|
||||
* Only call this method after a connection has been opened
|
||||
* by {@link #open open()}.
|
||||
*
|
||||
* @param timeout The timeout in milliseconds to use for the currently
|
||||
* open datagram socket connection.
|
||||
* @throws SocketException if an error setting the timeout
|
||||
***/
|
||||
public void setSoTimeout(int timeout) throws SocketException
|
||||
{
|
||||
_socket_.setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns the timeout in milliseconds of the currently opened socket.
|
||||
* If you call this method when the client socket is not open,
|
||||
* a NullPointerException is thrown.
|
||||
*
|
||||
* @return The timeout in milliseconds of the currently opened socket.
|
||||
* @throws SocketException if an error getting the timeout
|
||||
***/
|
||||
public int getSoTimeout() throws SocketException
|
||||
{
|
||||
return _socket_.getSoTimeout();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns the port number of the open socket on the local host used
|
||||
* for the connection. If you call this method when the client socket
|
||||
* is not open, a NullPointerException is thrown.
|
||||
*
|
||||
* @return The port number of the open socket on the local host used
|
||||
* for the connection.
|
||||
***/
|
||||
public int getLocalPort()
|
||||
{
|
||||
return _socket_.getLocalPort();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns the local address to which the client's socket is bound.
|
||||
* If you call this method when the client socket is not open, a
|
||||
* NullPointerException is thrown.
|
||||
*
|
||||
* @return The local address to which the client's socket is bound.
|
||||
***/
|
||||
public InetAddress getLocalAddress()
|
||||
{
|
||||
return _socket_.getLocalAddress();
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Sets the DatagramSocketFactory used by the DatagramSocketClient
|
||||
* to open DatagramSockets. If the factory value is null, then a default
|
||||
* factory is used (only do this to reset the factory after having
|
||||
* previously altered it).
|
||||
*
|
||||
* @param factory The new DatagramSocketFactory the DatagramSocketClient
|
||||
* should use.
|
||||
***/
|
||||
public void setDatagramSocketFactory(DatagramSocketFactory factory)
|
||||
{
|
||||
if (factory == null) {
|
||||
_socketFactory_ = __DEFAULT_SOCKET_FACTORY;
|
||||
} else {
|
||||
_socketFactory_ = factory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charset name.
|
||||
*
|
||||
* @return the charset name.
|
||||
* @since 3.3
|
||||
* TODO Will be deprecated once the code requires Java 1.6 as a mininmum
|
||||
*/
|
||||
public String getCharsetName() {
|
||||
return charset.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charset.
|
||||
*
|
||||
* @return the charset.
|
||||
* @since 3.3
|
||||
*/
|
||||
public Charset getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the charset.
|
||||
*
|
||||
* @param charset the charset.
|
||||
* @since 3.3
|
||||
*/
|
||||
public void setCharset(Charset charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
|
||||
/***
|
||||
* The DatagramSocketFactory interface provides a means for the
|
||||
* programmer to control the creation of datagram sockets and
|
||||
* provide his own DatagramSocket implementations for use by all
|
||||
* classes derived from
|
||||
* {@link org.apache.commons.net.DatagramSocketClient}
|
||||
* .
|
||||
* This allows you to provide your own DatagramSocket implementations and
|
||||
* to perform security checks or browser capability requests before
|
||||
* creating a DatagramSocket.
|
||||
*
|
||||
*
|
||||
***/
|
||||
|
||||
public interface DatagramSocketFactory
|
||||
{
|
||||
|
||||
/***
|
||||
* Creates a DatagramSocket on the local host at the first available port.
|
||||
* @return the socket
|
||||
*
|
||||
* @exception SocketException If the socket could not be created.
|
||||
***/
|
||||
public DatagramSocket createDatagramSocket() throws SocketException;
|
||||
|
||||
/***
|
||||
* Creates a DatagramSocket on the local host at a specified port.
|
||||
*
|
||||
* @param port The port to use for the socket.
|
||||
* @return the socket
|
||||
* @exception SocketException If the socket could not be created.
|
||||
***/
|
||||
public DatagramSocket createDatagramSocket(int port) throws SocketException;
|
||||
|
||||
/***
|
||||
* Creates a DatagramSocket at the specified address on the local host
|
||||
* at a specified port.
|
||||
*
|
||||
* @param port The port to use for the socket.
|
||||
* @param laddr The local address to use.
|
||||
* @return the socket
|
||||
* @exception SocketException If the socket could not be created.
|
||||
***/
|
||||
public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
|
||||
throws SocketException;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
|
||||
/***
|
||||
* DefaultDatagramSocketFactory implements the DatagramSocketFactory
|
||||
* interface by simply wrapping the java.net.DatagramSocket
|
||||
* constructors. It is the default DatagramSocketFactory used by
|
||||
* {@link org.apache.commons.net.DatagramSocketClient}
|
||||
* implementations.
|
||||
*
|
||||
*
|
||||
* @see DatagramSocketFactory
|
||||
* @see DatagramSocketClient
|
||||
* @see DatagramSocketClient#setDatagramSocketFactory
|
||||
***/
|
||||
|
||||
public class DefaultDatagramSocketFactory implements DatagramSocketFactory
|
||||
{
|
||||
|
||||
/***
|
||||
* Creates a DatagramSocket on the local host at the first available port.
|
||||
* @return a new DatagramSocket
|
||||
* @exception SocketException If the socket could not be created.
|
||||
***/
|
||||
@Override
|
||||
public DatagramSocket createDatagramSocket() throws SocketException
|
||||
{
|
||||
return new DatagramSocket();
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a DatagramSocket on the local host at a specified port.
|
||||
*
|
||||
* @param port The port to use for the socket.
|
||||
* @return a new DatagramSocket
|
||||
* @exception SocketException If the socket could not be created.
|
||||
***/
|
||||
@Override
|
||||
public DatagramSocket createDatagramSocket(int port) throws SocketException
|
||||
{
|
||||
return new DatagramSocket(port);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a DatagramSocket at the specified address on the local host
|
||||
* at a specified port.
|
||||
*
|
||||
* @param port The port to use for the socket.
|
||||
* @param laddr The local address to use.
|
||||
* @return a new DatagramSocket
|
||||
* @exception SocketException If the socket could not be created.
|
||||
***/
|
||||
@Override
|
||||
public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
|
||||
throws SocketException
|
||||
{
|
||||
return new DatagramSocket(port, laddr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/***
|
||||
* DefaultSocketFactory implements the SocketFactory interface by
|
||||
* simply wrapping the java.net.Socket and java.net.ServerSocket
|
||||
* constructors. It is the default SocketFactory used by
|
||||
* {@link org.apache.commons.net.SocketClient}
|
||||
* implementations.
|
||||
*
|
||||
*
|
||||
* @see SocketFactory
|
||||
* @see SocketClient
|
||||
* @see SocketClient#setSocketFactory
|
||||
***/
|
||||
|
||||
public class DefaultSocketFactory extends SocketFactory
|
||||
{
|
||||
/** The proxy to use when creating new sockets. */
|
||||
private final Proxy connProxy;
|
||||
|
||||
/**
|
||||
* The default constructor.
|
||||
*/
|
||||
public DefaultSocketFactory()
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructor for sockets with proxy support.
|
||||
*
|
||||
* @param proxy The Proxy to use when creating new Sockets.
|
||||
* @since 3.2
|
||||
*/
|
||||
public DefaultSocketFactory(Proxy proxy)
|
||||
{
|
||||
connProxy = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an unconnected Socket.
|
||||
*
|
||||
* @return A new unconnected Socket.
|
||||
* @exception IOException If an I/O error occurs while creating the Socket.
|
||||
* @since 3.2
|
||||
*/
|
||||
@Override
|
||||
public Socket createSocket() throws IOException
|
||||
{
|
||||
if (connProxy != null)
|
||||
{
|
||||
return new Socket(connProxy);
|
||||
}
|
||||
return new Socket();
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a Socket connected to the given host and port.
|
||||
*
|
||||
* @param host The hostname to connect to.
|
||||
* @param port The port to connect to.
|
||||
* @return A Socket connected to the given host and port.
|
||||
* @exception UnknownHostException If the hostname cannot be resolved.
|
||||
* @exception IOException If an I/O error occurs while creating the Socket.
|
||||
***/
|
||||
@Override
|
||||
public Socket createSocket(String host, int port)
|
||||
throws UnknownHostException, IOException
|
||||
{
|
||||
if (connProxy != null)
|
||||
{
|
||||
Socket s = new Socket(connProxy);
|
||||
s.connect(new InetSocketAddress(host, port));
|
||||
return s;
|
||||
}
|
||||
return new Socket(host, port);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a Socket connected to the given host and port.
|
||||
*
|
||||
* @param address The address of the host to connect to.
|
||||
* @param port The port to connect to.
|
||||
* @return A Socket connected to the given host and port.
|
||||
* @exception IOException If an I/O error occurs while creating the Socket.
|
||||
***/
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port)
|
||||
throws IOException
|
||||
{
|
||||
if (connProxy != null)
|
||||
{
|
||||
Socket s = new Socket(connProxy);
|
||||
s.connect(new InetSocketAddress(address, port));
|
||||
return s;
|
||||
}
|
||||
return new Socket(address, port);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a Socket connected to the given host and port and
|
||||
* originating from the specified local address and port.
|
||||
*
|
||||
* @param host The hostname to connect to.
|
||||
* @param port The port to connect to.
|
||||
* @param localAddr The local address to use.
|
||||
* @param localPort The local port to use.
|
||||
* @return A Socket connected to the given host and port.
|
||||
* @exception UnknownHostException If the hostname cannot be resolved.
|
||||
* @exception IOException If an I/O error occurs while creating the Socket.
|
||||
***/
|
||||
@Override
|
||||
public Socket createSocket(String host, int port,
|
||||
InetAddress localAddr, int localPort)
|
||||
throws UnknownHostException, IOException
|
||||
{
|
||||
if (connProxy != null)
|
||||
{
|
||||
Socket s = new Socket(connProxy);
|
||||
s.bind(new InetSocketAddress(localAddr, localPort));
|
||||
s.connect(new InetSocketAddress(host, port));
|
||||
return s;
|
||||
}
|
||||
return new Socket(host, port, localAddr, localPort);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a Socket connected to the given host and port and
|
||||
* originating from the specified local address and port.
|
||||
*
|
||||
* @param address The address of the host to connect to.
|
||||
* @param port The port to connect to.
|
||||
* @param localAddr The local address to use.
|
||||
* @param localPort The local port to use.
|
||||
* @return A Socket connected to the given host and port.
|
||||
* @exception IOException If an I/O error occurs while creating the Socket.
|
||||
***/
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port,
|
||||
InetAddress localAddr, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
if (connProxy != null)
|
||||
{
|
||||
Socket s = new Socket(connProxy);
|
||||
s.bind(new InetSocketAddress(localAddr, localPort));
|
||||
s.connect(new InetSocketAddress(address, port));
|
||||
return s;
|
||||
}
|
||||
return new Socket(address, port, localAddr, localPort);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a ServerSocket bound to a specified port. A port
|
||||
* of 0 will create the ServerSocket on a system-determined free port.
|
||||
*
|
||||
* @param port The port on which to listen, or 0 to use any free port.
|
||||
* @return A ServerSocket that will listen on a specified port.
|
||||
* @exception IOException If an I/O error occurs while creating
|
||||
* the ServerSocket.
|
||||
***/
|
||||
public ServerSocket createServerSocket(int port) throws IOException
|
||||
{
|
||||
return new ServerSocket(port);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a ServerSocket bound to a specified port with a given
|
||||
* maximum queue length for incoming connections. A port of 0 will
|
||||
* create the ServerSocket on a system-determined free port.
|
||||
*
|
||||
* @param port The port on which to listen, or 0 to use any free port.
|
||||
* @param backlog The maximum length of the queue for incoming connections.
|
||||
* @return A ServerSocket that will listen on a specified port.
|
||||
* @exception IOException If an I/O error occurs while creating
|
||||
* the ServerSocket.
|
||||
***/
|
||||
public ServerSocket createServerSocket(int port, int backlog)
|
||||
throws IOException
|
||||
{
|
||||
return new ServerSocket(port, backlog);
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a ServerSocket bound to a specified port on a given local
|
||||
* address with a given maximum queue length for incoming connections.
|
||||
* A port of 0 will
|
||||
* create the ServerSocket on a system-determined free port.
|
||||
*
|
||||
* @param port The port on which to listen, or 0 to use any free port.
|
||||
* @param backlog The maximum length of the queue for incoming connections.
|
||||
* @param bindAddr The local address to which the ServerSocket should bind.
|
||||
* @return A ServerSocket that will listen on a specified port.
|
||||
* @exception IOException If an I/O error occurs while creating
|
||||
* the ServerSocket.
|
||||
***/
|
||||
public ServerSocket createServerSocket(int port, int backlog,
|
||||
InetAddress bindAddr)
|
||||
throws IOException
|
||||
{
|
||||
return new ServerSocket(port, backlog, bindAddr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/***
|
||||
* This exception is used to indicate that the reply from a server
|
||||
* could not be interpreted. Most of the NetComponents classes attempt
|
||||
* to be as lenient as possible when receiving server replies. Many
|
||||
* server implementations deviate from IETF protocol specifications, making
|
||||
* it necessary to be as flexible as possible. However, there will be
|
||||
* certain situations where it is not possible to continue an operation
|
||||
* because the server reply could not be interpreted in a meaningful manner.
|
||||
* In these cases, a MalformedServerReplyException should be thrown.
|
||||
*
|
||||
*
|
||||
***/
|
||||
|
||||
public class MalformedServerReplyException extends IOException
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 6006765264250543945L;
|
||||
|
||||
/*** Constructs a MalformedServerReplyException with no message ***/
|
||||
public MalformedServerReplyException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/***
|
||||
* Constructs a MalformedServerReplyException with a specified message.
|
||||
*
|
||||
* @param message The message explaining the reason for the exception.
|
||||
***/
|
||||
public MalformedServerReplyException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/***
|
||||
* This is a support class for some of the example programs. It is
|
||||
* a sample implementation of the ProtocolCommandListener interface
|
||||
* which just prints out to a specified stream all command/reply traffic.
|
||||
*
|
||||
* @since 2.0
|
||||
***/
|
||||
|
||||
public class PrintCommandListener implements ProtocolCommandListener
|
||||
{
|
||||
private final PrintWriter __writer;
|
||||
private final boolean __nologin;
|
||||
private final char __eolMarker;
|
||||
private final boolean __directionMarker;
|
||||
|
||||
/**
|
||||
* Create the default instance which prints everything.
|
||||
*
|
||||
* @param stream where to write the commands and responses
|
||||
* e.g. System.out
|
||||
* @since 3.0
|
||||
*/
|
||||
public PrintCommandListener(PrintStream stream)
|
||||
{
|
||||
this(new PrintWriter(stream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance which optionally suppresses login command text
|
||||
* and indicates where the EOL starts with the specified character.
|
||||
*
|
||||
* @param stream where to write the commands and responses
|
||||
* @param suppressLogin if {@code true}, only print command name for login
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public PrintCommandListener(PrintStream stream, boolean suppressLogin) {
|
||||
this(new PrintWriter(stream), suppressLogin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance which optionally suppresses login command text
|
||||
* and indicates where the EOL starts with the specified character.
|
||||
*
|
||||
* @param stream where to write the commands and responses
|
||||
* @param suppressLogin if {@code true}, only print command name for login
|
||||
* @param eolMarker if non-zero, add a marker just before the EOL.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public PrintCommandListener(PrintStream stream, boolean suppressLogin, char eolMarker) {
|
||||
this(new PrintWriter(stream), suppressLogin, eolMarker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance which optionally suppresses login command text
|
||||
* and indicates where the EOL starts with the specified character.
|
||||
*
|
||||
* @param stream where to write the commands and responses
|
||||
* @param suppressLogin if {@code true}, only print command name for login
|
||||
* @param eolMarker if non-zero, add a marker just before the EOL.
|
||||
* @param showDirection if {@code true}, add {@code "> "} or {@code "< "} as appropriate to the output
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public PrintCommandListener(PrintStream stream, boolean suppressLogin, char eolMarker, boolean showDirection) {
|
||||
this(new PrintWriter(stream), suppressLogin, eolMarker, showDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default instance which prints everything.
|
||||
*
|
||||
* @param writer where to write the commands and responses
|
||||
*/
|
||||
public PrintCommandListener(PrintWriter writer)
|
||||
{
|
||||
this(writer, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance which optionally suppresses login command text.
|
||||
*
|
||||
* @param writer where to write the commands and responses
|
||||
* @param suppressLogin if {@code true}, only print command name for login
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public PrintCommandListener(PrintWriter writer, boolean suppressLogin)
|
||||
{
|
||||
this(writer, suppressLogin, (char) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance which optionally suppresses login command text
|
||||
* and indicates where the EOL starts with the specified character.
|
||||
*
|
||||
* @param writer where to write the commands and responses
|
||||
* @param suppressLogin if {@code true}, only print command name for login
|
||||
* @param eolMarker if non-zero, add a marker just before the EOL.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public PrintCommandListener(PrintWriter writer, boolean suppressLogin, char eolMarker)
|
||||
{
|
||||
this(writer, suppressLogin, eolMarker, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance which optionally suppresses login command text
|
||||
* and indicates where the EOL starts with the specified character.
|
||||
*
|
||||
* @param writer where to write the commands and responses
|
||||
* @param suppressLogin if {@code true}, only print command name for login
|
||||
* @param eolMarker if non-zero, add a marker just before the EOL.
|
||||
* @param showDirection if {@code true}, add {@code ">} " or {@code "< "} as appropriate to the output
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public PrintCommandListener(PrintWriter writer, boolean suppressLogin, char eolMarker, boolean showDirection)
|
||||
{
|
||||
__writer = writer;
|
||||
__nologin = suppressLogin;
|
||||
__eolMarker = eolMarker;
|
||||
__directionMarker = showDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void protocolCommandSent(ProtocolCommandEvent event)
|
||||
{
|
||||
if (__directionMarker) {
|
||||
__writer.print("> ");
|
||||
}
|
||||
if (__nologin) {
|
||||
String cmd = event.getCommand();
|
||||
if ("PASS".equalsIgnoreCase(cmd) || "USER".equalsIgnoreCase(cmd)) {
|
||||
__writer.print(cmd);
|
||||
__writer.println(" *******"); // Don't bother with EOL marker for this!
|
||||
} else {
|
||||
final String IMAP_LOGIN = "LOGIN";
|
||||
if (IMAP_LOGIN.equalsIgnoreCase(cmd)) { // IMAP
|
||||
String msg = event.getMessage();
|
||||
msg=msg.substring(0, msg.indexOf(IMAP_LOGIN)+IMAP_LOGIN.length());
|
||||
__writer.print(msg);
|
||||
__writer.println(" *******"); // Don't bother with EOL marker for this!
|
||||
} else {
|
||||
__writer.print(getPrintableString(event.getMessage()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
__writer.print(getPrintableString(event.getMessage()));
|
||||
}
|
||||
__writer.flush();
|
||||
}
|
||||
|
||||
private String getPrintableString(String msg){
|
||||
if (__eolMarker == 0) {
|
||||
return msg;
|
||||
}
|
||||
int pos = msg.indexOf(SocketClient.NETASCII_EOL);
|
||||
if (pos > 0) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(msg.substring(0,pos));
|
||||
sb.append(__eolMarker);
|
||||
sb.append(msg.substring(pos));
|
||||
return sb.toString();
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void protocolReplyReceived(ProtocolCommandEvent event)
|
||||
{
|
||||
if (__directionMarker) {
|
||||
__writer.print("< ");
|
||||
}
|
||||
__writer.print(event.getMessage());
|
||||
__writer.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
import java.util.EventObject;
|
||||
|
||||
/***
|
||||
* There exists a large class of IETF protocols that work by sending an
|
||||
* ASCII text command and arguments to a server, and then receiving an
|
||||
* ASCII text reply. For debugging and other purposes, it is extremely
|
||||
* useful to log or keep track of the contents of the protocol messages.
|
||||
* The ProtocolCommandEvent class coupled with the
|
||||
* {@link org.apache.commons.net.ProtocolCommandListener}
|
||||
* interface facilitate this process.
|
||||
*
|
||||
*
|
||||
* @see ProtocolCommandListener
|
||||
* @see ProtocolCommandSupport
|
||||
***/
|
||||
|
||||
public class ProtocolCommandEvent extends EventObject
|
||||
{
|
||||
private static final long serialVersionUID = 403743538418947240L;
|
||||
|
||||
private final int __replyCode;
|
||||
private final boolean __isCommand;
|
||||
private final String __message, __command;
|
||||
|
||||
/***
|
||||
* Creates a ProtocolCommandEvent signalling a command was sent to
|
||||
* the server. ProtocolCommandEvents created with this constructor
|
||||
* should only be sent after a command has been sent, but before the
|
||||
* reply has been received.
|
||||
*
|
||||
* @param source The source of the event.
|
||||
* @param command The string representation of the command type sent, not
|
||||
* including the arguments (e.g., "STAT" or "GET").
|
||||
* @param message The entire command string verbatim as sent to the server,
|
||||
* including all arguments.
|
||||
***/
|
||||
public ProtocolCommandEvent(Object source, String command, String message)
|
||||
{
|
||||
super(source);
|
||||
__replyCode = 0;
|
||||
__message = message;
|
||||
__isCommand = true;
|
||||
__command = command;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Creates a ProtocolCommandEvent signalling a reply to a command was
|
||||
* received. ProtocolCommandEvents created with this constructor
|
||||
* should only be sent after a complete command reply has been received
|
||||
* fromt a server.
|
||||
*
|
||||
* @param source The source of the event.
|
||||
* @param replyCode The integer code indicating the natureof the reply.
|
||||
* This will be the protocol integer value for protocols
|
||||
* that use integer reply codes, or the reply class constant
|
||||
* corresponding to the reply for protocols like POP3 that use
|
||||
* strings like OK rather than integer codes (i.e., POP3Repy.OK).
|
||||
* @param message The entire reply as received from the server.
|
||||
***/
|
||||
public ProtocolCommandEvent(Object source, int replyCode, String message)
|
||||
{
|
||||
super(source);
|
||||
__replyCode = replyCode;
|
||||
__message = message;
|
||||
__isCommand = false;
|
||||
__command = null;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the string representation of the command type sent (e.g., "STAT"
|
||||
* or "GET"). If the ProtocolCommandEvent is a reply event, then null
|
||||
* is returned.
|
||||
*
|
||||
* @return The string representation of the command type sent, or null
|
||||
* if this is a reply event.
|
||||
***/
|
||||
public String getCommand()
|
||||
{
|
||||
return __command;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns the reply code of the received server reply. Undefined if
|
||||
* this is not a reply event.
|
||||
*
|
||||
* @return The reply code of the received server reply. Undefined if
|
||||
* not a reply event.
|
||||
***/
|
||||
public int getReplyCode()
|
||||
{
|
||||
return __replyCode;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns true if the ProtocolCommandEvent was generated as a result
|
||||
* of sending a command.
|
||||
*
|
||||
* @return true If the ProtocolCommandEvent was generated as a result
|
||||
* of sending a command. False otherwise.
|
||||
***/
|
||||
public boolean isCommand()
|
||||
{
|
||||
return __isCommand;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns true if the ProtocolCommandEvent was generated as a result
|
||||
* of receiving a reply.
|
||||
*
|
||||
* @return true If the ProtocolCommandEvent was generated as a result
|
||||
* of receiving a reply. False otherwise.
|
||||
***/
|
||||
public boolean isReply()
|
||||
{
|
||||
return !isCommand();
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the entire message sent to or received from the server.
|
||||
* Includes the line terminator.
|
||||
*
|
||||
* @return The entire message sent to or received from the server.
|
||||
***/
|
||||
public String getMessage()
|
||||
{
|
||||
return __message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
import java.util.EventListener;
|
||||
|
||||
/***
|
||||
* There exists a large class of IETF protocols that work by sending an
|
||||
* ASCII text command and arguments to a server, and then receiving an
|
||||
* ASCII text reply. For debugging and other purposes, it is extremely
|
||||
* useful to log or keep track of the contents of the protocol messages.
|
||||
* The ProtocolCommandListener interface coupled with the
|
||||
* {@link ProtocolCommandEvent} class facilitate this process.
|
||||
* <p>
|
||||
* To receive ProtocolCommandEvents, you merely implement the
|
||||
* ProtocolCommandListener interface and register the class as a listener
|
||||
* with a ProtocolCommandEvent source such as
|
||||
* {@link org.apache.commons.net.ftp.FTPClient}.
|
||||
*
|
||||
*
|
||||
* @see ProtocolCommandEvent
|
||||
* @see ProtocolCommandSupport
|
||||
***/
|
||||
|
||||
public interface ProtocolCommandListener extends EventListener
|
||||
{
|
||||
|
||||
/***
|
||||
* This method is invoked by a ProtocolCommandEvent source after
|
||||
* sending a protocol command to a server.
|
||||
*
|
||||
* @param event The ProtocolCommandEvent fired.
|
||||
***/
|
||||
public void protocolCommandSent(ProtocolCommandEvent event);
|
||||
|
||||
/***
|
||||
* This method is invoked by a ProtocolCommandEvent source after
|
||||
* receiving a reply from a server.
|
||||
*
|
||||
* @param event The ProtocolCommandEvent fired.
|
||||
***/
|
||||
public void protocolReplyReceived(ProtocolCommandEvent event);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EventListener;
|
||||
|
||||
import org.apache.commons.net.util.ListenerList;
|
||||
|
||||
/***
|
||||
* ProtocolCommandSupport is a convenience class for managing a list of
|
||||
* ProtocolCommandListeners and firing ProtocolCommandEvents. You can
|
||||
* simply delegate ProtocolCommandEvent firing and listener
|
||||
* registering/unregistering tasks to this class.
|
||||
*
|
||||
*
|
||||
* @see ProtocolCommandEvent
|
||||
* @see ProtocolCommandListener
|
||||
***/
|
||||
|
||||
public class ProtocolCommandSupport implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = -8017692739988399978L;
|
||||
|
||||
private final Object __source;
|
||||
private final ListenerList __listeners;
|
||||
|
||||
/***
|
||||
* Creates a ProtocolCommandSupport instance using the indicated source
|
||||
* as the source of ProtocolCommandEvents.
|
||||
*
|
||||
* @param source The source to use for all generated ProtocolCommandEvents.
|
||||
***/
|
||||
public ProtocolCommandSupport(Object source)
|
||||
{
|
||||
__listeners = new ListenerList();
|
||||
__source = source;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Fires a ProtocolCommandEvent signalling the sending of a command to all
|
||||
* registered listeners, invoking their
|
||||
* {@link org.apache.commons.net.ProtocolCommandListener#protocolCommandSent protocolCommandSent() }
|
||||
* methods.
|
||||
*
|
||||
* @param command The string representation of the command type sent, not
|
||||
* including the arguments (e.g., "STAT" or "GET").
|
||||
* @param message The entire command string verbatim as sent to the server,
|
||||
* including all arguments.
|
||||
***/
|
||||
public void fireCommandSent(String command, String message)
|
||||
{
|
||||
ProtocolCommandEvent event;
|
||||
|
||||
event = new ProtocolCommandEvent(__source, command, message);
|
||||
|
||||
for (EventListener listener : __listeners)
|
||||
{
|
||||
((ProtocolCommandListener)listener).protocolCommandSent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Fires a ProtocolCommandEvent signalling the reception of a command reply
|
||||
* to all registered listeners, invoking their
|
||||
* {@link org.apache.commons.net.ProtocolCommandListener#protocolReplyReceived protocolReplyReceived() }
|
||||
* methods.
|
||||
*
|
||||
* @param replyCode The integer code indicating the natureof the reply.
|
||||
* This will be the protocol integer value for protocols
|
||||
* that use integer reply codes, or the reply class constant
|
||||
* corresponding to the reply for protocols like POP3 that use
|
||||
* strings like OK rather than integer codes (i.e., POP3Repy.OK).
|
||||
* @param message The entire reply as received from the server.
|
||||
***/
|
||||
public void fireReplyReceived(int replyCode, String message)
|
||||
{
|
||||
ProtocolCommandEvent event;
|
||||
event = new ProtocolCommandEvent(__source, replyCode, message);
|
||||
|
||||
for (EventListener listener : __listeners)
|
||||
{
|
||||
((ProtocolCommandListener)listener).protocolReplyReceived(event);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Adds a ProtocolCommandListener.
|
||||
*
|
||||
* @param listener The ProtocolCommandListener to add.
|
||||
***/
|
||||
public void addProtocolCommandListener(ProtocolCommandListener listener)
|
||||
{
|
||||
__listeners.addListener(listener);
|
||||
}
|
||||
|
||||
/***
|
||||
* Removes a ProtocolCommandListener.
|
||||
*
|
||||
* @param listener The ProtocolCommandListener to remove.
|
||||
***/
|
||||
public void removeProtocolCommandListener(ProtocolCommandListener listener)
|
||||
{
|
||||
__listeners.removeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns the number of ProtocolCommandListeners currently registered.
|
||||
*
|
||||
* @return The number of ProtocolCommandListeners currently registered.
|
||||
***/
|
||||
public int getListenerCount()
|
||||
{
|
||||
return __listeners.getListenerCount();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,888 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
|
||||
/**
|
||||
* The SocketClient provides the basic operations that are required of
|
||||
* client objects accessing sockets. It is meant to be
|
||||
* subclassed to avoid having to rewrite the same code over and over again
|
||||
* to open a socket, close a socket, set timeouts, etc. Of special note
|
||||
* is the {@link #setSocketFactory setSocketFactory }
|
||||
* method, which allows you to control the type of Socket the SocketClient
|
||||
* creates for initiating network connections. This is especially useful
|
||||
* for adding SSL or proxy support as well as better support for applets. For
|
||||
* example, you could create a
|
||||
* {@link javax.net.SocketFactory} that
|
||||
* requests browser security capabilities before creating a socket.
|
||||
* All classes derived from SocketClient should use the
|
||||
* {@link #_socketFactory_ _socketFactory_ } member variable to
|
||||
* create Socket and ServerSocket instances rather than instantiating
|
||||
* them by directly invoking a constructor. By honoring this contract
|
||||
* you guarantee that a user will always be able to provide his own
|
||||
* Socket implementations by substituting his own SocketFactory.
|
||||
* @see SocketFactory
|
||||
*/
|
||||
public abstract class SocketClient
|
||||
{
|
||||
/**
|
||||
* The end of line character sequence used by most IETF protocols. That
|
||||
* is a carriage return followed by a newline: "\r\n"
|
||||
*/
|
||||
public static final String NETASCII_EOL = "\r\n";
|
||||
|
||||
/** The default SocketFactory shared by all SocketClient instances. */
|
||||
private static final SocketFactory __DEFAULT_SOCKET_FACTORY =
|
||||
SocketFactory.getDefault();
|
||||
|
||||
/** The default {@link ServerSocketFactory} */
|
||||
private static final ServerSocketFactory __DEFAULT_SERVER_SOCKET_FACTORY =
|
||||
ServerSocketFactory.getDefault();
|
||||
|
||||
/**
|
||||
* A ProtocolCommandSupport object used to manage the registering of
|
||||
* ProtocolCommandListeners and the firing of ProtocolCommandEvents.
|
||||
*/
|
||||
private ProtocolCommandSupport __commandSupport;
|
||||
|
||||
/** The timeout to use after opening a socket. */
|
||||
protected int _timeout_;
|
||||
|
||||
/** The socket used for the connection. */
|
||||
protected Socket _socket_;
|
||||
|
||||
/** The hostname used for the connection (null = no hostname supplied). */
|
||||
protected String _hostname_;
|
||||
|
||||
/** The default port the client should connect to. */
|
||||
protected int _defaultPort_;
|
||||
|
||||
/** The socket's InputStream. */
|
||||
protected InputStream _input_;
|
||||
|
||||
/** The socket's OutputStream. */
|
||||
protected OutputStream _output_;
|
||||
|
||||
/** The socket's SocketFactory. */
|
||||
protected SocketFactory _socketFactory_;
|
||||
|
||||
/** The socket's ServerSocket Factory. */
|
||||
protected ServerSocketFactory _serverSocketFactory_;
|
||||
|
||||
/** The socket's connect timeout (0 = infinite timeout) */
|
||||
private static final int DEFAULT_CONNECT_TIMEOUT = 0;
|
||||
protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
|
||||
/** Hint for SO_RCVBUF size */
|
||||
private int receiveBufferSize = -1;
|
||||
|
||||
/** Hint for SO_SNDBUF size */
|
||||
private int sendBufferSize = -1;
|
||||
|
||||
/** The proxy to use when connecting. */
|
||||
private Proxy connProxy;
|
||||
|
||||
/**
|
||||
* Charset to use for byte IO.
|
||||
*/
|
||||
private Charset charset = Charset.defaultCharset();
|
||||
|
||||
/**
|
||||
* Default constructor for SocketClient. Initializes
|
||||
* _socket_ to null, _timeout_ to 0, _defaultPort to 0,
|
||||
* _isConnected_ to false, charset to {@code Charset.defaultCharset()}
|
||||
* and _socketFactory_ to a shared instance of
|
||||
* {@link org.apache.commons.net.DefaultSocketFactory}.
|
||||
*/
|
||||
public SocketClient()
|
||||
{
|
||||
_socket_ = null;
|
||||
_hostname_ = null;
|
||||
_input_ = null;
|
||||
_output_ = null;
|
||||
_timeout_ = 0;
|
||||
_defaultPort_ = 0;
|
||||
_socketFactory_ = __DEFAULT_SOCKET_FACTORY;
|
||||
_serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Because there are so many connect() methods, the _connectAction_()
|
||||
* method is provided as a means of performing some action immediately
|
||||
* after establishing a connection, rather than reimplementing all
|
||||
* of the connect() methods. The last action performed by every
|
||||
* connect() method after opening a socket is to call this method.
|
||||
* <p>
|
||||
* This method sets the timeout on the just opened socket to the default
|
||||
* timeout set by {@link #setDefaultTimeout setDefaultTimeout() },
|
||||
* sets _input_ and _output_ to the socket's InputStream and OutputStream
|
||||
* respectively, and sets _isConnected_ to true.
|
||||
* <p>
|
||||
* Subclasses overriding this method should start by calling
|
||||
* <code> super._connectAction_() </code> first to ensure the
|
||||
* initialization of the aforementioned protected variables.
|
||||
* @throws IOException (SocketException) if a problem occurs with the socket
|
||||
*/
|
||||
protected void _connectAction_() throws IOException
|
||||
{
|
||||
_socket_.setSoTimeout(_timeout_);
|
||||
_input_ = _socket_.getInputStream();
|
||||
_output_ = _socket_.getOutputStream();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens a Socket connected to a remote host at the specified port and
|
||||
* originating from the current host at a system assigned port.
|
||||
* Before returning, {@link #_connectAction_ _connectAction_() }
|
||||
* is called to perform connection initialization actions.
|
||||
* <p>
|
||||
* @param host The remote host.
|
||||
* @param port The port to connect to on the remote host.
|
||||
* @exception SocketException If the socket timeout could not be set.
|
||||
* @exception IOException If the socket could not be opened. In most
|
||||
* cases you will only want to catch IOException since SocketException is
|
||||
* derived from it.
|
||||
*/
|
||||
public void connect(InetAddress host, int port)
|
||||
throws SocketException, IOException
|
||||
{
|
||||
_hostname_ = null;
|
||||
_socket_ = _socketFactory_.createSocket();
|
||||
if (receiveBufferSize != -1) {
|
||||
_socket_.setReceiveBufferSize(receiveBufferSize);
|
||||
}
|
||||
if (sendBufferSize != -1) {
|
||||
_socket_.setSendBufferSize(sendBufferSize);
|
||||
}
|
||||
_socket_.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
_connectAction_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a Socket connected to a remote host at the specified port and
|
||||
* originating from the current host at a system assigned port.
|
||||
* Before returning, {@link #_connectAction_ _connectAction_() }
|
||||
* is called to perform connection initialization actions.
|
||||
* <p>
|
||||
* @param hostname The name of the remote host.
|
||||
* @param port The port to connect to on the remote host.
|
||||
* @exception SocketException If the socket timeout could not be set.
|
||||
* @exception IOException If the socket could not be opened. In most
|
||||
* cases you will only want to catch IOException since SocketException is
|
||||
* derived from it.
|
||||
* @exception java.net.UnknownHostException If the hostname cannot be resolved.
|
||||
*/
|
||||
public void connect(String hostname, int port)
|
||||
throws SocketException, IOException
|
||||
{
|
||||
connect(InetAddress.getByName(hostname), port);
|
||||
_hostname_ = hostname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens a Socket connected to a remote host at the specified port and
|
||||
* originating from the specified local address and port.
|
||||
* Before returning, {@link #_connectAction_ _connectAction_() }
|
||||
* is called to perform connection initialization actions.
|
||||
* <p>
|
||||
* @param host The remote host.
|
||||
* @param port The port to connect to on the remote host.
|
||||
* @param localAddr The local address to use.
|
||||
* @param localPort The local port to use.
|
||||
* @exception SocketException If the socket timeout could not be set.
|
||||
* @exception IOException If the socket could not be opened. In most
|
||||
* cases you will only want to catch IOException since SocketException is
|
||||
* derived from it.
|
||||
*/
|
||||
public void connect(InetAddress host, int port,
|
||||
InetAddress localAddr, int localPort)
|
||||
throws SocketException, IOException
|
||||
{
|
||||
_hostname_ = null;
|
||||
_socket_ = _socketFactory_.createSocket();
|
||||
if (receiveBufferSize != -1) {
|
||||
_socket_.setReceiveBufferSize(receiveBufferSize);
|
||||
}
|
||||
if (sendBufferSize != -1) {
|
||||
_socket_.setSendBufferSize(sendBufferSize);
|
||||
}
|
||||
_socket_.bind(new InetSocketAddress(localAddr, localPort));
|
||||
_socket_.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
_connectAction_();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens a Socket connected to a remote host at the specified port and
|
||||
* originating from the specified local address and port.
|
||||
* Before returning, {@link #_connectAction_ _connectAction_() }
|
||||
* is called to perform connection initialization actions.
|
||||
* <p>
|
||||
* @param hostname The name of the remote host.
|
||||
* @param port The port to connect to on the remote host.
|
||||
* @param localAddr The local address to use.
|
||||
* @param localPort The local port to use.
|
||||
* @exception SocketException If the socket timeout could not be set.
|
||||
* @exception IOException If the socket could not be opened. In most
|
||||
* cases you will only want to catch IOException since SocketException is
|
||||
* derived from it.
|
||||
* @exception java.net.UnknownHostException If the hostname cannot be resolved.
|
||||
*/
|
||||
public void connect(String hostname, int port,
|
||||
InetAddress localAddr, int localPort)
|
||||
throws SocketException, IOException
|
||||
{
|
||||
connect(InetAddress.getByName(hostname), port, localAddr, localPort);
|
||||
_hostname_ = hostname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens a Socket connected to a remote host at the current default port
|
||||
* and originating from the current host at a system assigned port.
|
||||
* Before returning, {@link #_connectAction_ _connectAction_() }
|
||||
* is called to perform connection initialization actions.
|
||||
* <p>
|
||||
* @param host The remote host.
|
||||
* @exception SocketException If the socket timeout could not be set.
|
||||
* @exception IOException If the socket could not be opened. In most
|
||||
* cases you will only want to catch IOException since SocketException is
|
||||
* derived from it.
|
||||
*/
|
||||
public void connect(InetAddress host) throws SocketException, IOException
|
||||
{
|
||||
_hostname_ = null;
|
||||
connect(host, _defaultPort_);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens a Socket connected to a remote host at the current default
|
||||
* port and originating from the current host at a system assigned port.
|
||||
* Before returning, {@link #_connectAction_ _connectAction_() }
|
||||
* is called to perform connection initialization actions.
|
||||
* <p>
|
||||
* @param hostname The name of the remote host.
|
||||
* @exception SocketException If the socket timeout could not be set.
|
||||
* @exception IOException If the socket could not be opened. In most
|
||||
* cases you will only want to catch IOException since SocketException is
|
||||
* derived from it.
|
||||
* @exception java.net.UnknownHostException If the hostname cannot be resolved.
|
||||
*/
|
||||
public void connect(String hostname) throws SocketException, IOException
|
||||
{
|
||||
connect(hostname, _defaultPort_);
|
||||
_hostname_ = hostname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects the socket connection.
|
||||
* You should call this method after you've finished using the class
|
||||
* instance and also before you call
|
||||
* {@link #connect connect() }
|
||||
* again. _isConnected_ is set to false, _socket_ is set to null,
|
||||
* _input_ is set to null, and _output_ is set to null.
|
||||
* <p>
|
||||
* @exception IOException If there is an error closing the socket.
|
||||
*/
|
||||
public void disconnect() throws IOException
|
||||
{
|
||||
closeQuietly(_socket_);
|
||||
closeQuietly(_input_);
|
||||
closeQuietly(_output_);
|
||||
_socket_ = null;
|
||||
_hostname_ = null;
|
||||
_input_ = null;
|
||||
_output_ = null;
|
||||
}
|
||||
|
||||
private void closeQuietly(Socket socket) {
|
||||
if (socket != null){
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void closeQuietly(Closeable close){
|
||||
if (close != null){
|
||||
try {
|
||||
close.close();
|
||||
} catch (IOException e) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns true if the client is currently connected to a server.
|
||||
* <p>
|
||||
* Delegates to {@link Socket#isConnected()}
|
||||
* @return True if the client is currently connected to a server,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean isConnected()
|
||||
{
|
||||
if (_socket_ == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _socket_.isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make various checks on the socket to test if it is available for use.
|
||||
* Note that the only sure test is to use it, but these checks may help
|
||||
* in some cases.
|
||||
* @see <a href="https://issues.apache.org/jira/browse/NET-350">NET-350</a>
|
||||
* @return {@code true} if the socket appears to be available for use
|
||||
* @since 3.0
|
||||
*/
|
||||
public boolean isAvailable(){
|
||||
if (isConnected()) {
|
||||
try
|
||||
{
|
||||
if (_socket_.getInetAddress() == null) {
|
||||
return false;
|
||||
}
|
||||
if (_socket_.getPort() == 0) {
|
||||
return false;
|
||||
}
|
||||
if (_socket_.getRemoteSocketAddress() == null) {
|
||||
return false;
|
||||
}
|
||||
if (_socket_.isClosed()) {
|
||||
return false;
|
||||
}
|
||||
/* these aren't exact checks (a Socket can be half-open),
|
||||
but since we usually require two-way data transfer,
|
||||
we check these here too: */
|
||||
if (_socket_.isInputShutdown()) {
|
||||
return false;
|
||||
}
|
||||
if (_socket_.isOutputShutdown()) {
|
||||
return false;
|
||||
}
|
||||
/* ignore the result, catch exceptions: */
|
||||
_socket_.getInputStream();
|
||||
_socket_.getOutputStream();
|
||||
}
|
||||
catch (IOException ioex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default port the SocketClient should connect to when a port
|
||||
* is not specified. The {@link #_defaultPort_ _defaultPort_ }
|
||||
* variable stores this value. If never set, the default port is equal
|
||||
* to zero.
|
||||
* <p>
|
||||
* @param port The default port to set.
|
||||
*/
|
||||
public void setDefaultPort(int port)
|
||||
{
|
||||
_defaultPort_ = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the default port (stored in
|
||||
* {@link #_defaultPort_ _defaultPort_ }).
|
||||
* <p>
|
||||
* @return The current value of the default port.
|
||||
*/
|
||||
public int getDefaultPort()
|
||||
{
|
||||
return _defaultPort_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the default timeout in milliseconds to use when opening a socket.
|
||||
* This value is only used previous to a call to
|
||||
* {@link #connect connect()}
|
||||
* and should not be confused with {@link #setSoTimeout setSoTimeout()}
|
||||
* which operates on an the currently opened socket. _timeout_ contains
|
||||
* the new timeout value.
|
||||
* <p>
|
||||
* @param timeout The timeout in milliseconds to use for the socket
|
||||
* connection.
|
||||
*/
|
||||
public void setDefaultTimeout(int timeout)
|
||||
{
|
||||
_timeout_ = timeout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the default timeout in milliseconds that is used when
|
||||
* opening a socket.
|
||||
* <p>
|
||||
* @return The default timeout in milliseconds that is used when
|
||||
* opening a socket.
|
||||
*/
|
||||
public int getDefaultTimeout()
|
||||
{
|
||||
return _timeout_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the timeout in milliseconds of a currently open connection.
|
||||
* Only call this method after a connection has been opened
|
||||
* by {@link #connect connect()}.
|
||||
* <p>
|
||||
* To set the initial timeout, use {@link #setDefaultTimeout(int)} instead.
|
||||
*
|
||||
* @param timeout The timeout in milliseconds to use for the currently
|
||||
* open socket connection.
|
||||
* @exception SocketException If the operation fails.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public void setSoTimeout(int timeout) throws SocketException
|
||||
{
|
||||
_socket_.setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the underlying socket send buffer size.
|
||||
* <p>
|
||||
* @param size The size of the buffer in bytes.
|
||||
* @throws SocketException never thrown, but subclasses might want to do so
|
||||
* @since 2.0
|
||||
*/
|
||||
public void setSendBufferSize(int size) throws SocketException {
|
||||
sendBufferSize = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sendBuffer size
|
||||
* @return the size, or -1 if not initialised
|
||||
* @since 3.0
|
||||
*/
|
||||
protected int getSendBufferSize(){
|
||||
return sendBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the underlying socket receive buffer size.
|
||||
* <p>
|
||||
* @param size The size of the buffer in bytes.
|
||||
* @throws SocketException never (but subclasses may wish to do so)
|
||||
* @since 2.0
|
||||
*/
|
||||
public void setReceiveBufferSize(int size) throws SocketException {
|
||||
receiveBufferSize = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current receivedBuffer size
|
||||
* @return the size, or -1 if not initialised
|
||||
* @since 3.0
|
||||
*/
|
||||
protected int getReceiveBufferSize(){
|
||||
return receiveBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timeout in milliseconds of the currently opened socket.
|
||||
* <p>
|
||||
* @return The timeout in milliseconds of the currently opened socket.
|
||||
* @exception SocketException If the operation fails.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public int getSoTimeout() throws SocketException
|
||||
{
|
||||
return _socket_.getSoTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the Nagle's algorithm (TCP_NODELAY) on the
|
||||
* currently opened socket.
|
||||
* <p>
|
||||
* @param on True if Nagle's algorithm is to be enabled, false if not.
|
||||
* @exception SocketException If the operation fails.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public void setTcpNoDelay(boolean on) throws SocketException
|
||||
{
|
||||
_socket_.setTcpNoDelay(on);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if Nagle's algorithm is enabled on the currently opened
|
||||
* socket.
|
||||
* <p>
|
||||
* @return True if Nagle's algorithm is enabled on the currently opened
|
||||
* socket, false otherwise.
|
||||
* @exception SocketException If the operation fails.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public boolean getTcpNoDelay() throws SocketException
|
||||
{
|
||||
return _socket_.getTcpNoDelay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SO_KEEPALIVE flag on the currently opened socket.
|
||||
*
|
||||
* From the Javadocs, the default keepalive time is 2 hours (although this is
|
||||
* implementation dependent). It looks as though the Windows WSA sockets implementation
|
||||
* allows a specific keepalive value to be set, although this seems not to be the case on
|
||||
* other systems.
|
||||
* @param keepAlive If true, keepAlive is turned on
|
||||
* @throws SocketException if there is a problem with the socket
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
* @since 2.2
|
||||
*/
|
||||
public void setKeepAlive(boolean keepAlive) throws SocketException {
|
||||
_socket_.setKeepAlive(keepAlive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value of the SO_KEEPALIVE flag on the currently opened socket.
|
||||
* Delegates to {@link Socket#getKeepAlive()}
|
||||
* @return True if SO_KEEPALIVE is enabled.
|
||||
* @throws SocketException if there is a problem with the socket
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
* @since 2.2
|
||||
*/
|
||||
public boolean getKeepAlive() throws SocketException {
|
||||
return _socket_.getKeepAlive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SO_LINGER timeout on the currently opened socket.
|
||||
* <p>
|
||||
* @param on True if linger is to be enabled, false if not.
|
||||
* @param val The linger timeout (in hundredths of a second?)
|
||||
* @exception SocketException If the operation fails.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public void setSoLinger(boolean on, int val) throws SocketException
|
||||
{
|
||||
_socket_.setSoLinger(on, val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current SO_LINGER timeout of the currently opened socket.
|
||||
* <p>
|
||||
* @return The current SO_LINGER timeout. If SO_LINGER is disabled returns
|
||||
* -1.
|
||||
* @exception SocketException If the operation fails.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public int getSoLinger() throws SocketException
|
||||
{
|
||||
return _socket_.getSoLinger();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the port number of the open socket on the local host used
|
||||
* for the connection.
|
||||
* Delegates to {@link Socket#getLocalPort()}
|
||||
* <p>
|
||||
* @return The port number of the open socket on the local host used
|
||||
* for the connection.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public int getLocalPort()
|
||||
{
|
||||
return _socket_.getLocalPort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the local address to which the client's socket is bound.
|
||||
* Delegates to {@link Socket#getLocalAddress()}
|
||||
* <p>
|
||||
* @return The local address to which the client's socket is bound.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public InetAddress getLocalAddress()
|
||||
{
|
||||
return _socket_.getLocalAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port number of the remote host to which the client is
|
||||
* connected.
|
||||
* Delegates to {@link Socket#getPort()}
|
||||
* <p>
|
||||
* @return The port number of the remote host to which the client is
|
||||
* connected.
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public int getRemotePort()
|
||||
{
|
||||
return _socket_.getPort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The remote address to which the client is connected.
|
||||
* Delegates to {@link Socket#getInetAddress()}
|
||||
* @throws NullPointerException if the socket is not currently open
|
||||
*/
|
||||
public InetAddress getRemoteAddress()
|
||||
{
|
||||
return _socket_.getInetAddress();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the remote end of the given socket is connected to the
|
||||
* the same host that the SocketClient is currently connected to. This
|
||||
* is useful for doing a quick security check when a client needs to
|
||||
* accept a connection from a server, such as an FTP data connection or
|
||||
* a BSD R command standard error stream.
|
||||
* <p>
|
||||
* @param socket the item to check against
|
||||
* @return True if the remote hosts are the same, false if not.
|
||||
*/
|
||||
public boolean verifyRemote(Socket socket)
|
||||
{
|
||||
InetAddress host1, host2;
|
||||
|
||||
host1 = socket.getInetAddress();
|
||||
host2 = getRemoteAddress();
|
||||
|
||||
return host1.equals(host2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the SocketFactory used by the SocketClient to open socket
|
||||
* connections. If the factory value is null, then a default
|
||||
* factory is used (only do this to reset the factory after having
|
||||
* previously altered it).
|
||||
* Any proxy setting is discarded.
|
||||
* <p>
|
||||
* @param factory The new SocketFactory the SocketClient should use.
|
||||
*/
|
||||
public void setSocketFactory(SocketFactory factory)
|
||||
{
|
||||
if (factory == null) {
|
||||
_socketFactory_ = __DEFAULT_SOCKET_FACTORY;
|
||||
} else {
|
||||
_socketFactory_ = factory;
|
||||
}
|
||||
// re-setting the socket factory makes the proxy setting useless,
|
||||
// so set the field to null so that getProxy() doesn't return a
|
||||
// Proxy that we're actually not using.
|
||||
connProxy = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ServerSocketFactory used by the SocketClient to open ServerSocket
|
||||
* connections. If the factory value is null, then a default
|
||||
* factory is used (only do this to reset the factory after having
|
||||
* previously altered it).
|
||||
* <p>
|
||||
* @param factory The new ServerSocketFactory the SocketClient should use.
|
||||
* @since 2.0
|
||||
*/
|
||||
public void setServerSocketFactory(ServerSocketFactory factory) {
|
||||
if (factory == null) {
|
||||
_serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
|
||||
} else {
|
||||
_serverSocketFactory_ = factory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's
|
||||
* connect() method.
|
||||
* @param connectTimeout The connection timeout to use (in ms)
|
||||
* @since 2.0
|
||||
*/
|
||||
public void setConnectTimeout(int connectTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying socket connection timeout.
|
||||
* @return timeout (in ms)
|
||||
* @since 2.0
|
||||
*/
|
||||
public int getConnectTimeout() {
|
||||
return connectTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying {@link ServerSocketFactory}
|
||||
* @return The server socket factory
|
||||
* @since 2.2
|
||||
*/
|
||||
public ServerSocketFactory getServerSocketFactory() {
|
||||
return _serverSocketFactory_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a ProtocolCommandListener.
|
||||
*
|
||||
* @param listener The ProtocolCommandListener to add.
|
||||
* @since 3.0
|
||||
*/
|
||||
public void addProtocolCommandListener(ProtocolCommandListener listener) {
|
||||
getCommandSupport().addProtocolCommandListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a ProtocolCommandListener.
|
||||
*
|
||||
* @param listener The ProtocolCommandListener to remove.
|
||||
* @since 3.0
|
||||
*/
|
||||
public void removeProtocolCommandListener(ProtocolCommandListener listener) {
|
||||
getCommandSupport().removeProtocolCommandListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* If there are any listeners, send them the reply details.
|
||||
*
|
||||
* @param replyCode the code extracted from the reply
|
||||
* @param reply the full reply text
|
||||
* @since 3.0
|
||||
*/
|
||||
protected void fireReplyReceived(int replyCode, String reply) {
|
||||
if (getCommandSupport().getListenerCount() > 0) {
|
||||
getCommandSupport().fireReplyReceived(replyCode, reply);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If there are any listeners, send them the command details.
|
||||
*
|
||||
* @param command the command name
|
||||
* @param message the complete message, including command name
|
||||
* @since 3.0
|
||||
*/
|
||||
protected void fireCommandSent(String command, String message) {
|
||||
if (getCommandSupport().getListenerCount() > 0) {
|
||||
getCommandSupport().fireCommandSent(command, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the CommandSupport instance if required
|
||||
*/
|
||||
protected void createCommandSupport(){
|
||||
__commandSupport = new ProtocolCommandSupport(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this if they need to provide their own
|
||||
* instance field for backwards compatibilty.
|
||||
*
|
||||
* @return the CommandSupport instance, may be {@code null}
|
||||
* @since 3.0
|
||||
*/
|
||||
protected ProtocolCommandSupport getCommandSupport() {
|
||||
return __commandSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the proxy for use with all the connections.
|
||||
* The proxy is used for connections established after the
|
||||
* call to this method.
|
||||
*
|
||||
* @param proxy the new proxy for connections.
|
||||
* @since 3.2
|
||||
*/
|
||||
public void setProxy(Proxy proxy) {
|
||||
setSocketFactory(new DefaultSocketFactory(proxy));
|
||||
connProxy = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the proxy for use with all the connections.
|
||||
* @return the current proxy for connections.
|
||||
*/
|
||||
public Proxy getProxy() {
|
||||
return connProxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charset name.
|
||||
*
|
||||
* @return the charset.
|
||||
* @since 3.3
|
||||
* @deprecated Since the code now requires Java 1.6 as a mininmum
|
||||
*/
|
||||
@Deprecated
|
||||
public String getCharsetName() {
|
||||
return charset.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charset.
|
||||
*
|
||||
* @return the charset.
|
||||
* @since 3.3
|
||||
*/
|
||||
public Charset getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the charset.
|
||||
*
|
||||
* @param charset the charset.
|
||||
* @since 3.3
|
||||
*/
|
||||
public void setCharset(Charset charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/*
|
||||
* N.B. Fields cannot be pulled up into a super-class without breaking binary compatibility,
|
||||
* so the abstract method is needed to pass the instance to the methods which were moved here.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* Implements the telnet echo option RFC 857.
|
||||
***/
|
||||
public class EchoOptionHandler extends TelnetOptionHandler
|
||||
{
|
||||
/***
|
||||
* Constructor for the EchoOptionHandler. Allows defining desired
|
||||
* initial setting for local/remote activation of this option and
|
||||
* behaviour in case a local/remote activation request for this
|
||||
* option is received.
|
||||
* <p>
|
||||
* @param initlocal - if set to true, a WILL is sent upon connection.
|
||||
* @param initremote - if set to true, a DO is sent upon connection.
|
||||
* @param acceptlocal - if set to true, any DO request is accepted.
|
||||
* @param acceptremote - if set to true, any WILL request is accepted.
|
||||
***/
|
||||
public EchoOptionHandler(boolean initlocal, boolean initremote,
|
||||
boolean acceptlocal, boolean acceptremote)
|
||||
{
|
||||
super(TelnetOption.ECHO, initlocal, initremote,
|
||||
acceptlocal, acceptremote);
|
||||
}
|
||||
|
||||
/***
|
||||
* Constructor for the EchoOptionHandler. Initial and accept
|
||||
* behaviour flags are set to false
|
||||
***/
|
||||
public EchoOptionHandler()
|
||||
{
|
||||
super(TelnetOption.ECHO, false, false, false, false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* The InvalidTelnetOptionException is the exception that is
|
||||
* thrown whenever a TelnetOptionHandler with an invlaid
|
||||
* option code is registered in TelnetClient with addOptionHandler.
|
||||
***/
|
||||
public class InvalidTelnetOptionException extends Exception
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -2516777155928793597L;
|
||||
|
||||
/***
|
||||
* Option code
|
||||
***/
|
||||
private final int optionCode;
|
||||
|
||||
/***
|
||||
* Error message
|
||||
***/
|
||||
private final String msg;
|
||||
|
||||
/***
|
||||
* Constructor for the exception.
|
||||
* <p>
|
||||
* @param message - Error message.
|
||||
* @param optcode - Option code.
|
||||
***/
|
||||
public InvalidTelnetOptionException(String message, int optcode)
|
||||
{
|
||||
optionCode = optcode;
|
||||
msg = message;
|
||||
}
|
||||
|
||||
/***
|
||||
* Gets the error message of ths exception.
|
||||
* <p>
|
||||
* @return the error message.
|
||||
***/
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
return (msg + ": " + optionCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* Simple option handler that can be used for options
|
||||
* that don't require subnegotiation.
|
||||
***/
|
||||
public class SimpleOptionHandler extends TelnetOptionHandler
|
||||
{
|
||||
/***
|
||||
* Constructor for the SimpleOptionHandler. Allows defining desired
|
||||
* initial setting for local/remote activation of this option and
|
||||
* behaviour in case a local/remote activation request for this
|
||||
* option is received.
|
||||
* <p>
|
||||
* @param optcode - option code.
|
||||
* @param initlocal - if set to true, a WILL is sent upon connection.
|
||||
* @param initremote - if set to true, a DO is sent upon connection.
|
||||
* @param acceptlocal - if set to true, any DO request is accepted.
|
||||
* @param acceptremote - if set to true, any WILL request is accepted.
|
||||
***/
|
||||
public SimpleOptionHandler(int optcode,
|
||||
boolean initlocal,
|
||||
boolean initremote,
|
||||
boolean acceptlocal,
|
||||
boolean acceptremote)
|
||||
{
|
||||
super(optcode, initlocal, initremote,
|
||||
acceptlocal, acceptremote);
|
||||
}
|
||||
|
||||
/***
|
||||
* Constructor for the SimpleOptionHandler. Initial and accept
|
||||
* behaviour flags are set to false
|
||||
* <p>
|
||||
* @param optcode - option code.
|
||||
***/
|
||||
public SimpleOptionHandler(int optcode)
|
||||
{
|
||||
super(optcode, false, false, false, false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* Implements the telnet suppress go ahead option RFC 858.
|
||||
***/
|
||||
public class SuppressGAOptionHandler extends TelnetOptionHandler
|
||||
{
|
||||
/***
|
||||
* Constructor for the SuppressGAOptionHandler. Allows defining desired
|
||||
* initial setting for local/remote activation of this option and
|
||||
* behaviour in case a local/remote activation request for this
|
||||
* option is received.
|
||||
* <p>
|
||||
* @param initlocal - if set to true, a WILL is sent upon connection.
|
||||
* @param initremote - if set to true, a DO is sent upon connection.
|
||||
* @param acceptlocal - if set to true, any DO request is accepted.
|
||||
* @param acceptremote - if set to true, any WILL request is accepted.
|
||||
***/
|
||||
public SuppressGAOptionHandler(boolean initlocal, boolean initremote,
|
||||
boolean acceptlocal, boolean acceptremote)
|
||||
{
|
||||
super(TelnetOption.SUPPRESS_GO_AHEAD, initlocal, initremote,
|
||||
acceptlocal, acceptremote);
|
||||
}
|
||||
|
||||
/***
|
||||
* Constructor for the SuppressGAOptionHandler. Initial and accept
|
||||
* behaviour flags are set to false
|
||||
***/
|
||||
public SuppressGAOptionHandler()
|
||||
{
|
||||
super(TelnetOption.SUPPRESS_GO_AHEAD, false, false, false, false);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/***
|
||||
* The TelnetClient class implements the simple network virtual
|
||||
* terminal (NVT) for the Telnet protocol according to RFC 854. It
|
||||
* does not implement any of the extra Telnet options because it
|
||||
* is meant to be used within a Java program providing automated
|
||||
* access to Telnet accessible resources.
|
||||
* <p>
|
||||
* The class can be used by first connecting to a server using the
|
||||
* SocketClient
|
||||
* {@link org.apache.commons.net.SocketClient#connect connect}
|
||||
* method. Then an InputStream and OutputStream for sending and
|
||||
* receiving data over the Telnet connection can be obtained by
|
||||
* using the {@link #getInputStream getInputStream() } and
|
||||
* {@link #getOutputStream getOutputStream() } methods.
|
||||
* When you finish using the streams, you must call
|
||||
* {@link #disconnect disconnect } rather than simply
|
||||
* closing the streams.
|
||||
***/
|
||||
|
||||
public class TelnetClient extends Telnet
|
||||
{
|
||||
private InputStream __input;
|
||||
private OutputStream __output;
|
||||
protected boolean readerThread = true;
|
||||
private TelnetInputListener inputListener;
|
||||
|
||||
/***
|
||||
* Default TelnetClient constructor, sets terminal-type {@code VT100}.
|
||||
***/
|
||||
public TelnetClient()
|
||||
{
|
||||
/* TERMINAL-TYPE option (start)*/
|
||||
super ("VT100");
|
||||
/* TERMINAL-TYPE option (end)*/
|
||||
__input = null;
|
||||
__output = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance with the specified terminal type.
|
||||
*
|
||||
* @param termtype the terminal type to use, e.g. {@code VT100}
|
||||
*/
|
||||
/* TERMINAL-TYPE option (start)*/
|
||||
public TelnetClient(String termtype)
|
||||
{
|
||||
super (termtype);
|
||||
__input = null;
|
||||
__output = null;
|
||||
}
|
||||
/* TERMINAL-TYPE option (end)*/
|
||||
|
||||
void _flushOutputStream() throws IOException
|
||||
{
|
||||
_output_.flush();
|
||||
}
|
||||
void _closeOutputStream() throws IOException
|
||||
{
|
||||
_output_.close();
|
||||
}
|
||||
|
||||
/***
|
||||
* Handles special connection requirements.
|
||||
*
|
||||
* @exception IOException If an error occurs during connection setup.
|
||||
***/
|
||||
@Override
|
||||
protected void _connectAction_() throws IOException
|
||||
{
|
||||
super._connectAction_();
|
||||
TelnetInputStream tmp = new TelnetInputStream(_input_, this, readerThread);
|
||||
if(readerThread)
|
||||
{
|
||||
tmp._start();
|
||||
}
|
||||
// __input CANNOT refer to the TelnetInputStream. We run into
|
||||
// blocking problems when some classes use TelnetInputStream, so
|
||||
// we wrap it with a BufferedInputStream which we know is safe.
|
||||
// This blocking behavior requires further investigation, but right
|
||||
// now it looks like classes like InputStreamReader are not implemented
|
||||
// in a safe manner.
|
||||
__input = new BufferedInputStream(tmp);
|
||||
__output = new TelnetOutputStream(this);
|
||||
}
|
||||
|
||||
/***
|
||||
* Disconnects the telnet session, closing the input and output streams
|
||||
* as well as the socket. If you have references to the
|
||||
* input and output streams of the telnet connection, you should not
|
||||
* close them yourself, but rather call disconnect to properly close
|
||||
* the connection.
|
||||
***/
|
||||
@Override
|
||||
public void disconnect() throws IOException
|
||||
{
|
||||
if (__input != null) {
|
||||
__input.close();
|
||||
}
|
||||
if (__output != null) {
|
||||
__output.close();
|
||||
}
|
||||
super.disconnect();
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the telnet connection output stream. You should not close the
|
||||
* stream when you finish with it. Rather, you should call
|
||||
* {@link #disconnect disconnect }.
|
||||
*
|
||||
* @return The telnet connection output stream.
|
||||
***/
|
||||
public OutputStream getOutputStream()
|
||||
{
|
||||
return __output;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the telnet connection input stream. You should not close the
|
||||
* stream when you finish with it. Rather, you should call
|
||||
* {@link #disconnect disconnect }.
|
||||
*
|
||||
* @return The telnet connection input stream.
|
||||
***/
|
||||
public InputStream getInputStream()
|
||||
{
|
||||
return __input;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the state of the option on the local side.
|
||||
*
|
||||
* @param option - Option to be checked.
|
||||
*
|
||||
* @return The state of the option on the local side.
|
||||
***/
|
||||
public boolean getLocalOptionState(int option)
|
||||
{
|
||||
/* BUG (option active when not already acknowledged) (start)*/
|
||||
return (_stateIsWill(option) && _requestedWill(option));
|
||||
/* BUG (option active when not already acknowledged) (end)*/
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns the state of the option on the remote side.
|
||||
*
|
||||
* @param option - Option to be checked.
|
||||
*
|
||||
* @return The state of the option on the remote side.
|
||||
***/
|
||||
public boolean getRemoteOptionState(int option)
|
||||
{
|
||||
/* BUG (option active when not already acknowledged) (start)*/
|
||||
return (_stateIsDo(option) && _requestedDo(option));
|
||||
/* BUG (option active when not already acknowledged) (end)*/
|
||||
}
|
||||
/* open TelnetOptionHandler functionality (end)*/
|
||||
|
||||
/* Code Section added for supporting AYT (start)*/
|
||||
|
||||
/***
|
||||
* Sends an Are You There sequence and waits for the result.
|
||||
*
|
||||
* @param timeout - Time to wait for a response (millis.)
|
||||
*
|
||||
* @return true if AYT received a response, false otherwise
|
||||
*
|
||||
* @throws InterruptedException on error
|
||||
* @throws IllegalArgumentException on error
|
||||
* @throws IOException on error
|
||||
***/
|
||||
public boolean sendAYT(long timeout)
|
||||
throws IOException, IllegalArgumentException, InterruptedException
|
||||
{
|
||||
return (_sendAYT(timeout));
|
||||
}
|
||||
/* Code Section added for supporting AYT (start)*/
|
||||
|
||||
/***
|
||||
* Sends a protocol-specific subnegotiation message to the remote peer.
|
||||
* {@link TelnetClient} will add the IAC SB & IAC SE framing bytes;
|
||||
* the first byte in {@code message} should be the appropriate telnet
|
||||
* option code.
|
||||
*
|
||||
* <p>
|
||||
* This method does not wait for any response. Subnegotiation messages
|
||||
* sent by the remote end can be handled by registering an approrpriate
|
||||
* {@link TelnetOptionHandler}.
|
||||
* </p>
|
||||
*
|
||||
* @param message option code followed by subnegotiation payload
|
||||
* @throws IllegalArgumentException if {@code message} has length zero
|
||||
* @throws IOException if an I/O error occurs while writing the message
|
||||
* @since 3.0
|
||||
***/
|
||||
public void sendSubnegotiation(int[] message)
|
||||
throws IOException, IllegalArgumentException
|
||||
{
|
||||
if (message.length < 1) {
|
||||
throw new IllegalArgumentException("zero length message");
|
||||
}
|
||||
_sendSubnegotiation(message);
|
||||
}
|
||||
|
||||
/***
|
||||
* Sends a command byte to the remote peer, adding the IAC prefix.
|
||||
*
|
||||
* <p>
|
||||
* This method does not wait for any response. Messages
|
||||
* sent by the remote end can be handled by registering an approrpriate
|
||||
* {@link TelnetOptionHandler}.
|
||||
* </p>
|
||||
*
|
||||
* @param command the code for the command
|
||||
* @throws IOException if an I/O error occurs while writing the message
|
||||
* @throws IllegalArgumentException on error
|
||||
* @since 3.0
|
||||
***/
|
||||
public void sendCommand(byte command)
|
||||
throws IOException, IllegalArgumentException
|
||||
{
|
||||
_sendCommand(command);
|
||||
}
|
||||
|
||||
/* open TelnetOptionHandler functionality (start)*/
|
||||
|
||||
/***
|
||||
* Registers a new TelnetOptionHandler for this telnet client to use.
|
||||
*
|
||||
* @param opthand - option handler to be registered.
|
||||
*
|
||||
* @throws InvalidTelnetOptionException on error
|
||||
* @throws IOException on error
|
||||
***/
|
||||
@Override
|
||||
public void addOptionHandler(TelnetOptionHandler opthand)
|
||||
throws InvalidTelnetOptionException, IOException
|
||||
{
|
||||
super.addOptionHandler(opthand);
|
||||
}
|
||||
/* open TelnetOptionHandler functionality (end)*/
|
||||
|
||||
/***
|
||||
* Unregisters a TelnetOptionHandler.
|
||||
*
|
||||
* @param optcode - Code of the option to be unregistered.
|
||||
*
|
||||
* @throws InvalidTelnetOptionException on error
|
||||
* @throws IOException on error
|
||||
***/
|
||||
@Override
|
||||
public void deleteOptionHandler(int optcode)
|
||||
throws InvalidTelnetOptionException, IOException
|
||||
{
|
||||
super.deleteOptionHandler(optcode);
|
||||
}
|
||||
|
||||
/* Code Section added for supporting spystreams (start)*/
|
||||
/***
|
||||
* Registers an OutputStream for spying what's going on in
|
||||
* the TelnetClient session.
|
||||
*
|
||||
* @param spystream - OutputStream on which session activity
|
||||
* will be echoed.
|
||||
***/
|
||||
public void registerSpyStream(OutputStream spystream)
|
||||
{
|
||||
super._registerSpyStream(spystream);
|
||||
}
|
||||
|
||||
/***
|
||||
* Stops spying this TelnetClient.
|
||||
*
|
||||
***/
|
||||
public void stopSpyStream()
|
||||
{
|
||||
super._stopSpyStream();
|
||||
}
|
||||
/* Code Section added for supporting spystreams (end)*/
|
||||
|
||||
/***
|
||||
* Registers a notification handler to which will be sent
|
||||
* notifications of received telnet option negotiation commands.
|
||||
*
|
||||
* @param notifhand - TelnetNotificationHandler to be registered
|
||||
***/
|
||||
@Override
|
||||
public void registerNotifHandler(TelnetNotificationHandler notifhand)
|
||||
{
|
||||
super.registerNotifHandler(notifhand);
|
||||
}
|
||||
|
||||
/***
|
||||
* Unregisters the current notification handler.
|
||||
*
|
||||
***/
|
||||
@Override
|
||||
public void unregisterNotifHandler()
|
||||
{
|
||||
super.unregisterNotifHandler();
|
||||
}
|
||||
|
||||
/***
|
||||
* Sets the status of the reader thread.
|
||||
*
|
||||
* <p>
|
||||
* When enabled, a seaparate internal reader thread is created for new
|
||||
* connections to read incoming data as it arrives. This results in
|
||||
* immediate handling of option negotiation, notifications, etc.
|
||||
* (at least until the fixed-size internal buffer fills up).
|
||||
* Otherwise, no thread is created an all negotiation and option
|
||||
* handling is deferred until a read() is performed on the
|
||||
* {@link #getInputStream input stream}.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The reader thread must be enabled for {@link TelnetInputListener}
|
||||
* support.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* When this method is invoked, the reader thread status will apply to all
|
||||
* subsequent connections; the current connection (if any) is not affected.
|
||||
* </p>
|
||||
*
|
||||
* @param flag true to enable the reader thread, false to disable
|
||||
* @see #registerInputListener
|
||||
***/
|
||||
public void setReaderThread(boolean flag)
|
||||
{
|
||||
readerThread = flag;
|
||||
}
|
||||
|
||||
/***
|
||||
* Gets the status of the reader thread.
|
||||
*
|
||||
* @return true if the reader thread is enabled, false otherwise
|
||||
***/
|
||||
public boolean getReaderThread()
|
||||
{
|
||||
return (readerThread);
|
||||
}
|
||||
|
||||
/***
|
||||
* Register a listener to be notified when new incoming data is
|
||||
* available to be read on the {@link #getInputStream input stream}.
|
||||
* Only one listener is supported at a time.
|
||||
*
|
||||
* <p>
|
||||
* More precisely, notifications are issued whenever the number of
|
||||
* bytes available for immediate reading (i.e., the value returned
|
||||
* by {@link InputStream#available}) transitions from zero to non-zero.
|
||||
* Note that (in general) multiple reads may be required to empty the
|
||||
* buffer and reset this notification, because incoming bytes are being
|
||||
* added to the internal buffer asynchronously.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Notifications are only supported when a {@link #setReaderThread
|
||||
* reader thread} is enabled for the connection.
|
||||
* </p>
|
||||
*
|
||||
* @param listener listener to be registered; replaces any previous
|
||||
* @since 3.0
|
||||
***/
|
||||
public synchronized void registerInputListener(TelnetInputListener listener)
|
||||
{
|
||||
this.inputListener = listener;
|
||||
}
|
||||
|
||||
/***
|
||||
* Unregisters the current {@link TelnetInputListener}, if any.
|
||||
*
|
||||
* @since 3.0
|
||||
***/
|
||||
public synchronized void unregisterInputListener()
|
||||
{
|
||||
this.inputListener = null;
|
||||
}
|
||||
|
||||
// Notify input listener
|
||||
void notifyInputListener() {
|
||||
TelnetInputListener listener;
|
||||
synchronized (this) {
|
||||
listener = this.inputListener;
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.telnetInputAvailable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/**
|
||||
* The TelnetCommand class cannot be instantiated and only serves as a
|
||||
* storehouse for telnet command constants.
|
||||
* @see org.apache.commons.net.telnet.Telnet
|
||||
* @see org.apache.commons.net.telnet.TelnetClient
|
||||
*/
|
||||
|
||||
public final class TelnetCommand
|
||||
{
|
||||
/*** The maximum value a command code can have. This value is 255. ***/
|
||||
public static final int MAX_COMMAND_VALUE = 255;
|
||||
|
||||
/*** Interpret As Command code. Value is 255 according to RFC 854. ***/
|
||||
public static final int IAC = 255;
|
||||
|
||||
/*** Don't use option code. Value is 254 according to RFC 854. ***/
|
||||
public static final int DONT = 254;
|
||||
|
||||
/*** Request to use option code. Value is 253 according to RFC 854. ***/
|
||||
public static final int DO = 253;
|
||||
|
||||
/*** Refuse to use option code. Value is 252 according to RFC 854. ***/
|
||||
public static final int WONT = 252;
|
||||
|
||||
/*** Agree to use option code. Value is 251 according to RFC 854. ***/
|
||||
public static final int WILL = 251;
|
||||
|
||||
/*** Start subnegotiation code. Value is 250 according to RFC 854. ***/
|
||||
public static final int SB = 250;
|
||||
|
||||
/*** Go Ahead code. Value is 249 according to RFC 854. ***/
|
||||
public static final int GA = 249;
|
||||
|
||||
/*** Erase Line code. Value is 248 according to RFC 854. ***/
|
||||
public static final int EL = 248;
|
||||
|
||||
/*** Erase Character code. Value is 247 according to RFC 854. ***/
|
||||
public static final int EC = 247;
|
||||
|
||||
/*** Are You There code. Value is 246 according to RFC 854. ***/
|
||||
public static final int AYT = 246;
|
||||
|
||||
/*** Abort Output code. Value is 245 according to RFC 854. ***/
|
||||
public static final int AO = 245;
|
||||
|
||||
/*** Interrupt Process code. Value is 244 according to RFC 854. ***/
|
||||
public static final int IP = 244;
|
||||
|
||||
/*** Break code. Value is 243 according to RFC 854. ***/
|
||||
public static final int BREAK = 243;
|
||||
|
||||
/*** Data mark code. Value is 242 according to RFC 854. ***/
|
||||
public static final int DM = 242;
|
||||
|
||||
/*** No Operation code. Value is 241 according to RFC 854. ***/
|
||||
public static final int NOP = 241;
|
||||
|
||||
/*** End subnegotiation code. Value is 240 according to RFC 854. ***/
|
||||
public static final int SE = 240;
|
||||
|
||||
/*** End of record code. Value is 239. ***/
|
||||
public static final int EOR = 239;
|
||||
|
||||
/*** Abort code. Value is 238. ***/
|
||||
public static final int ABORT = 238;
|
||||
|
||||
/*** Suspend process code. Value is 237. ***/
|
||||
public static final int SUSP = 237;
|
||||
|
||||
/*** End of file code. Value is 236. ***/
|
||||
public static final int EOF = 236;
|
||||
|
||||
/*** Synchronize code. Value is 242. ***/
|
||||
public static final int SYNCH = 242;
|
||||
|
||||
/*** String representations of commands. ***/
|
||||
private static final String __commandString[] = {
|
||||
"IAC", "DONT", "DO", "WONT", "WILL", "SB", "GA", "EL", "EC", "AYT",
|
||||
"AO", "IP", "BRK", "DMARK", "NOP", "SE", "EOR", "ABORT", "SUSP", "EOF"
|
||||
};
|
||||
|
||||
private static final int __FIRST_COMMAND = IAC;
|
||||
private static final int __LAST_COMMAND = EOF;
|
||||
|
||||
/***
|
||||
* Returns the string representation of the telnet protocol command
|
||||
* corresponding to the given command code.
|
||||
* <p>
|
||||
* @param code The command code of the telnet protocol command.
|
||||
* @return The string representation of the telnet protocol command.
|
||||
***/
|
||||
public static final String getCommand(int code)
|
||||
{
|
||||
return __commandString[__FIRST_COMMAND - code];
|
||||
}
|
||||
|
||||
/***
|
||||
* Determines if a given command code is valid. Returns true if valid,
|
||||
* false if not.
|
||||
* <p>
|
||||
* @param code The command code to test.
|
||||
* @return True if the command code is valid, false if not.
|
||||
**/
|
||||
public static final boolean isValidCommand(int code)
|
||||
{
|
||||
return (code <= __FIRST_COMMAND && code >= __LAST_COMMAND);
|
||||
}
|
||||
|
||||
// Cannot be instantiated
|
||||
private TelnetCommand()
|
||||
{ }
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* Listener interface used for notification that incoming data is
|
||||
* available to be read.
|
||||
*
|
||||
* @see TelnetClient
|
||||
* @since 3.0
|
||||
***/
|
||||
public interface TelnetInputListener
|
||||
{
|
||||
|
||||
/***
|
||||
* Callback method invoked when new incoming data is available on a
|
||||
* {@link TelnetClient}'s {@link TelnetClient#getInputStream input stream}.
|
||||
*
|
||||
* @see TelnetClient#registerInputListener
|
||||
***/
|
||||
public void telnetInputAvailable();
|
||||
}
|
||||
@@ -0,0 +1,680 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
|
||||
final class TelnetInputStream extends BufferedInputStream implements Runnable
|
||||
{
|
||||
/** End of file has been reached */
|
||||
private static final int EOF = -1;
|
||||
|
||||
/** Read would block */
|
||||
private static final int WOULD_BLOCK = -2;
|
||||
|
||||
// TODO should these be private enums?
|
||||
static final int _STATE_DATA = 0, _STATE_IAC = 1, _STATE_WILL = 2,
|
||||
_STATE_WONT = 3, _STATE_DO = 4, _STATE_DONT = 5,
|
||||
_STATE_SB = 6, _STATE_SE = 7, _STATE_CR = 8, _STATE_IAC_SB = 9;
|
||||
|
||||
private boolean __hasReachedEOF; // @GuardedBy("__queue")
|
||||
private volatile boolean __isClosed;
|
||||
private boolean __readIsWaiting;
|
||||
private int __receiveState, __queueHead, __queueTail, __bytesAvailable;
|
||||
private final int[] __queue;
|
||||
private final TelnetClient __client;
|
||||
private final Thread __thread;
|
||||
private IOException __ioException;
|
||||
|
||||
/* TERMINAL-TYPE option (start)*/
|
||||
private final int __suboption[] = new int[512];
|
||||
private int __suboption_count = 0;
|
||||
/* TERMINAL-TYPE option (end)*/
|
||||
|
||||
private volatile boolean __threaded;
|
||||
|
||||
TelnetInputStream(InputStream input, TelnetClient client,
|
||||
boolean readerThread)
|
||||
{
|
||||
super(input);
|
||||
__client = client;
|
||||
__receiveState = _STATE_DATA;
|
||||
__isClosed = true;
|
||||
__hasReachedEOF = false;
|
||||
// Make it 2049, because when full, one slot will go unused, and we
|
||||
// want a 2048 byte buffer just to have a round number (base 2 that is)
|
||||
__queue = new int[2049];
|
||||
__queueHead = 0;
|
||||
__queueTail = 0;
|
||||
__bytesAvailable = 0;
|
||||
__ioException = null;
|
||||
__readIsWaiting = false;
|
||||
__threaded = false;
|
||||
if(readerThread) {
|
||||
__thread = new Thread(this);
|
||||
} else {
|
||||
__thread = null;
|
||||
}
|
||||
}
|
||||
|
||||
TelnetInputStream(InputStream input, TelnetClient client) {
|
||||
this(input, client, true);
|
||||
}
|
||||
|
||||
void _start()
|
||||
{
|
||||
if(__thread == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int priority;
|
||||
__isClosed = false;
|
||||
// TODO remove this
|
||||
// Need to set a higher priority in case JVM does not use pre-emptive
|
||||
// threads. This should prevent scheduler induced deadlock (rather than
|
||||
// deadlock caused by a bug in this code).
|
||||
priority = Thread.currentThread().getPriority() + 1;
|
||||
if (priority > Thread.MAX_PRIORITY) {
|
||||
priority = Thread.MAX_PRIORITY;
|
||||
}
|
||||
__thread.setPriority(priority);
|
||||
__thread.setDaemon(true);
|
||||
__thread.start();
|
||||
__threaded = true; // tell _processChar that we are running threaded
|
||||
}
|
||||
|
||||
|
||||
// synchronized(__client) critical sections are to protect against
|
||||
// TelnetOutputStream writing through the telnet client at same time
|
||||
// as a processDo/Will/etc. command invoked from TelnetInputStream
|
||||
// tries to write.
|
||||
/**
|
||||
* Get the next byte of data.
|
||||
* IAC commands are processed internally and do not return data.
|
||||
*
|
||||
* @param mayBlock true if method is allowed to block
|
||||
* @return the next byte of data,
|
||||
* or -1 (EOF) if end of stread reached,
|
||||
* or -2 (WOULD_BLOCK) if mayBlock is false and there is no data available
|
||||
*/
|
||||
private int __read(boolean mayBlock) throws IOException
|
||||
{
|
||||
int ch;
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
// If there is no more data AND we were told not to block,
|
||||
// just return WOULD_BLOCK (-2). (More efficient than exception.)
|
||||
if(!mayBlock && super.available() == 0) {
|
||||
return WOULD_BLOCK;
|
||||
}
|
||||
|
||||
// Otherwise, exit only when we reach end of stream.
|
||||
if ((ch = super.read()) < 0) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
ch = (ch & 0xff);
|
||||
|
||||
/* Code Section added for supporting AYT (start)*/
|
||||
synchronized (__client)
|
||||
{
|
||||
__client._processAYTResponse();
|
||||
}
|
||||
/* Code Section added for supporting AYT (end)*/
|
||||
|
||||
/* Code Section added for supporting spystreams (start)*/
|
||||
__client._spyRead(ch);
|
||||
/* Code Section added for supporting spystreams (end)*/
|
||||
|
||||
switch (__receiveState)
|
||||
{
|
||||
|
||||
case _STATE_CR:
|
||||
if (ch == '\0')
|
||||
{
|
||||
// Strip null
|
||||
continue;
|
||||
}
|
||||
// How do we handle newline after cr?
|
||||
// else if (ch == '\n' && _requestedDont(TelnetOption.ECHO) &&
|
||||
|
||||
// Handle as normal data by falling through to _STATE_DATA case
|
||||
|
||||
//$FALL-THROUGH$
|
||||
case _STATE_DATA:
|
||||
if (ch == TelnetCommand.IAC)
|
||||
{
|
||||
__receiveState = _STATE_IAC;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (ch == '\r')
|
||||
{
|
||||
synchronized (__client)
|
||||
{
|
||||
if (__client._requestedDont(TelnetOption.BINARY)) {
|
||||
__receiveState = _STATE_CR;
|
||||
} else {
|
||||
__receiveState = _STATE_DATA;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
__receiveState = _STATE_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case _STATE_IAC:
|
||||
switch (ch)
|
||||
{
|
||||
case TelnetCommand.WILL:
|
||||
__receiveState = _STATE_WILL;
|
||||
continue;
|
||||
case TelnetCommand.WONT:
|
||||
__receiveState = _STATE_WONT;
|
||||
continue;
|
||||
case TelnetCommand.DO:
|
||||
__receiveState = _STATE_DO;
|
||||
continue;
|
||||
case TelnetCommand.DONT:
|
||||
__receiveState = _STATE_DONT;
|
||||
continue;
|
||||
/* TERMINAL-TYPE option (start)*/
|
||||
case TelnetCommand.SB:
|
||||
__suboption_count = 0;
|
||||
__receiveState = _STATE_SB;
|
||||
continue;
|
||||
/* TERMINAL-TYPE option (end)*/
|
||||
case TelnetCommand.IAC:
|
||||
__receiveState = _STATE_DATA;
|
||||
break; // exit to enclosing switch to return IAC from read
|
||||
case TelnetCommand.SE: // unexpected byte! ignore it (don't send it as a command)
|
||||
__receiveState = _STATE_DATA;
|
||||
continue;
|
||||
default:
|
||||
__receiveState = _STATE_DATA;
|
||||
__client._processCommand(ch); // Notify the user
|
||||
continue; // move on the next char
|
||||
}
|
||||
break; // exit and return from read
|
||||
case _STATE_WILL:
|
||||
synchronized (__client)
|
||||
{
|
||||
__client._processWill(ch);
|
||||
__client._flushOutputStream();
|
||||
}
|
||||
__receiveState = _STATE_DATA;
|
||||
continue;
|
||||
case _STATE_WONT:
|
||||
synchronized (__client)
|
||||
{
|
||||
__client._processWont(ch);
|
||||
__client._flushOutputStream();
|
||||
}
|
||||
__receiveState = _STATE_DATA;
|
||||
continue;
|
||||
case _STATE_DO:
|
||||
synchronized (__client)
|
||||
{
|
||||
__client._processDo(ch);
|
||||
__client._flushOutputStream();
|
||||
}
|
||||
__receiveState = _STATE_DATA;
|
||||
continue;
|
||||
case _STATE_DONT:
|
||||
synchronized (__client)
|
||||
{
|
||||
__client._processDont(ch);
|
||||
__client._flushOutputStream();
|
||||
}
|
||||
__receiveState = _STATE_DATA;
|
||||
continue;
|
||||
/* TERMINAL-TYPE option (start)*/
|
||||
case _STATE_SB:
|
||||
switch (ch)
|
||||
{
|
||||
case TelnetCommand.IAC:
|
||||
__receiveState = _STATE_IAC_SB;
|
||||
continue;
|
||||
default:
|
||||
// store suboption char
|
||||
if (__suboption_count < __suboption.length) {
|
||||
__suboption[__suboption_count++] = ch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
__receiveState = _STATE_SB;
|
||||
continue;
|
||||
case _STATE_IAC_SB: // IAC received during SB phase
|
||||
switch (ch)
|
||||
{
|
||||
case TelnetCommand.SE:
|
||||
synchronized (__client)
|
||||
{
|
||||
__client._processSuboption(__suboption, __suboption_count);
|
||||
__client._flushOutputStream();
|
||||
}
|
||||
__receiveState = _STATE_DATA;
|
||||
continue;
|
||||
case TelnetCommand.IAC: // De-dup the duplicated IAC
|
||||
if (__suboption_count < __suboption.length) {
|
||||
__suboption[__suboption_count++] = ch;
|
||||
}
|
||||
break;
|
||||
default: // unexpected byte! ignore it
|
||||
break;
|
||||
}
|
||||
__receiveState = _STATE_SB;
|
||||
continue;
|
||||
/* TERMINAL-TYPE option (end)*/
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
// synchronized(__client) critical sections are to protect against
|
||||
// TelnetOutputStream writing through the telnet client at same time
|
||||
// as a processDo/Will/etc. command invoked from TelnetInputStream
|
||||
// tries to write. Returns true if buffer was previously empty.
|
||||
private boolean __processChar(int ch) throws InterruptedException
|
||||
{
|
||||
// Critical section because we're altering __bytesAvailable,
|
||||
// __queueTail, and the contents of _queue.
|
||||
boolean bufferWasEmpty;
|
||||
synchronized (__queue)
|
||||
{
|
||||
bufferWasEmpty = (__bytesAvailable == 0);
|
||||
while (__bytesAvailable >= __queue.length - 1)
|
||||
{
|
||||
// The queue is full. We need to wait before adding any more data to it. Hopefully the stream owner
|
||||
// will consume some data soon!
|
||||
if(__threaded)
|
||||
{
|
||||
__queue.notify();
|
||||
try
|
||||
{
|
||||
__queue.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We've been asked to add another character to the queue, but it is already full and there's
|
||||
// no other thread to drain it. This should not have happened!
|
||||
throw new IllegalStateException("Queue is full! Cannot process another character.");
|
||||
}
|
||||
}
|
||||
|
||||
// Need to do this in case we're not full, but block on a read
|
||||
if (__readIsWaiting && __threaded)
|
||||
{
|
||||
__queue.notify();
|
||||
}
|
||||
|
||||
__queue[__queueTail] = ch;
|
||||
++__bytesAvailable;
|
||||
|
||||
if (++__queueTail >= __queue.length) {
|
||||
__queueTail = 0;
|
||||
}
|
||||
}
|
||||
return bufferWasEmpty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException
|
||||
{
|
||||
// Critical section because we're altering __bytesAvailable,
|
||||
// __queueHead, and the contents of _queue in addition to
|
||||
// testing value of __hasReachedEOF.
|
||||
synchronized (__queue)
|
||||
{
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (__ioException != null)
|
||||
{
|
||||
IOException e;
|
||||
e = __ioException;
|
||||
__ioException = null;
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (__bytesAvailable == 0)
|
||||
{
|
||||
// Return EOF if at end of file
|
||||
if (__hasReachedEOF) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
// Otherwise, we have to wait for queue to get something
|
||||
if(__threaded)
|
||||
{
|
||||
__queue.notify();
|
||||
try
|
||||
{
|
||||
__readIsWaiting = true;
|
||||
__queue.wait();
|
||||
__readIsWaiting = false;
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
throw new InterruptedIOException("Fatal thread interruption during read.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//__alreadyread = false;
|
||||
__readIsWaiting = true;
|
||||
int ch;
|
||||
boolean mayBlock = true; // block on the first read only
|
||||
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((ch = __read(mayBlock)) < 0) { // must be EOF
|
||||
if(ch != WOULD_BLOCK) {
|
||||
return (ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InterruptedIOException e)
|
||||
{
|
||||
synchronized (__queue)
|
||||
{
|
||||
__ioException = e;
|
||||
__queue.notifyAll();
|
||||
try
|
||||
{
|
||||
__queue.wait(100);
|
||||
}
|
||||
catch (InterruptedException interrupted)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if(ch != WOULD_BLOCK)
|
||||
{
|
||||
__processChar(ch);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
if (__isClosed) {
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
|
||||
// Reads should not block on subsequent iterations. Potentially, this could happen if the
|
||||
// remaining buffered socket data consists entirely of Telnet command sequence and no "user" data.
|
||||
mayBlock = false;
|
||||
|
||||
}
|
||||
// Continue reading as long as there is data available and the queue is not full.
|
||||
while (super.available() > 0 && __bytesAvailable < __queue.length - 1);
|
||||
|
||||
__readIsWaiting = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ch;
|
||||
|
||||
ch = __queue[__queueHead];
|
||||
|
||||
if (++__queueHead >= __queue.length) {
|
||||
__queueHead = 0;
|
||||
}
|
||||
|
||||
--__bytesAvailable;
|
||||
|
||||
// Need to explicitly notify() so available() works properly
|
||||
if(__bytesAvailable == 0 && __threaded) {
|
||||
__queue.notify();
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Reads the next number of bytes from the stream into an array and
|
||||
* returns the number of bytes read. Returns -1 if the end of the
|
||||
* stream has been reached.
|
||||
* <p>
|
||||
* @param buffer The byte array in which to store the data.
|
||||
* @return The number of bytes read. Returns -1 if the
|
||||
* end of the message has been reached.
|
||||
* @exception IOException If an error occurs in reading the underlying
|
||||
* stream.
|
||||
***/
|
||||
@Override
|
||||
public int read(byte buffer[]) throws IOException
|
||||
{
|
||||
return read(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Reads the next number of bytes from the stream into an array and returns
|
||||
* the number of bytes read. Returns -1 if the end of the
|
||||
* message has been reached. The characters are stored in the array
|
||||
* starting from the given offset and up to the length specified.
|
||||
* <p>
|
||||
* @param buffer The byte array in which to store the data.
|
||||
* @param offset The offset into the array at which to start storing data.
|
||||
* @param length The number of bytes to read.
|
||||
* @return The number of bytes read. Returns -1 if the
|
||||
* end of the stream has been reached.
|
||||
* @exception IOException If an error occurs while reading the underlying
|
||||
* stream.
|
||||
***/
|
||||
@Override
|
||||
public int read(byte buffer[], int offset, int length) throws IOException
|
||||
{
|
||||
int ch, off;
|
||||
|
||||
if (length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Critical section because run() may change __bytesAvailable
|
||||
synchronized (__queue)
|
||||
{
|
||||
if (length > __bytesAvailable) {
|
||||
length = __bytesAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ch = read()) == EOF) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
off = offset;
|
||||
|
||||
do
|
||||
{
|
||||
buffer[offset++] = (byte)ch;
|
||||
}
|
||||
while (--length > 0 && (ch = read()) != EOF);
|
||||
|
||||
//__client._spyRead(buffer, off, offset - off);
|
||||
return (offset - off);
|
||||
}
|
||||
|
||||
|
||||
/*** Returns false. Mark is not supported. ***/
|
||||
@Override
|
||||
public boolean markSupported()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException
|
||||
{
|
||||
// Critical section because run() may change __bytesAvailable
|
||||
synchronized (__queue)
|
||||
{
|
||||
if (__threaded) { // Must not call super.available when running threaded: NET-466
|
||||
return __bytesAvailable;
|
||||
} else {
|
||||
return __bytesAvailable + super.available();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Cannot be synchronized. Will cause deadlock if run() is blocked
|
||||
// in read because BufferedInputStream read() is synchronized.
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
// Completely disregard the fact thread may still be running.
|
||||
// We can't afford to block on this close by waiting for
|
||||
// thread to terminate because few if any JVM's will actually
|
||||
// interrupt a system read() from the interrupt() method.
|
||||
super.close();
|
||||
|
||||
synchronized (__queue)
|
||||
{
|
||||
__hasReachedEOF = true;
|
||||
__isClosed = true;
|
||||
|
||||
if (__thread != null && __thread.isAlive())
|
||||
{
|
||||
__thread.interrupt();
|
||||
}
|
||||
|
||||
__queue.notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
int ch;
|
||||
|
||||
try
|
||||
{
|
||||
_outerLoop:
|
||||
while (!__isClosed)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((ch = __read(true)) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (InterruptedIOException e)
|
||||
{
|
||||
synchronized (__queue)
|
||||
{
|
||||
__ioException = e;
|
||||
__queue.notifyAll();
|
||||
try
|
||||
{
|
||||
__queue.wait(100);
|
||||
}
|
||||
catch (InterruptedException interrupted)
|
||||
{
|
||||
if (__isClosed) {
|
||||
break _outerLoop;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} catch(RuntimeException re) {
|
||||
// We treat any runtime exceptions as though the
|
||||
// stream has been closed. We close the
|
||||
// underlying stream just to be sure.
|
||||
super.close();
|
||||
// Breaking the loop has the effect of setting
|
||||
// the state to closed at the end of the method.
|
||||
break _outerLoop;
|
||||
}
|
||||
|
||||
// Process new character
|
||||
boolean notify = false;
|
||||
try
|
||||
{
|
||||
notify = __processChar(ch);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
if (__isClosed) {
|
||||
break _outerLoop;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify input listener if buffer was previously empty
|
||||
if (notify) {
|
||||
__client.notifyInputListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
synchronized (__queue)
|
||||
{
|
||||
__ioException = ioe;
|
||||
}
|
||||
__client.notifyInputListener();
|
||||
}
|
||||
|
||||
synchronized (__queue)
|
||||
{
|
||||
__isClosed = true; // Possibly redundant
|
||||
__hasReachedEOF = true;
|
||||
__queue.notify();
|
||||
}
|
||||
|
||||
__threaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Emacs configuration
|
||||
* Local variables: **
|
||||
* mode: java **
|
||||
* c-basic-offset: 4 **
|
||||
* indent-tabs-mode: nil **
|
||||
* End: **
|
||||
*/
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* The TelnetNotificationHandler interface can be used to handle
|
||||
* notification of options negotiation commands received on a telnet
|
||||
* session.
|
||||
* <p>
|
||||
* The user can implement this interface and register a
|
||||
* TelnetNotificationHandler by using the registerNotificationHandler()
|
||||
* of TelnetClient to be notified of option negotiation commands.
|
||||
***/
|
||||
|
||||
public interface TelnetNotificationHandler
|
||||
{
|
||||
/***
|
||||
* The remote party sent a DO command.
|
||||
***/
|
||||
public static final int RECEIVED_DO = 1;
|
||||
|
||||
/***
|
||||
* The remote party sent a DONT command.
|
||||
***/
|
||||
public static final int RECEIVED_DONT = 2;
|
||||
|
||||
/***
|
||||
* The remote party sent a WILL command.
|
||||
***/
|
||||
public static final int RECEIVED_WILL = 3;
|
||||
|
||||
/***
|
||||
* The remote party sent a WONT command.
|
||||
***/
|
||||
public static final int RECEIVED_WONT = 4;
|
||||
|
||||
/***
|
||||
* The remote party sent a COMMAND.
|
||||
* @since 2.2
|
||||
***/
|
||||
public static final int RECEIVED_COMMAND = 5;
|
||||
|
||||
/***
|
||||
* Callback method called when TelnetClient receives an
|
||||
* command or option negotiation command
|
||||
*
|
||||
* @param negotiation_code - type of (negotiation) command received
|
||||
* (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT, RECEIVED_COMMAND)
|
||||
*
|
||||
* @param option_code - code of the option negotiated, or the command code itself (e.g. NOP).
|
||||
***/
|
||||
public void receivedNegotiation(int negotiation_code, int option_code);
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* The TelnetOption class cannot be instantiated and only serves as a
|
||||
* storehouse for telnet option constants.
|
||||
* <p>
|
||||
* Details regarding Telnet option specification can be found in RFC 855.
|
||||
*
|
||||
*
|
||||
* @see org.apache.commons.net.telnet.Telnet
|
||||
* @see org.apache.commons.net.telnet.TelnetClient
|
||||
***/
|
||||
|
||||
public class TelnetOption
|
||||
{
|
||||
/*** The maximum value an option code can have. This value is 255. ***/
|
||||
public static final int MAX_OPTION_VALUE = 255;
|
||||
|
||||
public static final int BINARY = 0;
|
||||
|
||||
public static final int ECHO = 1;
|
||||
|
||||
public static final int PREPARE_TO_RECONNECT = 2;
|
||||
|
||||
public static final int SUPPRESS_GO_AHEAD = 3;
|
||||
|
||||
public static final int APPROXIMATE_MESSAGE_SIZE = 4;
|
||||
|
||||
public static final int STATUS = 5;
|
||||
|
||||
public static final int TIMING_MARK = 6;
|
||||
|
||||
public static final int REMOTE_CONTROLLED_TRANSMISSION = 7;
|
||||
|
||||
public static final int NEGOTIATE_OUTPUT_LINE_WIDTH = 8;
|
||||
|
||||
public static final int NEGOTIATE_OUTPUT_PAGE_SIZE = 9;
|
||||
|
||||
public static final int NEGOTIATE_CARRIAGE_RETURN = 10;
|
||||
|
||||
public static final int NEGOTIATE_HORIZONTAL_TAB_STOP = 11;
|
||||
|
||||
public static final int NEGOTIATE_HORIZONTAL_TAB = 12;
|
||||
|
||||
public static final int NEGOTIATE_FORMFEED = 13;
|
||||
|
||||
public static final int NEGOTIATE_VERTICAL_TAB_STOP = 14;
|
||||
|
||||
public static final int NEGOTIATE_VERTICAL_TAB = 15;
|
||||
|
||||
public static final int NEGOTIATE_LINEFEED = 16;
|
||||
|
||||
public static final int EXTENDED_ASCII = 17;
|
||||
|
||||
public static final int FORCE_LOGOUT = 18;
|
||||
|
||||
public static final int BYTE_MACRO = 19;
|
||||
|
||||
public static final int DATA_ENTRY_TERMINAL = 20;
|
||||
|
||||
public static final int SUPDUP = 21;
|
||||
|
||||
public static final int SUPDUP_OUTPUT = 22;
|
||||
|
||||
public static final int SEND_LOCATION = 23;
|
||||
|
||||
public static final int TERMINAL_TYPE = 24;
|
||||
|
||||
public static final int END_OF_RECORD = 25;
|
||||
|
||||
public static final int TACACS_USER_IDENTIFICATION = 26;
|
||||
|
||||
public static final int OUTPUT_MARKING = 27;
|
||||
|
||||
public static final int TERMINAL_LOCATION_NUMBER = 28;
|
||||
|
||||
public static final int REGIME_3270 = 29;
|
||||
|
||||
public static final int X3_PAD = 30;
|
||||
|
||||
public static final int WINDOW_SIZE = 31;
|
||||
|
||||
public static final int TERMINAL_SPEED = 32;
|
||||
|
||||
public static final int REMOTE_FLOW_CONTROL = 33;
|
||||
|
||||
public static final int LINEMODE = 34;
|
||||
|
||||
public static final int X_DISPLAY_LOCATION = 35;
|
||||
|
||||
public static final int OLD_ENVIRONMENT_VARIABLES = 36;
|
||||
|
||||
public static final int AUTHENTICATION = 37;
|
||||
|
||||
public static final int ENCRYPTION = 38;
|
||||
|
||||
public static final int NEW_ENVIRONMENT_VARIABLES = 39;
|
||||
|
||||
public static final int EXTENDED_OPTIONS_LIST = 255;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final int __FIRST_OPTION = BINARY;
|
||||
private static final int __LAST_OPTION = EXTENDED_OPTIONS_LIST;
|
||||
|
||||
private static final String __optionString[] = {
|
||||
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS",
|
||||
"TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD",
|
||||
"NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT",
|
||||
"BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
|
||||
"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID",
|
||||
"OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED",
|
||||
"LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
|
||||
"ENCRYPT", "NEW-ENVIRON", "TN3270E", "XAUTH", "CHARSET", "RSP",
|
||||
"Com Port Control", "Suppress Local Echo", "Start TLS",
|
||||
"KERMIT", "SEND-URL", "FORWARD_X", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "TELOPT PRAGMA LOGON", "TELOPT SSPI LOGON",
|
||||
"TELOPT PRAGMA HEARTBEAT", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"Extended-Options-List"
|
||||
};
|
||||
|
||||
|
||||
/***
|
||||
* Returns the string representation of the telnet protocol option
|
||||
* corresponding to the given option code.
|
||||
*
|
||||
* @param code The option code of the telnet protocol option
|
||||
* @return The string representation of the telnet protocol option.
|
||||
***/
|
||||
public static final String getOption(int code)
|
||||
{
|
||||
if(__optionString[code].length() == 0)
|
||||
{
|
||||
return "UNASSIGNED";
|
||||
}
|
||||
else
|
||||
{
|
||||
return __optionString[code];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Determines if a given option code is valid. Returns true if valid,
|
||||
* false if not.
|
||||
*
|
||||
* @param code The option code to test.
|
||||
* @return True if the option code is valid, false if not.
|
||||
**/
|
||||
public static final boolean isValidOption(int code)
|
||||
{
|
||||
return (code <= __LAST_OPTION);
|
||||
}
|
||||
|
||||
// Cannot be instantiated
|
||||
private TelnetOption()
|
||||
{ }
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* The TelnetOptionHandler class is the base class to be used
|
||||
* for implementing handlers for telnet options.
|
||||
* <p>
|
||||
* TelnetOptionHandler implements basic option handling
|
||||
* functionality and defines abstract methods that must be
|
||||
* implemented to define subnegotiation behaviour.
|
||||
***/
|
||||
public abstract class TelnetOptionHandler
|
||||
{
|
||||
/***
|
||||
* Option code
|
||||
***/
|
||||
private int optionCode = -1;
|
||||
|
||||
/***
|
||||
* true if the option should be activated on the local side
|
||||
***/
|
||||
private boolean initialLocal = false;
|
||||
|
||||
/***
|
||||
* true if the option should be activated on the remote side
|
||||
***/
|
||||
private boolean initialRemote = false;
|
||||
|
||||
/***
|
||||
* true if the option should be accepted on the local side
|
||||
***/
|
||||
private boolean acceptLocal = false;
|
||||
|
||||
/***
|
||||
* true if the option should be accepted on the remote side
|
||||
***/
|
||||
private boolean acceptRemote = false;
|
||||
|
||||
/***
|
||||
* true if the option is active on the local side
|
||||
***/
|
||||
private boolean doFlag = false;
|
||||
|
||||
/***
|
||||
* true if the option is active on the remote side
|
||||
***/
|
||||
private boolean willFlag = false;
|
||||
|
||||
/***
|
||||
* Constructor for the TelnetOptionHandler. Allows defining desired
|
||||
* initial setting for local/remote activation of this option and
|
||||
* behaviour in case a local/remote activation request for this
|
||||
* option is received.
|
||||
* <p>
|
||||
* @param optcode - Option code.
|
||||
* @param initlocal - if set to true, a WILL is sent upon connection.
|
||||
* @param initremote - if set to true, a DO is sent upon connection.
|
||||
* @param acceptlocal - if set to true, any DO request is accepted.
|
||||
* @param acceptremote - if set to true, any WILL request is accepted.
|
||||
***/
|
||||
public TelnetOptionHandler(int optcode,
|
||||
boolean initlocal,
|
||||
boolean initremote,
|
||||
boolean acceptlocal,
|
||||
boolean acceptremote)
|
||||
{
|
||||
optionCode = optcode;
|
||||
initialLocal = initlocal;
|
||||
initialRemote = initremote;
|
||||
acceptLocal = acceptlocal;
|
||||
acceptRemote = acceptremote;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns the option code for this option.
|
||||
* <p>
|
||||
* @return Option code.
|
||||
***/
|
||||
public int getOptionCode()
|
||||
{
|
||||
return (optionCode);
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns a boolean indicating whether to accept a DO
|
||||
* request coming from the other end.
|
||||
* <p>
|
||||
* @return true if a DO request shall be accepted.
|
||||
***/
|
||||
public boolean getAcceptLocal()
|
||||
{
|
||||
return (acceptLocal);
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns a boolean indicating whether to accept a WILL
|
||||
* request coming from the other end.
|
||||
* <p>
|
||||
* @return true if a WILL request shall be accepted.
|
||||
***/
|
||||
public boolean getAcceptRemote()
|
||||
{
|
||||
return (acceptRemote);
|
||||
}
|
||||
|
||||
/***
|
||||
* Set behaviour of the option for DO requests coming from
|
||||
* the other end.
|
||||
* <p>
|
||||
* @param accept - if true, subsequent DO requests will be accepted.
|
||||
***/
|
||||
public void setAcceptLocal(boolean accept)
|
||||
{
|
||||
acceptLocal = accept;
|
||||
}
|
||||
|
||||
/***
|
||||
* Set behaviour of the option for WILL requests coming from
|
||||
* the other end.
|
||||
* <p>
|
||||
* @param accept - if true, subsequent WILL requests will be accepted.
|
||||
***/
|
||||
public void setAcceptRemote(boolean accept)
|
||||
{
|
||||
acceptRemote = accept;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns a boolean indicating whether to send a WILL request
|
||||
* to the other end upon connection.
|
||||
* <p>
|
||||
* @return true if a WILL request shall be sent upon connection.
|
||||
***/
|
||||
public boolean getInitLocal()
|
||||
{
|
||||
return (initialLocal);
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns a boolean indicating whether to send a DO request
|
||||
* to the other end upon connection.
|
||||
* <p>
|
||||
* @return true if a DO request shall be sent upon connection.
|
||||
***/
|
||||
public boolean getInitRemote()
|
||||
{
|
||||
return (initialRemote);
|
||||
}
|
||||
|
||||
/***
|
||||
* Tells this option whether to send a WILL request upon connection.
|
||||
* <p>
|
||||
* @param init - if true, a WILL request will be sent upon subsequent
|
||||
* connections.
|
||||
***/
|
||||
public void setInitLocal(boolean init)
|
||||
{
|
||||
initialLocal = init;
|
||||
}
|
||||
|
||||
/***
|
||||
* Tells this option whether to send a DO request upon connection.
|
||||
* <p>
|
||||
* @param init - if true, a DO request will be sent upon subsequent
|
||||
* connections.
|
||||
***/
|
||||
public void setInitRemote(boolean init)
|
||||
{
|
||||
initialRemote = init;
|
||||
}
|
||||
|
||||
/***
|
||||
* Method called upon reception of a subnegotiation for this option
|
||||
* coming from the other end.
|
||||
* <p>
|
||||
* This implementation returns null, and
|
||||
* must be overridden by the actual TelnetOptionHandler to specify
|
||||
* which response must be sent for the subnegotiation request.
|
||||
* <p>
|
||||
* @param suboptionData - the sequence received, without IAC SB & IAC SE
|
||||
* @param suboptionLength - the length of data in suboption_data
|
||||
* <p>
|
||||
* @return response to be sent to the subnegotiation sequence. TelnetClient
|
||||
* will add IAC SB & IAC SE. null means no response
|
||||
***/
|
||||
public int[] answerSubnegotiation(int suboptionData[], int suboptionLength) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/***
|
||||
* This method is invoked whenever this option is acknowledged active on
|
||||
* the local end (TelnetClient sent a WILL, remote side sent a DO).
|
||||
* The method is used to specify a subnegotiation sequence that will be
|
||||
* sent by TelnetClient when the option is activated.
|
||||
* <p>
|
||||
* This implementation returns null, and must be overriden by
|
||||
* the actual TelnetOptionHandler to specify
|
||||
* which response must be sent for the subnegotiation request.
|
||||
* @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
|
||||
* will add IAC SB & IAC SE. null means no subnegotiation.
|
||||
***/
|
||||
public int[] startSubnegotiationLocal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/***
|
||||
* This method is invoked whenever this option is acknowledged active on
|
||||
* the remote end (TelnetClient sent a DO, remote side sent a WILL).
|
||||
* The method is used to specify a subnegotiation sequence that will be
|
||||
* sent by TelnetClient when the option is activated.
|
||||
* <p>
|
||||
* This implementation returns null, and must be overriden by
|
||||
* the actual TelnetOptionHandler to specify
|
||||
* which response must be sent for the subnegotiation request.
|
||||
* @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
|
||||
* will add IAC SB & IAC SE. null means no subnegotiation.
|
||||
***/
|
||||
public int[] startSubnegotiationRemote() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns a boolean indicating whether a WILL request sent to the other
|
||||
* side has been acknowledged.
|
||||
* <p>
|
||||
* @return true if a WILL sent to the other side has been acknowledged.
|
||||
***/
|
||||
boolean getWill()
|
||||
{
|
||||
return willFlag;
|
||||
}
|
||||
|
||||
/***
|
||||
* Tells this option whether a WILL request sent to the other
|
||||
* side has been acknowledged (invoked by TelnetClient).
|
||||
* <p>
|
||||
* @param state - if true, a WILL request has been acknowledged.
|
||||
***/
|
||||
void setWill(boolean state)
|
||||
{
|
||||
willFlag = state;
|
||||
}
|
||||
|
||||
/***
|
||||
* Returns a boolean indicating whether a DO request sent to the other
|
||||
* side has been acknowledged.
|
||||
* <p>
|
||||
* @return true if a DO sent to the other side has been acknowledged.
|
||||
***/
|
||||
boolean getDo()
|
||||
{
|
||||
return doFlag;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Tells this option whether a DO request sent to the other
|
||||
* side has been acknowledged (invoked by TelnetClient).
|
||||
* <p>
|
||||
* @param state - if true, a DO request has been acknowledged.
|
||||
***/
|
||||
void setDo(boolean state)
|
||||
{
|
||||
doFlag = state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Wraps an output stream.
|
||||
* <p>
|
||||
* In binary mode, the only conversion is to double IAC.
|
||||
* <p>
|
||||
* In ASCII mode, if convertCRtoCRLF is true (currently always true), any CR is converted to CRLF.
|
||||
* IACs are doubled.
|
||||
* Also a bare LF is converted to CRLF and a bare CR is converted to CR\0
|
||||
* <p>
|
||||
***/
|
||||
|
||||
|
||||
final class TelnetOutputStream extends OutputStream
|
||||
{
|
||||
private final TelnetClient __client;
|
||||
// TODO there does not appear to be any way to change this value - should it be a ctor parameter?
|
||||
private final boolean __convertCRtoCRLF = true;
|
||||
private boolean __lastWasCR = false;
|
||||
|
||||
TelnetOutputStream(TelnetClient client)
|
||||
{
|
||||
__client = client;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Writes a byte to the stream.
|
||||
* <p>
|
||||
* @param ch The byte to write.
|
||||
* @exception IOException If an error occurs while writing to the underlying
|
||||
* stream.
|
||||
***/
|
||||
@Override
|
||||
public void write(int ch) throws IOException
|
||||
{
|
||||
|
||||
synchronized (__client)
|
||||
{
|
||||
ch &= 0xff;
|
||||
|
||||
if (__client._requestedWont(TelnetOption.BINARY)) // i.e. ASCII
|
||||
{
|
||||
if (__lastWasCR)
|
||||
{
|
||||
if (__convertCRtoCRLF)
|
||||
{
|
||||
__client._sendByte('\n');
|
||||
if (ch == '\n') // i.e. was CRLF anyway
|
||||
{
|
||||
__lastWasCR = false;
|
||||
return ;
|
||||
}
|
||||
} // __convertCRtoCRLF
|
||||
else if (ch != '\n')
|
||||
{
|
||||
__client._sendByte('\0'); // RFC854 requires CR NUL for bare CR
|
||||
}
|
||||
}
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '\r':
|
||||
__client._sendByte('\r');
|
||||
__lastWasCR = true;
|
||||
break;
|
||||
case '\n':
|
||||
if (!__lastWasCR) { // convert LF to CRLF
|
||||
__client._sendByte('\r');
|
||||
}
|
||||
__client._sendByte(ch);
|
||||
__lastWasCR = false;
|
||||
break;
|
||||
case TelnetCommand.IAC:
|
||||
__client._sendByte(TelnetCommand.IAC);
|
||||
__client._sendByte(TelnetCommand.IAC);
|
||||
__lastWasCR = false;
|
||||
break;
|
||||
default:
|
||||
__client._sendByte(ch);
|
||||
__lastWasCR = false;
|
||||
break;
|
||||
}
|
||||
} // end ASCII
|
||||
else if (ch == TelnetCommand.IAC)
|
||||
{
|
||||
__client._sendByte(ch);
|
||||
__client._sendByte(TelnetCommand.IAC);
|
||||
} else {
|
||||
__client._sendByte(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Writes a byte array to the stream.
|
||||
* <p>
|
||||
* @param buffer The byte array to write.
|
||||
* @exception IOException If an error occurs while writing to the underlying
|
||||
* stream.
|
||||
***/
|
||||
@Override
|
||||
public void write(byte buffer[]) throws IOException
|
||||
{
|
||||
write(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Writes a number of bytes from a byte array to the stream starting from
|
||||
* a given offset.
|
||||
* <p>
|
||||
* @param buffer The byte array to write.
|
||||
* @param offset The offset into the array at which to start copying data.
|
||||
* @param length The number of bytes to write.
|
||||
* @exception IOException If an error occurs while writing to the underlying
|
||||
* stream.
|
||||
***/
|
||||
@Override
|
||||
public void write(byte buffer[], int offset, int length) throws IOException
|
||||
{
|
||||
synchronized (__client)
|
||||
{
|
||||
while (length-- > 0) {
|
||||
write(buffer[offset++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*** Flushes the stream. ***/
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
__client._flushOutputStream();
|
||||
}
|
||||
|
||||
/*** Closes the stream. ***/
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
__client._closeOutputStream();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* Implements the telnet terminal type option RFC 1091.
|
||||
***/
|
||||
public class TerminalTypeOptionHandler extends TelnetOptionHandler
|
||||
{
|
||||
/***
|
||||
* Terminal type
|
||||
***/
|
||||
private final String termType;
|
||||
|
||||
/***
|
||||
* Terminal type option
|
||||
***/
|
||||
protected static final int TERMINAL_TYPE = 24;
|
||||
|
||||
/***
|
||||
* Send (for subnegotiation)
|
||||
***/
|
||||
protected static final int TERMINAL_TYPE_SEND = 1;
|
||||
|
||||
/***
|
||||
* Is (for subnegotiation)
|
||||
***/
|
||||
protected static final int TERMINAL_TYPE_IS = 0;
|
||||
|
||||
/***
|
||||
* Constructor for the TerminalTypeOptionHandler. Allows defining desired
|
||||
* initial setting for local/remote activation of this option and
|
||||
* behaviour in case a local/remote activation request for this
|
||||
* option is received.
|
||||
* <p>
|
||||
* @param termtype - terminal type that will be negotiated.
|
||||
* @param initlocal - if set to true, a WILL is sent upon connection.
|
||||
* @param initremote - if set to true, a DO is sent upon connection.
|
||||
* @param acceptlocal - if set to true, any DO request is accepted.
|
||||
* @param acceptremote - if set to true, any WILL request is accepted.
|
||||
***/
|
||||
public TerminalTypeOptionHandler(String termtype,
|
||||
boolean initlocal,
|
||||
boolean initremote,
|
||||
boolean acceptlocal,
|
||||
boolean acceptremote)
|
||||
{
|
||||
super(TelnetOption.TERMINAL_TYPE, initlocal, initremote,
|
||||
acceptlocal, acceptremote);
|
||||
termType = termtype;
|
||||
}
|
||||
|
||||
/***
|
||||
* Constructor for the TerminalTypeOptionHandler. Initial and accept
|
||||
* behaviour flags are set to false
|
||||
* <p>
|
||||
* @param termtype - terminal type that will be negotiated.
|
||||
***/
|
||||
public TerminalTypeOptionHandler(String termtype)
|
||||
{
|
||||
super(TelnetOption.TERMINAL_TYPE, false, false, false, false);
|
||||
termType = termtype;
|
||||
}
|
||||
|
||||
/***
|
||||
* Implements the abstract method of TelnetOptionHandler.
|
||||
* <p>
|
||||
* @param suboptionData - the sequence received, without IAC SB & IAC SE
|
||||
* @param suboptionLength - the length of data in suboption_data
|
||||
* <p>
|
||||
* @return terminal type information
|
||||
***/
|
||||
@Override
|
||||
public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
|
||||
{
|
||||
if ((suboptionData != null) && (suboptionLength > 1)
|
||||
&& (termType != null))
|
||||
{
|
||||
if ((suboptionData[0] == TERMINAL_TYPE)
|
||||
&& (suboptionData[1] == TERMINAL_TYPE_SEND))
|
||||
{
|
||||
int response[] = new int[termType.length() + 2];
|
||||
|
||||
response[0] = TERMINAL_TYPE;
|
||||
response[1] = TERMINAL_TYPE_IS;
|
||||
|
||||
for (int ii = 0; ii < termType.length(); ii++)
|
||||
{
|
||||
response[ii + 2] = termType.charAt(ii);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.telnet;
|
||||
|
||||
/***
|
||||
* Implements the telnet window size option RFC 1073.
|
||||
* @version $Id: WindowSizeOptionHandler.java 1697293 2015-08-24 01:01:00Z sebb $
|
||||
* @since 2.0
|
||||
***/
|
||||
public class WindowSizeOptionHandler extends TelnetOptionHandler
|
||||
{
|
||||
/***
|
||||
* Horizontal Size
|
||||
***/
|
||||
private int m_nWidth = 80;
|
||||
|
||||
/***
|
||||
* Vertical Size
|
||||
***/
|
||||
private int m_nHeight = 24;
|
||||
|
||||
/***
|
||||
* Window size option
|
||||
***/
|
||||
protected static final int WINDOW_SIZE = 31;
|
||||
|
||||
/***
|
||||
* Constructor for the WindowSizeOptionHandler. Allows defining desired
|
||||
* initial setting for local/remote activation of this option and
|
||||
* behaviour in case a local/remote activation request for this
|
||||
* option is received.
|
||||
* <p>
|
||||
* @param nWidth - Window width.
|
||||
* @param nHeight - Window Height
|
||||
* @param initlocal - if set to true, a WILL is sent upon connection.
|
||||
* @param initremote - if set to true, a DO is sent upon connection.
|
||||
* @param acceptlocal - if set to true, any DO request is accepted.
|
||||
* @param acceptremote - if set to true, any WILL request is accepted.
|
||||
***/
|
||||
public WindowSizeOptionHandler(
|
||||
int nWidth,
|
||||
int nHeight,
|
||||
boolean initlocal,
|
||||
boolean initremote,
|
||||
boolean acceptlocal,
|
||||
boolean acceptremote
|
||||
) {
|
||||
super (
|
||||
TelnetOption.WINDOW_SIZE,
|
||||
initlocal,
|
||||
initremote,
|
||||
acceptlocal,
|
||||
acceptremote
|
||||
);
|
||||
|
||||
m_nWidth = nWidth;
|
||||
m_nHeight = nHeight;
|
||||
}
|
||||
|
||||
/***
|
||||
* Constructor for the WindowSizeOptionHandler. Initial and accept
|
||||
* behaviour flags are set to false
|
||||
* <p>
|
||||
* @param nWidth - Window width.
|
||||
* @param nHeight - Window Height
|
||||
***/
|
||||
public WindowSizeOptionHandler(
|
||||
int nWidth,
|
||||
int nHeight
|
||||
) {
|
||||
super (
|
||||
TelnetOption.WINDOW_SIZE,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
m_nWidth = nWidth;
|
||||
m_nHeight = nHeight;
|
||||
}
|
||||
|
||||
/***
|
||||
* Implements the abstract method of TelnetOptionHandler.
|
||||
* This will send the client Height and Width to the server.
|
||||
* <p>
|
||||
* @return array to send to remote system
|
||||
***/
|
||||
@Override
|
||||
public int[] startSubnegotiationLocal()
|
||||
{
|
||||
int nCompoundWindowSize = m_nWidth * 0x10000 + m_nHeight;
|
||||
int nResponseSize = 5;
|
||||
int nIndex;
|
||||
int nShift;
|
||||
int nTurnedOnBits;
|
||||
|
||||
if ((m_nWidth % 0x100) == 0xFF) {
|
||||
nResponseSize += 1;
|
||||
}
|
||||
|
||||
if ((m_nWidth / 0x100) == 0xFF) {
|
||||
nResponseSize += 1;
|
||||
}
|
||||
|
||||
if ((m_nHeight % 0x100) == 0xFF) {
|
||||
nResponseSize += 1;
|
||||
}
|
||||
|
||||
if ((m_nHeight / 0x100) == 0xFF) {
|
||||
nResponseSize += 1;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate response array
|
||||
//
|
||||
int response[] = new int[nResponseSize];
|
||||
|
||||
//
|
||||
// Build response array.
|
||||
// ---------------------
|
||||
// 1. put option name.
|
||||
// 2. loop through Window size and fill the values,
|
||||
// 3. duplicate 'ff' if needed.
|
||||
//
|
||||
|
||||
response[0] = WINDOW_SIZE; // 1 //
|
||||
|
||||
for ( // 2 //
|
||||
nIndex=1, nShift = 24;
|
||||
nIndex < nResponseSize;
|
||||
nIndex++, nShift -=8
|
||||
) {
|
||||
nTurnedOnBits = 0xFF;
|
||||
nTurnedOnBits <<= nShift;
|
||||
response[nIndex] = (nCompoundWindowSize & nTurnedOnBits) >>> nShift;
|
||||
|
||||
if (response[nIndex] == 0xff) { // 3 //
|
||||
nIndex++;
|
||||
response[nIndex] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.commons.net.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
public class ListenerList implements Serializable, Iterable<EventListener>
|
||||
{
|
||||
private static final long serialVersionUID = -1934227607974228213L;
|
||||
|
||||
private final CopyOnWriteArrayList<EventListener> __listeners;
|
||||
|
||||
public ListenerList()
|
||||
{
|
||||
__listeners = new CopyOnWriteArrayList<EventListener>();
|
||||
}
|
||||
|
||||
public void addListener(EventListener listener)
|
||||
{
|
||||
__listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(EventListener listener)
|
||||
{
|
||||
__listeners.remove(listener);
|
||||
}
|
||||
|
||||
public int getListenerCount()
|
||||
{
|
||||
return __listeners.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@link Iterator} for the {@link EventListener} instances.
|
||||
*
|
||||
* @return an {@link Iterator} for the {@link EventListener} instances
|
||||
* @since 2.0
|
||||
* TODO Check that this is a good defensive strategy
|
||||
*/
|
||||
@Override
|
||||
public Iterator<EventListener> iterator() {
|
||||
return __listeners.iterator();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user