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.net.DatagramPacket;
019    import java.net.InetAddress;
020    
021    /***
022     * A final class derived from TFTPPacket definiing the TFTP Error
023     * packet type.
024     * <p>
025     * Details regarding the TFTP protocol and the format of TFTP packets can
026     * be found in RFC 783.  But the point of these classes is to keep you
027     * from having to worry about the internals.  Additionally, only very
028     * few people should have to care about any of the TFTPPacket classes
029     * or derived classes.  Almost all users should only be concerned with the
030     * {@link org.apache.commons.net.tftp.TFTPClient} class
031     * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
032     * and
033     * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
034     * methods.
035     * <p>
036     * <p>
037     * @author Daniel F. Savarese
038     * @see TFTPPacket
039     * @see TFTPPacketException
040     * @see TFTP
041     ***/
042    
043    public final class TFTPErrorPacket extends TFTPPacket
044    {
045        /*** The undefined error code according to RFC 783, value 0. ***/
046        public static final int UNDEFINED = 0;
047    
048        /*** The file not found error code according to RFC 783, value 1. ***/
049        public static final int FILE_NOT_FOUND = 1;
050    
051        /*** The access violation error code according to RFC 783, value 2. ***/
052        public static final int ACCESS_VIOLATION = 2;
053    
054        /*** The disk full error code according to RFC 783, value 3. ***/
055        public static final int OUT_OF_SPACE = 3;
056    
057        /***
058         * The illegal TFTP operation error code according to RFC 783, value 4.
059         ***/
060        public static final int ILLEGAL_OPERATION = 4;
061    
062        /*** The unknown transfer id error code according to RFC 783, value 5. ***/
063        public static final int UNKNOWN_TID = 5;
064    
065        /*** The file already exists error code according to RFC 783, value 6. ***/
066        public static final int FILE_EXISTS = 6;
067    
068        /*** The no such user error code according to RFC 783, value 7. ***/
069        public static final int NO_SUCH_USER = 7;
070    
071        /*** The error code of this packet. ***/
072        int _error;
073    
074        /*** The error message of this packet. ***/
075        String _message;
076    
077        /***
078         * Creates an error packet to be sent to a host at a given port
079         * with an error code and error message.
080         * <p>
081         * @param destination  The host to which the packet is going to be sent.
082         * @param port  The port to which the packet is going to be sent.
083         * @param error The error code of the packet.
084         * @param message The error message of the packet.
085         ***/
086        public TFTPErrorPacket(InetAddress destination, int port,
087                               int error, String message)
088        {
089            super(TFTPPacket.ERROR, destination, port);
090    
091            _error = error;
092            _message = message;
093        }
094    
095        /***
096         * Creates an error packet based from a received
097         * datagram.  Assumes the datagram is at least length 4, else an
098         * ArrayIndexOutOfBoundsException may be thrown.
099         * <p>
100         * @param datagram  The datagram containing the received error.
101         * @throws TFTPPacketException  If the datagram isn't a valid TFTP
102         *         error packet.
103         ***/
104        TFTPErrorPacket(DatagramPacket datagram) throws TFTPPacketException
105        {
106            super(TFTPPacket.ERROR, datagram.getAddress(), datagram.getPort());
107            int index, length;
108            byte[] data;
109            StringBuffer buffer;
110    
111            data = datagram.getData();
112            length = datagram.getLength();
113    
114            if (getType() != data[1])
115                throw new TFTPPacketException("TFTP operator code does not match type.");
116    
117            _error = (((data[2] & 0xff) << 8) | (data[3] & 0xff));
118    
119            if (length < 5)
120                throw new TFTPPacketException("Bad error packet. No message.");
121    
122            index = 4;
123            buffer = new StringBuffer();
124    
125            while (index < length && data[index] != 0)
126            {
127                buffer.append((char)data[index]);
128                ++index;
129            }
130    
131            _message = buffer.toString();
132        }
133    
134        /***
135         * This is a method only available within the package for
136         * implementing efficient datagram transport by elminating buffering.
137         * It takes a datagram as an argument, and a byte buffer in which
138         * to store the raw datagram data.  Inside the method, the data
139         * is set as the datagram's data and the datagram returned.
140         * <p>
141         * @param datagram  The datagram to create.
142         * @param data The buffer to store the packet and to use in the datagram.
143         * @return The datagram argument.
144         ***/
145        DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
146        {
147            int length;
148    
149            length = _message.length();
150    
151            data[0] = 0;
152            data[1] = (byte)_type;
153            data[2] = (byte)((_error & 0xffff) >> 8);
154            data[3] = (byte)(_error & 0xff);
155    
156            System.arraycopy(_message.getBytes(), 0, data, 4, length);
157    
158            data[length + 4] = 0;
159    
160            datagram.setAddress(_address);
161            datagram.setPort(_port);
162            datagram.setData(data);
163            datagram.setLength(length + 4);
164    
165            return datagram;
166        }
167    
168    
169        /***
170         * Creates a UDP datagram containing all the TFTP
171         * error packet data in the proper format.
172         * This is a method exposed to the programmer in case he
173         * wants to implement his own TFTP client instead of using
174         * the {@link org.apache.commons.net.tftp.TFTPClient}
175         * class.
176         * Under normal circumstances, you should not have a need to call this
177         * method.
178         * <p>
179         * @return A UDP datagram containing the TFTP error packet.
180         ***/
181        public DatagramPacket newDatagram()
182        {
183            byte[] data;
184            int length;
185    
186            length = _message.length();
187    
188            data = new byte[length + 5];
189            data[0] = 0;
190            data[1] = (byte)_type;
191            data[2] = (byte)((_error & 0xffff) >> 8);
192            data[3] = (byte)(_error & 0xff);
193    
194            System.arraycopy(_message.getBytes(), 0, data, 4, length);
195    
196            data[length + 4] = 0;
197    
198            return new DatagramPacket(data, data.length, _address, _port);
199        }
200    
201    
202        /***
203         * Returns the error code of the packet.
204         * <p>
205         * @return The error code of the packet.
206         ***/
207        public int getError()
208        {
209            return _error;
210        }
211    
212    
213        /***
214         * Returns the error message of the packet.
215         * <p>
216         * @return The error message of the packet.
217         ***/
218        public String getMessage()
219        {
220            return _message;
221        }
222    }