    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            catch (SocketException e)
    157            {
    158                // Do nothing.  We timed out so we hope we're caught up.
    159            }
    160            catch (InterruptedIOException e)
    161            {
    162                // Do nothing.  We timed out so we hope we're caught up.
    163            }
    164
    165            setSoTimeout(to);
    166        }
    167
    168
    169        /***
    170         * This is a special method to perform a more efficient packet receive.
    171         * It should only be used after calling
    172         * {@link #beginBufferedOps  beginBufferedOps() }.  beginBufferedOps()
    173         * initializes a set of buffers used internally that prevent the new
    174         * allocation of a DatagramPacket and byte array for each send and receive.
    175         * To use these buffers you must call the bufferedReceive() and
    176         * bufferedSend() methods instead of send() and receive().  You must
    177         * also be certain that you don't manipulate the resulting packet in
    178         * such a way that it interferes with future buffered operations.
    179         * For example, a TFTPDataPacket received with bufferedReceive() will
    180         * have a reference to the internal byte buffer.  You must finish using
    181         * this data before calling bufferedReceive() again, or else the data
    182         * will be overwritten by the the call.
    183         * <p>
    184         * @return The TFTPPacket received.
    185         * @exception InterruptedIOException  If a socket timeout occurs.  The
    186         *       Java documentation claims an InterruptedIOException is thrown
    187         *       on a DatagramSocket timeout, but in practice we find a
    188         *       SocketException is thrown.  You should catch both to be safe.
    189         * @exception SocketException  If a socket timeout occurs.  The
    190         *       Java documentation claims an InterruptedIOException is thrown
    191         *       on a DatagramSocket timeout, but in practice we find a
    192         *       SocketException is thrown.  You should catch both to be safe.
    193         * @exception IOException  If some other I/O error occurs.
    194         * @exception TFTPPacketException If an invalid TFTP packet is received.
    195         ***/
    196        public final TFTPPacket bufferedReceive() throws IOException,
    197                    InterruptedIOException, SocketException, TFTPPacketException
    198        {
    199            __receiveDatagram.setData(__receiveBuffer);
    200            __receiveDatagram.setLength(__receiveBuffer.length);
    201            _socket_.receive(__receiveDatagram);
    202
    203            return TFTPPacket.newTFTPPacket(__receiveDatagram);
    204        }
    205
    206        /***
    207         * This is a special method to perform a more efficient packet send.
    208         * It should only be used after calling
    209         * {@link #beginBufferedOps  beginBufferedOps() }.  beginBufferedOps()
    210         * initializes a set of buffers used internally that prevent the new
    211         * allocation of a DatagramPacket and byte array for each send and receive.
    212         * To use these buffers you must call the bufferedReceive() and
    213         * bufferedSend() methods instead of send() and receive().  You must
    214         * also be certain that you don't manipulate the resulting packet in
    215         * such a way that it interferes with future buffered operations.
    216         * For example, a TFTPDataPacket received with bufferedReceive() will
    217         * have a reference to the internal byte buffer.  You must finish using
    218         * this data before calling bufferedReceive() again, or else the data
    219         * will be overwritten by the the call.
    220         * <p>
    221         * @param packet  The TFTP packet to send.
    222         * @exception IOException  If some  I/O error occurs.
    223         ***/
    224        public final void bufferedSend(TFTPPacket packet) throws IOException
    225        {
    226            _socket_.send(packet._newDatagram(__sendDatagram, _sendBuffer));
    227        }
    228
    229
    230        /***
    231         * Initializes the internal buffers. Buffers are used by
    232         * {@link #bufferedSend  bufferedSend() } and
    233         * {@link #bufferedReceive  bufferedReceive() }.  This
    234         * method must be called before calling either one of those two
    235         * methods.  When you finish using buffered operations, you must
    236         * call {@link #endBufferedOps  endBufferedOps() }.
    237         ***/
    238        public final void beginBufferedOps()
    239        {
    240            __receiveBuffer = new byte[PACKET_SIZE];
    241            __receiveDatagram =
    242                new DatagramPacket(__receiveBuffer, __receiveBuffer.length);
    243            _sendBuffer = new byte[PACKET_SIZE];
    244            __sendDatagram =
    245                new DatagramPacket(_sendBuffer, _sendBuffer.length);
    246        }
    247
    248        /***
    249         * Releases the resources used to perform buffered sends and receives.
    250         ***/
    251        public final void endBufferedOps()
    252        {
    253            __receiveBuffer = null;
    254            __receiveDatagram = null;
    255            _sendBuffer = null;
    256            __sendDatagram = null;
    257        }
    258
    259
    260        /***
    261         * Sends a TFTP packet to its destination.
    262         * <p>
    263         * @param packet  The TFTP packet to send.
    264         * @exception IOException  If some  I/O error occurs.
    265         ***/
    266        public final void send(TFTPPacket packet) throws IOException
    267        {
    268            _socket_.send(packet.newDatagram());
    269        }
    270
    271
    272        /***
    273         * Receives a TFTPPacket.
    274         * <p>
    275         * @return The TFTPPacket received.
    276         * @exception InterruptedIOException  If a socket timeout occurs.  The
    277         *       Java documentation claims an InterruptedIOException is thrown
    278         *       on a DatagramSocket timeout, but in practice we find a
    279         *       SocketException is thrown.  You should catch both to be safe.
    280         * @exception SocketException  If a socket timeout occurs.  The
    281         *       Java documentation claims an InterruptedIOException is thrown
    282         *       on a DatagramSocket timeout, but in practice we find a
    283         *       SocketException is thrown.  You should catch both to be safe.
    284         * @exception IOException  If some other I/O error occurs.
    285         * @exception TFTPPacketException If an invalid TFTP packet is received.
    286         ***/
    287        public final TFTPPacket receive() throws IOException, InterruptedIOException,
    288                    SocketException, TFTPPacketException
    289        {
    290            DatagramPacket packet;
    291
    292            packet = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
    293
    294            _socket_.receive(packet);
    295
    296            return TFTPPacket.newTFTPPacket(packet);
    297        }
    298
    299
    300    }