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