View Javadoc
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  
18  package org.apache.commons.net.tftp;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.Random;
25  
26  import org.apache.commons.io.FileUtils;
27  
28  /**
29   * Main class for TFTPServer. This allows CLI use of the server.
30   *
31   * @since 3.6
32   */
33  public class TFTPServerMain {
34  
35      private static final String USAGE = "Usage: TFTPServerMain [options] [port]\n\n" + "port   - the port to use (default 6901)\n"
36              + "\t-p path to server directory (default java.io.tempdir)\n" + "\t-r randomly introduce errors\n" + "\t-v verbose (trace packets)\n";
37  
38      public static void main(final String[] args) throws Exception {
39          int port = 6901;
40          int argc;
41          final Map<String, String> opts = new HashMap<>();
42          opts.put("-p", FileUtils.getTempDirectoryPath());
43          // Parse options
44          for (argc = 0; argc < args.length; argc++) {
45              final String arg = args[argc];
46              if (!arg.startsWith("-")) {
47                  break;
48              }
49              if (arg.equals("-v") || arg.equals("-r")) {
50                  opts.put(arg, arg);
51              } else if (arg.equals("-p")) {
52                  opts.put(arg, args[++argc]);
53              } else {
54                  System.err.println("Error: unrecognized option.");
55                  System.err.print(USAGE);
56                  System.exit(1);
57              }
58          }
59  
60          if (argc < args.length) {
61              port = Integer.parseInt(args[argc]);
62              argc++;
63          }
64          final boolean verbose = opts.containsKey("-v");
65          final boolean randomErrors = opts.containsKey("-r");
66          final Random rand = randomErrors ? new Random() : null;
67  
68          final File serverDirectory = new File(opts.get("-p"));
69          System.out.println("Server directory: " + serverDirectory);
70          final TFTPServer tftpS = new TFTPServer(serverDirectory, serverDirectory, port, TFTPServer.ServerMode.GET_AND_PUT, null, null) {
71              @Override
72              TFTP newTFTP() {
73                  if (verbose) {
74                      return new TFTP() {
75                          @Override
76                          protected void trace(final String direction, final TFTPPacket packet) {
77                              System.out.println(direction + " " + packet.toString());
78                          }
79                      };
80                  }
81                  return new TFTP();
82              }
83  
84              @Override
85              void sendData(final TFTP tftp, final TFTPPacket packet) throws IOException {
86                  if (rand == null) {
87                      super.sendData(tftp, packet);
88                      return;
89                  }
90                  final int rint = rand.nextInt(10);
91                  switch (rint) {
92                  case 0:
93                      System.out.println("Bump port " + packet);
94                      final int port = packet.getPort();
95                      packet.setPort(port + 5);
96                      super.sendData(tftp, packet);
97                      packet.setPort(port);
98                      break;
99                  case 1:
100                     if (packet instanceof TFTPDataPacket) {
101                         final TFTPDataPacket data = (TFTPDataPacket) packet;
102                         System.out.println("Change data block num");
103                         data.blockNumber--;
104                         super.sendData(tftp, packet);
105                         data.blockNumber++;
106                     }
107                     if (packet instanceof TFTPAckPacket) {
108                         final TFTPAckPacket ack = (TFTPAckPacket) packet;
109                         System.out.println("Change ack block num");
110                         ack.blockNumber--;
111                         super.sendData(tftp, packet);
112                         ack.blockNumber++;
113                     }
114                     break;
115                 case 2:
116                     System.out.println("Drop packet: " + packet);
117                     break;
118                 case 3:
119                     System.out.println("Dupe packet: " + packet);
120                     super.sendData(tftp, packet);
121                     super.sendData(tftp, packet);
122                     break;
123                 default:
124                     super.sendData(tftp, packet);
125                     break;
126                 }
127             }
128         };
129 
130         Runtime.getRuntime().addShutdownHook(new Thread() {
131             @Override
132             public void run() {
133                 System.out.println("Server shutting down");
134                 tftpS.close();
135                 System.out.println("Server exit");
136             }
137         });
138         System.out.println("Started the server on " + port);
139         Thread.sleep(99999999L);
140     }
141 
142 }