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.net.DatagramPacket;
  18. import java.net.InetAddress;
  19. /***
  20. * An abstract class derived from TFTPPacket definiing a TFTP Request
  21. * packet type. It is subclassed by the
  22. * <a href="org.apache.commons.net.tftp.TFTPReadRequestPacket.html#_top_">
  23. * TFTPReadRequestPacket</a> and
  24. * <a href="org.apache.commons.net.tftp.TFTPWriteRequestPacket.html#_top_">
  25. * TFTPWriteRequestPacket</a> classes.
  26. * <p>
  27. * Details regarding the TFTP protocol and the format of TFTP packets can
  28. * be found in RFC 783. But the point of these classes is to keep you
  29. * from having to worry about the internals. Additionally, only very
  30. * few people should have to care about any of the TFTPPacket classes
  31. * or derived classes. Almost all users should only be concerned with the
  32. * <a href="org.apache.commons.net.tftp.TFTPClient.html#_top_">TFTPClient</a> class
  33. * <a href="org.apache.commons.net.tftp.TFTPClient.html#receiveFile">receiveFile()</a>
  34. * and
  35. * <a href="org.apache.commons.net.tftp.TFTPClient.html#sendFile">sendFile()</a>
  36. * methods.
  37. * <p>
  38. * <p>
  39. * @author Daniel F. Savarese
  40. * @see TFTPPacket
  41. * @see TFTPReadRequestPacket
  42. * @see TFTPWriteRequestPacket
  43. * @see TFTPPacketException
  44. * @see TFTP
  45. ***/
  46. public abstract class TFTPRequestPacket extends TFTPPacket
  47. {
  48. /***
  49. * An array containing the string names of the transfer modes and indexed
  50. * by the transfer mode constants.
  51. ***/
  52. static final String[] _modeStrings = { "netascii", "octet" };
  53. /***
  54. * A null terminated byte array representation of the ascii names of the
  55. * transfer mode constants. This is convenient for creating the TFTP
  56. * request packets.
  57. ***/
  58. static final byte[] _modeBytes[] = {
  59. { (byte)'n', (byte)'e', (byte)'t', (byte)'a', (byte)'s', (byte)'c',
  60. (byte)'i', (byte)'i', 0 },
  61. { (byte)'o', (byte)'c', (byte)'t', (byte)'e', (byte)'t', 0 }
  62. };
  63. /*** The transfer mode of the request. ***/
  64. int _mode;
  65. /*** The filename of the request. ***/
  66. String _filename;
  67. /***
  68. * Creates a request packet of a given type to be sent to a host at a
  69. * given port with a filename and transfer mode request.
  70. * <p>
  71. * @param destination The host to which the packet is going to be sent.
  72. * @param port The port to which the packet is going to be sent.
  73. * @param type The type of the request (either TFTPPacket.READ_REQUEST or
  74. * TFTPPacket.WRITE_REQUEST).
  75. * @param filename The requested filename.
  76. * @param mode The requested transfer mode. This should be on of the TFTP
  77. * class MODE constants (e.g., TFTP.NETASCII_MODE).
  78. ***/
  79. TFTPRequestPacket(InetAddress destination, int port,
  80. int type, String filename, int mode)
  81. {
  82. super(type, destination, port);
  83. _filename = filename;
  84. _mode = mode;
  85. }
  86. /***
  87. * Creates a request packet of a given type based on a received
  88. * datagram. Assumes the datagram is at least length 4, else an
  89. * ArrayIndexOutOfBoundsException may be thrown.
  90. * <p>
  91. * @param type The type of the request (either TFTPPacket.READ_REQUEST or
  92. * TFTPPacket.WRITE_REQUEST).
  93. * @param datagram The datagram containing the received request.
  94. * @throws TFTPPacketException If the datagram isn't a valid TFTP
  95. * request packet of the appropriate type.
  96. ***/
  97. TFTPRequestPacket(int type, DatagramPacket datagram)
  98. throws TFTPPacketException
  99. {
  100. super(type, datagram.getAddress(), datagram.getPort());
  101. byte[] data;
  102. int index, length;
  103. String mode;
  104. StringBuffer buffer;
  105. data = datagram.getData();
  106. if (getType() != data[1])
  107. throw new TFTPPacketException("TFTP operator code does not match type.");
  108. buffer = new StringBuffer();
  109. index = 2;
  110. length = datagram.getLength();
  111. while (index < length && data[index] != 0)
  112. {
  113. buffer.append((char)data[index]);
  114. ++index;
  115. }
  116. _filename = buffer.toString();
  117. if (index >= length)
  118. throw new TFTPPacketException("Bad filename and mode format.");
  119. buffer.setLength(0);
  120. ++index; // need to advance beyond the end of string marker
  121. while (index < length && data[index] != 0)
  122. {
  123. buffer.append((char)data[index]);
  124. ++index;
  125. }
  126. mode = buffer.toString().toLowerCase();
  127. length = _modeStrings.length;
  128. for (index = 0; index < length; index++)
  129. {
  130. if (mode.equals(_modeStrings[index]))
  131. {
  132. _mode = index;
  133. break;
  134. }
  135. }
  136. if (index >= length)
  137. {
  138. throw new TFTPPacketException("Unrecognized TFTP transfer mode: " + mode);
  139. // May just want to default to binary mode instead of throwing
  140. // exception.
  141. //_mode = TFTP.OCTET_MODE;
  142. }
  143. }
  144. /***
  145. * This is a method only available within the package for
  146. * implementing efficient datagram transport by elminating buffering.
  147. * It takes a datagram as an argument, and a byte buffer in which
  148. * to store the raw datagram data. Inside the method, the data
  149. * is set as the datagram's data and the datagram returned.
  150. * <p>
  151. * @param datagram The datagram to create.
  152. * @param data The buffer to store the packet and to use in the datagram.
  153. * @return The datagram argument.
  154. ***/
  155. final DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
  156. {
  157. int fileLength, modeLength;
  158. fileLength = _filename.length();
  159. modeLength = _modeBytes[_mode].length;
  160. data[0] = 0;
  161. data[1] = (byte)_type;
  162. System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength);
  163. data[fileLength + 2] = 0;
  164. System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3,
  165. modeLength);
  166. datagram.setAddress(_address);
  167. datagram.setPort(_port);
  168. datagram.setData(data);
  169. datagram.setLength(fileLength + modeLength + 4);
  170. return datagram;
  171. }
  172. /***
  173. * Creates a UDP datagram containing all the TFTP
  174. * request packet data in the proper format.
  175. * This is a method exposed to the programmer in case he
  176. * wants to implement his own TFTP client instead of using
  177. * the <a href="org.apache.commons.net.tftp.TFTPClient.html#_top_">TFTPClient</a>
  178. * class. Under normal circumstances, you should not have a need to call
  179. * this method.
  180. * <p>
  181. * @return A UDP datagram containing the TFTP request packet.
  182. ***/
  183. public final DatagramPacket newDatagram()
  184. {
  185. int fileLength, modeLength;
  186. byte[] data;
  187. fileLength = _filename.length();
  188. modeLength = _modeBytes[_mode].length;
  189. data = new byte[fileLength + modeLength + 4];
  190. data[0] = 0;
  191. data[1] = (byte)_type;
  192. System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength);
  193. data[fileLength + 2] = 0;
  194. System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3,
  195. modeLength);
  196. return new DatagramPacket(data, data.length, _address, _port);
  197. }
  198. /***
  199. * Returns the transfer mode of the request.
  200. * <p>
  201. * @return The transfer mode of the request.
  202. ***/
  203. public final int getMode()
  204. {
  205. return _mode;
  206. }
  207. /***
  208. * Returns the requested filename.
  209. * <p>
  210. * @return The requested filename.
  211. ***/
  212. public final String getFilename()
  213. {
  214. return _filename;
  215. }
  216. }