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 }