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 * @see TFTPPacket 040 * @see TFTPPacketException 041 * @see TFTP 042 ***/ 043 044 public 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 * <p> 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 public TFTPDataPacket(InetAddress destination, int port, int blockNumber, 095 byte[] data) 096 { 097 this(destination, port, blockNumber, data, 0, data.length); 098 } 099 100 101 /*** 102 * Creates a data packet based from a received 103 * datagram. Assumes the datagram is at least length 4, else an 104 * ArrayIndexOutOfBoundsException may be thrown. 105 * <p> 106 * @param datagram The datagram containing the received data. 107 * @throws TFTPPacketException If the datagram isn't a valid TFTP 108 * data packet. 109 ***/ 110 TFTPDataPacket(DatagramPacket datagram) throws TFTPPacketException 111 { 112 super(TFTPPacket.DATA, datagram.getAddress(), datagram.getPort()); 113 114 _data = datagram.getData(); 115 _offset = 4; 116 117 if (getType() != _data[1]) 118 throw new TFTPPacketException("TFTP operator code does not match type."); 119 120 _blockNumber = (((_data[2] & 0xff) << 8) | (_data[3] & 0xff)); 121 122 _length = datagram.getLength() - 4; 123 124 if (_length > MAX_DATA_LENGTH) 125 _length = MAX_DATA_LENGTH; 126 } 127 128 /*** 129 * This is a method only available within the package for 130 * implementing efficient datagram transport by elminating buffering. 131 * It takes a datagram as an argument, and a byte buffer in which 132 * to store the raw datagram data. Inside the method, the data 133 * is set as the datagram's data and the datagram returned. 134 * <p> 135 * @param datagram The datagram to create. 136 * @param data The buffer to store the packet and to use in the datagram. 137 * @return The datagram argument. 138 ***/ 139 @Override 140 DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) 141 { 142 data[0] = 0; 143 data[1] = (byte)_type; 144 data[2] = (byte)((_blockNumber & 0xffff) >> 8); 145 data[3] = (byte)(_blockNumber & 0xff); 146 147 // Doublecheck we're not the same 148 if (data != _data) 149 System.arraycopy(_data, _offset, data, 4, _length); 150 151 datagram.setAddress(_address); 152 datagram.setPort(_port); 153 datagram.setData(data); 154 datagram.setLength(_length + 4); 155 156 return datagram; 157 } 158 159 /*** 160 * Creates a UDP datagram containing all the TFTP 161 * data packet data in the proper format. 162 * This is a method exposed to the programmer in case he 163 * wants to implement his own TFTP client instead of using 164 * the {@link org.apache.commons.net.tftp.TFTPClient} 165 * class. 166 * Under normal circumstances, you should not have a need to call this 167 * method. 168 * <p> 169 * @return A UDP datagram containing the TFTP data packet. 170 ***/ 171 @Override 172 public DatagramPacket newDatagram() 173 { 174 byte[] data; 175 176 data = new byte[_length + 4]; 177 data[0] = 0; 178 data[1] = (byte)_type; 179 data[2] = (byte)((_blockNumber & 0xffff) >> 8); 180 data[3] = (byte)(_blockNumber & 0xff); 181 182 System.arraycopy(_data, _offset, data, 4, _length); 183 184 return new DatagramPacket(data, _length + 4, _address, _port); 185 } 186 187 /*** 188 * Returns the block number of the data packet. 189 * <p> 190 * @return The block number of the data packet. 191 ***/ 192 public int getBlockNumber() 193 { 194 return _blockNumber; 195 } 196 197 /*** Sets the block number of the data packet. ***/ 198 public void setBlockNumber(int blockNumber) 199 { 200 _blockNumber = blockNumber; 201 } 202 203 /*** 204 * Sets the data for the data packet. 205 * <p> 206 * @param data The byte array containing the data. 207 * @param offset The offset into the array where the data starts. 208 * @param length The length of the data. 209 ***/ 210 public void setData(byte[] data, int offset, int length) 211 { 212 _data = data; 213 _offset = offset; 214 _length = length; 215 216 if (length > MAX_DATA_LENGTH) 217 _length = MAX_DATA_LENGTH; 218 else 219 _length = length; 220 } 221 222 /*** 223 * Returns the length of the data part of the data packet. 224 * <p> 225 * @return The length of the data part of the data packet. 226 ***/ 227 public int getDataLength() 228 { 229 return _length; 230 } 231 232 /*** 233 * Returns the offset into the byte array where the packet data actually 234 * starts. 235 * <p> 236 * @return The offset into the byte array where the packet data actually 237 * starts. 238 ***/ 239 public int getDataOffset() 240 { 241 return _offset; 242 } 243 244 /*** 245 * Returns the byte array containing the packet data. 246 * <p> 247 * @return The byte array containing the packet data. 248 ***/ 249 public byte[] getData() 250 { 251 return _data; 252 } 253 }