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 * @see org.apache.commons.net.DatagramSocketClient
043 * @see TFTPPacket
044 * @see TFTPPacketException
045 * @see TFTPClient
046 ***/
047
048 public class TFTP extends DatagramSocketClient
049 {
050 /***
051 * The ascii transfer mode. Its value is 0 and equivalent to NETASCII_MODE
052 ***/
053 public static final int ASCII_MODE = 0;
054
055 /***
056 * The netascii transfer mode. Its value is 0.
057 ***/
058 public static final int NETASCII_MODE = 0;
059
060 /***
061 * The binary transfer mode. Its value is 1 and equivalent to OCTET_MODE.
062 ***/
063 public static final int BINARY_MODE = 1;
064
065 /***
066 * The image transfer mode. Its value is 1 and equivalent to OCTET_MODE.
067 ***/
068 public static final int IMAGE_MODE = 1;
069
070 /***
071 * The octet transfer mode. Its value is 1.
072 ***/
073 public static final int OCTET_MODE = 1;
074
075 /***
076 * The default number of milliseconds to wait to receive a datagram
077 * before timing out. The default is 5000 milliseconds (5 seconds).
078 ***/
079 public static final int DEFAULT_TIMEOUT = 5000;
080
081 /***
082 * The default TFTP port according to RFC 783 is 69.
083 ***/
084 public static final int DEFAULT_PORT = 69;
085
086 /***
087 * The size to use for TFTP packet buffers. Its 4 plus the
088 * TFTPPacket.SEGMENT_SIZE, i.e. 516.
089 ***/
090 static final int PACKET_SIZE = TFTPPacket.SEGMENT_SIZE + 4;
091
092 /*** A buffer used to accelerate receives in bufferedReceive() ***/
093 private byte[] __receiveBuffer;
094
095 /*** A datagram used to minimize memory allocation in bufferedReceive() ***/
096 private DatagramPacket __receiveDatagram;
097
098 /*** A datagram used to minimize memory allocation in bufferedSend() ***/
099 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 }