PortCommandHandler.java revision 4ca3386623ce60063f27955ad1b2b1b6cbba8b09
1/* 2 * Copyright 2007 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package org.mockftpserver.stub.command; 17 18import java.net.InetAddress; 19import java.net.UnknownHostException; 20import java.util.Arrays; 21 22import org.apache.log4j.Logger; 23import org.mockftpserver.core.command.Command; 24import org.mockftpserver.core.command.CommandHandler; 25import org.mockftpserver.core.command.InvocationRecord; 26import org.mockftpserver.core.command.ReplyCodes; 27import org.mockftpserver.core.session.Session; 28import org.mockftpserver.core.util.Assert; 29import org.mockftpserver.core.util.AssertFailedException; 30 31/** 32 * CommandHandler for the PORT command. Send back a reply code of 200. 33 * <p> 34 * Each invocation record stored by this CommandHandler includes the following data element key/values: 35 * <ul> 36 * <li>{@link #HOST_KEY} ("host") - the client data host (InetAddress) submitted on the invocation (from parameters 1-4) 37 * <li>{@link #PORT_KEY} ("port") - the port number (Integer) submitted on the invocation (from parameter 5-6) 38 * </ul> 39 * 40 * @version $Revision$ - $Date$ 41 * 42 * @author Chris Mair 43 */ 44public final class PortCommandHandler extends AbstractStubCommandHandler implements CommandHandler { 45 46 public static final String HOST_KEY = "host"; 47 public static final String PORT_KEY = "port"; 48 private static final Logger LOG = Logger.getLogger(PortCommandHandler.class); 49 50 /** 51 * Constructor. Initialize the replyCode. 52 */ 53 public PortCommandHandler() { 54 setReplyCode(ReplyCodes.PORT_OK); 55 } 56 57 /** 58 * @throws UnknownHostException 59 * @throws UnknownHostException 60 * @see org.mockftpserver.core.command.CommandHandler#handleCommand(Command, Session, InvocationRecord) 61 */ 62 public void handleCommand(Command command, Session session, InvocationRecord invocationRecord) throws UnknownHostException { 63 InetAddress host = parseHost(command.getParameters()); 64 int port = parsePortNumber(command.getParameters()); 65 LOG.debug("host=" + host + " port=" + port); 66 session.setClientDataHost(host); 67 session.setClientDataPort(port); 68 invocationRecord.set(HOST_KEY, host); 69 invocationRecord.set(PORT_KEY, new Integer(port)); 70 sendReply(session); 71 } 72 73 /** 74 * Parse a 32-bit IP address from the String[] of FTP command parameters. 75 * 76 * @param parameters - the String[] of command parameters. It is the concatenation 77 * of a 32-bit internet host address and a 16-bit TCP port address. This address 78 * information is broken into 8-bit fields and the value of each field is encoded 79 * as a separate parameter whose value is a decimal number (in character string 80 * representation). Thus, the six parameters for the port command would be: 81 * h1,h2,h3,h4,p1,p2 82 * where h1 is the high order 8 bits of the internet host address, and p1 is the 83 * high order 8 bits of the port number. 84 * 85 * @return the InetAddres representing the host parsed from the parameters 86 * 87 * @throws AssertFailedException - if parameters is null or contains an insufficient number of elements 88 * @throws NumberFormatException - if one of the parameters does not contain a parsable integer 89 * @throws UnknownHostException 90 */ 91 static InetAddress parseHost(String[] parameters) throws UnknownHostException { 92 verifySufficientParameters(parameters); 93 94 byte host1 = Byte.parseByte(parameters[0]); 95 byte host2 = Byte.parseByte(parameters[1]); 96 byte host3 = Byte.parseByte(parameters[2]); 97 byte host4 = Byte.parseByte(parameters[3]); 98 99 byte[] address = { host1, host2, host3, host4 }; 100 InetAddress inetAddress = InetAddress.getByAddress(address); 101 102 return inetAddress; 103 } 104 105 /** 106 * Parse a 16-bit port number from the String[] of FTP command parameters. 107 * 108 * @param parameters - the String[] of command parameters. It is the concatenation 109 * of a 32-bit internet host address and a 16-bit TCP port address. This address 110 * information is broken into 8-bit fields and the value of each field is encoded 111 * as a separate parameter whose value is a decimal number (in character string 112 * representation). Thus, the six parameters for the port command would be: 113 * h1,h2,h3,h4,p1,p2 114 * where h1 is the high order 8 bits of the internet host address, and p1 is the 115 * high order 8 bits of the port number. 116 * 117 * @return the port number parsed from the parameters 118 * 119 * @throws AssertFailedException - if parameters is null or contains an insufficient number of elements 120 * @throws NumberFormatException - if one of the parameters does not contain a parsable integer 121 */ 122 static int parsePortNumber(String[] parameters) { 123 verifySufficientParameters(parameters); 124 125 int port1 = Integer.parseInt(parameters[4]); 126 int port2 = Integer.parseInt(parameters[5]); 127 int port = (port1 << 8) + port2; 128 129 return port; 130 } 131 132 /** 133 * Verify that the parameters is not null and contains the required number of elements 134 * @param parameters - the String[] of command parameters 135 * @throws AssertFailedException - if parameters is null or contains an insufficient number of elements 136 */ 137 private static void verifySufficientParameters(String[] parameters) { 138 Assert.notNull(parameters, "parameters"); 139 Assert.isTrue(parameters.length >= 6, "The PORT command must contain least be 6 parameters: " + Arrays.asList(parameters)); 140 } 141 142} 143