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 018 package org.apache.commons.net.tftp; 019 020 import java.net.DatagramPacket; 021 import 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 * <p> 038 * <p> 039 * @author Daniel F. Savarese 040 * @see TFTPPacket 041 * @see TFTPPacketException 042 * @see TFTP 043 ***/ 044 045 public final class TFTPDataPacket extends TFTPPacket 046 { 047 /*** The maximum number of bytes in a TFTP data packet (512) ***/ 048 public static final int MAX_DATA_LENGTH = 512; 049 050 /*** The minimum number of bytes in a TFTP data packet (0) ***/ 051 public static final int MIN_DATA_LENGTH = 0; 052 053 /*** The block number of the packet. ***/ 054 int _blockNumber; 055 056 /*** The length of the data. ***/ 057 int _length; 058 059 /*** The offset into the _data array at which the data begins. ***/ 060 int _offset; 061 062 /*** The data stored in the packet. ***/ 063 byte[] _data; 064 065 /*** 066 * Creates a data packet to be sent to a host at a given port 067 * with a given block number. The actual data to be sent is passed as 068 * an array, an offset, and a length. The offset is the offset into 069 * the byte array where the data starts. The length is the length of 070 * the data. If the length is greater than MAX_DATA_LENGTH, it is 071 * truncated. 072 * <p> 073 * @param destination The host to which the packet is going to be sent. 074 * @param port The port to which the packet is going to be sent. 075 * @param blockNumber The block number of the data. 076 * @param data The byte array containing the data. 077 * @param offset The offset into the array where the data starts. 078 * @param length The length of the data. 079 ***/ 080 public TFTPDataPacket(InetAddress destination, int port, int blockNumber, 081 byte[] data, int offset, int length) 082 { 083 super(TFTPPacket.DATA, destination, port); 084 085 _blockNumber = blockNumber; 086 _data = data; 087 _offset = offset; 088 089 if (length > MAX_DATA_LENGTH) 090 _length = MAX_DATA_LENGTH; 091 else 092 _length = length; 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 * <p> 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 _blockNumber = (((_data[2] & 0xff) << 8) | (_data[3] & 0xff)); 122 123 _length = datagram.getLength() - 4; 124 125 if (_length > MAX_DATA_LENGTH) 126 _length = MAX_DATA_LENGTH; 127 } 128 129 /*** 130 * This is a method only available within the package for 131 * implementing efficient datagram transport by elminating buffering. 132 * It takes a datagram as an argument, and a byte buffer in which 133 * to store the raw datagram data. Inside the method, the data 134 * is set as the datagram's data and the datagram returned. 135 * <p> 136 * @param datagram The datagram to create. 137 * @param data The buffer to store the packet and to use in the datagram. 138 * @return The datagram argument. 139 ***/ 140 @Override 141 DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) 142 { 143 data[0] = 0; 144 data[1] = (byte)_type; 145 data[2] = (byte)((_blockNumber & 0xffff) >> 8); 146 data[3] = (byte)(_blockNumber & 0xff); 147 148 // Doublecheck we're not the same 149 if (data != _data) 150 System.arraycopy(_data, _offset, data, 4, _length); 151 152 datagram.setAddress(_address); 153 datagram.setPort(_port); 154 datagram.setData(data); 155 datagram.setLength(_length + 4); 156 157 return datagram; 158 } 159 160 /*** 161 * Creates a UDP datagram containing all the TFTP 162 * data packet data in the proper format. 163 * This is a method exposed to the programmer in case he 164 * wants to implement his own TFTP client instead of using 165 * the {@link org.apache.commons.net.tftp.TFTPClient} 166 * class. 167 * Under normal circumstances, you should not have a need to call this 168 * method. 169 * <p> 170 * @return A UDP datagram containing the TFTP data packet. 171 ***/ 172 @Override 173 public DatagramPacket newDatagram() 174 { 175 byte[] data; 176 177 data = new byte[_length + 4]; 178 data[0] = 0; 179 data[1] = (byte)_type; 180 data[2] = (byte)((_blockNumber & 0xffff) >> 8); 181 data[3] = (byte)(_blockNumber & 0xff); 182 183 System.arraycopy(_data, _offset, data, 4, _length); 184 185 return new DatagramPacket(data, _length + 4, _address, _port); 186 } 187 188 /*** 189 * Returns the block number of the data packet. 190 * <p> 191 * @return The block number of the data packet. 192 ***/ 193 public int getBlockNumber() 194 { 195 return _blockNumber; 196 } 197 198 /*** Sets the block number of the data packet. ***/ 199 public void setBlockNumber(int blockNumber) 200 { 201 _blockNumber = blockNumber; 202 } 203 204 /*** 205 * Sets the data for the data packet. 206 * <p> 207 * @param data The byte array containing the data. 208 * @param offset The offset into the array where the data starts. 209 * @param length The length of the data. 210 ***/ 211 public void setData(byte[] data, int offset, int length) 212 { 213 _data = data; 214 _offset = offset; 215 _length = length; 216 217 if (length > MAX_DATA_LENGTH) 218 _length = MAX_DATA_LENGTH; 219 else 220 _length = length; 221 } 222 223 /*** 224 * Returns the length of the data part of the data packet. 225 * <p> 226 * @return The length of the data part of the data packet. 227 ***/ 228 public int getDataLength() 229 { 230 return _length; 231 } 232 233 /*** 234 * Returns the offset into the byte array where the packet data actually 235 * starts. 236 * <p> 237 * @return The offset into the byte array where the packet data actually 238 * starts. 239 ***/ 240 public int getDataOffset() 241 { 242 return _offset; 243 } 244 245 /*** 246 * Returns the byte array containing the packet data. 247 * <p> 248 * @return The byte array containing the packet data. 249 ***/ 250 public byte[] getData() 251 { 252 return _data; 253 } 254 }