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