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

package org.apache.commons.net.tftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketTimeoutException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;

import org.apache.commons.net.io.FromNetASCIIOutputStream;
import org.apache.commons.net.io.ToNetASCIIInputStream;

/**
 * A fully multi-threaded tftp server. Can handle multiple clients at the same time. Implements RFC
 * 1350 and wrapping block numbers for large file support.
 *
 * To launch, just create an instance of the class. An IOException will be thrown if the server
 * fails to start for reasons such as port in use, port denied, etc.
 *
 * To stop, use the shutdown method.
 *
 * To check to see if the server is still running (or if it stopped because of an error), call the
 * isRunning() method.
 *
 * By default, events are not logged to stdout/stderr. This can be changed with the
 * setLog and setLogError methods.
 *
 * <p>
 * Example usage is below:
 *
 * <code>
 * public static void main(String[] args) throws Exception
 *  {
 *      if (args.length != 1)
 *      {
 *          System.out
 *                  .println("You must provide 1 argument - the base path for the server to serve from.");
 *          System.exit(1);
 *      }
 *
 *      TFTPServer ts = new TFTPServer(new File(args[0]), new File(args[0]), GET_AND_PUT);
 *      ts.setSocketTimeout(2000);
 *
 *      System.out.println("TFTP Server running.  Press enter to stop.");
 *      new InputStreamReader(System.in).read();
 *
 *      ts.shutdown();
 *      System.out.println("Server shut down.");
 *      System.exit(0);
 *  }
 *
 * </code>
 *
 * @since 2.0
 */

public class TFTPServer implements Runnable
{
    public enum ServerMode { GET_ONLY, PUT_ONLY, GET_AND_PUT}
    /*
     * An instance of an ongoing transfer.
     */
    private class TFTPTransfer implements Runnable
    {
        private final TFTPPacket tftpPacket_;

        private boolean shutdownTransfer;

        TFTP transferTftp_;

        public TFTPTransfer(final TFTPPacket tftpPacket)
        {
            tftpPacket_ = tftpPacket;
        }

        /*
         * Utility method to make sure that paths provided by tftp clients do not get outside of the
         * serverRoot directory.
         */
        private File buildSafeFile(final File serverDirectory, final String fileName, final boolean createSubDirs)
                throws IOException
        {
            File temp = new File(serverDirectory, fileName);
            temp = temp.getCanonicalFile();

            if (!isSubdirectoryOf(serverDirectory, temp))
            {
                throw new IOException("Cannot access files outside of tftp server root.");
            }

            // ensure directory exists (if requested)
            if (createSubDirs)
            {
                createDirectory(temp.getParentFile());
            }

            return temp;
        }

        /*
         * recursively create subdirectories
         */
        private void createDirectory(final File file) throws IOException
        {
            final File parent = file.getParentFile();
            if (parent == null)
            {
                throw new IOException("Unexpected error creating requested directory");
            }
            if (!parent.exists())
            {
                // recurse...
                createDirectory(parent);
            }

            if (!parent.isDirectory()) {
                throw new IOException(
                        "Invalid directory path - file in the way of requested folder");
            }
            if (file.isDirectory())
            {
                return;
            }
            final boolean result = file.mkdir();
            if (!result)
            {
                throw new IOException("Couldn't create requested directory");
            }
        }

        /*
         * Handle a tftp read request.
         */
        private void handleRead(final TFTPReadRequestPacket trrp) throws IOException, TFTPPacketException
        {
            InputStream is = null;
            try
            {
                if (mode_ == ServerMode.PUT_ONLY)
                {
                    transferTftp_.bufferedSend(new TFTPErrorPacket(trrp.getAddress(), trrp
                            .getPort(), TFTPErrorPacket.ILLEGAL_OPERATION,
                            "Read not allowed by server."));
                    return;
                }

                try
                {
                    is = new BufferedInputStream(new FileInputStream(buildSafeFile(
                            serverReadDirectory_, trrp.getFilename(), false)));
                }
                catch (final FileNotFoundException e)
                {
                    transferTftp_.bufferedSend(new TFTPErrorPacket(trrp.getAddress(), trrp
                            .getPort(), TFTPErrorPacket.FILE_NOT_FOUND, e.getMessage()));
                    return;
                }
                catch (final Exception e)
                {
                    transferTftp_.bufferedSend(new TFTPErrorPacket(trrp.getAddress(), trrp
                            .getPort(), TFTPErrorPacket.UNDEFINED, e.getMessage()));
                    return;
                }

                if (trrp.getMode() == TFTP.NETASCII_MODE)
                {
                    is = new ToNetASCIIInputStream(is);
                }

                final byte[] temp = new byte[TFTPDataPacket.MAX_DATA_LENGTH];

                TFTPPacket answer;

                int block = 1;
                boolean sendNext = true;

                int readLength = TFTPDataPacket.MAX_DATA_LENGTH;

                TFTPDataPacket lastSentData = null;

                // We are reading a file, so when we read less than the
                // requested bytes, we know that we are at the end of the file.
                while (readLength == TFTPDataPacket.MAX_DATA_LENGTH && !shutdownTransfer)
                {
                    if (sendNext)
                    {
                        readLength = is.read(temp);
                        if (readLength == -1)
                        {
                            readLength = 0;
                        }

                        lastSentData = new TFTPDataPacket(trrp.getAddress(), trrp.getPort(), block,
                                temp, 0, readLength);
                        sendData(transferTftp_, lastSentData); // send the data
                    }

                    answer = null;

                    int timeoutCount = 0;

                    while (!shutdownTransfer
                            && (answer == null || !answer.getAddress().equals(trrp.getAddress()) || answer
                                    .getPort() != trrp.getPort()))
                    {
                        // listen for an answer.
                        if (answer != null)
                        {
                            // The answer that we got didn't come from the
                            // expected source, fire back an error, and continue
                            // listening.
                            log_.println("TFTP Server ignoring message from unexpected source.");
                            transferTftp_.bufferedSend(new TFTPErrorPacket(answer.getAddress(),
                                    answer.getPort(), TFTPErrorPacket.UNKNOWN_TID,
                                    "Unexpected Host or Port"));
                        }
                        try
                        {
                            answer = transferTftp_.bufferedReceive();
                        }
                        catch (final SocketTimeoutException e)
                        {
                            if (timeoutCount >= maxTimeoutRetries_)
                            {
                                throw e;
                            }
                            // didn't get an ack for this data. need to resend
                            // it.
                            timeoutCount++;
                            transferTftp_.bufferedSend(lastSentData);
                            continue;
                        }
                    }

                    if (answer == null || !(answer instanceof TFTPAckPacket))
                    {
                        if (!shutdownTransfer)
                        {
                            logError_
                                    .println("Unexpected response from tftp client during transfer ("
                                            + answer + ").  Transfer aborted.");
                        }
                        break;
                    }
                    // once we get here, we know we have an answer packet
                    // from the correct host.
                    final TFTPAckPacket ack = (TFTPAckPacket) answer;
                    if (ack.getBlockNumber() != block)
                    {
                        /*
                         * The origional tftp spec would have called on us to resend the
                         * previous data here, however, that causes the SAS Syndrome.
                         * http://www.faqs.org/rfcs/rfc1123.html section 4.2.3.1 The modified
                         * spec says that we ignore a duplicate ack. If the packet was really
                         * lost, we will time out on receive, and resend the previous data at
                         * that point.
                         */
                        sendNext = false;
                    }
                    else
                    {
                        // send the next block
                        block++;
                        if (block > 65535)
                        {
                            // wrap the block number
                            block = 0;
                        }
                        sendNext = true;
                    }
                }
            }
            finally
            {
                try
                {
                    if (is != null)
                    {
                        is.close();
                    }
                }
                catch (final IOException e)
                {
                    // noop
                }
            }
        }

