📄 ftpcontrolsocket.java
字号:
// output stream
OutputStream os = controlSock.getOutputStream();
writer = new OutputStreamWriter(os, encoding);
}
/**
* Get the name of the remote host
*
* @return remote host name
*/
String getRemoteHostName() {
InetAddress addr = controlSock.getInetAddress();
return addr.getHostName();
}
/**
* Set strict checking of FTP return codes. If strict
* checking is on (the default) code must exactly match the expected
* code. If strict checking is off, only the first digit must match.
*
* @param strict true for strict checking, false for loose checking
*/
void setStrictReturnCodes(boolean strict) {
this.strictReturnCodes = strict;
}
/**
* Listen on all interfaces for active mode transfers (the default).
*
* @param listenOnAll true if listen on all interfaces, false to listen on the control interface
*/
void setListenOnAllInterfaces(boolean listenOnAll) {
this.listenOnAllInterfaces = listenOnAll;
}
/**
* Are we listening on all interfaces in active mode, which is the default?
*
* @return true if listening on all interfaces, false if listening just on the control interface
*/
boolean getListenOnAllInterfaces() {
return listenOnAllInterfaces;
}
/**
* Set the TCP timeout on the underlying control socket.
*
* If a timeout is set, then any operation which
* takes longer than the timeout value will be
* killed with a java.io.InterruptedException.
*
* @param millis The length of the timeout, in milliseconds
*/
void setTimeout(int millis)
throws IOException {
if (controlSock == null)
throw new IllegalStateException(
"Failed to set timeout - no control socket");
controlSock.setSoTimeout(millis);
}
/**
* Set a listener that handles all FTP messages
*
* @param listener message listener
*/
void setMessageListener(FTPMessageListener listener) {
this.messageListener = listener;
}
/**
* Close the socket
*
* @throws IOException
*/
public void close() throws IOException {
controlSock.close();
}
/**
* Quit this FTP session and clean up.
*/
public void logout()
throws IOException {
IOException ex = null;
try {
writer.close();
}
catch (IOException e) {
ex = e;
}
try {
reader.close();
}
catch (IOException e) {
ex = e;
}
try {
controlSock.close();
}
catch (IOException e) {
ex = e;
}
if (ex != null)
throw ex;
}
/**
* Request a data socket be created on the
* server, connect to it and return our
* connected socket.
*
* @param active if true, create in active mode, else
* in passive mode
* @return connected data socket
*/
FTPDataSocket createDataSocket(FTPConnectMode connectMode)
throws IOException, FTPException {
if (connectMode == FTPConnectMode.ACTIVE) {
return createDataSocketActive();
}
else { // PASV
return createDataSocketPASV();
}
}
/**
* Request a data socket be created on the Client
* client on any free port, do not connect it to yet.
*
* @return not connected data socket
*/
FTPDataSocket createDataSocketActive()
throws IOException, FTPException {
try {
int count = 0;
int maxCount = MAX_ACTIVE_RETRY;
if (lowPort >= 0 && highPort >= 0) {
int range = highPort-lowPort+1;
if (range < MAX_ACTIVE_RETRY)
maxCount = range;
}
while (count < maxCount)
{
count++;
try
{
// use the next port in list (or 0 by default, indicating any port number)
FTPDataSocket socket = newActiveDataSocket(nextPort);
short port = (short)socket.getLocalPort();
sendPORTCommand(port);
return socket;
}
catch (SocketException ex)
{
// check ok to retry
if (count < maxCount)
{
log.warn("Detected socket in use - retrying and selecting new port");
setNextAvailablePortFromRange();
}
}
}
throw new FTPException("Exhausted active port retry count - giving up");
}
finally {
setNextAvailablePortFromRange();
}
}
private void setNextAvailablePortFromRange()
{
// keep using 0 if using OS ports
if (lowPort < 0 && highPort < 0)
return;
// need to set next port to random port in range if it is 0 and we
// get to here - means the active port ranges have been changed
if (nextPort == 0) {
nextPort = lowPort + new Random().nextInt(highPort-lowPort);
}
else
nextPort++;
// if exceeded the high port drop to low
if (nextPort > highPort)
nextPort = lowPort;
log.debug("Next active port will be: " + nextPort);
}
/**
* Send the PORT command to the server
*
* @param socket data socket
* @throws IOException
* @throws FTPException
*/
void sendPORTCommand(short port)
throws IOException, FTPException {
// get the local address to which the control socket is bound.
InetAddress localhost = controlSock.getLocalAddress();
// send the PORT command to the server
setDataPort(localhost, port);
}
/**
* Helper method to convert a byte into an unsigned short value
*
* @param value value to convert
* @return the byte value as an unsigned short
*/
private short toUnsignedShort(byte value) {
return ( value < 0 )
? (short) (value + 256)
: (short) value;
}
/**
* Convert a short into a byte array
*
* @param value value to convert
* @return a byte array
*/
protected byte[] toByteArray (short value) {
byte[] bytes = new byte[2];
bytes[0] = (byte) (value >> 8); // bits 1- 8
bytes[1] = (byte) (value & 0x00FF); // bits 9-16
return bytes;
}
/**
* We can force PORT to send a fixed IP address, which can be useful with certain
* NAT configurations. Must be connected to the remote host to call this method.
*
* @param forcedActiveIP IP address to force
*/
void setActivePortIPAddress(String forcedActiveIP) {
this.forcedActiveIP = forcedActiveIP;
}
/**
* Set the port number range for active mode
*
* @param lowest lowest port number in range
* @param highest highest port number in range
*/
public void setActivePortRange(int lowest, int highest) {
this.lowPort = lowest;
this.highPort = highest;
this.nextPort = lowPort;
}
/**
* Gets the IP address bytes from an IPV4 address that is
* a string
*
* @param IPAddress ip address such as 192.168.10.0
* @return
* @throws FTPException
*/
private byte[] getIPAddressBytes(String IPAddress)
throws FTPException {
byte ipbytes[] = new byte[4];
int len = IPAddress.length();
int partCount = 0;
StringBuffer buf = new StringBuffer();
// loop thru and examine each char
for (int i = 0; i < len && partCount <= 4; i++) {
char ch = IPAddress.charAt(i);
if (Character.isDigit(ch))
buf.append(ch);
else if (ch != '.') {
throw new FTPException("Incorrectly formatted IP address: " + IPAddress);
}
// get the part
if (ch == '.' || i+1 == len) { // at end or at separator
try {
ipbytes[partCount++] = (byte)Integer.parseInt(buf.toString());
buf.setLength(0);
}
catch (NumberFormatException ex) {
throw new FTPException("Incorrectly formatted IP address: " + IPAddress);
}
}
}
return ipbytes;
}
/**
* Sets the data port on the server, that is, sends a PORT
* command.
*
* @param host the local host the server will connect to
* @param portNo the port number to connect to
*/
protected void setDataPort(InetAddress host, short portNo)
throws IOException, FTPException {
byte[] hostBytes = host.getAddress();
byte[] portBytes = toByteArray(portNo);
if (forcedActiveIP != null) {
log.info("Forcing use of fixed IP for PORT command");
hostBytes = getIPAddressBytes(forcedActiveIP);
}
// assemble the PORT command
String cmd = new StringBuffer ("PORT ")
.append (toUnsignedShort (hostBytes[0])) .append (",")
.append (toUnsignedShort (hostBytes[1])) .append (",")
.append (toUnsignedShort (hostBytes[2])) .append (",")
.append (toUnsignedShort (hostBytes[3])) .append (",")
.append (toUnsignedShort (portBytes[0])) .append (",")
.append (toUnsignedShort (portBytes[1])) .toString ();
// send command and check reply
// CoreFTP returns 250 incorrectly
FTPReply reply = sendCommand(cmd);
String[] validCodes = {"200", "250"};
validateReply(reply, validCodes);
}
/**
* Request a data socket be created on the
* server, connect to it and return our
* connected socket.
*
* @return connected data socket
*/
protected FTPDataSocket createDataSocketPASV()
throws IOException, FTPException {
// PASSIVE command - tells the server to listen for
// a connection attempt rather than initiating it
FTPReply replyObj = sendCommand("PASV");
validateReply(replyObj, "227");
String reply = replyObj.getReplyText();
int[] parts = getPASVParts(reply);
// assemble the IP address
// we try connecting, so we don't bother checking digits etc
String ipAddress = parts[0] + "."+ parts[1]+ "." +
parts[2] + "." + parts[3];
// assemble the port number
int port = (parts[4] << 8) + parts[5];
String hostIP = ipAddress;
if (autoPassiveIPSubstitution) {
hostIP = remoteAddr.getHostAddress();
StringBuffer msg = new StringBuffer("Substituting server supplied IP (");
msg.append(ipAddress).append(") with remote host IP (").append(hostIP).append(")");
log.debug(msg.toString());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -