TFTPExample.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.net.examples.ftp;

  18. import java.io.Closeable;
  19. import java.io.File;
  20. import java.io.FileInputStream;
  21. import java.io.FileOutputStream;
  22. import java.io.IOException;
  23. import java.net.SocketException;
  24. import java.net.UnknownHostException;
  25. import java.time.Duration;

  26. import org.apache.commons.net.tftp.TFTP;
  27. import org.apache.commons.net.tftp.TFTPClient;
  28. import org.apache.commons.net.tftp.TFTPPacket;

  29. /**
  30.  * This is an example of a simple Java TFTP client. Notice how all the code is really just argument processing and error handling.
  31.  * <p>
  32.  * Usage: TFTPExample [options] hostname localfile remotefile hostname - The name of the remote host, with optional :port localfile - The name of the local file
  33.  * to send or the name to use for the received file remotefile - The name of the remote file to receive or the name for the remote server to use to name the
  34.  * local file being sent. options: (The default is to assume -r -b) -s Send a local file -r Receive a remote file -a Use ASCII transfer mode -b Use binary
  35.  * transfer mode.
  36.  * </p>
  37.  */
  38. public final class TFTPExample {
  39.     static final String USAGE = "Usage: TFTPExample [options] hostname localfile remotefile\n\n" + "hostname   - The name of the remote host [:port]\n"
  40.             + "localfile  - The name of the local file to send or the name to use for\n" + "\tthe received file\n"
  41.             + "remotefile - The name of the remote file to receive or the name for\n" + "\tthe remote server to use to name the local file being sent.\n\n"
  42.             + "options: (The default is to assume -r -b)\n" + "\t-t timeout in seconds (default 60s)\n" + "\t-s Send a local file\n"
  43.             + "\t-r Receive a remote file\n" + "\t-a Use ASCII transfer mode\n" + "\t-b Use binary transfer mode\n" + "\t-v Verbose (trace packets)\n";

  44.     private static boolean close(final TFTPClient tftp, final Closeable output) {
  45.         boolean closed;
  46.         tftp.close();
  47.         try {
  48.             if (output != null) {
  49.                 output.close();
  50.             }
  51.             closed = true;
  52.         } catch (final IOException e) {
  53.             closed = false;
  54.             System.err.println("Error: error closing file.");
  55.             System.err.println(e.getMessage());
  56.         }
  57.         return closed;
  58.     }

  59.     public static void main(final String[] args) throws IOException {
  60.         boolean receiveFile = true, closed;
  61.         int transferMode = TFTP.BINARY_MODE, argc;
  62.         String arg;
  63.         final String hostname;
  64.         final String localFilename;
  65.         final String remoteFilename;
  66.         final TFTPClient tftp;
  67.         int timeout = 60000;
  68.         boolean verbose = false;

  69.         // Parse options
  70.         for (argc = 0; argc < args.length; argc++) {
  71.             arg = args[argc];
  72.             if (!arg.startsWith("-")) {
  73.                 break;
  74.             }
  75.             if (arg.equals("-r")) {
  76.                 receiveFile = true;
  77.             } else if (arg.equals("-s")) {
  78.                 receiveFile = false;
  79.             } else if (arg.equals("-a")) {
  80.                 transferMode = TFTP.ASCII_MODE;
  81.             } else if (arg.equals("-b")) {
  82.                 transferMode = TFTP.BINARY_MODE;
  83.             } else if (arg.equals("-t")) {
  84.                 timeout = 1000 * Integer.parseInt(args[++argc]);
  85.             } else if (arg.equals("-v")) {
  86.                 verbose = true;
  87.             } else {
  88.                 System.err.println("Error: unrecognized option.");
  89.                 System.err.print(USAGE);
  90.                 System.exit(1);
  91.             }
  92.         }

  93.         // Make sure there are enough arguments
  94.         if (args.length - argc != 3) {
  95.             System.err.println("Error: invalid number of arguments.");
  96.             System.err.print(USAGE);
  97.             System.exit(1);
  98.         }

  99.         // Get host and file arguments
  100.         hostname = args[argc];
  101.         localFilename = args[argc + 1];
  102.         remoteFilename = args[argc + 2];

  103.         // Create our TFTP instance to handle the file transfer.
  104.         if (verbose) {
  105.             tftp = new TFTPClient() {
  106.                 @Override
  107.                 protected void trace(final String direction, final TFTPPacket packet) {
  108.                     System.out.println(direction + " " + packet);
  109.                 }
  110.             };
  111.         } else {
  112.             tftp = new TFTPClient();
  113.         }

  114.         // We want to timeout if a response takes longer than 60 seconds
  115.         tftp.setDefaultTimeout(Duration.ofSeconds(timeout));

  116.         // We haven't closed the local file yet.
  117.         closed = false;

  118.         // If we're receiving a file, receive, otherwise send.
  119.         if (receiveFile) {
  120.             closed = receive(transferMode, hostname, localFilename, remoteFilename, tftp);
  121.         } else {
  122.             // We're sending a file
  123.             closed = send(transferMode, hostname, localFilename, remoteFilename, tftp);
  124.         }

  125.         System.out.println("Recd: " + tftp.getTotalBytesReceived() + " Sent: " + tftp.getTotalBytesSent());

  126.         if (!closed) {
  127.             System.out.println("Failed");
  128.             System.exit(1);
  129.         }

  130.         System.out.println("OK");
  131.     }

  132.     private static void open(final TFTPClient tftp) throws IOException {
  133.         try {
  134.             tftp.open();
  135.         } catch (final SocketException e) {
  136.             throw new IOException("Error: could not open local UDP socket.", e);
  137.         }
  138.     }

  139.     private static boolean receive(final int transferMode, final String hostname, final String localFilename, final String remoteFilename,
  140.             final TFTPClient tftp) throws IOException {
  141.         final File file = new File(localFilename);
  142.         // If file exists, don't overwrite it.
  143.         if (file.exists()) {
  144.             System.err.println("Error: " + localFilename + " already exists.");
  145.             return false;
  146.         }
  147.         FileOutputStream output;
  148.         // Try to open local file for writing
  149.         try {
  150.             output = new FileOutputStream(file);
  151.         } catch (final IOException e) {
  152.             tftp.close();
  153.             throw new IOException("Error: could not open local file for writing.", e);
  154.         }
  155.         open(tftp);
  156.         final boolean closed;
  157.         // Try to receive remote file via TFTP
  158.         try {
  159.             final String[] parts = hostname.split(":");
  160.             if (parts.length == 2) {
  161.                 tftp.receiveFile(remoteFilename, transferMode, output, parts[0], Integer.parseInt(parts[1]));
  162.             } else {
  163.                 tftp.receiveFile(remoteFilename, transferMode, output, hostname);
  164.             }
  165.         } catch (final UnknownHostException e) {
  166.             System.err.println("Error: could not resolve hostname.");
  167.             System.err.println(e.getMessage());
  168.             System.exit(1);
  169.         } catch (final IOException e) {
  170.             System.err.println("Error: I/O exception occurred while receiving file.");
  171.             System.err.println(e.getMessage());
  172.             System.exit(1);
  173.         } finally {
  174.             // Close local socket and output file
  175.             closed = close(tftp, output);
  176.         }
  177.         return closed;
  178.     }

  179.     private static boolean send(final int transferMode, final String hostname, final String localFilename, final String remoteFilename, final TFTPClient tftp)
  180.             throws IOException {
  181.         FileInputStream input;
  182.         // Try to open local file for reading
  183.         try {
  184.             input = new FileInputStream(localFilename);
  185.         } catch (final IOException e) {
  186.             tftp.close();
  187.             throw new IOException("Error: could not open local file for reading.", e);
  188.         }
  189.         open(tftp);
  190.         final boolean closed;
  191.         // Try to send local file via TFTP
  192.         try {
  193.             final String[] parts = hostname.split(":");
  194.             if (parts.length == 2) {
  195.                 tftp.sendFile(remoteFilename, transferMode, input, parts[0], Integer.parseInt(parts[1]));
  196.             } else {
  197.                 tftp.sendFile(remoteFilename, transferMode, input, hostname);
  198.             }
  199.         } catch (final UnknownHostException e) {
  200.             System.err.println("Error: could not resolve hostname.");
  201.             System.err.println(e.getMessage());
  202.             System.exit(1);
  203.         } catch (final IOException e) {
  204.             System.err.println("Error: I/O exception occurred while sending file.");
  205.             System.err.println(e.getMessage());
  206.             System.exit(1);
  207.         } finally {
  208.             // Close local socket and input file
  209.             closed = close(tftp, input);
  210.         }
  211.         return closed;
  212.     }

  213. }