        /*
         * handle a tftp write request.
         */
        private void handleWrite(final TFTPWriteRequestPacket twrp) throws IOException,
                TFTPPacketException
        {
            OutputStream bos = null;
            try
            {
                if (mode_ == ServerMode.GET_ONLY)
                {
                    transferTftp_.bufferedSend(new TFTPErrorPacket(twrp.getAddress(), twrp
                            .getPort(), TFTPErrorPacket.ILLEGAL_OPERATION,
                            "Write not allowed by server."));
                    return;
                }

                int lastBlock = 0;
                final String fileName = twrp.getFilename();

                try
                {
                    final File temp = buildSafeFile(serverWriteDirectory_, fileName, true);
                    if (temp.exists())
                    {
                        transferTftp_.bufferedSend(new TFTPErrorPacket(twrp.getAddress(), twrp
                                .getPort(), TFTPErrorPacket.FILE_EXISTS, "File already exists"));
                        return;
                    }
                    bos = new BufferedOutputStream(new FileOutputStream(temp));

                    if (twrp.getMode() == TFTP.NETASCII_MODE)
                    {
                        bos = new FromNetASCIIOutputStream(bos);
                    }
                }
                catch (final Exception e)
                {
                    transferTftp_.bufferedSend(new TFTPErrorPacket(twrp.getAddress(), twrp
                            .getPort(), TFTPErrorPacket.UNDEFINED, e.getMessage()));
                    return;
                }

                TFTPAckPacket lastSentAck = new TFTPAckPacket(twrp.getAddress(), twrp.getPort(), 0);
                sendData(transferTftp_, lastSentAck); // send the data

                while (true)
                {
                    // get the response - ensure it is from the right place.
                    TFTPPacket dataPacket = null;

                    int timeoutCount = 0;

                    while (!shutdownTransfer
                            && (dataPacket == null
                                    || !dataPacket.getAddress().equals(twrp.getAddress()) || dataPacket
                                    .getPort() != twrp.getPort()))
                    {
                        // listen for an answer.
                        if (dataPacket != null)
                        {
                            // The data that we got didn't come from the
                            // expected source, fire back an error, and continue
                            // listening.
                            log_.println("TFTP Server ignoring message from unexpected source.");
                            transferTftp_.bufferedSend(new TFTPErrorPacket(dataPacket.getAddress(),
                                    dataPacket.getPort(), TFTPErrorPacket.UNKNOWN_TID,
                                    "Unexpected Host or Port"));
                        }

                        try
                        {
                            dataPacket = transferTftp_.bufferedReceive();
                        }
                        catch (final SocketTimeoutException e)
                        {
                            if (timeoutCount >= maxTimeoutRetries_)
                            {
                                throw e;
                            }
                            // It didn't get our ack. Resend it.
                            transferTftp_.bufferedSend(lastSentAck);
                            timeoutCount++;
                            continue;
                        }
                    }

                    if (dataPacket instanceof TFTPWriteRequestPacket)
                    {
                        // it must have missed our initial ack. Send another.
                        lastSentAck = new TFTPAckPacket(twrp.getAddress(), twrp.getPort(), 0);
                        transferTftp_.bufferedSend(lastSentAck);
                    }
                    else if (dataPacket == null || !(dataPacket instanceof TFTPDataPacket))
                    {
                        if (!shutdownTransfer)
                        {
                            logError_
                                    .println("Unexpected response from tftp client during transfer ("
                                            + dataPacket + ").  Transfer aborted.");
                        }
                        break;
                    }
                    else
                    {
                        final int block = ((TFTPDataPacket) dataPacket).getBlockNumber();
                        final byte[] data = ((TFTPDataPacket) dataPacket).getData();
                        final int dataLength = ((TFTPDataPacket) dataPacket).getDataLength();
                        final int dataOffset = ((TFTPDataPacket) dataPacket).getDataOffset();

                        if (block > lastBlock || lastBlock == 65535 && block == 0)
                        {
                            // it might resend a data block if it missed our ack
                            // - don't rewrite the block.
                            bos.write(data, dataOffset, dataLength);
                            lastBlock = block;
                        }

                        lastSentAck = new TFTPAckPacket(twrp.getAddress(), twrp.getPort(), block);
                        sendData(transferTftp_, lastSentAck); // send the data
                        if (dataLength < TFTPDataPacket.MAX_DATA_LENGTH)
                        {
                            // end of stream signal - The tranfer is complete.
                            bos.close();

                            // But my ack may be lost - so listen to see if I
                            // need to resend the ack.
                            for (int i = 0; i < maxTimeoutRetries_; i++)
                            {
                                try
                                {
                                    dataPacket = transferTftp_.bufferedReceive();
                                }
                                catch (final SocketTimeoutException e)
                                {
                                    // this is the expected route - the client
                                    // shouldn't be sending any more packets.
                                    break;
                                }

                                if (dataPacket != null
                                        && (!dataPacket.getAddress().equals(twrp.getAddress()) || dataPacket
                                                .getPort() != twrp.getPort()))
                                {
                                    // make sure it was from the right client...
                                    transferTftp_
                                            .bufferedSend(new TFTPErrorPacket(dataPacket
                                                    .getAddress(), dataPacket.getPort(),
                                                    TFTPErrorPacket.UNKNOWN_TID,
                                                    "Unexpected Host or Port"));
                                }
                                else
                                {
                                    // This means they sent us the last
                                    // datapacket again, must have missed our
                                    // ack. resend it.
                                    transferTftp_.bufferedSend(lastSentAck);
                                }
                            }

                            // all done.
                            break;
                        }
                    }
                }
            }
            finally
            {
                if (bos != null)
                {
                    bos.close();
                }
            }
        }

