import java.io.*; import java.net.*; import java.util.*; public class KaZaServer implements Runnable { public static final int LISTEN_PORT = 3442; private ServerSocket m_serverSocket; private HashMap m_clientData; private Vector m_peerGroupLeaders; public void run() { try { m_serverSocket = new ServerSocket(LISTEN_PORT); /* porcess connection requests */ for (;;) { Socket clientSocket = m_serverSocket.accept(); Thread thread = new Thread(new ClientHandler(clientSocket)); thread.start(); } } catch (IOException ioe) { System.out.println("KaZaServer: IO Exception!"); ioe.printStackTrace(); return; } } public void connectToPeerGroupLeader(String peerName) { Socket s; try { s = new Socket(peerName, LISTEN_PORT); DataOutputStream os = new DataOutputStream(s.getOutputStream()); os.writeBytes("USER KaZaServer\n"); } catch (Exception e) { return; } synchronized (m_peerGroupLeaders) { m_peerGroupLeaders.add(s); } } public void close() { } public String[] getClientList() { Set s; synchronized (m_clientData) { s = m_clientData.keySet(); } return (String[]) s.toArray(); } private class ClientInfo { String userName = "Anonymous"; HashMap files = new HashMap(); } private class ClientHandler implements Runnable { private Socket m_socket; private String m_clientIP; ClientInfo m_clientInfo; public ClientHandler(Socket socket) { m_socket = socket; m_clientIP = m_socket.getInetAddress().getHostAddress(); synchronized (m_clientData) { if (!m_clientData.containsKey(m_clientIP)) { m_clientData.put(socket.getInetAddress().getHostAddress(), new ClientInfo()); } m_clientInfo = m_clientData.get(m_clientIP); } } public void run() { try { BufferedReader br = new BufferedReader( new InputStreamReader( m_socket.getInputStream())); DataOutputStream os = new DataOutputStream( m_socket.getOutputStream()); /* loop processing client messages */ for (;;) { String inLine = br.readLine(); StringTokenizer tokens = new StringTokenizer(inLine); if (!tokens.hasMoreTokens()) continue; String opCode = tokens.nextToken(); opCode = opCode.toUpperCase(); if (opCode.equals("HELO")) { /* user is announcing his or her username */ synchronized (m_clientData) { m_clientInfo.userName = inLine.substring(5); } } else if (opCode.equals("DESC")) { /* user is giving us a description of a file */ String fileName = inLine.substring(5); String fileDesc = br.readLine(); synchronized (m_clientData) { m_clientInfo.files.put(fileName, fileDesc); } } else if (opCode.equals("SRCH")) { /* user is requesting a search */ if (tokens.hasMoreTokens()) { int depth = Integer.parseInt(tokens.nextToken()); if (tokens.hasMoreTokens()) { String query = tokens.nextToken(); String searchResults = performSearch(depth, query); os.writeBytes(searchResults); os.writeBytes(".\n"); } } } } } catch (Exception e) { } } } private String performSearch(int depth, String query) { String results = ""; String querylc = query.toLowerCase(); if (depth > 0) { synchronized (m_peerGroupLeaders) { for (Socket s : m_peerGroupLeaders) { String peerResults = getSearchResultsFromPeerGroupLeader(s, depth-1, query); results += peerResults; } } } /* now search my own file list */ synchronized (m_clientData) { Set clients = m_clientData.keySet(); for (String clientIP : clients) { HashMap files = m_clientData.get(clientIP).files; Set clientFiles = files.keySet(); for (String fileName : clientFiles) { String fnamelc = fileName.toLowerCase(); if ( (fnamelc.indexOf(querylc) >= 0) || (files.get(fileName).toLowerCase().indexOf(querylc) >= 0) ) { results += clientIP + "|" + m_clientData.get(clientIP).userName + "|" + fileName + "|" + files.get(fileName) + "\n"; } } } } return results; } private String getSearchResultsFromPeerGroupLeader(Socket s, int depth, String query) { String searchResults = ""; try { BufferedReader br = new BufferedReader( new InputStreamReader( s.getInputStream())); DataOutputStream os = new DataOutputStream(s.getOutputStream()); os.writeBytes("SRCH " + depth + " " + query); for (;;) { String inLine = br.readLine(); if (inLine.equals(".")) break; searchResults += inLine + "\n"; } } catch (Exception e) { return ""; } return searchResults; } }