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 018package org.apache.commons.net.examples.ftp; 019 020import java.io.Closeable; 021import java.io.File; 022import java.io.FileInputStream; 023import java.io.FileOutputStream; 024import java.io.IOException; 025import java.net.SocketException; 026import java.net.UnknownHostException; 027import java.time.Duration; 028 029import org.apache.commons.net.tftp.TFTP; 030import org.apache.commons.net.tftp.TFTPClient; 031import org.apache.commons.net.tftp.TFTPPacket; 032 033/** 034 * This is an example of a simple Java TFTP client. Notice how all the code is really just argument processing and error handling. 035 * <p> 036 * Usage: TFTPExample [options] hostname localfile remotefile hostname - The name of the remote host, with optional :port localfile - The name of the local file 037 * 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 038 * 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 039 * transfer mode. 040 * </p> 041 */ 042public final class TFTPExample { 043 static final String USAGE = "Usage: TFTPExample [options] hostname localfile remotefile\n\n" + "hostname - The name of the remote host [:port]\n" 044 + "localfile - The name of the local file to send or the name to use for\n" + "\tthe received file\n" 045 + "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" 046 + "options: (The default is to assume -r -b)\n" + "\t-t timeout in seconds (default 60s)\n" + "\t-s Send a local file\n" 047 + "\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"; 048 049 private static boolean close(final TFTPClient tftp, final Closeable output) { 050 boolean closed; 051 tftp.close(); 052 try { 053 if (output != null) { 054 output.close(); 055 } 056 closed = true; 057 } catch (final IOException e) { 058 closed = false; 059 System.err.println("Error: error closing file."); 060 System.err.println(e.getMessage()); 061 } 062 return closed; 063 } 064 065 public static void main(final String[] args) throws IOException { 066 boolean receiveFile = true, closed; 067 int transferMode = TFTP.BINARY_MODE, argc; 068 String arg; 069 final String hostname; 070 final String localFilename; 071 final String remoteFilename; 072 final TFTPClient tftp; 073 int timeout = 60000; 074 boolean verbose = false; 075 076 // Parse options 077 for (argc = 0; argc < args.length; argc++) { 078 arg = args[argc]; 079 if (!arg.startsWith("-")) { 080 break; 081 } 082 if (arg.equals("-r")) { 083 receiveFile = true; 084 } else if (arg.equals("-s")) { 085 receiveFile = false; 086 } else if (arg.equals("-a")) { 087 transferMode = TFTP.ASCII_MODE; 088 } else if (arg.equals("-b")) { 089 transferMode = TFTP.BINARY_MODE; 090 } else if (arg.equals("-t")) { 091 timeout = 1000 * Integer.parseInt(args[++argc]); 092 } else if (arg.equals("-v")) { 093 verbose = true; 094 } else { 095 System.err.println("Error: unrecognized option."); 096 System.err.print(USAGE); 097 System.exit(1); 098 } 099 } 100 101 // Make sure there are enough arguments 102 if (args.length - argc != 3) { 103 System.err.println("Error: invalid number of arguments."); 104 System.err.print(USAGE); 105 System.exit(1); 106 } 107 108 // Get host and file arguments 109 hostname = args[argc]; 110 localFilename = args[argc + 1]; 111 remoteFilename = args[argc + 2]; 112 113 // Create our TFTP instance to handle the file transfer. 114 if (verbose) { 115 tftp = new TFTPClient() { 116 @Override 117 protected void trace(final String direction, final TFTPPacket packet) { 118 System.out.println(direction + " " + packet); 119 } 120 }; 121 } else { 122 tftp = new TFTPClient(); 123 } 124 125 // We want to timeout if a response takes longer than 60 seconds 126 tftp.setDefaultTimeout(Duration.ofSeconds(timeout)); 127 128 // We haven't closed the local file yet. 129 closed = false; 130 131 // If we're receiving a file, receive, otherwise send. 132 if (receiveFile) { 133 closed = receive(transferMode, hostname, localFilename, remoteFilename, tftp); 134 } else { 135 // We're sending a file 136 closed = send(transferMode, hostname, localFilename, remoteFilename, tftp); 137 } 138 139 System.out.println("Recd: " + tftp.getTotalBytesReceived() + " Sent: " + tftp.getTotalBytesSent()); 140 141 if (!closed) { 142 System.out.println("Failed"); 143 System.exit(1); 144 } 145 146 System.out.println("OK"); 147 } 148 149 private static void open(final TFTPClient tftp) throws IOException { 150 try { 151 tftp.open(); 152 } catch (final SocketException e) { 153 throw new IOException("Error: could not open local UDP socket.", e); 154 } 155 } 156 157 private static boolean receive(final int transferMode, final String hostname, final String localFilename, final String remoteFilename, 158 final TFTPClient tftp) throws IOException { 159 final File file = new File(localFilename); 160 // If file exists, don't overwrite it. 161 if (file.exists()) { 162 System.err.println("Error: " + localFilename + " already exists."); 163 return false; 164 } 165 FileOutputStream output; 166 // Try to open local file for writing 167 try { 168 output = new FileOutputStream(file); 169 } catch (final IOException e) { 170 tftp.close(); 171 throw new IOException("Error: could not open local file for writing.", e); 172 } 173 open(tftp); 174 final boolean closed; 175 // Try to receive remote file via TFTP 176 try { 177 final String[] parts = hostname.split(":"); 178 if (parts.length == 2) { 179 tftp.receiveFile(remoteFilename, transferMode, output, parts[0], Integer.parseInt(parts[1])); 180 } else { 181 tftp.receiveFile(remoteFilename, transferMode, output, hostname); 182 } 183 } catch (final UnknownHostException e) { 184 System.err.println("Error: could not resolve hostname."); 185 System.err.println(e.getMessage()); 186 System.exit(1); 187 } catch (final IOException e) { 188 System.err.println("Error: I/O exception occurred while receiving file."); 189 System.err.println(e.getMessage()); 190 System.exit(1); 191 } finally { 192 // Close local socket and output file 193 closed = close(tftp, output); 194 } 195 return closed; 196 } 197 198 private static boolean send(final int transferMode, final String hostname, final String localFilename, final String remoteFilename, final TFTPClient tftp) 199 throws IOException { 200 FileInputStream input; 201 // Try to open local file for reading 202 try { 203 input = new FileInputStream(localFilename); 204 } catch (final IOException e) { 205 tftp.close(); 206 throw new IOException("Error: could not open local file for reading.", e); 207 } 208 open(tftp); 209 final boolean closed; 210 // Try to send local file via TFTP 211 try { 212 final String[] parts = hostname.split(":"); 213 if (parts.length == 2) { 214 tftp.sendFile(remoteFilename, transferMode, input, parts[0], Integer.parseInt(parts[1])); 215 } else { 216 tftp.sendFile(remoteFilename, transferMode, input, hostname); 217 } 218 } catch (final UnknownHostException e) { 219 System.err.println("Error: could not resolve hostname."); 220 System.err.println(e.getMessage()); 221 System.exit(1); 222 } catch (final IOException e) { 223 System.err.println("Error: I/O exception occurred while sending file."); 224 System.err.println(e.getMessage()); 225 System.exit(1); 226 } finally { 227 // Close local socket and input file 228 closed = close(tftp, input); 229 } 230 return closed; 231 } 232 233}