        /*
         * recursively check to see if one directory is a parent of another.
         */
        private boolean isSubdirectoryOf(final File parent, final File child)
        {
            final File childsParent = child.getParentFile();
            if (childsParent == null)
            {
                return false;
            }
            if (childsParent.equals(parent))
            {
                return true;
            }
            return isSubdirectoryOf(parent, childsParent);
        }

        @Override
        public void run()
        {
            try
            {
                transferTftp_ = newTFTP();

                transferTftp_.beginBufferedOps();
                transferTftp_.setDefaultTimeout(socketTimeout_);

                transferTftp_.open();

                if (tftpPacket_ instanceof TFTPReadRequestPacket)
                {
                    handleRead((TFTPReadRequestPacket) tftpPacket_);
                }
                else if (tftpPacket_ instanceof TFTPWriteRequestPacket)
                {
                    handleWrite((TFTPWriteRequestPacket) tftpPacket_);
                }
                else
                {
                    log_.println("Unsupported TFTP request (" + tftpPacket_ + ") - ignored.");
                }
            }
            catch (final Exception e)
            {
                if (!shutdownTransfer)
                {
                    logError_
                            .println("Unexpected Error in during TFTP file transfer.  Transfer aborted. "
                                    + e);
                }
            }
            finally
            {
                try
                {
                    if (transferTftp_ != null && transferTftp_.isOpen())
                    {
                        transferTftp_.endBufferedOps();
                        transferTftp_.close();
                    }
                }
                catch (final Exception e)
                {
                    // noop
                }
                synchronized(transfers_)
                {
                    transfers_.remove(this);
                }
            }
        }

        public void shutdown()
        {
            shutdownTransfer = true;
            try
            {
                transferTftp_.close();
            }
            catch (final RuntimeException e)
            {
                // noop
            }
        }
    }

    private static final int DEFAULT_TFTP_PORT = 69;
    /* /dev/null output stream (default) */
    private static final PrintStream nullStream = new PrintStream(
            new OutputStream() {
                @Override
                public void write(final byte[] b) throws IOException {}
                @Override
                public void write(final int b){}
                }
            );
    private final HashSet<TFTPTransfer> transfers_ = new HashSet<>();
    private volatile boolean shutdownServer;
    private TFTP serverTftp_;
    private File serverReadDirectory_;
    private File serverWriteDirectory_;
    private final int port_;
    private final InetAddress laddr_;

    private Exception serverException;

    private final ServerMode mode_;
    // don't have access to a logger api, so we will log to these streams, which
    // by default are set to a no-op logger
    private PrintStream log_;

    private PrintStream logError_;
    private int maxTimeoutRetries_ = 3;
    private int socketTimeout_;


    private Thread serverThread;

    /**
     * Start a TFTP Server on the specified port. Gets and Puts occur in the specified directory.
     *
     * The server will start in another thread, allowing this constructor to return immediately.
     *
     * If a get or a put comes in with a relative path that tries to get outside of the
     * serverDirectory, then the get or put will be denied.
     *
     * GET_ONLY mode only allows gets, PUT_ONLY mode only allows puts, and GET_AND_PUT allows both.
     * Modes are defined as int constants in this class.
     *
     * @param serverReadDirectory directory for GET requests
     * @param serverWriteDirectory directory for PUT requests
     * @param port The local port to bind to.
     * @param localaddr The local address to bind to.
     * @param mode A value as specified above.
     * @param log Stream to write log message to. If not provided, uses System.out
     * @param errorLog Stream to write error messages to. If not provided, uses System.err.
     * @throws IOException if the server directory is invalid or does not exist.
     */
    public TFTPServer(final File serverReadDirectory, final File serverWriteDirectory, final int port,
        final InetAddress localaddr, final ServerMode mode, final PrintStream log, final PrintStream errorLog)
        throws IOException
    {
        port_ = port;
        mode_ = mode;
        laddr_ = localaddr;
        log_ = log == null ? nullStream: log;
        logError_ = errorLog == null ? nullStream : errorLog;
        launch(serverReadDirectory, serverWriteDirectory);
    }

