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