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.io.IOException;
21 import java.io.InterruptedIOException;
22 import java.net.DatagramPacket;
23 import java.net.SocketException;
24
25 import org.apache.commons.net.DatagramSocketClient;
26
27 /***
28 * The TFTP class exposes a set of methods to allow you to deal with the TFTP
29 * protocol directly, in case you want to write your own TFTP client or
30 * server. However, almost every user should only be concerend with
31 * the {@link org.apache.commons.net.DatagramSocketClient#open open() },
32 * and {@link org.apache.commons.net.DatagramSocketClient#close close() },
33 * methods. Additionally,the a
34 * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() }
35 * method may be of importance for performance tuning.
36 * <p>
37 * Details regarding the TFTP protocol and the format of TFTP packets can
38 * be found in RFC 783. But the point of these classes is to keep you
39 * from having to worry about the internals.
40 * <p>
41 * <p>
42 * @see org.apache.commons.net.DatagramSocketClient
43 * @see TFTPPacket
44 * @see TFTPPacketException
45 * @see TFTPClient
46 ***/
47
48 public class TFTP extends DatagramSocketClient
49 {
50 /***
51 * The ascii transfer mode. Its value is 0 and equivalent to NETASCII_MODE
52 ***/
53 public static final int ASCII_MODE = 0;
54
55 /***
56 * The netascii transfer mode. Its value is 0.
57 ***/
58 public static final int NETASCII_MODE = 0;
59
60 /***
61 * The binary transfer mode. Its value is 1 and equivalent to OCTET_MODE.
62 ***/
63 public static final int BINARY_MODE = 1;
64
65 /***
66 * The image transfer mode. Its value is 1 and equivalent to OCTET_MODE.
67 ***/
68 public static final int IMAGE_MODE = 1;
69
70 /***
71 * The octet transfer mode. Its value is 1.
72 ***/
73 public static final int OCTET_MODE = 1;
74
75 /***
76 * The default number of milliseconds to wait to receive a datagram
77 * before timing out. The default is 5000 milliseconds (5 seconds).
78 ***/
79 public static final int DEFAULT_TIMEOUT = 5000;
80
81 /***
82 * The default TFTP port according to RFC 783 is 69.
83 ***/
84 public static final int DEFAULT_PORT = 69;
85
86 /***
87 * The size to use for TFTP packet buffers. Its 4 plus the
88 * TFTPPacket.SEGMENT_SIZE, i.e. 516.
89 ***/
90 static final int PACKET_SIZE = TFTPPacket.SEGMENT_SIZE + 4;
91
92 /*** A buffer used to accelerate receives in bufferedReceive() ***/
93 private byte[] __receiveBuffer;
94
95 /*** A datagram used to minimize memory allocation in bufferedReceive() ***/
96 private DatagramPacket __receiveDatagram;
97
98 /*** A datagram used to minimize memory allocation in bufferedSend() ***/
99 private DatagramPacket __sendDatagram;
100
101 /***
102 * A buffer used to accelerate sends in bufferedSend().
103 * It is left package visible so that TFTPClient may be slightly more
104 * efficient during file sends. It saves the creation of an
105 * additional buffer and prevents a buffer copy in _newDataPcket().
106 ***/
107 byte[] _sendBuffer;
108
109
110 /***
111 * Returns the TFTP string representation of a TFTP transfer mode.
112 * Will throw an ArrayIndexOutOfBoundsException if an invalid transfer
113 * mode is specified.
114 * <p>
115 * @param mode The TFTP transfer mode. One of the MODE constants.
116 * @return The TFTP string representation of the TFTP transfer mode.
117 ***/
118 public static final String getModeName(int mode)
119 {
120 return TFTPRequestPacket._modeStrings[mode];
121 }
122
123 /***
124 * Creates a TFTP instance with a default timeout of DEFAULT_TIMEOUT,
125 * a null socket, and buffered operations disabled.
126 ***/
127 public TFTP()
128 {
129 setDefaultTimeout(DEFAULT_TIMEOUT);
130 __receiveBuffer = null;
131 __receiveDatagram = null;
132 }
133
134 /***
135 * This method synchronizes a connection by discarding all packets that
136 * may be in the local socket buffer. This method need only be called
137 * when you implement your own TFTP client or server.
138 * <p>
139 * @exception IOException if an I/O error occurs.
140 ***/
141 public final void discardPackets() throws IOException
142 {
143 int to;
144 DatagramPacket datagram;
145
146 datagram = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
147
148 to = getSoTimeout();
149 setSoTimeout(1);
150
151 try
152 {
153 while (true) {
154 _socket_.receive(datagram);
155 }
156 }
157 catch (SocketException e)
158 {
159 // Do nothing. We timed out so we hope we're caught up.
160 }
161 catch (InterruptedIOException e)
162 {
163 // Do nothing. We timed out so we hope we're caught up.
164 }
165
166 setSoTimeout(to);
167 }
168
169
170 /***
171 * This is a special method to perform a more efficient packet receive.
172 * It should only be used after calling
173 * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps()
174 * initializes a set of buffers used internally that prevent the new
175 * allocation of a DatagramPacket and byte array for each send and receive.
176 * To use these buffers you must call the bufferedReceive() and
177 * bufferedSend() methods instead of send() and receive(). You must
178 * also be certain that you don't manipulate the resulting packet in
179 * such a way that it interferes with future buffered operations.
180 * For example, a TFTPDataPacket received with bufferedReceive() will
181 * have a reference to the internal byte buffer. You must finish using
182 * this data before calling bufferedReceive() again, or else the data
183 * will be overwritten by the the call.
184 * <p>
185 * @return The TFTPPacket received.
186 * @exception InterruptedIOException If a socket timeout occurs. The
187 * Java documentation claims an InterruptedIOException is thrown
188 * on a DatagramSocket timeout, but in practice we find a
189 * SocketException is thrown. You should catch both to be safe.
190 * @exception SocketException If a socket timeout occurs. The
191 * Java documentation claims an InterruptedIOException is thrown
192 * on a DatagramSocket timeout, but in practice we find a
193 * SocketException is thrown. You should catch both to be safe.
194 * @exception IOException If some other I/O error occurs.
195 * @exception TFTPPacketException If an invalid TFTP packet is received.
196 ***/
197 public final TFTPPacket bufferedReceive() throws IOException,
198 InterruptedIOException, SocketException, TFTPPacketException
199 {
200 __receiveDatagram.setData(__receiveBuffer);
201 __receiveDatagram.setLength(__receiveBuffer.length);
202 _socket_.receive(__receiveDatagram);
203
204 return TFTPPacket.newTFTPPacket(__receiveDatagram);
205 }
206
207 /***
208 * This is a special method to perform a more efficient packet send.
209 * It should only be used after calling
210 * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps()
211 * initializes a set of buffers used internally that prevent the new
212 * allocation of a DatagramPacket and byte array for each send and receive.
213 * To use these buffers you must call the bufferedReceive() and
214 * bufferedSend() methods instead of send() and receive(). You must
215 * also be certain that you don't manipulate the resulting packet in
216 * such a way that it interferes with future buffered operations.
217 * For example, a TFTPDataPacket received with bufferedReceive() will
218 * have a reference to the internal byte buffer. You must finish using
219 * this data before calling bufferedReceive() again, or else the data
220 * will be overwritten by the the call.
221 * <p>
222 * @param packet The TFTP packet to send.
223 * @exception IOException If some I/O error occurs.
224 ***/
225 public final void bufferedSend(TFTPPacket packet) throws IOException
226 {
227 _socket_.send(packet._newDatagram(__sendDatagram, _sendBuffer));
228 }
229
230
231 /***
232 * Initializes the internal buffers. Buffers are used by
233 * {@link #bufferedSend bufferedSend() } and
234 * {@link #bufferedReceive bufferedReceive() }. This
235 * method must be called before calling either one of those two
236 * methods. When you finish using buffered operations, you must
237 * call {@link #endBufferedOps endBufferedOps() }.
238 ***/
239 public final void beginBufferedOps()
240 {
241 __receiveBuffer = new byte[PACKET_SIZE];
242 __receiveDatagram =
243 new DatagramPacket(__receiveBuffer, __receiveBuffer.length);
244 _sendBuffer = new byte[PACKET_SIZE];
245 __sendDatagram =
246 new DatagramPacket(_sendBuffer, _sendBuffer.length);
247 }
248
249 /***
250 * Releases the resources used to perform buffered sends and receives.
251 ***/
252 public final void endBufferedOps()
253 {
254 __receiveBuffer = null;
255 __receiveDatagram = null;
256 _sendBuffer = null;
257 __sendDatagram = null;
258 }
259
260
261 /***
262 * Sends a TFTP packet to its destination.
263 * <p>
264 * @param packet The TFTP packet to send.
265 * @exception IOException If some I/O error occurs.
266 ***/
267 public final void send(TFTPPacket packet) throws IOException
268 {
269 _socket_.send(packet.newDatagram());
270 }
271
272
273 /***
274 * Receives a TFTPPacket.
275 * <p>
276 * @return The TFTPPacket received.
277 * @exception InterruptedIOException If a socket timeout occurs. The
278 * Java documentation claims an InterruptedIOException is thrown
279 * on a DatagramSocket timeout, but in practice we find a
280 * SocketException is thrown. You should catch both to be safe.
281 * @exception SocketException If a socket timeout occurs. The
282 * Java documentation claims an InterruptedIOException is thrown
283 * on a DatagramSocket timeout, but in practice we find a
284 * SocketException is thrown. You should catch both to be safe.
285 * @exception IOException If some other I/O error occurs.
286 * @exception TFTPPacketException If an invalid TFTP packet is received.
287 ***/
288 public final TFTPPacket receive() throws IOException, InterruptedIOException,
289 SocketException, TFTPPacketException
290 {
291 DatagramPacket packet;
292
293 packet = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
294
295 _socket_.receive(packet);
296
297 return TFTPPacket.newTFTPPacket(packet);
298 }
299
300
301 }