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