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 }