package edu.ncsu.ftp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.HashMap; public class Ident extends Thread { private volatile static boolean running = false; private volatile static boolean enabled = false; private static String userid; private static int expectedConns; private static ServerSocket ss; private static HashMap requestMap = null; private static Ident ident = null; private Ident(String id) throws Exception { if (running) throw new Exception("Already running"); setUserID(id); expectedConns = 0; } private synchronized void doNotify() { notifyAll(); } private synchronized void doWait() { try { wait(); } catch (InterruptedException e) { } } public static Ident getInstance() { return Ident.getInstance(Ident.getUserId()); } public static Ident getInstance(String user_id) { if (requestMap == null) requestMap = new HashMap(); if (ident == null) try { running = false; // should never matter ident = new Ident(user_id); } catch (Exception e) { e.printStackTrace(); // Should never get here.. } return ident; } public static Ident startServer(String userid) throws Exception { //Ident.userid = userid; Ident.setUserID(userid); return Ident.startServer(); } public static Ident startServer() throws Exception { if (userid == null) throw new Exception("IDENT service could not start (cannot start when user_id is empty)"); if (ident == null) ident = Ident.getInstance(); if (running == true) throw new Exception("IDENT service is already runnning"); if (enabled == false) throw new Exception("IDENT service could not start (disabled)"); ident.start(); Thread.yield(); return ident; } public static void setUserID(String userid) { Ident.userid = userid; Ident.enable(); } public static String getUserId() { return userid; } public static void expectRequest() { if (!enabled) return; expectedConns++; Ident.getInstance().doNotify(); } /** * @param ipAddress * @param customId */ public static void expectRequest(String ipAddress, String customId) { if (!enabled) return; requestMap.put(ipAddress, customId); Ident.expectRequest(); } public static void doneRequest() { if (expectedConns > 0) expectedConns--; if (ss != null && expectedConns <= 0) try { ss.close(); } catch (IOException e) { } } public static void enable() { enabled = true; } public static boolean isEnabled() { return enabled; } public static void disable() { enabled = false; expectedConns = 0; Ident.doneRequest(); if (requestMap == null) return; requestMap.clear(); requestMap = null; if (!ss.isClosed()) try { ss.close(); } catch (Exception e) { e.printStackTrace(); } } public static boolean isRunning() { return running; } public static void stopServer() { Ident.disable(); Ident.getInstance().doNotify(); try { ident.join(); } catch (InterruptedException e) { System.err.println(e.toString()); e.printStackTrace(); } finally { ident = null; } } public void run() { // 1 at a time, please if (running == true) return; running = true; while (running) { try { while (expectedConns <= 0) { /* * try { Thread.sleep(500); } catch (InterruptedException e) { } */ Ident.getInstance().doWait(); continue; } try { ss = new ServerSocket(113); } catch (BindException e) { System.err .println("IDENT service unable to listen on port 113 (port already in use)"); expectedConns = 0; continue; } catch (Exception e) { e.printStackTrace(); expectedConns = 0; System.out .println("IDENT service unable to listen on port 113 (unknown error)"); continue; } // ss.setSoTimeout(30 * 1000); while (expectedConns > 0) { IdentConn ic = new IdentConn(ss.accept()); ic.start(); Thread.yield(); } ss.close(); } catch (IOException e) { // e.printStackTrace(); } ss = null; } running = false; } class IdentConn extends Thread { private Socket sock; public IdentConn(Socket s) throws SocketException { sock = s; sock.setSoTimeout(30 * 1000); } public void run() { try { System.out.println("IDENT: Received IDENT request from " + sock.getInetAddress().getHostAddress()); BufferedReader in = new BufferedReader(new InputStreamReader(sock .getInputStream())); PrintStream out = new PrintStream(sock.getOutputStream()); Object o = requestMap.get(sock.getInetAddress().getHostAddress()); String tmp_id = o == null ? userid : o.toString(); String line = in.readLine(); if (line != null) { out.print(line + " : USERID : UNIX : " + tmp_id + "\r\n"); System.out.println(line + " : USERID : UNIX : " + tmp_id); } in.close(); out.close(); sock.close(); } catch (SocketException e) { // boomshakalaka don't care } catch (IOException e) { e.printStackTrace(); } } } }