001 /* 002 * Copyright 2001-2005 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.net.tftp; 017 018 import java.io.IOException; 019 import java.io.InterruptedIOException; 020 import java.net.DatagramPacket; 021 import java.net.SocketException; 022 import org.apache.commons.net.DatagramSocketClient; 023 024 /*** 025 * The TFTP class exposes a set of methods to allow you to deal with the TFTP 026 * protocol directly, in case you want to write your own TFTP client or 027 * server. However, almost every user should only be concerend with 028 * the {@link org.apache.commons.net.DatagramSocketClient#open open() }, 029 * and {@link org.apache.commons.net.DatagramSocketClient#close close() }, 030 * methods. Additionally,the a 031 * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() } 032 * method may be of importance for performance tuning. 033 * <p> 034 * Details regarding the TFTP protocol and the format of TFTP packets can 035 * be found in RFC 783. But the point of these classes is to keep you 036 * from having to worry about the internals. 037 * <p> 038 * <p> 039 * @author Daniel F. Savarese 040 * @see org.apache.commons.net.DatagramSocketClient 041 * @see TFTPPacket 042 * @see TFTPPacketException 043 * @see TFTPClient 044 ***/ 045 046 public class TFTP extends DatagramSocketClient 047 { 048 /*** 049 * The ascii transfer mode. Its value is 0 and equivalent to NETASCII_MODE 050 ***/ 051 public static final int ASCII_MODE = 0; 052 053 /*** 054 * The netascii transfer mode. Its value is 0. 055 ***/ 056 public static final int NETASCII_MODE = 0; 057 058 /*** 059 * The binary transfer mode. Its value is 1 and equivalent to OCTET_MODE. 060 ***/ 061 public static final int BINARY_MODE = 1; 062 063 /*** 064 * The image transfer mode. Its value is 1 and equivalent to OCTET_MODE. 065 ***/ 066 public static final int IMAGE_MODE = 1; 067 068 /*** 069 * The octet transfer mode. Its value is 1. 070 ***/ 071 public static final int OCTET_MODE = 1; 072 073 /*** 074 * The default number of milliseconds to wait to receive a datagram 075 * before timing out. The default is 5000 milliseconds (5 seconds). 076 ***/ 077 public static final int DEFAULT_TIMEOUT = 5000; 078 079 /*** 080 * The default TFTP port according to RFC 783 is 69. 081 ***/ 082 public static final int DEFAULT_PORT = 69; 083 084 /*** 085 * The size to use for TFTP packet buffers. Its 4 plus the 086 * TFTPPacket.SEGMENT_SIZE, i.e. 516. 087 ***/ 088 static final int PACKET_SIZE = TFTPPacket.SEGMENT_SIZE + 4; 089 090 /*** A buffer used to accelerate receives in bufferedReceive() ***/ 091 private byte[] __receiveBuffer; 092 093 /*** A datagram used to minimize memory allocation in bufferedReceive() ***/ 094 private DatagramPacket __receiveDatagram; 095 096 /*** A datagram used to minimize memory allocation in bufferedSend() ***/ 097 private DatagramPacket __sendDatagram; 098 099 /*** 100 * A buffer used to accelerate sends in bufferedSend(). 101 * It is left package visible so that TFTPClient may be slightly more 102 * efficient during file sends. It saves the creation of an 103 * additional buffer and prevents a buffer copy in _newDataPcket(). 104 ***/ 105 byte[] _sendBuffer; 106 107 108 /*** 109 * Returns the TFTP string representation of a TFTP transfer mode. 110 * Will throw an ArrayIndexOutOfBoundsException if an invalid transfer 111 * mode is specified. 112 * <p> 113 * @param mode The TFTP transfer mode. One of the MODE constants. 114 * @return The TFTP string representation of the TFTP transfer mode. 115 ***/ 116 public static final String getModeName(int mode) 117 { 118 return TFTPRequestPacket._modeStrings[mode]; 119 } 120 121 /*** 122 * Creates a TFTP instance with a default timeout of DEFAULT_TIMEOUT, 123 * a null socket, and buffered operations disabled. 124 ***/ 125 public TFTP() 126 { 127 setDefaultTimeout(DEFAULT_TIMEOUT); 128 __receiveBuffer = null; 129 __receiveDatagram = null; 130 } 131 132 /*** 133 * This method synchronizes a connection by discarding all packets that 134 * may be in the local socket buffer. This method need only be called 135 * when you implement your own TFTP client or server. 136 * <p> 137 * @exception IOException if an I/O error occurs. 138 ***/ 139 public final void discardPackets() throws IOException 140 { 141 int to; 142 DatagramPacket datagram; 143 144 datagram = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE); 145 146 to = getSoTimeout(); 147 setSoTimeout(1); 148 149 try 150 { 151 while (true) 152 _socket_.receive(datagram); 153 } 154 catch (SocketException e) 155 { 156 // Do nothing. We timed out so we hope we're caught up. 157 } 158 catch (InterruptedIOException e) 159 { 160 // Do nothing. We timed out so we hope we're caught up. 161 } 162 163 setSoTimeout(to); 164 } 165 166 167 /*** 168 * This is a special method to perform a more efficient packet receive. 169 * It should only be used after calling 170 * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps() 171 * initializes a set of buffers used internally that prevent the new 172 * allocation of a DatagramPacket and byte array for each send and receive. 173 * To use these buffers you must call the bufferedReceive() and 174 * bufferedSend() methods instead of send() and receive(). You must 175 * also be certain that you don't manipulate the resulting packet in 176 * such a way that it interferes with future buffered operations. 177 * For example, a TFTPDataPacket received with bufferedReceive() will 178 * have a reference to the internal byte buffer. You must finish using 179 * this data before calling bufferedReceive() again, or else the data 180 * will be overwritten by the the call. 181 * <p> 182 * @return The TFTPPacket received. 183 * @exception InterruptedIOException If a socket timeout occurs. The 184 * Java documentation claims an InterruptedIOException is thrown 185 * on a DatagramSocket timeout, but in practice we find a 186 * SocketException is thrown. You should catch both to be safe. 187 * @exception SocketException If a socket timeout occurs. The 188 * Java documentation claims an InterruptedIOException is thrown 189 * on a DatagramSocket timeout, but in practice we find a 190 * SocketException is thrown. You should catch both to be safe. 191 * @exception IOException If some other I/O error occurs. 192 * @exception TFTPPacketException If an invalid TFTP packet is received. 193 ***/ 194 public final TFTPPacket bufferedReceive() throws IOException, 195 InterruptedIOException, SocketException, TFTPPacketException 196 { 197 __receiveDatagram.setData(__receiveBuffer); 198 __receiveDatagram.setLength(__receiveBuffer.length); 199 _socket_.receive(__receiveDatagram); 200 201 return TFTPPacket.newTFTPPacket(__receiveDatagram); 202 } 203 204 /*** 205 * This is a special method to perform a more efficient packet send. 206 * It should only be used after calling 207 * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps() 208 * initializes a set of buffers used internally that prevent the new 209 * allocation of a DatagramPacket and byte array for each send and receive. 210 * To use these buffers you must call the bufferedReceive() and 211 * bufferedSend() methods instead of send() and receive(). You must 212 * also be certain that you don't manipulate the resulting packet in 213 * such a way that it interferes with future buffered operations. 214 * For example, a TFTPDataPacket received with bufferedReceive() will 215 * have a reference to the internal byte buffer. You must finish using 216 * this data before calling bufferedReceive() again, or else the data 217 * will be overwritten by the the call. 218 * <p> 219 * @param packet The TFTP packet to send. 220 * @exception IOException If some I/O error occurs. 221 ***/ 222 public final void bufferedSend(TFTPPacket packet) throws IOException 223 { 224 _socket_.send(packet._newDatagram(__sendDatagram, _sendBuffer)); 225 } 226 227 228 /*** 229 * Initializes the internal buffers. Buffers are used by 230 * {@link #bufferedSend bufferedSend() } and 231 * {@link #bufferedReceive bufferedReceive() }. This 232 * method must be called before calling either one of those two 233 * methods. When you finish using buffered operations, you must 234 * call {@link #endBufferedOps endBufferedOps() }. 235 ***/ 236 public final void beginBufferedOps() 237 { 238 __receiveBuffer = new byte[PACKET_SIZE]; 239 __receiveDatagram = 240 new DatagramPacket(__receiveBuffer, __receiveBuffer.length); 241 _sendBuffer = new byte[PACKET_SIZE]; 242 __sendDatagram = 243 new DatagramPacket(_sendBuffer, _sendBuffer.length); 244 } 245 246 /*** 247 * Releases the resources used to perform buffered sends and receives. 248 ***/ 249 public final void endBufferedOps() 250 { 251 __receiveBuffer = null; 252 __receiveDatagram = null; 253 _sendBuffer = null; 254 __sendDatagram = null; 255 } 256 257 258 /*** 259 * Sends a TFTP packet to its destination. 260 * <p> 261 * @param packet The TFTP packet to send. 262 * @exception IOException If some I/O error occurs. 263 ***/ 264 public final void send(TFTPPacket packet) throws IOException 265 { 266 _socket_.send(packet.newDatagram()); 267 } 268 269 270 /*** 271 * Receives a TFTPPacket. 272 * <p> 273 * @return The TFTPPacket received. 274 * @exception InterruptedIOException If a socket timeout occurs. The 275 * Java documentation claims an InterruptedIOException is thrown 276 * on a DatagramSocket timeout, but in practice we find a 277 * SocketException is thrown. You should catch both to be safe. 278 * @exception SocketException If a socket timeout occurs. The 279 * Java documentation claims an InterruptedIOException is thrown 280 * on a DatagramSocket timeout, but in practice we find a 281 * SocketException is thrown. You should catch both to be safe. 282 * @exception IOException If some other I/O error occurs. 283 * @exception TFTPPacketException If an invalid TFTP packet is received. 284 ***/ 285 public final TFTPPacket receive() throws IOException, InterruptedIOException, 286 SocketException, TFTPPacketException 287 { 288 DatagramPacket packet; 289 290 packet = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE); 291 292 _socket_.receive(packet); 293 294 return TFTPPacket.newTFTPPacket(packet); 295 } 296 297 298 }