summaryrefslogtreecommitdiff
path: root/org/apache/commons/net/tftp/TFTPClient.java
diff options
context:
space:
mode:
Diffstat (limited to 'org/apache/commons/net/tftp/TFTPClient.java')
-rw-r--r--org/apache/commons/net/tftp/TFTPClient.java610
1 files changed, 0 insertions, 610 deletions
diff --git a/org/apache/commons/net/tftp/TFTPClient.java b/org/apache/commons/net/tftp/TFTPClient.java
deleted file mode 100644
index 71d4ec6..0000000
--- a/org/apache/commons/net/tftp/TFTPClient.java
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * 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.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import org.apache.commons.net.io.FromNetASCIIOutputStream;
-import org.apache.commons.net.io.ToNetASCIIInputStream;
-
-/***
- * The TFTPClient class encapsulates all the aspects of the TFTP protocol
- * necessary to receive and send files through TFTP. It is derived from
- * the {@link org.apache.commons.net.tftp.TFTP} because
- * it is more convenient than using aggregation, and as a result exposes
- * the same set of methods to allow you to deal with the TFTP protocol
- * directly. However, almost every user should only be concerend with the
- * the {@link org.apache.commons.net.DatagramSocketClient#open open() },
- * {@link org.apache.commons.net.DatagramSocketClient#close close() },
- * {@link #sendFile sendFile() }, and
- * {@link #receiveFile receiveFile() } methods. Additionally, the
- * {@link #setMaxTimeouts setMaxTimeouts() } and
- * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() }
- * methods may be of importance for performance
- * tuning.
- * <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.
- * <p>
- * <p>
- * @author Daniel F. Savarese
- * @see TFTP
- * @see TFTPPacket
- * @see TFTPPacketException
- ***/
-
-public class TFTPClient extends TFTP
-{
- /***
- * The default number of times a receive attempt is allowed to timeout
- * before ending attempts to retry the receive and failing. The default
- * is 5 timeouts.
- ***/
- public static final int DEFAULT_MAX_TIMEOUTS = 5;
-
- /*** The maximum number of timeouts allowed before failing. ***/
- private int __maxTimeouts;
-
- /***
- * Creates a TFTPClient instance with a default timeout of DEFAULT_TIMEOUT,
- * maximum timeouts value of DEFAULT_MAX_TIMEOUTS, a null socket,
- * and buffered operations disabled.
- ***/
- public TFTPClient()
- {
- __maxTimeouts = DEFAULT_MAX_TIMEOUTS;
- }
-
- /***
- * Sets the maximum number of times a receive attempt is allowed to
- * timeout during a receiveFile() or sendFile() operation before ending
- * attempts to retry the receive and failing.
- * The default is DEFAULT_MAX_TIMEOUTS.
- * <p>
- * @param numTimeouts The maximum number of timeouts to allow. Values
- * less than 1 should not be used, but if they are, they are
- * treated as 1.
- ***/
- public void setMaxTimeouts(int numTimeouts)
- {
- if (numTimeouts < 1)
- __maxTimeouts = 1;
- else
- __maxTimeouts = numTimeouts;
- }
-
- /***
- * Returns the maximum number of times a receive attempt is allowed to
- * timeout before ending attempts to retry the receive and failing.
- * <p>
- * @return The maximum number of timeouts allowed.
- ***/
- public int getMaxTimeouts()
- {
- return __maxTimeouts;
- }
-
-
- /***
- * Requests a named file from a remote host, writes the
- * file to an OutputStream, closes the connection, and returns the number
- * of bytes read. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the OutputStream
- * containing the file; you must close it after the method invocation.
- * <p>
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param host The remote host serving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- InetAddress host, int port) throws IOException
- {
- int bytesRead, timeouts, lastBlock, block, hostPort, dataLength;
- TFTPPacket sent, received = null;
- TFTPErrorPacket error;
- TFTPDataPacket data;
- TFTPAckPacket ack = new TFTPAckPacket(host, port, 0);
-
- beginBufferedOps();
-
- dataLength = lastBlock = hostPort = bytesRead = 0;
- block = 1;
-
- if (mode == TFTP.ASCII_MODE)
- output = new FromNetASCIIOutputStream(output);
-
- sent =
- new TFTPReadRequestPacket(host, port, filename, mode);
-
-_sendPacket:
- do
- {
- bufferedSend(sent);
-
-_receivePacket:
- while (true)
- {
- timeouts = 0;
- while (timeouts < __maxTimeouts)
- {
- try
- {
- received = bufferedReceive();
- break;
- }
- catch (SocketException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (InterruptedIOException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (TFTPPacketException e)
- {
- endBufferedOps();
- throw new IOException("Bad packet: " + e.getMessage());
- }
- }
-
- // The first time we receive we get the port number and
- // answering host address (for hosts with multiple IPs)
- if (lastBlock == 0)
- {
- hostPort = received.getPort();
- ack.setPort(hostPort);
- if(!host.equals(received.getAddress()))
- {
- host = received.getAddress();
- ack.setAddress(host);
- sent.setAddress(host);
- }
- }
-
- // Comply with RFC 783 indication that an error acknowledgement
- // should be sent to originator if unexpected TID or host.
- if (host.equals(received.getAddress()) &&
- received.getPort() == hostPort)
- {
-
- switch (received.getType())
- {
- case TFTPPacket.ERROR:
- error = (TFTPErrorPacket)received;
- endBufferedOps();
- throw new IOException("Error code " + error.getError() +
- " received: " + error.getMessage());
- case TFTPPacket.DATA:
- data = (TFTPDataPacket)received;
- dataLength = data.getDataLength();
-
- lastBlock = data.getBlockNumber();
-
- if (lastBlock == block)
- {
- try
- {
- output.write(data.getData(), data.getDataOffset(),
- dataLength);
- }
- catch (IOException e)
- {
- error = new TFTPErrorPacket(host, hostPort,
- TFTPErrorPacket.OUT_OF_SPACE,
- "File write failed.");
- bufferedSend(error);
- endBufferedOps();
- throw e;
- }
- ++block;
- if (block > 65535)
- {
- // wrap the block number
- block = 0;
- }
-
- break _receivePacket;
- }
- else
- {
- discardPackets();
-
- if (lastBlock == (block == 0 ? 65535 : (block - 1)))
- continue _sendPacket; // Resend last acknowledgement.
-
- continue _receivePacket; // Start fetching packets again.
- }
- //break;
-
- default:
- endBufferedOps();
- throw new IOException("Received unexpected packet type.");
- }
- }
- else
- {
- error = new TFTPErrorPacket(received.getAddress(),
- received.getPort(),
- TFTPErrorPacket.UNKNOWN_TID,
- "Unexpected host or port.");
- bufferedSend(error);
- continue _sendPacket;
- }
-
- // We should never get here, but this is a safety to avoid
- // infinite loop. If only Java had the goto statement.
- //break;
- }
-
- ack.setBlockNumber(lastBlock);
- sent = ack;
- bytesRead += dataLength;
- } // First data packet less than 512 bytes signals end of stream.
-
- while (dataLength == TFTPPacket.SEGMENT_SIZE);
-
- bufferedSend(sent);
- endBufferedOps();
-
- return bytesRead;
- }
-
-
- /***
- * Requests a named file from a remote host, writes the
- * file to an OutputStream, closes the connection, and returns the number
- * of bytes read. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the OutputStream
- * containing the file; you must close it after the method invocation.
- * <p>
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param hostname The name of the remote host serving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- String hostname, int port)
- throws UnknownHostException, IOException
- {
- return receiveFile(filename, mode, output, InetAddress.getByName(hostname),
- port);
- }
-
-
- /***
- * Same as calling receiveFile(filename, mode, output, host, TFTP.DEFAULT_PORT).
- *
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param host The remote host serving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- InetAddress host)
- throws IOException
- {
- return receiveFile(filename, mode, output, host, DEFAULT_PORT);
- }
-
- /***
- * Same as calling receiveFile(filename, mode, output, hostname, TFTP.DEFAULT_PORT).
- *
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param hostname The name of the remote host serving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- String hostname)
- throws UnknownHostException, IOException
- {
- return receiveFile(filename, mode, output, InetAddress.getByName(hostname),
- DEFAULT_PORT);
- }
-
-
- /***
- * Requests to send a file to a remote host, reads the file from an
- * InputStream, sends the file to the remote host, and closes the
- * connection. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the InputStream
- * containing the file; you must close it after the method invocation.
- * <p>
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param host The remote host receiving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- InetAddress host, int port) throws IOException
- {
- int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset, totalThisPacket;
- TFTPPacket sent, received = null;
- TFTPErrorPacket error;
- TFTPDataPacket data =
- new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0);
- TFTPAckPacket ack;
-
- boolean justStarted = true;
-
- beginBufferedOps();
-
- dataLength = lastBlock = hostPort = bytesRead = totalThisPacket = 0;
- block = 0;
- boolean lastAckWait = false;
-
- if (mode == TFTP.ASCII_MODE)
- input = new ToNetASCIIInputStream(input);
-
- sent =
- new TFTPWriteRequestPacket(host, port, filename, mode);
-
-_sendPacket:
- do
- {
- // first time: block is 0, lastBlock is 0, send a request packet.
- // subsequent: block is integer starting at 1, send data packet.
- bufferedSend(sent);
-
- // this is trying to receive an ACK
-_receivePacket:
- while (true)
- {
-
-
- timeouts = 0;
- while (timeouts < __maxTimeouts)
- {
- try
- {
- received = bufferedReceive();
- break;
- }
- catch (SocketException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (InterruptedIOException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (TFTPPacketException e)
- {
- endBufferedOps();
- throw new IOException("Bad packet: " + e.getMessage());
- }
- } // end of while loop over tries to receive
-
- // The first time we receive we get the port number and
- // answering host address (for hosts with multiple IPs)
- if (justStarted)
- {
- justStarted = false;
- hostPort = received.getPort();
- data.setPort(hostPort);
- if(!host.equals(received.getAddress()))
- {
- host = received.getAddress();
- data.setAddress(host);
- sent.setAddress(host);
- }
- }
-
- // Comply with RFC 783 indication that an error acknowledgement
- // should be sent to originator if unexpected TID or host.
- if (host.equals(received.getAddress()) &&
- received.getPort() == hostPort)
- {
-
- switch (received.getType())
- {
- case TFTPPacket.ERROR:
- error = (TFTPErrorPacket)received;
- endBufferedOps();
- throw new IOException("Error code " + error.getError() +
- " received: " + error.getMessage());
- case TFTPPacket.ACKNOWLEDGEMENT:
- ack = (TFTPAckPacket)received;
-
- lastBlock = ack.getBlockNumber();
-
- if (lastBlock == block)
- {
- ++block;
- if (block > 65535)
- {
- // wrap the block number
- block = 0;
- }
- if (lastAckWait) {
-
- break _sendPacket;
- }
- else {
- break _receivePacket;
- }
- }
- else
- {
- discardPackets();
-
- if (lastBlock == (block == 0 ? 65535 : (block - 1)))
- continue _sendPacket; // Resend last acknowledgement.
-
- continue _receivePacket; // Start fetching packets again.
- }
- //break;
-
- default:
- endBufferedOps();
- throw new IOException("Received unexpected packet type.");
- }
- }
- else
- {
- error = new TFTPErrorPacket(received.getAddress(),
- received.getPort(),
- TFTPErrorPacket.UNKNOWN_TID,
- "Unexpected host or port.");
- bufferedSend(error);
- continue _sendPacket;
- }
-
- // We should never get here, but this is a safety to avoid
- // infinite loop. If only Java had the goto statement.
- //break;
- }
-
- // OK, we have just gotten ACK about the last data we sent. Make another
- // and send it
-
- dataLength = TFTPPacket.SEGMENT_SIZE;
- offset = 4;
- totalThisPacket = 0;
- while (dataLength > 0 &&
- (bytesRead = input.read(_sendBuffer, offset, dataLength)) > 0)
- {
- offset += bytesRead;
- dataLength -= bytesRead;
- totalThisPacket += bytesRead;
- }
-
- if( totalThisPacket < TFTPPacket.SEGMENT_SIZE ) {
- /* this will be our last packet -- send, wait for ack, stop */
- lastAckWait = true;
- }
- data.setBlockNumber(block);
- data.setData(_sendBuffer, 4, totalThisPacket);
- sent = data;
- }
- while ( totalThisPacket > 0 || lastAckWait );
- // Note: this was looping while dataLength == 0 || lastAckWait,
- // which was discarding the last packet if it was not full size
- // Should send the packet.
-
- endBufferedOps();
- }
-
-
- /***
- * Requests to send a file to a remote host, reads the file from an
- * InputStream, sends the file to the remote host, and closes the
- * connection. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the InputStream
- * containing the file; you must close it after the method invocation.
- * <p>
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param hostname The name of the remote host receiving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- String hostname, int port)
- throws UnknownHostException, IOException
- {
- sendFile(filename, mode, input, InetAddress.getByName(hostname), port);
- }
-
-
- /***
- * Same as calling sendFile(filename, mode, input, host, TFTP.DEFAULT_PORT).
- *
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param host The name of the remote host receiving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- InetAddress host)
- throws IOException
- {
- sendFile(filename, mode, input, host, DEFAULT_PORT);
- }
-
- /***
- * Same as calling sendFile(filename, mode, input, hostname, TFTP.DEFAULT_PORT).
- *
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param hostname The name of the remote host receiving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- String hostname)
- throws UnknownHostException, IOException
- {
- sendFile(filename, mode, input, InetAddress.getByName(hostname),
- DEFAULT_PORT);
- }
-}