yatftps.Yatftps.java Source code

Java tutorial

Introduction

Here is the source code for yatftps.Yatftps.java

Source

/*
 * 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;
    }
}