1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.net.tftp;
17
18 import java.net.DatagramPacket;
19 import java.net.InetAddress;
20
21 /***
22 * A final class derived from TFTPPacket definiing the TFTP Error
23 * packet type.
24 * <p>
25 * Details regarding the TFTP protocol and the format of TFTP packets can
26 * be found in RFC 783. But the point of these classes is to keep you
27 * from having to worry about the internals. Additionally, only very
28 * few people should have to care about any of the TFTPPacket classes
29 * or derived classes. Almost all users should only be concerned with the
30 * {@link org.apache.commons.net.tftp.TFTPClient} class
31 * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
32 * and
33 * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
34 * methods.
35 * <p>
36 * <p>
37 * @author Daniel F. Savarese
38 * @see TFTPPacket
39 * @see TFTPPacketException
40 * @see TFTP
41 ***/
42
43 public final class TFTPErrorPacket extends TFTPPacket
44 {
45 /*** The undefined error code according to RFC 783, value 0. ***/
46 public static final int UNDEFINED = 0;
47
48 /*** The file not found error code according to RFC 783, value 1. ***/
49 public static final int FILE_NOT_FOUND = 1;
50
51 /*** The access violation error code according to RFC 783, value 2. ***/
52 public static final int ACCESS_VIOLATION = 2;
53
54 /*** The disk full error code according to RFC 783, value 3. ***/
55 public static final int OUT_OF_SPACE = 3;
56
57 /***
58 * The illegal TFTP operation error code according to RFC 783, value 4.
59 ***/
60 public static final int ILLEGAL_OPERATION = 4;
61
62 /*** The unknown transfer id error code according to RFC 783, value 5. ***/
63 public static final int UNKNOWN_TID = 5;
64
65 /*** The file already exists error code according to RFC 783, value 6. ***/
66 public static final int FILE_EXISTS = 6;
67
68 /*** The no such user error code according to RFC 783, value 7. ***/
69 public static final int NO_SUCH_USER = 7;
70
71 /*** The error code of this packet. ***/
72 int _error;
73
74 /*** The error message of this packet. ***/
75 String _message;
76
77 /***
78 * Creates an error packet to be sent to a host at a given port
79 * with an error code and error message.
80 * <p>
81 * @param destination The host to which the packet is going to be sent.
82 * @param port The port to which the packet is going to be sent.
83 * @param error The error code of the packet.
84 * @param message The error message of the packet.
85 ***/
86 public TFTPErrorPacket(InetAddress destination, int port,
87 int error, String message)
88 {
89 super(TFTPPacket.ERROR, destination, port);
90
91 _error = error;
92 _message = message;
93 }
94
95 /***
96 * Creates an error packet based from a received
97 * datagram. Assumes the datagram is at least length 4, else an
98 * ArrayIndexOutOfBoundsException may be thrown.
99 * <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 }