001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.net.tftp; 019 020import java.net.DatagramPacket; 021import java.net.InetAddress; 022 023/** 024 * TFTPPacket is an abstract class encapsulating the functionality common to the 5 types of TFTP packets. It also provides a static factory method that will 025 * create the correct TFTP packet instance from a datagram. This relieves the programmer from having to figure out what kind of TFTP packet is contained in a 026 * datagram and create it himself. 027 * <p> 028 * Details regarding the TFTP protocol and the format of TFTP packets can be found in RFC 783. But the point of these classes is to keep you from having to 029 * worry about the internals. Additionally, only very few people should have to care about any of the TFTPPacket classes or derived classes. Almost all users 030 * should only be concerned with the {@link org.apache.commons.net.tftp.TFTPClient} class {@link org.apache.commons.net.tftp.TFTPClient#receiveFile 031 * receiveFile()} and {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} methods. 032 * </p> 033 * 034 * @see TFTPPacketException 035 * @see TFTP 036 */ 037 038public abstract class TFTPPacket { 039 040 /** 041 * The minimum size of a packet. This is 4 bytes. It is enough to store the opcode and blocknumber or other required data depending on the packet type. 042 */ 043 static final int MIN_PACKET_SIZE = 4; 044 045 /** 046 * This is the actual TFTP spec identifier and is equal to 1. Identifier returned by {@link #getType getType()} indicating a read request packet. 047 */ 048 public static final int READ_REQUEST = 1; 049 050 /** 051 * This is the actual TFTP spec identifier and is equal to 2. Identifier returned by {@link #getType getType()} indicating a write request packet. 052 */ 053 public static final int WRITE_REQUEST = 2; 054 055 /** 056 * This is the actual TFTP spec identifier and is equal to 3. Identifier returned by {@link #getType getType()} indicating a data packet. 057 */ 058 public static final int DATA = 3; 059 060 /** 061 * This is the actual TFTP spec identifier and is equal to 4. Identifier returned by {@link #getType getType()} indicating an acknowledgement packet. 062 */ 063 public static final int ACKNOWLEDGEMENT = 4; 064 065 /** 066 * This is the actual TFTP spec identifier and is equal to 5. Identifier returned by {@link #getType getType()} indicating an error packet. 067 */ 068 public static final int ERROR = 5; 069 070 /** 071 * TFTP spec identifier {@value}. Identifier returned by {@link #getType getType()} indicating an options acknowledgement packet. 072 * 073 * @since 3.12.0 074 */ 075 public static final int OACK = 6; 076 077 /** 078 * The TFTP data packet maximum segment size in bytes. This is 512 and is useful for those familiar with the TFTP protocol who want to use the 079 * {@link org.apache.commons.net.tftp.TFTP} class methods to implement their own TFTP servers or clients. 080 */ 081 public static final int SEGMENT_SIZE = 512; 082 083 /** 084 * When you receive a datagram that you expect to be a TFTP packet, you use this factory method to create the proper TFTPPacket object encapsulating the 085 * data contained in that datagram. This method is the only way you can instantiate a TFTPPacket derived class from a datagram. 086 * 087 * @param datagram The datagram containing a TFTP packet. 088 * @return The TFTPPacket object corresponding to the datagram. 089 * @throws TFTPPacketException If the datagram does not contain a valid TFTP packet. 090 */ 091 public static final TFTPPacket newTFTPPacket(final DatagramPacket datagram) throws TFTPPacketException { 092 if (datagram.getLength() < MIN_PACKET_SIZE) { 093 throw new TFTPPacketException("Bad packet. Datagram data length is too short."); 094 } 095 final byte[] data = datagram.getData(); 096 final TFTPPacket packet; 097 switch (data[1]) { 098 case READ_REQUEST: 099 packet = new TFTPReadRequestPacket(datagram); 100 break; 101 case WRITE_REQUEST: 102 packet = new TFTPWriteRequestPacket(datagram); 103 break; 104 case DATA: 105 packet = new TFTPDataPacket(datagram); 106 break; 107 case ACKNOWLEDGEMENT: 108 packet = new TFTPAckPacket(datagram); 109 break; 110 case ERROR: 111 packet = new TFTPErrorPacket(datagram); 112 break; 113 default: 114 throw new TFTPPacketException("Bad packet. Invalid TFTP operator code."); 115 } 116 return packet; 117 } 118 119 /** The type of packet. */ 120 int type; 121 122 /** The port the packet came from or is going to. */ 123 int port; 124 125 /** The host the packet is going to be sent or where it came from. */ 126 InetAddress address; 127 128 /** 129 * This constructor is not visible outside the package. It is used by subclasses within the package to initialize base data. 130 * 131 * @param type The type of the packet. 132 * @param address The host the packet came from or is going to be sent. 133 * @param port The port the packet came from or is going to be sent. 134 **/ 135 TFTPPacket(final int type, final InetAddress address, final int port) { 136 this.type = type; 137 this.address = address; 138 this.port = port; 139 } 140 141 /** 142 * Gets the address of the host where the packet is going to be sent or where it came from. 143 * 144 * @return The type of the packet. 145 */ 146 public final InetAddress getAddress() { 147 return address; 148 } 149 150 /** 151 * Gets the port where the packet is going to be sent or where it came from. 152 * 153 * @return The port where the packet came from or where it is going. 154 */ 155 public final int getPort() { 156 return port; 157 } 158 159 /** 160 * Gets the type of the packet. 161 * 162 * @return The type of the packet. 163 */ 164 public final int getType() { 165 return type; 166 } 167 168 /** 169 * Creates a UDP datagram containing all the TFTP packet data in the proper format. This is an abstract method, exposed to the programmer in case he wants 170 * to implement his own TFTP client instead of using the {@link org.apache.commons.net.tftp.TFTPClient} class. Under normal circumstances, you should not 171 * have a need to call this method. 172 * 173 * @return A UDP datagram containing the TFTP packet. 174 */ 175 public abstract DatagramPacket newDatagram(); 176 177 /** 178 * This is an abstract method only available within the package for implementing efficient datagram transport by eliminating buffering. It takes a datagram 179 * as an argument, and a byte buffer in which to store the raw datagram data. Inside the method, the data should be set as the datagram's data and the 180 * datagram returned. 181 * 182 * @param datagram The datagram to create. 183 * @param data The buffer to store the packet and to use in the datagram. 184 * @return The datagram argument. 185 */ 186 abstract DatagramPacket newDatagram(DatagramPacket datagram, byte[] data); 187 188 /** 189 * Sets the host address where the packet is going to be sent. 190 * 191 * @param address the address to set 192 */ 193 public final void setAddress(final InetAddress address) { 194 this.address = address; 195 } 196 197 /** 198 * Sets the port where the packet is going to be sent. 199 * 200 * @param port the port to set 201 */ 202 public final void setPort(final int port) { 203 this.port = port; 204 } 205 206 /** 207 * For debugging 208 * 209 * @since 3.6 210 */ 211 @Override 212 public String toString() { 213 return address + " " + port + " " + type; 214 } 215}