001 /* 002 * Copyright 2001-2005 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.net.tftp; 017 018 import java.net.DatagramPacket; 019 import java.net.InetAddress; 020 021 /*** 022 * A final class derived from TFTPPacket definiing the TFTP Data 023 * packet type. 024 * <p> 025 * Details regarding the TFTP protocol and the format of TFTP packets can 026 * be found in RFC 783. But the point of these classes is to keep you 027 * from having to worry about the internals. Additionally, only very 028 * few people should have to care about any of the TFTPPacket classes 029 * or derived classes. Almost all users should only be concerned with the 030 * {@link org.apache.commons.net.tftp.TFTPClient} class 031 * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()} 032 * and 033 * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()} 034 * methods. 035 * <p> 036 * <p> 037 * @author Daniel F. Savarese 038 * @see TFTPPacket 039 * @see TFTPPacketException 040 * @see TFTP 041 ***/ 042 043 public final class TFTPDataPacket extends TFTPPacket 044 { 045 /*** The maximum number of bytes in a TFTP data packet (512) ***/ 046 public static final int MAX_DATA_LENGTH = 512; 047 048 /*** The minimum number of bytes in a TFTP data packet (0) ***/ 049 public static final int MIN_DATA_LENGTH = 0; 050 051 /*** The block number of the packet. ***/ 052 int _blockNumber; 053 054 /*** The length of the data. ***/ 055 int _length; 056 057 /*** The offset into the _data array at which the data begins. ***/ 058 int _offset; 059 060 /*** The data stored in the packet. ***/ 061 byte[] _data; 062 063 /*** 064 * Creates a data packet to be sent to a host at a given port 065 * with a given block number. The actual data to be sent is passed as 066 * an array, an offset, and a length. The offset is the offset into 067 * the byte array where the data starts. The length is the length of 068 * the data. If the length is greater than MAX_DATA_LENGTH, it is 069 * truncated. 070 * <p> 071 * @param destination The host to which the packet is going to be sent. 072 * @param port The port to which the packet is going to be sent. 073 * @param blockNumber The block number of the data. 074 * @param data The byte array containing the data. 075 * @param offset The offset into the array where the data starts. 076 * @param length The length of the data. 077 ***/ 078 public TFTPDataPacket(InetAddress destination, int port, int blockNumber, 079 byte[] data, int offset, int length) 080 { 081 super(TFTPPacket.DATA, destination, port); 082 083 _blockNumber = blockNumber; 084 _data = data; 085 _offset = offset; 086 087 if (length > MAX_DATA_LENGTH) 088 _length = MAX_DATA_LENGTH; 089 else 090 _length = length; 091 } 092 093 public TFTPDataPacket(InetAddress destination, int port, int blockNumber, 094 byte[] data) 095 { 096 this(destination, port, blockNumber, data, 0, data.length); 097 } 098 099 100 /*** 101 * Creates a data packet based from a received 102 * datagram. Assumes the datagram is at least length 4, else an 103 * ArrayIndexOutOfBoundsException may be thrown. 104 * <p> 105 * @param datagram The datagram containing the received data. 106 * @throws TFTPPacketException If the datagram isn't a valid TFTP 107 * data packet. 108 ***/ 109 TFTPDataPacket(DatagramPacket datagram) throws TFTPPacketException 110 { 111 super(TFTPPacket.DATA, datagram.getAddress(), datagram.getPort()); 112 113 _data = datagram.getData(); 114 _offset = 4; 115 116 if (getType() != _data[1]) 117 throw new TFTPPacketException("TFTP operator code does not match type."); 118 119 _blockNumber = (((_data[2] & 0xff) << 8) | (_data[3] & 0xff)); 120 121 _length = datagram.getLength() - 4; 122 123 if (_length > MAX_DATA_LENGTH) 124 _length = MAX_DATA_LENGTH; 125 } 126 127 /*** 128 * This is a method only available within the package for 129 * implementing efficient datagram transport by elminating buffering. 130 * It takes a datagram as an argument, and a byte buffer in which 131 * to store the raw datagram data. Inside the method, the data 132 * is set as the datagram's data and the datagram returned. 133 * <p> 134 * @param datagram The datagram to create. 135 * @param data The buffer to store the packet and to use in the datagram. 136 * @return The datagram argument. 137 ***/ 138 DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) 139 { 140 data[0] = 0; 141 data[1] = (byte)_type; 142 data[2] = (byte)((_blockNumber & 0xffff) >> 8); 143 data[3] = (byte)(_blockNumber & 0xff); 144 145 // Doublecheck we're not the same 146 if (data != _data) 147 System.arraycopy(_data, _offset, data, 4, _length); 148 149 datagram.setAddress(_address); 150 datagram.setPort(_port); 151 datagram.setData(data); 152 datagram.setLength(_length + 4); 153 154 return datagram; 155 } 156 157 /*** 158 * Creates a UDP datagram containing all the TFTP 159 * data packet data in the proper format. 160 * This is a method exposed to the programmer in case he 161 * wants to implement his own TFTP client instead of using 162 * the {@link org.apache.commons.net.tftp.TFTPClient} 163 * class. 164 * Under normal circumstances, you should not have a need to call this 165 * method. 166 * <p> 167 * @return A UDP datagram containing the TFTP data packet. 168 ***/ 169 public DatagramPacket newDatagram() 170 { 171 byte[] data; 172 173 data = new byte[_length + 4]; 174 data[0] = 0; 175 data[1] = (byte)_type; 176 data[2] = (byte)((_blockNumber & 0xffff) >> 8); 177 data[3] = (byte)(_blockNumber & 0xff); 178 179 System.arraycopy(_data, _offset, data, 4, _length); 180 181 return new DatagramPacket(data, _length + 4, _address, _port); 182 } 183 184 /*** 185 * Returns the block number of the data packet. 186 * <p> 187 * @return The block number of the data packet. 188 ***/ 189 public int getBlockNumber() 190 { 191 return _blockNumber; 192 } 193 194 /*** Sets the block number of the data packet. ***/ 195 public void setBlockNumber(int blockNumber) 196 { 197 _blockNumber = blockNumber; 198 } 199 200 /*** 201 * Sets the data for the data packet. 202 * <p> 203 * @param data The byte array containing the data. 204 * @param offset The offset into the array where the data starts. 205 * @param length The length of the data. 206 ***/ 207 public void setData(byte[] data, int offset, int length) 208 { 209 _data = data; 210 _offset = offset; 211 _length = length; 212 213 if (length > MAX_DATA_LENGTH) 214 _length = MAX_DATA_LENGTH; 215 else 216 _length = length; 217 } 218 219 /*** 220 * Returns the length of the data part of the data packet. 221 * <p> 222 * @return The length of the data part of the data packet. 223 ***/ 224 public int getDataLength() 225 { 226 return _length; 227 } 228 229 /*** 230 * Returns the offset into the byte array where the packet data actually 231 * starts. 232 * <p> 233 * @return The offset into the byte array where the packet data actually 234 * starts. 235 ***/ 236 public int getDataOffset() 237 { 238 return _offset; 239 } 240 241 /*** 242 * Returns the byte array containing the packet data. 243 * <p> 244 * @return The byte array containing the packet data. 245 ***/ 246 public byte[] getData() 247 { 248 return _data; 249 } 250 }