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