Download | Plain Text | No Line Numbers
- /*
- * Copyright (c) 2010, Manuel Mausz. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
- import java.util.Arrays;
-
- import java.net.*;
- import java.io.*;
-
- /*
- * Client implementation for Lab#1 of DSLab WS10
- * See angabe.pdf for details
- *
- * This code is not documented at all. This is volitional
- *
- * @author Manuel Mausz (0728348)
- */
- public class Client
- {
- public class ProxyConnection
- extends CommandNetwork
- implements Runnable
- {
-
- {
- this.downloadDir = downloadDir;
- this.mainLock = mainLock;
- this.intLock = intLock;
-
- cmdHandler.register("!error", this, "cmdError");
- cmdHandler.register("!output", this, "cmdOutput");
- cmdHandler.register("!download", this, "cmdDownload");
- cmdHandler.register("unknown", this, "cmdUnknown");
- }
-
- /*------------------------------------------------------------------------*/
-
- public void notifyInteractive()
- {
- synchronized(intLock)
- {
- intLock.notify();
- }
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- long num;
- if ((num = Utils.parseHeaderNum(args, 0)) < 0)
- return;
-
- String msg;
- for (; num > 0 && (msg = oin.readUTF()) != null; --num)
- out.println(msg);
- notifyInteractive();
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- cmdPrintOutput(err, cmd, args);
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- cmdPrintOutput(out, cmd, args);
- }
-
- /*------------------------------------------------------------------------*/
-
- {
- if (args.length < 2 || args[1].length() <= 0)
- {
- err.println("Error: Invalid " + cmd + "-command paket from proxy. Ignoring...");
- notifyInteractive();
- return;
- }
-
- long filesize;
- if ((filesize = Utils.parseHeaderNum(args, 1)) < 0)
- return;
-
- file.delete();
- try
- {
- try
- {
- }
- {
- err.println("Error: Unable to write to file '" + file + "': " + e.getMessage());
- }
-
- byte[] buffer = new byte[8 * 1024];
- int toread = buffer.length;
- while(filesize > 0)
- {
- if (filesize < toread)
- toread = (int) filesize;
- int count = oin.read(buffer, 0, toread);
- if (count == -1)
- if (fout != null)
- fout.write(buffer, 0, count);
- filesize -= count;
- }
-
- if (fout != null)
- out.println("File '" + file + "' successfully downloaded.");
- }
- {
- err.println("Error: Error during file transfer: " + e.getMessage());
- }
- notifyInteractive();
- }
-
- /*------------------------------------------------------------------------*/
-
- {
- err.println("Error: Unknown data from proxy: " + cmd + " "
- notifyInteractive();
- }
-
- /*------------------------------------------------------------------------*/
-
- public void run()
- {
- try
- {
- run(oin);
- }
- {
- err.println("Internal Error: " + e.getMessage());
- }
- {
- /* ignore that exception
- * thread will shutdown and unlock the main thread
- * which will shutdown the application
- */
- }
-
- notifyInteractive();
- synchronized(mainLock)
- {
- mainLock.notify();
- }
- }
- }
-
- /*==========================================================================*/
-
- public class Interactive
- extends CommandInteractive
- implements Runnable
- {
-
- {
- this.sin = sin;
- this.sout = sout;
- this.mainLock = mainLock;
- this.intLock = intLock;
-
- cmdHandler.register("unknown", this, "cmdUnknown");
- cmdHandler.register("!exit", this, "cmdExit");
- }
-
- /*------------------------------------------------------------------------*/
-
- public void waitForSocket()
- {
- synchronized(intLock)
- {
- try
- {
- intLock.wait(1000);
- }
- {
- /* if we get interrupted -> ignore */
- }
- }
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- oout.flush();
- waitForSocket();
- }
-
- /*------------------------------------------------------------------------*/
-
- {
- stop();
- }
-
- /*------------------------------------------------------------------------*/
-
- public void printPrompt()
- {
- out.print(">: ");
- out.flush();
- }
-
- /*------------------------------------------------------------------------*/
-
- public void shutdown()
- {
- try
- {
- oout.flush();
- }
- {}
- }
-
- /*------------------------------------------------------------------------*/
-
- public void run()
- {
- try
- {
- run(sin);
- }
- {
- err.println("Internal Error: " + e.getMessage());
- }
- {
- /* ignore that exception
- * thread will shutdown and unlock the main thread
- * which will shutdown the application
- */
- }
-
- shutdown();
- synchronized(mainLock)
- {
- mainLock.notify();
- }
- }
- }
-
- /*==========================================================================*/
-
- private static int proxyTCPPort;
-
- /*--------------------------------------------------------------------------*/
-
- public static void usage()
- throws Utils.Shutdown
- {
- out.println("Usage: Client downloadDir proxyHost proxyTCPPort\n");
- out.println("downloadDir\t...the directory to put downloaded files");
- out.println("proxyHost\t...the host name or an IP address where the Proxy is running");
- out.println("proxyTCPPort\t...the TCP port where the server is listening for client connections");
-
- // Java is some piece of crap which doesn't allow me to set exitcode w/o
- // using System.exit. Maybe someday Java will be a fully functional
- // programming language, but I wouldn't bet my money
- //System.exit(1);
- throw new Utils.Shutdown("FUCK YOU JAVA");
- }
-
- /*--------------------------------------------------------------------------*/
-
- throws Utils.Shutdown
- {
- err.println("Error: " + error);
- shutdown();
-
- // Java is some piece of crap which doesn't allow me to set exitcode w/o
- // using System.exit. Maybe someday Java will be a fully functional
- // programming language, but I wouldn't bet my money
- //System.exit(2);
- throw new Utils.Shutdown("FUCK YOU JAVA");
- }
-
- /*--------------------------------------------------------------------------*/
-
- {
- if (args.length != 3)
- usage();
-
- downloadDir = args[0];
- if (!dldir.isDirectory())
- bailout("downloadDir '" + downloadDir + "' is not a directory");
- if (!dldir.canWrite())
- bailout("downloadDir '" + downloadDir + "' is not writeable");
-
- proxyHost = args[1];
- if (proxyHost.length() == 0)
- bailout("proxyHost is empty");
-
- try
- {
- if (proxyTCPPort <= 0 || proxyTCPPort > 65536)
- bailout("proxyTCPPort must be a valid port number (1 - 65535)");
- }
- {
- bailout("proxyTCPPort must be numeric");
- }
- }
-
- /*--------------------------------------------------------------------------*/
-
- public void shutdown()
- {
- try
- {
- if (sockin != null)
- sockin.close();
- }
- {}
-
- try
- {
- if (sockout != null)
- sockout.close();
- }
- {}
-
- try
- {
- if (sock != null && !sock.isClosed())
- sock.close();
- }
- {}
-
- try
- {
- if (tPConnection != null)
- tPConnection.join();
- }
- {}
-
- try
- {
- if (tInteractive != null)
- {
- tInteractive.interrupt();
- tInteractive.join();
- }
- }
- {}
-
- try
- {
- if (stdin != null)
- stdin.close();
- }
- {}
- }
-
- /*--------------------------------------------------------------------------*/
-
- {
- parseArgs(args);
-
- try
- {
- out.println("Connecting to " + proxyHost + ":" + proxyTCPPort + "...");
- sockin = sock.getInputStream();
- sockout = sock.getOutputStream();
- out.println("Connected...");
- }
- {
- bailout("Unable to resolve hostname: " + e.getMessage());
- }
- {
- bailout("Unable to connect to proxy: " + e.getMessage());
- }
-
- synchronized(mainLock)
- {
- try
- {
- mainLock, interactiveLock));
- tPConnection.start();
- }
- {
- bailout("Unable to setup remote command handler");
- }
- {
- bailout("Unable to create object input stream: " + e.getMessage());
- }
-
- try
- {
- mainLock, interactiveLock));
- tInteractive.start();
- }
- {
- bailout("Unable to setup interactive command handler");
- }
- {
- bailout("Unable to create object output stream: " + e.getMessage());
- }
-
- out.println("Client startup successful!");
- try
- {
- mainLock.wait();
- }
- {
- /* if we get interrupted -> ignore */
- }
-
- try
- {
- /* let the threads shutdown */
- }
- {}
- }
-
- if (tPConnection != null && !tPConnection.isAlive())
- bailout("Connection to proxy closed unexpected. Terminating...");
-
- shutdown();
- }
-
- /*--------------------------------------------------------------------------*/
-
- {
- try
- {
- Client cli = new Client();
- cli.run(args);
- }
- catch(Utils.Shutdown e)
- {}
- }
- }
-