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.io.IOException;
021 import java.io.InterruptedIOException;
022 import java.net.DatagramPacket;
023 import java.net.SocketException;
024
025 import org.apache.commons.net.DatagramSocketClient;
026
027 /***
028 * The TFTP class exposes a set of methods to allow you to deal with the TFTP
029 * protocol directly, in case you want to write your own TFTP client or
030 * server. However, almost every user should only be concerend with
031 * the {@link org.apache.commons.net.DatagramSocketClient#open open() },
032 * and {@link org.apache.commons.net.DatagramSocketClient#close close() },
033 * methods. Additionally,the a
034 * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() }
035 * method may be of importance for performance tuning.
036 * <p>
037 * Details regarding the TFTP protocol and the format of TFTP packets can
038 * be found in RFC 783. But the point of these classes is to keep you
039 * from having to worry about the internals.
040 * <p>
041 * <p>
042 * @author Daniel F. Savarese
043 * @see org.apache.commons.net.DatagramSocketClient
044 * @see TFTPPacket
045 * @see TFTPPacketException
046 * @see TFTPClient
047 ***/
048
049 public class TFTP extends DatagramSocketClient
050 {
051 /***
052 * The ascii transfer mode. Its value is 0 and equivalent to NETASCII_MODE
053 ***/
054 public static final int ASCII_MODE = 0;
055
056 /***
057 * The netascii transfer mode. Its value is 0.
058 ***/
059 public static final int NETASCII_MODE = 0;
060
061 /***
062 * The binary transfer mode. Its value is 1 and equivalent to OCTET_MODE.
063 ***/
064 public static final int BINARY_MODE = 1;
065
066 /***
067 * The image transfer mode. Its value is 1 and equivalent to OCTET_MODE.
068 ***/
069 public static final int IMAGE_MODE = 1;
070
071 /***
072 * The octet transfer mode. Its value is 1.
073 ***/
074 public static final int OCTET_MODE = 1;
075
076 /***
077 * The default number of milliseconds to wait to receive a datagram
078 * before timing out. The default is 5000 milliseconds (5 seconds).
079 ***/
080 public static final int DEFAULT_TIMEOUT = 5000;
081
082 /***
083 * The default TFTP port according to RFC 783 is 69.
084 ***/
085 public static final int DEFAULT_PORT = 69;
086
087 /***
088 * The size to use for TFTP packet buffers. Its 4 plus the
089 * TFTPPacket.SEGMENT_SIZE, i.e. 516.
090 ***/
091 static final int PACKET_SIZE = TFTPPacket.SEGMENT_SIZE + 4;
092
093 /*** A buffer used to accelerate receives in bufferedReceive() ***/
094 private byte[] __receiveBuffer;
095
096 /*** A datagram used to minimize memory allocation in bufferedReceive() ***/
097 private DatagramPacket __receiveDatagram;
098
099 /*** A datagram used to minimize memory allocation in bufferedSend() ***/
100 private DatagramPacket __sendDatagram;
101
102 /***
103 * A buffer used to accelerate sends in bufferedSend().
104 * It is left package visible so that TFTPClient may be slightly more
105 * efficient during file sends. It saves the creation of an
106 * additional buffer and prevents a buffer copy in _newDataPcket().
107 ***/
108 byte[] _sendBuffer;
109
110
111 /***
112 * Returns the TFTP string representation of a TFTP transfer mode.
113 * Will throw an ArrayIndexOutOfBoundsException if an invalid transfer
114 * mode is specified.
115 * <p>
116 * @param mode The TFTP transfer mode. One of the MODE constants.
117 * @return The TFTP string representation of the TFTP transfer mode.
118 ***/
119 public static final String getModeName(int mode)
120 {
121 return TFTPRequestPacket._modeStrings[mode];
122 }
123
124 /***
125 * Creates a TFTP instance with a default timeout of DEFAULT_TIMEOUT,
126 * a null socket, and buffered operations disabled.
127 ***/
128 public TFTP()
129 {
130 setDefaultTimeout(DEFAULT_TIMEOUT);
131 __receiveBuffer = null;
132 __receiveDatagram = null;
133 }
134
135 /***
136 * This method synchronizes a connection by discarding all packets that
137 * may be in the local socket buffer. This method need only be called
138 * when you implement your own TFTP client or server.
139 * <p>
140 * @exception IOException if an I/O error occurs.
141 ***/
142 public final void discardPackets() throws IOException
143 {
144 int to;
145 DatagramPacket datagram;
146
147 datagram = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
148
149 to = getSoTimeout();
150 setSoTimeout(1);
151
152 try
153 {
154 while (true)
155 _socket_.receive(datagram);
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 }