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