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 * @see TFTPPacket 040 * @see TFTPPacketException 041 * @see TFTP 042 ***/ 043 044 public 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 int _error; 074 075 /*** The error message of this packet. ***/ 076 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 * <p> 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(InetAddress destination, int port, 088 int error, String message) 089 { 090 super(TFTPPacket.ERROR, destination, port); 091 092 _error = error; 093 _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 * <p> 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(DatagramPacket datagram) throws TFTPPacketException 106 { 107 super(TFTPPacket.ERROR, datagram.getAddress(), datagram.getPort()); 108 int index, length; 109 byte[] data; 110 StringBuilder buffer; 111 112 data = datagram.getData(); 113 length = datagram.getLength(); 114 115 if (getType() != data[1]) { 116 throw new TFTPPacketException("TFTP operator code does not match type."); 117 } 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 125 index = 4; 126 buffer = new StringBuilder(); 127 128 while (index < length && data[index] != 0) 129 { 130 buffer.append((char)data[index]); 131 ++index; 132 } 133 134 _message = buffer.toString(); 135 } 136 137 /*** 138 * This is a method only available within the package for 139 * implementing efficient datagram transport by elminating buffering. 140 * It takes a datagram as an argument, and a byte buffer in which 141 * to store the raw datagram data. Inside the method, the data 142 * is set as the datagram's data and the datagram returned. 143 * <p> 144 * @param datagram The datagram to create. 145 * @param data The buffer to store the packet and to use in the datagram. 146 * @return The datagram argument. 147 ***/ 148 @Override 149 DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data) 150 { 151 int length; 152 153 length = _message.length(); 154 155 data[0] = 0; 156 data[1] = (byte)_type; 157 data[2] = (byte)((_error & 0xffff) >> 8); 158 data[3] = (byte)(_error & 0xff); 159 160 System.arraycopy(_message.getBytes(), 0, data, 4, length); 161 162 data[length + 4] = 0; 163 164 datagram.setAddress(_address); 165 datagram.setPort(_port); 166 datagram.setData(data); 167 datagram.setLength(length + 4); 168 169 return datagram; 170 } 171 172 173 /*** 174 * Creates a UDP datagram containing all the TFTP 175 * error packet data in the proper format. 176 * This is a method exposed to the programmer in case he 177 * wants to implement his own TFTP client instead of using 178 * the {@link org.apache.commons.net.tftp.TFTPClient} 179 * class. 180 * Under normal circumstances, you should not have a need to call this 181 * method. 182 * <p> 183 * @return A UDP datagram containing the TFTP error packet. 184 ***/ 185 @Override 186 public DatagramPacket newDatagram() 187 { 188 byte[] data; 189 int length; 190 191 length = _message.length(); 192 193 data = new byte[length + 5]; 194 data[0] = 0; 195 data[1] = (byte)_type; 196 data[2] = (byte)((_error & 0xffff) >> 8); 197 data[3] = (byte)(_error & 0xff); 198 199 System.arraycopy(_message.getBytes(), 0, data, 4, length); 200 201 data[length + 4] = 0; 202 203 return new DatagramPacket(data, data.length, _address, _port); 204 } 205 206 207 /*** 208 * Returns the error code of the packet. 209 * <p> 210 * @return The error code of the packet. 211 ***/ 212 public int getError() 213 { 214 return _error; 215 } 216 217 218 /*** 219 * Returns the error message of the packet. 220 * <p> 221 * @return The error message of the packet. 222 ***/ 223 public String getMessage() 224 { 225 return _message; 226 } 227 }