Java tutorial
/* * Copyright (C) 2014 Andrey Belorus <andrei.belorus@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package yatftps; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; import java.util.logging.Logger; import java.io.IOException; import org.apache.commons.daemon.Daemon; import org.apache.commons.daemon.DaemonContext; import org.apache.commons.daemon.DaemonInitException; /** * Yatftps - Yet another TFTP server. * * @author Andrey Belorus <andrei.belorus@gmail.com> */ public class Yatftps implements Daemon { private Thread yatftpsThread; private boolean stopped = false; private boolean lastOneWasATick = false; private static int datagramLength; private static Logger log; private static boolean exitFlag = false; /** * main method listen to 69 port UDP. * After receiving connection creates new thread for processing request. * @param args the command line arguments */ //public static void main(String[] args) { @Override public void init(DaemonContext daemonContext) throws DaemonInitException, Exception { String[] args = daemonContext.getArguments(); LogWriter.readConfig(); log = LogWriter.getLogger(); Config cfg; /* * Accordingly RFC 1350 the data field is from zero to 512 bytes long. https://tools.ietf.org/html/rfc1350 * Respectively (Data Field) + (Block Field) + (Opcode Field) = 512 + 2 + 2 = 516 bytes */ datagramLength = 516; /* * Reading config file and getting application settings */ cfg = Config.getConfig(); /* * Checking for start arguments */ if (args.length >= 1) { for (String s : args) { switch (s) { case "--debug": LogWriter.setDebug(true); break; case "--check-config": Config.checkConfig(); System.exit(0); } } } yatftpsThread = new Thread() { @Override public synchronized void start() { Yatftps.this.stopped = false; super.start(); } @Override public void run() { while (!stopped) { log.info("Server started"); // trying to listen port 69 try (DatagramSocket socket = new DatagramSocket(69)) { // receive first packet from client DatagramPacket datapacket = new DatagramPacket(new byte[datagramLength], 0, datagramLength); socket.receive(datapacket); // create new thread for handling TFTP request TftpHandler tftphandler = new TftpHandler(socket, datapacket); Thread thread = new Thread(tftphandler); thread.setDaemon(true); thread.start(); } catch (SocketException e) { log.severe( "SocketException: socket could not be opened, or the socket could not bind to the specified local port. " + e); log.info("Exiting"); System.exit(1); } catch (SecurityException e) { log.severe( "SecurityException: security manager exists and its checkListen method doesn't allow the operation " + e); log.info("Exiting"); System.exit(1); } catch (IOException e) { log.info("I/O error occurs" + e); } } } }; } @Override public void start() throws Exception { yatftpsThread.start(); } @Override public void stop() throws Exception { stopped = true; try { yatftpsThread.join(1000); } catch (InterruptedException e) { System.err.println(e.getMessage()); throw e; } } @Override public void destroy() { yatftpsThread = null; } }