    /**
     * Start a TFTP Server on the specified port. Gets and Puts occur in the specified directory.
     *
     * The server will start in another thread, allowing this constructor to return immediately.
     *
     * If a get or a put comes in with a relative path that tries to get outside of the
     * serverDirectory, then the get or put will be denied.
     *
     * GET_ONLY mode only allows gets, PUT_ONLY mode only allows puts, and GET_AND_PUT allows both.
     * Modes are defined as int constants in this class.
     *
     * @param serverReadDirectory directory for GET requests
     * @param serverWriteDirectory directory for PUT requests
     * @param port the port to use
     * @param localiface The local network interface to bind to.
     *  The interface's first address wil be used.
     * @param mode A value as specified above.
     * @param log Stream to write log message to. If not provided, uses System.out
     * @param errorLog Stream to write error messages to. If not provided, uses System.err.
     * @throws IOException if the server directory is invalid or does not exist.
     */
    public TFTPServer(final File serverReadDirectory, final File serverWriteDirectory, final int port,
        final NetworkInterface localiface, final ServerMode mode, final PrintStream log, final PrintStream errorLog)
        throws IOException
    {
        mode_ = mode;
        port_= port;
        InetAddress iaddr = null;
        if (localiface != null)
        {
            final Enumeration<InetAddress> ifaddrs = localiface.getInetAddresses();
            if ((ifaddrs != null) && ifaddrs.hasMoreElements()) {
                iaddr = ifaddrs.nextElement();
            }
        }
        log_ = log == null ? nullStream: log;
        logError_ = errorLog == null ? nullStream : errorLog;
        laddr_ = iaddr;
        launch(serverReadDirectory, serverWriteDirectory);
    }

    /**
     * Start a TFTP Server on the specified port. Gets and Puts occur in the specified directory.
     *
     * The server will start in another thread, allowing this constructor to return immediately.
     *
     * If a get or a put comes in with a relative path that tries to get outside of the
     * serverDirectory, then the get or put will be denied.
     *
     * GET_ONLY mode only allows gets, PUT_ONLY mode only allows puts, and GET_AND_PUT allows both.
     * Modes are defined as int constants in this class.
     *
     * @param serverReadDirectory directory for GET requests
     * @param serverWriteDirectory directory for PUT requests
     * @param port the port to use
     * @param mode A value as specified above.
     * @param log Stream to write log message to. If not provided, uses System.out
     * @param errorLog Stream to write error messages to. If not provided, uses System.err.
     * @throws IOException if the server directory is invalid or does not exist.
     */
    public TFTPServer(final File serverReadDirectory, final File serverWriteDirectory, final int port, final ServerMode mode,
            final PrintStream log, final PrintStream errorLog) throws IOException
    {
        port_ = port;
        mode_ = mode;
        log_ = log == null ? nullStream: log;
        logError_ = errorLog == null ? nullStream : errorLog;
        laddr_ = null;
        launch(serverReadDirectory, serverWriteDirectory);
    }

    /**
     * Start a TFTP Server on the default port (69). Gets and Puts occur in the specified
     * directories.
     *
     * The server will start in another thread, allowing this constructor to return immediately.
     *
     * If a get or a put comes in with a relative path that tries to get outside of the
     * serverDirectory, then the get or put will be denied.
     *
     * GET_ONLY mode only allows gets, PUT_ONLY mode only allows puts, and GET_AND_PUT allows both.
     * Modes are defined as int constants in this class.
     *
     * @param serverReadDirectory directory for GET requests
     * @param serverWriteDirectory directory for PUT requests
     * @param mode A value as specified above.
     * @throws IOException if the server directory is invalid or does not exist.
     */
    public TFTPServer(final File serverReadDirectory, final File serverWriteDirectory, final ServerMode mode)
            throws IOException
    {
        this(serverReadDirectory, serverWriteDirectory, DEFAULT_TFTP_PORT, mode, null, null);
    }

    @Override
    protected void finalize() throws Throwable
    {
        shutdown();
    }

    /**
     * Get the current value for maxTimeoutRetries
     * @return the max allowed number of retries
     */
    public int getMaxTimeoutRetries()
    {
        return maxTimeoutRetries_;
    }

    /**
     * The current socket timeout used during transfers in milliseconds.
     * @return the timeout value
     */
    public int getSocketTimeout()
    {
        return socketTimeout_;
    }

    /**
     * check if the server thread is still running.
     *
     * @return true if running, false if stopped.
     * @throws Exception throws the exception that stopped the server if the server is stopped from
     *             an exception.
     */
    public boolean isRunning() throws Exception
    {
        if (shutdownServer && serverException != null)
        {
            throw serverException;
        }
        return !shutdownServer;
    }

