blob: 4c93cadc47dbf1bbaafb1d930c0ac6ed12282fd9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.net.tftp;
import java.net.DatagramPacket;
import java.net.InetAddress;
/***
* A final class derived from TFTPPacket definiing the TFTP Error
* packet type.
* <p>
* Details regarding the TFTP protocol and the format of TFTP packets can
* be found in RFC 783. But the point of these classes is to keep you
* from having to worry about the internals. Additionally, only very
* few people should have to care about any of the TFTPPacket classes
* or derived classes. Almost all users should only be concerned with the
* {@link org.apache.commons.net.tftp.TFTPClient} class
* {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
* and
* {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
* methods.
*
*
* @see TFTPPacket
* @see TFTPPacketException
* @see TFTP
***/
public final class TFTPErrorPacket extends TFTPPacket
{
/*** The undefined error code according to RFC 783, value 0. ***/
public static final int UNDEFINED = 0;
/*** The file not found error code according to RFC 783, value 1. ***/
public static final int FILE_NOT_FOUND = 1;
/*** The access violation error code according to RFC 783, value 2. ***/
public static final int ACCESS_VIOLATION = 2;
/*** The disk full error code according to RFC 783, value 3. ***/
public static final int OUT_OF_SPACE = 3;
/***
* The illegal TFTP operation error code according to RFC 783, value 4.
***/
public static final int ILLEGAL_OPERATION = 4;
/*** The unknown transfer id error code according to RFC 783, value 5. ***/
public static final int UNKNOWN_TID = 5;
/*** The file already exists error code according to RFC 783, value 6. ***/
public static final int FILE_EXISTS = 6;
/*** The no such user error code according to RFC 783, value 7. ***/
public static final int NO_SUCH_USER = 7;
/*** The error code of this packet. ***/
private final int error;
/*** The error message of this packet. ***/
private final String message;
/***
* Creates an error packet to be sent to a host at a given port
* with an error code and error message.
*
* @param destination The host to which the packet is going to be sent.
* @param port The port to which the packet is going to be sent.
* @param error The error code of the packet.
* @param message The error message of the packet.
***/
public TFTPErrorPacket(final InetAddress destination, final int port,
final int error, final String message)
{
super(TFTPPacket.ERROR, destination, port);
this.error = error;
this.message = message;
}
/***
* Creates an error packet based from a received
* datagram. Assumes the datagram is at least length 4, else an
* ArrayIndexOutOfBoundsException may be thrown.
*
* @param datagram The datagram containing the received error.
* @throws TFTPPacketException If the datagram isn't a valid TFTP
* error packet.
***/
TFTPErrorPacket(final DatagramPacket datagram) throws TFTPPacketException
{
super(TFTPPacket.ERROR, datagram.getAddress(), datagram.getPort());
int index, length;
byte[] data;
StringBuilder buffer;
data = datagram.getData();
length = datagram.getLength();
if (getType() != data[1]) {
throw new TFTPPacketException("TFTP operator code does not match type.");
}
error = (data[2] & 0xff) << 8 | data[3] & 0xff;
if (length < 5) {
throw new TFTPPacketException("Bad error packet. No message.");
}
index = 4;
buffer = new StringBuilder();
while (index < length && data[index] != 0)
{
buffer.append((char)data[index]);
++index;
}
message = buffer.toString();
}
/***
* This is a method only available within the package for
* implementing efficient datagram transport by elminating buffering.
* It takes a datagram as an argument, and a byte buffer in which
* to store the raw datagram data. Inside the method, the data
* is set as the datagram's data and the datagram returned.
*
* @param datagram The datagram to create.
* @param data The buffer to store the packet and to use in the datagram.
* @return The datagram argument.
***/
@Override
DatagramPacket _newDatagram(final DatagramPacket datagram, final byte[] data)
{
int length;
length = message.length();
data[0] = 0;
data[1] = (byte)type;
data[2] = (byte)((error & 0xffff) >> 8);
data[3] = (byte)(error & 0xff);
System.arraycopy(message.getBytes(), 0, data, 4, length);
data[length + 4] = 0;
datagram.setAddress(address);
datagram.setPort(port);
datagram.setData(data);
datagram.setLength(length + 4);
return datagram;
}
/***
* Creates a UDP datagram containing all the TFTP
* error packet data in the proper format.
* This is a method exposed to the programmer in case he
* wants to implement his own TFTP client instead of using
* the {@link org.apache.commons.net.tftp.TFTPClient}
* class.
* Under normal circumstances, you should not have a need to call this
* method.
*
* @return A UDP datagram containing the TFTP error packet.
***/
@Override
public DatagramPacket newDatagram()
{
byte[] data;
int length;
length = message.length();
data = new byte[length + 5];
data[0] = 0;
data[1] = (byte)type;
data[2] = (byte)((error & 0xffff) >> 8);
data[3] = (byte)(error & 0xff);
System.arraycopy(message.getBytes(), 0, data, 4, length);
data[length + 4] = 0;
return new DatagramPacket(data, data.length, address, port);
}
/***
* Returns the error code of the packet.
*
* @return The error code of the packet.
***/
public int getError()
{
return error;
}
/***
* Returns the error message of the packet.
*
* @return The error message of the packet.
***/
public String getMessage()
{
return message;
}
/**
* For debugging
* @since 3.6
*/
@Override
public String toString() {
return super.toString() + " ERR " + error + " " + message;
}
}