177391c2a01ce1fed085906743cc240a4d58edd92chrismair/* 277391c2a01ce1fed085906743cc240a4d58edd92chrismair * Copyright 2007 the original author or authors. 377391c2a01ce1fed085906743cc240a4d58edd92chrismair * 477391c2a01ce1fed085906743cc240a4d58edd92chrismair * Licensed under the Apache License, Version 2.0 (the "License"); 577391c2a01ce1fed085906743cc240a4d58edd92chrismair * you may not use this file except in compliance with the License. 677391c2a01ce1fed085906743cc240a4d58edd92chrismair * You may obtain a copy of the License at 777391c2a01ce1fed085906743cc240a4d58edd92chrismair * 877391c2a01ce1fed085906743cc240a4d58edd92chrismair * http://www.apache.org/licenses/LICENSE-2.0 977391c2a01ce1fed085906743cc240a4d58edd92chrismair * 1077391c2a01ce1fed085906743cc240a4d58edd92chrismair * Unless required by applicable law or agreed to in writing, software 1177391c2a01ce1fed085906743cc240a4d58edd92chrismair * distributed under the License is distributed on an "AS IS" BASIS, 1277391c2a01ce1fed085906743cc240a4d58edd92chrismair * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1377391c2a01ce1fed085906743cc240a4d58edd92chrismair * See the License for the specific language governing permissions and 1477391c2a01ce1fed085906743cc240a4d58edd92chrismair * limitations under the License. 1577391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 1677391c2a01ce1fed085906743cc240a4d58edd92chrismairpackage org.mockftpserver.stub.command; 1777391c2a01ce1fed085906743cc240a4d58edd92chrismair 1877391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.net.InetAddress; 1977391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.net.UnknownHostException; 2077391c2a01ce1fed085906743cc240a4d58edd92chrismairimport java.util.Arrays; 2177391c2a01ce1fed085906743cc240a4d58edd92chrismair 2277391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.apache.log4j.Logger; 2377391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.command.Command; 2477391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.command.CommandHandler; 2577391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.command.InvocationRecord; 2677391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.command.ReplyCodes; 2777391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.session.Session; 2877391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.util.Assert; 2977391c2a01ce1fed085906743cc240a4d58edd92chrismairimport org.mockftpserver.core.util.AssertFailedException; 3077391c2a01ce1fed085906743cc240a4d58edd92chrismair 3177391c2a01ce1fed085906743cc240a4d58edd92chrismair/** 3277391c2a01ce1fed085906743cc240a4d58edd92chrismair * CommandHandler for the PORT command. Send back a reply code of 200. 3377391c2a01ce1fed085906743cc240a4d58edd92chrismair * <p> 3477391c2a01ce1fed085906743cc240a4d58edd92chrismair * Each invocation record stored by this CommandHandler includes the following data element key/values: 3577391c2a01ce1fed085906743cc240a4d58edd92chrismair * <ul> 3677391c2a01ce1fed085906743cc240a4d58edd92chrismair * <li>{@link #HOST_KEY} ("host") - the client data host (InetAddress) submitted on the invocation (from parameters 1-4) 3777391c2a01ce1fed085906743cc240a4d58edd92chrismair * <li>{@link #PORT_KEY} ("port") - the port number (Integer) submitted on the invocation (from parameter 5-6) 3877391c2a01ce1fed085906743cc240a4d58edd92chrismair * </ul> 3977391c2a01ce1fed085906743cc240a4d58edd92chrismair * 4077391c2a01ce1fed085906743cc240a4d58edd92chrismair * @version $Revision$ - $Date$ 4177391c2a01ce1fed085906743cc240a4d58edd92chrismair * 4277391c2a01ce1fed085906743cc240a4d58edd92chrismair * @author Chris Mair 4377391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 4477391c2a01ce1fed085906743cc240a4d58edd92chrismairpublic final class PortCommandHandler extends AbstractStubCommandHandler implements CommandHandler { 4577391c2a01ce1fed085906743cc240a4d58edd92chrismair 4677391c2a01ce1fed085906743cc240a4d58edd92chrismair public static final String HOST_KEY = "host"; 4777391c2a01ce1fed085906743cc240a4d58edd92chrismair public static final String PORT_KEY = "port"; 4877391c2a01ce1fed085906743cc240a4d58edd92chrismair private static final Logger LOG = Logger.getLogger(PortCommandHandler.class); 4977391c2a01ce1fed085906743cc240a4d58edd92chrismair 5077391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 5177391c2a01ce1fed085906743cc240a4d58edd92chrismair * Constructor. Initialize the replyCode. 5277391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 5377391c2a01ce1fed085906743cc240a4d58edd92chrismair public PortCommandHandler() { 5477391c2a01ce1fed085906743cc240a4d58edd92chrismair setReplyCode(ReplyCodes.PORT_OK); 5577391c2a01ce1fed085906743cc240a4d58edd92chrismair } 5677391c2a01ce1fed085906743cc240a4d58edd92chrismair 5777391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 5877391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws UnknownHostException 5977391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws UnknownHostException 6077391c2a01ce1fed085906743cc240a4d58edd92chrismair * @see org.mockftpserver.core.command.CommandHandler#handleCommand(Command, Session, InvocationRecord) 6177391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 6277391c2a01ce1fed085906743cc240a4d58edd92chrismair public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws UnknownHostException { 6377391c2a01ce1fed085906743cc240a4d58edd92chrismair InetAddress host = parseHost(command.getParameters()); 6477391c2a01ce1fed085906743cc240a4d58edd92chrismair int port = parsePortNumber(command.getParameters()); 6577391c2a01ce1fed085906743cc240a4d58edd92chrismair LOG.debug("host=" + host + " port=" + port); 6677391c2a01ce1fed085906743cc240a4d58edd92chrismair session.setClientDataHost(host); 6777391c2a01ce1fed085906743cc240a4d58edd92chrismair session.setClientDataPort(port); 6877391c2a01ce1fed085906743cc240a4d58edd92chrismair invocationRecord.set(HOST_KEY, host); 6977391c2a01ce1fed085906743cc240a4d58edd92chrismair invocationRecord.set(PORT_KEY, new Integer(port)); 7077391c2a01ce1fed085906743cc240a4d58edd92chrismair sendReply(session); 7177391c2a01ce1fed085906743cc240a4d58edd92chrismair } 7277391c2a01ce1fed085906743cc240a4d58edd92chrismair 7377391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 7477391c2a01ce1fed085906743cc240a4d58edd92chrismair * Parse a 32-bit IP address from the String[] of FTP command parameters. 7577391c2a01ce1fed085906743cc240a4d58edd92chrismair * 7677391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param parameters - the String[] of command parameters. It is the concatenation 7777391c2a01ce1fed085906743cc240a4d58edd92chrismair * of a 32-bit internet host address and a 16-bit TCP port address. This address 7877391c2a01ce1fed085906743cc240a4d58edd92chrismair * information is broken into 8-bit fields and the value of each field is encoded 7977391c2a01ce1fed085906743cc240a4d58edd92chrismair * as a separate parameter whose value is a decimal number (in character string 8077391c2a01ce1fed085906743cc240a4d58edd92chrismair * representation). Thus, the six parameters for the port command would be: 8177391c2a01ce1fed085906743cc240a4d58edd92chrismair * h1,h2,h3,h4,p1,p2 8277391c2a01ce1fed085906743cc240a4d58edd92chrismair * where h1 is the high order 8 bits of the internet host address, and p1 is the 8377391c2a01ce1fed085906743cc240a4d58edd92chrismair * high order 8 bits of the port number. 8477391c2a01ce1fed085906743cc240a4d58edd92chrismair * 8577391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the InetAddres representing the host parsed from the parameters 8677391c2a01ce1fed085906743cc240a4d58edd92chrismair * 8777391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws AssertFailedException - if parameters is null or contains an insufficient number of elements 8877391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws NumberFormatException - if one of the parameters does not contain a parsable integer 8977391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws UnknownHostException 9077391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 9177391c2a01ce1fed085906743cc240a4d58edd92chrismair static InetAddress parseHost(String[] parameters) throws UnknownHostException { 9277391c2a01ce1fed085906743cc240a4d58edd92chrismair verifySufficientParameters(parameters); 9377391c2a01ce1fed085906743cc240a4d58edd92chrismair 9477391c2a01ce1fed085906743cc240a4d58edd92chrismair byte host1 = Byte.parseByte(parameters[0]); 9577391c2a01ce1fed085906743cc240a4d58edd92chrismair byte host2 = Byte.parseByte(parameters[1]); 9677391c2a01ce1fed085906743cc240a4d58edd92chrismair byte host3 = Byte.parseByte(parameters[2]); 9777391c2a01ce1fed085906743cc240a4d58edd92chrismair byte host4 = Byte.parseByte(parameters[3]); 9877391c2a01ce1fed085906743cc240a4d58edd92chrismair 9977391c2a01ce1fed085906743cc240a4d58edd92chrismair byte[] address = { host1, host2, host3, host4 }; 10077391c2a01ce1fed085906743cc240a4d58edd92chrismair InetAddress inetAddress = InetAddress.getByAddress(address); 10177391c2a01ce1fed085906743cc240a4d58edd92chrismair 10277391c2a01ce1fed085906743cc240a4d58edd92chrismair return inetAddress; 10377391c2a01ce1fed085906743cc240a4d58edd92chrismair } 10477391c2a01ce1fed085906743cc240a4d58edd92chrismair 10577391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 10677391c2a01ce1fed085906743cc240a4d58edd92chrismair * Parse a 16-bit port number from the String[] of FTP command parameters. 10777391c2a01ce1fed085906743cc240a4d58edd92chrismair * 10877391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param parameters - the String[] of command parameters. It is the concatenation 10977391c2a01ce1fed085906743cc240a4d58edd92chrismair * of a 32-bit internet host address and a 16-bit TCP port address. This address 11077391c2a01ce1fed085906743cc240a4d58edd92chrismair * information is broken into 8-bit fields and the value of each field is encoded 11177391c2a01ce1fed085906743cc240a4d58edd92chrismair * as a separate parameter whose value is a decimal number (in character string 11277391c2a01ce1fed085906743cc240a4d58edd92chrismair * representation). Thus, the six parameters for the port command would be: 11377391c2a01ce1fed085906743cc240a4d58edd92chrismair * h1,h2,h3,h4,p1,p2 11477391c2a01ce1fed085906743cc240a4d58edd92chrismair * where h1 is the high order 8 bits of the internet host address, and p1 is the 11577391c2a01ce1fed085906743cc240a4d58edd92chrismair * high order 8 bits of the port number. 11677391c2a01ce1fed085906743cc240a4d58edd92chrismair * 11777391c2a01ce1fed085906743cc240a4d58edd92chrismair * @return the port number parsed from the parameters 11877391c2a01ce1fed085906743cc240a4d58edd92chrismair * 11977391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws AssertFailedException - if parameters is null or contains an insufficient number of elements 12077391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws NumberFormatException - if one of the parameters does not contain a parsable integer 12177391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 12277391c2a01ce1fed085906743cc240a4d58edd92chrismair static int parsePortNumber(String[] parameters) { 12377391c2a01ce1fed085906743cc240a4d58edd92chrismair verifySufficientParameters(parameters); 12477391c2a01ce1fed085906743cc240a4d58edd92chrismair 12577391c2a01ce1fed085906743cc240a4d58edd92chrismair int port1 = Integer.parseInt(parameters[4]); 12677391c2a01ce1fed085906743cc240a4d58edd92chrismair int port2 = Integer.parseInt(parameters[5]); 12777391c2a01ce1fed085906743cc240a4d58edd92chrismair int port = (port1 << 8) + port2; 12877391c2a01ce1fed085906743cc240a4d58edd92chrismair 12977391c2a01ce1fed085906743cc240a4d58edd92chrismair return port; 13077391c2a01ce1fed085906743cc240a4d58edd92chrismair } 13177391c2a01ce1fed085906743cc240a4d58edd92chrismair 13277391c2a01ce1fed085906743cc240a4d58edd92chrismair /** 13377391c2a01ce1fed085906743cc240a4d58edd92chrismair * Verify that the parameters is not null and contains the required number of elements 13477391c2a01ce1fed085906743cc240a4d58edd92chrismair * @param parameters - the String[] of command parameters 13577391c2a01ce1fed085906743cc240a4d58edd92chrismair * @throws AssertFailedException - if parameters is null or contains an insufficient number of elements 13677391c2a01ce1fed085906743cc240a4d58edd92chrismair */ 13777391c2a01ce1fed085906743cc240a4d58edd92chrismair private static void verifySufficientParameters(String[] parameters) { 13877391c2a01ce1fed085906743cc240a4d58edd92chrismair Assert.notNull(parameters, "parameters"); 13977391c2a01ce1fed085906743cc240a4d58edd92chrismair Assert.isTrue(parameters.length >= 6, "The PORT command must contain least be 6 parameters: " + Arrays.asList(parameters)); 14077391c2a01ce1fed085906743cc240a4d58edd92chrismair } 14177391c2a01ce1fed085906743cc240a4d58edd92chrismair 14277391c2a01ce1fed085906743cc240a4d58edd92chrismair} 143