    /*
     * start the server, throw an error if it can't start.
     */
    private void launch(final File serverReadDirectory, final File serverWriteDirectory) throws IOException
    {
        log_.println("Starting TFTP Server on port " + port_ + ".  Read directory: "
                + serverReadDirectory + " Write directory: " + serverWriteDirectory
                + " Server Mode is " + mode_);

        serverReadDirectory_ = serverReadDirectory.getCanonicalFile();
        if (!serverReadDirectory_.exists() || !serverReadDirectory.isDirectory())
        {
            throw new IOException("The server read directory " + serverReadDirectory_
                    + " does not exist");
        }

        serverWriteDirectory_ = serverWriteDirectory.getCanonicalFile();
        if (!serverWriteDirectory_.exists() || !serverWriteDirectory.isDirectory())
        {
            throw new IOException("The server write directory " + serverWriteDirectory_
                    + " does not exist");
        }

        serverTftp_ = new TFTP();

        // This is the value used in response to each client.
        socketTimeout_ = serverTftp_.getDefaultTimeout();

        // we want the server thread to listen forever.
        serverTftp_.setDefaultTimeout(0);

        if (laddr_ != null) {
            serverTftp_.open(port_, laddr_);
        } else {
            serverTftp_.open(port_);
        }

        serverThread = new Thread(this);
        serverThread.setDaemon(true);
        serverThread.start();
    }

    /*
     * Allow test code to customise the TFTP instance
     */
    TFTP newTFTP() {
        return new TFTP();
    }

    @Override
    public void run()
    {
        try
        {
            while (!shutdownServer)
            {
                final TFTPPacket tftpPacket;

                tftpPacket = serverTftp_.receive();

                final TFTPTransfer tt = new TFTPTransfer(tftpPacket);
                synchronized(transfers_)
                {
                    transfers_.add(tt);
                }

                final Thread thread = new Thread(tt);
                thread.setDaemon(true);
                thread.start();
            }
        }
        catch (final Exception e)
        {
            if (!shutdownServer)
            {
                serverException = e;
                logError_.println("Unexpected Error in TFTP Server - Server shut down! + " + e);
            }
        }
        finally
        {
            shutdownServer = true; // set this to true, so the launching thread can check to see if it started.
            if (serverTftp_ != null && serverTftp_.isOpen())
            {
                serverTftp_.close();
            }
        }
    }

    /*
     * Also allow customisation of sending data/ack so can generate errors if needed
     */
    void sendData(final TFTP tftp, final TFTPPacket data) throws IOException {
        tftp.bufferedSend(data);
    }

    /**
     * Set the stream object to log debug / informational messages. By default, this is a no-op
     *
     * @param log the stream to use for logging
     */
    public void setLog(final PrintStream log)
    {
        this.log_ = log;
    }

    /**
     * Set the stream object to log error messsages. By default, this is a no-op
     *
     * @param logError the stream to use for logging errors
     */
    public void setLogError(final PrintStream logError)
    {
        this.logError_ = logError;
    }

    /**
     * Set the max number of retries in response to a timeout. Default 3. Min 0.
     *
     * @param retries number of retries, must be &gt; 0
     */
    public void setMaxTimeoutRetries(final int retries)
    {
        if (retries < 0)
        {
            throw new RuntimeException("Invalid Value");
        }
        maxTimeoutRetries_ = retries;
    }

    /**
     * Set the socket timeout in milliseconds used in transfers. Defaults to the value here:
     * https://commons.apache.org/net/apidocs/org/apache/commons/net/tftp/TFTP.html#DEFAULT_TIMEOUT
     * (5000 at the time I write this) Min value of 10.
     * @param timeout the timeout; must be larger than 10
     */
    public void setSocketTimeout(final int timeout)
    {
        if (timeout < 10)
        {
            throw new RuntimeException("Invalid Value");
        }
        socketTimeout_ = timeout;
    }

    /**
     * Stop the tftp server (and any currently running transfers) and release all opened network
     * resources.
     */
    public void shutdown()
    {
        shutdownServer = true;

        synchronized(transfers_)
        {
            final Iterator<TFTPTransfer> it = transfers_.iterator();
            while (it.hasNext())
            {
                it.next().shutdown();
            }
        }

        try
        {
            serverTftp_.close();
        }
        catch (final RuntimeException e)
        {
            // noop
        }

        try {
            serverThread.join();
        } catch (final InterruptedException e) {
            // we've done the best we could, return
        }
    }
}
