1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.net.tftp;
19
20 import java.net.DatagramPacket;
21 import java.net.InetAddress;
22
23 /***
24 * TFTPPacket is an abstract class encapsulating the functionality common
25 * to the 5 types of TFTP packets. It also provides a static factory
26 * method that will create the correct TFTP packet instance from a
27 * datagram. This relieves the programmer from having to figure out what
28 * kind of TFTP packet is contained in a datagram and create it himself.
29 * <p>
30 * Details regarding the TFTP protocol and the format of TFTP packets can
31 * be found in RFC 783. But the point of these classes is to keep you
32 * from having to worry about the internals. Additionally, only very
33 * few people should have to care about any of the TFTPPacket classes
34 * or derived classes. Almost all users should only be concerned with the
35 * {@link org.apache.commons.net.tftp.TFTPClient} class
36 * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
37 * and
38 * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
39 * methods.
40 * <p>
41 * <p>
42 * @see TFTPPacketException
43 * @see TFTP
44 ***/
45
46 public abstract class TFTPPacket
47 {
48 /***
49 * The minimum size of a packet. This is 4 bytes. It is enough
50 * to store the opcode and blocknumber or other required data
51 * depending on the packet type.
52 ***/
53 static final int MIN_PACKET_SIZE = 4;
54
55 /***
56 * This is the actual TFTP spec
57 * identifier and is equal to 1.
58 * Identifier returned by {@link #getType getType()}
59 * indicating a read request packet.
60 ***/
61 public static final int READ_REQUEST = 1;
62
63 /***
64 * This is the actual TFTP spec
65 * identifier and is equal to 2.
66 * Identifier returned by {@link #getType getType()}
67 * indicating a write request packet.
68 ***/
69 public static final int WRITE_REQUEST = 2;
70
71 /***
72 * This is the actual TFTP spec
73 * identifier and is equal to 3.
74 * Identifier returned by {@link #getType getType()}
75 * indicating a data packet.
76 ***/
77 public static final int DATA = 3;
78
79 /***
80 * This is the actual TFTP spec
81 * identifier and is equal to 4.
82 * Identifier returned by {@link #getType getType()}
83 * indicating an acknowledgement packet.
84 ***/
85 public static final int ACKNOWLEDGEMENT = 4;
86
87 /***
88 * This is the actual TFTP spec
89 * identifier and is equal to 5.
90 * Identifier returned by {@link #getType getType()}
91 * indicating an error packet.
92 ***/
93 public static final int ERROR = 5;
94
95 /***
96 * The TFTP data packet maximum segment size in bytes. This is 512
97 * and is useful for those familiar with the TFTP protocol who want
98 * to use the {@link org.apache.commons.net.tftp.TFTP}
99 * class methods to implement their own TFTP servers or clients.
100 ***/
101 public static final int SEGMENT_SIZE = 512;
102
103 /*** The type of packet. ***/
104 int _type;
105
106 /*** The port the packet came from or is going to. ***/
107 int _port;
108
109 /*** The host the packet is going to be sent or where it came from. ***/
110 InetAddress _address;
111
112 /***
113 * When you receive a datagram that you expect to be a TFTP packet, you use
114 * this factory method to create the proper TFTPPacket object
115 * encapsulating the data contained in that datagram. This method is the
116 * only way you can instantiate a TFTPPacket derived class from a
117 * datagram.
118 * <p>
119 * @param datagram The datagram containing a TFTP packet.
120 * @return The TFTPPacket object corresponding to the datagram.
121 * @exception TFTPPacketException If the datagram does not contain a valid
122 * TFTP packet.
123 ***/
124 public final static TFTPPacket newTFTPPacket(DatagramPacket datagram)
125 throws TFTPPacketException
126 {
127 byte[] data;
128 TFTPPacket packet = null;
129
130 if (datagram.getLength() < MIN_PACKET_SIZE) {
131 throw new TFTPPacketException(
132 "Bad packet. Datagram data length is too short.");
133 }
134
135 data = datagram.getData();
136
137 switch (data[1])
138 {
139 case READ_REQUEST:
140 packet = new TFTPReadRequestPacket(datagram);
141 break;
142 case WRITE_REQUEST:
143 packet = new TFTPWriteRequestPacket(datagram);
144 break;
145 case DATA:
146 packet = new TFTPDataPacket(datagram);
147 break;
148 case ACKNOWLEDGEMENT:
149 packet = new TFTPAckPacket(datagram);
150 break;
151 case ERROR:
152 packet = new TFTPErrorPacket(datagram);
153 break;
154 default:
155 throw new TFTPPacketException(
156 "Bad packet. Invalid TFTP operator code.");
157 }
158
159 return packet;
160 }
161
162 /***
163 * This constructor is not visible outside of the package. It is used
164 * by subclasses within the package to initialize base data.
165 * <p>
166 * @param type The type of the packet.
167 * @param address The host the packet came from or is going to be sent.
168 * @param port The port the packet came from or is going to be sent.
169 **/
170 TFTPPacket(int type, InetAddress address, int port)
171 {
172 _type = type;
173 _address = address;
174 _port = port;
175 }
176
177 /***
178 * This is an abstract method only available within the package for
179 * implementing efficient datagram transport by elminating buffering.
180 * It takes a datagram as an argument, and a byte buffer in which
181 * to store the raw datagram data. Inside the method, the data
182 * should be set as the datagram's data and the datagram returned.
183 * <p>
184 * @param datagram The datagram to create.
185 * @param data The buffer to store the packet and to use in the datagram.
186 * @return The datagram argument.
187 ***/
188 abstract DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data);
189
190 /***
191 * Creates a UDP datagram containing all the TFTP packet
192 * data in the proper format.
193 * This is an abstract method, exposed to the programmer in case he
194 * wants to implement his own TFTP client instead of using
195 * the {@link org.apache.commons.net.tftp.TFTPClient}
196 * class.
197 * Under normal circumstances, you should not have a need to call this
198 * method.
199 * <p>
200 * @return A UDP datagram containing the TFTP packet.
201 ***/
202 public abstract DatagramPacket newDatagram();
203
204 /***
205 * Returns the type of the packet.
206 * <p>
207 * @return The type of the packet.
208 ***/
209 public final int getType()
210 {
211 return _type;
212 }
213
214 /***
215 * Returns the address of the host where the packet is going to be sent
216 * or where it came from.
217 * <p>
218 * @return The type of the packet.
219 ***/
220 public final InetAddress getAddress()
221 {
222 return _address;
223 }
224
225 /***
226 * Returns the port where the packet is going to be sent
227 * or where it came from.
228 * <p>
229 * @return The port where the packet came from or where it is going.
230 ***/
231 public final int getPort()
232 {
233 return _port;
234 }
235
236 /*** Sets the port where the packet is going to be sent. ***/
237 public final void setPort(int port)
238 {
239 _port = port;
240 }
241
242 /*** Sets the host address where the packet is going to be sent. ***/
243 public final void setAddress(InetAddress address)
244 {
245 _address = address;
246 }
247 }