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.nio.ByteBuffer;
- import java.nio.channels.ServerSocketChannel;
- import java.nio.channels.SocketChannel;
- import java.nio.channels.DatagramChannel;
-
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.ScheduledFuture;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.TimeUnit;
- import java.util.Collections;
- import java.util.Properties;
- import java.util.ArrayList;
- import java.util.Calendar;
- import java.util.Iterator;
- import java.util.HashMap;
- import java.util.Arrays;
- import java.util.Map;
- import java.net.*;
- import java.io.*;
-
- /*
- * Proxy 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 FSRecord
- implements Comparable<FSRecord>
- {
- public final int port;
- public int usage;
- public boolean online;
- public long lastUpdate;
-
- {
- this.host = host;
- this.port = port;
- usage = 0;
- online = true;
- }
-
- public void ping()
- {
- online = true;
- }
-
- public boolean equals(FSRecord o)
- {
- return online == o.online && usage == o.usage;
- }
-
- public int compareTo(FSRecord o)
- {
- return usage - o.usage;
- }
- }
-
- public class FSRecords
- {}
-
- /*==========================================================================*/
-
- public class UserRecord
- {
- public int credits;
- public ArrayList<String> loggedin;
-
- {
- this.name = name;
- this.pass = pass;
- credits = 0;
- loggedin = new ArrayList<String>();
- }
- }
-
- public class UserRecords
- {}
-
- /*==========================================================================*/
-
-
- public class ProxyConnection
- implements Runnable
- {
- private final int port;
- private FSRecords fileservers;
-
- {
- this.host = host;
- this.port = port;
- this.fileservers = fileservers;
- }
-
- /*------------------------------------------------------------------------*/
-
- public void run()
- {
- synchronized(fileservers)
- {
- FSRecord record = fileservers.get(key);
- if (record == null)
- {
- fileservers.put(key, new FSRecord(host, port));
- out.println("New fileserver registered: " + key);
- }
- else
- {
- if (!record.online)
- out.println("Fileserver is online again: " + key);
- record.ping();
- }
- }
- }
- }
-
- /*==========================================================================*/
-
- public class UDPSocketReader
- implements Runnable
- {
- private final DatagramChannel dchannel;
- private FSRecords fileservers;
- private final ExecutorService pool;
-
- UDPSocketReader(DatagramChannel dchannel, FSRecords fileservers,
- Object mainLock)
- {
- this.dchannel = dchannel;
- this.fileservers = fileservers;
- this.mainLock = mainLock;
- this.pool = Executors.newCachedThreadPool();
- }
-
- /*------------------------------------------------------------------------*/
-
- public void run()
- {
- try
- {
- ByteBuffer buffer = ByteBuffer.allocate(4);
- while(true)
- {
- buffer.clear();
- InetSocketAddress proxyaddr = (InetSocketAddress) dchannel.receive(buffer);
- try
- {
- pool.execute(new ProxyConnection(proxyaddr.getHostName(),
- buffer.getInt(0), fileservers));
- }
- {
- /* simple ignore that packet */
- }
- }
- }
- {
- /* ignore that exception
- * thread will shutdown and unlock the main thread
- * which will shutdown the application
- */
- }
-
- pool.shutdown();
- try
- {
- if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS))
- out.println("Trying to shutdown the UDP Proxy connections. This may take up to 15 seconds...");
- if (!pool.awaitTermination(5, TimeUnit.SECONDS))
- {
- pool.shutdownNow();
- if (!pool.awaitTermination(5, TimeUnit.SECONDS))
- err.println("Error: UDP Proxy connections did not terminate. You may have to kill that appplication.");
- }
- }
- {
- pool.shutdownNow();
- }
-
- synchronized(mainLock)
- {
- mainLock.notify();
- }
- }
- }
-
- /*==========================================================================*/
-
- public class ClientConnection
- extends CommandNetwork
- implements Runnable
- {
- private final SocketChannel sock;
- private final FSRecords fileservers;
- private final UserRecords users;
- private UserRecord user = null;
-
- private CommandNetwork fscmd;
- private FSRecord fileserver = null;
- private SocketChannel fsschannel = null;
-
- ClientConnection(SocketChannel sock, FSRecords fileservers,
- UserRecords users)
- {
- this.sock = sock;
- this.fileservers = fileservers;
- this.users = users;
- this.clientaddr = "tcp:/" + sock.socket().getInetAddress() + ":" + sock.socket().getPort();
-
- cmdHandler.register("!login", this, "cmdLogin");
- cmdHandler.register("!buy", this, "cmdBuy");
- cmdHandler.register("!credits", this, "cmdCredits");
- cmdHandler.register("!list", this, "cmdList");
- cmdHandler.register("!download", this, "cmdDownload");
- cmdHandler.register("unknown", this, "cmdUnknown");
-
- fscmd = new CommandNetwork();
- fscmd.setOneCommandMode(true);
- fscmd.cmdHandler.register("!error", this, "cmdFSRelayOutput");
- fscmd.cmdHandler.register("!output", this, "cmdFSRelayOutput");
- fscmd.cmdHandler.register("!download", this, "cmdFSDownload");
- fscmd.cmdHandler.register("unknown", this, "cmdFSRelayOutput");
- }
-
- /*------------------------------------------------------------------------*/
-
- public boolean checkLogin()
- throws IOException
- {
- if (user == null)
- {
- Utils.sendError(clout, "Not logged in");
- return false;
- }
- return true;
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- if (user != null)
- {
- Utils.sendError(clout, "Already logged in");
- return;
- }
-
- if (args.length != 2)
- {
- Utils.sendError(clout, "Invalid Syntax: !login <username> <password>");
- return;
- }
-
- synchronized(users)
- {
- UserRecord record = users.get(args[0]);
- if (record == null || !record.pass.equals(args[1]))
- {
- Utils.sendError(clout, "Invalid username or password");
- return;
- }
-
- user = record;
- user.loggedin.add(clientaddr);
- }
-
- Utils.sendOutput(clout, "Successfully logged in");
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- if (!checkLogin())
- return;
- if (args.length != 1)
- {
- Utils.sendError(clout, "Invalid Syntax: !buy <credits>");
- return;
- }
-
- int add = 0;
- try
- {
- if (add <= 0)
- }
- {
- Utils.sendError(clout, "Credits must be numberic and positive");
- return;
- }
-
- synchronized(users)
- {
- Utils.sendError(clout, "You can't buy that much/more credits");
- else
- {
- user.credits += add;
- Utils.sendOutput(clout, "You now have " + user.credits + " credits");
- }
- }
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- if (!checkLogin())
- return;
- if (args.length != 0)
- {
- Utils.sendError(clout, "Invalid Syntax: !credits");
- return;
- }
-
- synchronized(users)
- {
- Utils.sendOutput(clout, "You have " + user.credits + " credits left");
- }
- }
-
- /*------------------------------------------------------------------------*/
-
- public FSRecord getFileserver()
- {
- synchronized(fileservers)
- {
- ArrayList<FSRecord> fslist = new ArrayList<FSRecord>();
- for(FSRecord record : fileservers.values())
- {
- if (!record.online)
- continue;
- fslist.add(record);
- }
- if (fslist.size() == 0)
- return null;
- return fslist.get(0);
- }
- }
-
- /*------------------------------------------------------------------------*/
-
- public boolean connectFileserver()
- throws IOException
- {
- disconnectFileserver();
-
- fileserver = getFileserver();
- if (fileserver == null)
- {
- Utils.sendError(clout, "Unable to execute command. No fileservers online");
- return false;
- }
-
- try
- {
- fsschannel = SocketChannel.open(new InetSocketAddress(fileserver.host,
- fileserver.port));
- fsschannel.socket().getInputStream()));
- }
- {
- err.println("Error: Unable to connect to fileserver: " + e.getMessage());
- Utils.sendError(clout, "Unable to connect to fileserver");
-
- synchronized(fileservers)
- {
- fileserver.online = false;
- out.println("Fileserver marked as offline: " + fileserver.host + ":" + fileserver.port);
- }
-
- disconnectFileserver();
- return false;
- }
-
- return true;
- }
-
- /*------------------------------------------------------------------------*/
-
- public void disconnectFileserver()
- {
- try
- {
- if (fsin != null)
- fsout.flush();
- }
- {}
-
- try
- {
- if (fsin != null)
- fsin.close();
- }
- {}
-
- try
- {
- if (fsout != null)
- fsout.close();
- }
- {}
-
- try
- {
- if (fsschannel != null)
- fsschannel.close();
- }
- {}
-
- fsin = null;
- fsout = null;
- fileserver = null;
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- if (!checkLogin())
- return;
- if (args.length != 0)
- {
- Utils.sendError(clout, "Invalid Syntax: !list");
- return;
- }
-
- try
- {
- if (!connectFileserver())
- return;
- fsout.flush();
- fscmd.run(fsin);
- }
- {
- Utils.sendError(clout, "Connection to fileserver terminated unexpected");
- }
- clout.flush();
- disconnectFileserver();
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- if (!checkLogin())
- return;
- if (args.length != 1)
- {
- Utils.sendError(clout, "Invalid Syntax: !download <filename>");
- return;
- }
-
- try
- {
- if (!connectFileserver())
- return;
- synchronized(users)
- {
- }
- fsout.flush();
- fscmd.run(fsin);
- }
- {
- Utils.sendError(clout, "Connection to fileserver terminated unexpected");
- }
- clout.flush();
- disconnectFileserver();
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- err.println("Error: Unknown data from client: " + cmd + " "
- Utils.sendError(clout, "Unknown command");
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- long num;
- if ((num = Utils.parseHeaderNum(args, 0)) < 0)
- return;
- String msg;
- for (; num > 0 && (msg = fsin.readUTF()) != null; --num)
- clout.writeUTF(msg);
- }
-
- /*------------------------------------------------------------------------*/
-
- throws IOException
- {
- if (args.length < 2 || args[1].length() <= 0)
- {
- err.println("Error: Invalid " + cmd + "-command paket from fileserver. Ignoring...");
- Utils.sendError(clout, "Internal Error: Invalid packet from fileserver");
- return;
- }
-
- long filesize, filesizecpy;
- if ((filesize = Utils.parseHeaderNum(args, 1)) < 0)
- return;
- filesizecpy = filesize;
-
-
- try
- {
- byte[] buffer = new byte[8 * 1024];
- int toread = buffer.length;
- while(filesize > 0)
- {
- if (filesize < toread)
- toread = (int) filesize;
- int count = fsin.read(buffer, 0, toread);
- if (count == -1)
- clout.write(buffer, 0, count);
- filesize -= count;
- }
-
- synchronized(users)
- {
- user.credits -= filesizecpy;
- }
-
- synchronized(fileservers)
- {
- fileserver.usage += filesizecpy;
- }
- }
- {
- err.println("Error during file transfer: " + e.getMessage() + ". Closing connection to client");
- stop();
-
- synchronized(fileservers)
- {
- fileserver.usage += filesizecpy;
- fileserver.online = false;
- out.println("Fileserver marked as offline: " + fileserver.host + ":" + fileserver.port);
- }
- }
- }
-
- /*------------------------------------------------------------------------*/
-
-
- public void shutdown()
- {
- disconnectFileserver();
-
- try
- {
- clout.flush();
- }
- {}
-
- try
- {
- clin.close();
- }
- {}
-
- try
- {
- clout.close();
- }
- {}
-
- try
- {
- if (sock.isOpen())
- sock.close();
- }
- {}
- }
-
- /*------------------------------------------------------------------------*/
-
- public void run()
- {
- try
- {
- + clientaddr);
- run(clin);
- clout.flush();
- }
- {
- err.println("Internal Error: " + e.getMessage());
- e.printStackTrace();
- }
- {
- /* ignore that exception
- * it's usually a closed connection from client so
- * we can't do anything about it anyway
- */
- }
-
- if (user != null)
- {
- synchronized(users)
- {
- user.loggedin.remove(user.loggedin.indexOf(clientaddr));
- }
- }
-
- shutdown();
- }
- }
-
- /*==========================================================================*/
-
- public class TCPSocketReader
- implements Runnable
- {
- private final ServerSocketChannel sschannel;
- private final FSRecords fileservers;
- private final UserRecords users;
- private final ExecutorService pool;
-
- TCPSocketReader(ServerSocketChannel sschannel, FSRecords fileservers,
- UserRecords users, Object mainLock)
- {
- this.sschannel = sschannel;
- this.fileservers = fileservers;
- this.users = users;
- this.mainLock = mainLock;
- this.pool = Executors.newCachedThreadPool();
- }
-
- /*------------------------------------------------------------------------*/
-
- public void run()
- {
- try
- {
- while(true)
- pool.execute(new ClientConnection(sschannel.accept(), fileservers, users));
- }
- {
- err.println("Error: Unable to setup remote command handler");
- }
- {
- /* ignore that exception
- * thread will shutdown and unlock the main thread
- * which will shutdown the application
- */
- }
-
- pool.shutdown();
- try
- {
- if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS))
- out.println("Trying to shutdown the client connections. This may take up to 15 seconds...");
- if (!pool.awaitTermination(5, TimeUnit.SECONDS))
- {
- pool.shutdownNow();
- if (!pool.awaitTermination(5, TimeUnit.SECONDS))
- err.println("Error: Client connections did not terminate. You may have to kill that appplication.");
- }
- }
- {
- pool.shutdownNow();
- }
-
- synchronized(mainLock)
- {
- mainLock.notify();
- }
- }
- }
-
- /*==========================================================================*/
-
- public class Interactive
- extends CommandInteractive
- implements Runnable
- {
-
- throws NoSuchMethodException
- {
- this.sin = sin;
- this.mainLock = mainLock;
-
- cmdHandler.register("unknown", this, "cmdUnknown");
- cmdHandler.register("!fileservers", this, "cmdFileservers");
- cmdHandler.register("!users", this, "cmdUsers");
- cmdHandler.register("!exit", this, "cmdExit");
- }
-
- /*------------------------------------------------------------------------*/
-
- {
- err.println("Unknown command: " + cmd + " "
- }
-
- /*------------------------------------------------------------------------*/
-
- {
- synchronized(fileservers)
- {
- if (fileservers.size() == 0)
- out.println("No fileservers registered");
- else
- {
- int line = 1;
- {
- FSRecord record = entry.getValue();
- line, record.host, record.port,
- (record.online) ? "online" : "offline",
- record.usage));
- ++line;
- }
- }
- }
- }
-
- /*------------------------------------------------------------------------*/
-
- {
- synchronized(users)
- {
- if (users.size() == 0)
- out.println("No users registered");
- else
- {
- int line = 1;
- {
- UserRecord record = entry.getValue();
- line, record.name,
- (record.loggedin.size() > 0) ? "online" : "offline",
- record.credits));
- " ", host));
- ++line;
- }
- }
- }
- }
-
- /*------------------------------------------------------------------------*/
-
- {
- stop();
- }
-
- /*------------------------------------------------------------------------*/
-
- public void printPrompt()
- {
- out.print(">: ");
- out.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
- */
- }
-
- synchronized(mainLock)
- {
- mainLock.notify();
- }
- }
- }
-
- /*==========================================================================*/
-
- public class CheckFSTask
- implements Runnable
- {
- private FSRecords fileservers;
- private final int fserverTimeout;
-
- CheckFSTask(FSRecords fileservers, int fserverTimeout)
- {
- this.fileservers = fileservers;
- this.fserverTimeout = fserverTimeout;
- }
-
- /*------------------------------------------------------------------------*/
-
- public void run()
- {
- synchronized(fileservers)
- {
- {
- if (entry.getValue().online && entry.getValue().lastUpdate + fserverTimeout < curTime)
- {
- entry.getValue().online = false;
- out.println("Fileserver has gone offline: " + entry.getKey());
- }
- }
- }
- }
- }
-
- /*==========================================================================*/
-
- private static int tcpPort;
- private static int udpPort;
- private static int fserverTimeout;
- private static int checkPeriod;
- private FSRecords fileservers;
- private UserRecords users;
- private ScheduledExecutorService scheduler = null;
- private DatagramChannel dchannel = null;
- private ServerSocketChannel sschannel = null;
-
- /*--------------------------------------------------------------------------*/
-
- {
- fileservers = new FSRecords();
- users = new UserRecords();
- }
-
- /*--------------------------------------------------------------------------*/
-
- public static void usage()
- throws Utils.Shutdown
- {
- out.println("Usage: Proxy tcpPort udpPort fserverTimeout checkPeriod\n");
- out.println("tcpPort\t\t...the port to be used for instantiating a ServerSocket");
- out.println("udpPort\t\t...the port to be used for instantiating a DatagramSocket");
- out.println("fserverTimeout\t...the period in milliseconds each fileserver has to send an isAlive packet");
- out.println("\t\t if no such packet is received within this time, the fileserver is assumed");
- out.println("\t\t to be offline and is no longer available for handling requests");
- out.println("checkPeriod\t...specifies that the test whether a fileserver has timed-out or not");
- out.println("\t\t (see fileserverTimeout). is repeated every checkPeriod milliseconds");
-
- // 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 != 4)
- usage();
-
- try
- {
- if (tcpPort <= 0 || tcpPort > 65536)
- bailout("tcpPort must be a valid port number (1 - 65535)");
- }
- {
- bailout("tcpPort must be numeric");
- }
-
- try
- {
- if (udpPort <= 0 || udpPort > 65536)
- bailout("udpPort must be a valid port number (1 - 65535)");
- }
- {
- bailout("udpPort must be numeric");
- }
-
- try
- {
- if (fserverTimeout <= 0)
- bailout("fserverTimeout must be positive");
- }
- {
- bailout("fserverTimeout must be numeric");
- }
-
- try
- {
- if (checkPeriod <= 0)
- bailout("checkPeriod must be positive");
- }
- {
- bailout("checkPeriod must be numeric");
- }
- }
-
- /*--------------------------------------------------------------------------*/
-
- {
- if (in == null)
- props.load(in);
- {
-
- if (pieces.length == 1)
- users.put(user, new UserRecord(user, props.getProperty(prop)));
- else if (pieces.length == 2)
- {
- UserRecord record = users.get(user);
- if (record == null)
- {
- err.println("Can't load user properties for unknown user '" + user + "'. Skipping...");
- continue;
- }
-
- if (pieces[1].equals("credits"))
- {
- try
- {
- if (credits < 0)
- {
- err.println("Property " + prop + " must be positive number. Skipping...");
- continue;
- }
- record.credits = credits;
- }
- {
- err.println("Property " + prop + " must be numeric. Skipping...");
- }
- }
- else
- err.println("Property " + prop + " is unknown. Skipping...");
- }
- else
- err.println("Property " + prop + " is unknown. Skipping...");
- }
- }
-
- /*--------------------------------------------------------------------------*/
-
- public void shutdown()
- {
- try
- {
- if (scheduler != null)
- {
- scheduler.shutdownNow();
- }
- }
- {}
-
- try
- {
- if (dchannel != null)
- dchannel.close();
- }
- {}
-
- try
- {
- if (tUDPSocketReader != null)
- tUDPSocketReader.join();
- }
- {}
-
- try
- {
- if (sschannel != null)
- sschannel.close();
- }
- {}
-
- try
- {
- if (tTCPSocketReader != null)
- tTCPSocketReader.join();
- }
- {}
-
- try
- {
- if (tInteractive != null)
- {
- tInteractive.interrupt();
- tInteractive.join();
- }
- }
- {}
-
- try
- {
- if (stdin != null)
- stdin.close();
- }
- {}
- }
-
- /*--------------------------------------------------------------------------*/
-
- {
- parseArgs(args);
-
- synchronized(users)
- {
- try
- {
- if (in == null)
- bailout("Properties file doesn't exist or isn't readable");
- parseUsers(in);
- in.close();
- out.println("Users loaded successfully");
- }
- {
- bailout("Unable to read from properties file: " + e.getMessage());
- }
- {
- bailout("Malformed properties file: " + e.getMessage());
- }
- }
-
- synchronized(mainLock)
- {
- scheduler = Executors.newScheduledThreadPool(1);
- ScheduledFuture<?> checkFSTimer = scheduler.scheduleAtFixedRate(
- new CheckFSTask(fileservers, fserverTimeout),
- 0, checkPeriod, TimeUnit.MILLISECONDS);
-
- try
- {
- dchannel = DatagramChannel.open();
- dchannel.socket().bind(new InetSocketAddress(udpPort));
- mainLock));
- tUDPSocketReader.start();
- out.println("Listening on udp:/" + dchannel.socket().getLocalSocketAddress());
- }
- {
- bailout("Unable to create UDP Socket: " + e.getMessage());
- }
-
- try
- {
- sschannel = ServerSocketChannel.open();
- sschannel.socket().bind(new InetSocketAddress(tcpPort));
- fileservers, users, mainLock));
- tTCPSocketReader.start();
- out.println("Listening on tcp:/" + sschannel.socket().getLocalSocketAddress());
- }
- {
- bailout("Unable to create TCP Socket: " + e.getMessage());
- }
-
- try
- {
- tInteractive.start();
- }
- {
- bailout("Unable to setup interactive command handler");
- }
-
- out.println("Proxy startup successful!");
- try
- {
- mainLock.wait();
- }
- {
- /* if we get interrupted -> ignore */
- }
-
- try
- {
- /* let the threads shutdown */
- }
- {}
- }
-
- if (tUDPSocketReader != null && !tUDPSocketReader.isAlive())
- bailout("Listening UDP socket closed unexpected. Terminating...");
- if (tTCPSocketReader != null && !tTCPSocketReader.isAlive())
- bailout("Listening TCP socket closed unexpected. Terminating...");
-
- shutdown();
- }
-
- /*--------------------------------------------------------------------------*/
-
- {
- try
- {
- proxy.run(args);
- }
- catch(Utils.Shutdown e)
- {}
- }
- }
-