gvsu/cs654/proj1/KaZaServer.java
josh 3fdc401fca implemented automatic reverse connections with GRPL message type
git-svn-id: svn://anubis/gvsu@60 45c1a28c-8058-47b2-ae61-ca45b979098e
2008-03-09 22:01:30 +00:00

324 lines
11 KiB
Java

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<String, ClientInfo> m_clientData;
private Vector<Socket> m_peerGroupLeaders;
private HashMap<String, Integer> m_currentSearches;
public KaZaServer()
{
m_clientData = new HashMap<String, ClientInfo>();
m_peerGroupLeaders = new Vector<Socket>();
m_currentSearches = new HashMap<String, Integer>();
}
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,
boolean sendReverseConnectMsg)
{
/* check if the peer group leader is already in our list */
synchronized (m_peerGroupLeaders)
{
for (Socket s : m_peerGroupLeaders)
{
if (s.getInetAddress().getHostAddress().equals(peerName))
return;
}
}
Socket s;
try
{
s = new Socket(peerName, LISTEN_PORT);
DataOutputStream os = new DataOutputStream(s.getOutputStream());
os.writeBytes("HELO KaZaServer\n");
if (sendReverseConnectMsg)
os.writeBytes("GRPL\n");
}
catch (Exception e)
{
return;
}
/* add new peer group leader to the peer group leaders list */
synchronized (m_peerGroupLeaders)
{
m_peerGroupLeaders.add(s);
}
}
public void close()
{
}
public Object[] getClientList()
{
Set<String> s;
synchronized (m_clientData)
{
s = m_clientData.keySet();
}
return s.toArray();
}
public Object[] getPeerGroupLeaderList()
{
Vector<String> peers = new Vector<String>();
synchronized (m_peerGroupLeaders)
{
for (Socket s : m_peerGroupLeaders)
{
peers.add(s.getInetAddress().getHostAddress());
}
}
return peers.toArray();
}
private class ClientInfo
{
String userName = "Anonymous";
int speed = 1500;
HashMap<String, String> files = new HashMap<String, String>();
}
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 */
boolean running = true;
while (running)
{
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);
}
// System.out.println("Got HELO from " + m_clientInfo.userName);
}
else if (opCode.equals("SPED"))
{
/* user is telling us their connection speed */
if (tokens.hasMoreTokens())
{
int speed = Integer.parseInt(tokens.nextToken());
synchronized (m_clientData)
{
m_clientInfo.speed = speed;
}
// System.out.println("Got SPED of " + m_clientInfo.speed);
}
}
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);
}
// System.out.println("Got DESC of '" + 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");
// System.out.println("Got SRCH for " + query +
// ", results:\n" + searchResults);
}
}
}
else if (opCode.equals("QUIT"))
{
/* user is requesting to leave the system */
br.close();
os.close();
m_socket.close();
running = false;
}
else if (opCode.equals("GRPL"))
{
/* user is a peer group leader, initiate a connection
* to it if one is not established */
connectToPeerGroupLeader(m_clientIP, false);
}
}
}
catch (Exception e) { }
finally
{
synchronized (m_clientData)
{
m_clientData.remove(m_clientIP);
}
}
}
}
private String performSearch(int depth, String query)
{
String results = "";
String querylc = query.toLowerCase();
synchronized (m_currentSearches)
{
if (m_currentSearches.containsKey(querylc))
return results;
m_currentSearches.put(querylc, 1);
}
if (depth > 0)
{
synchronized (m_peerGroupLeaders)
{
for (int i = 0; i < m_peerGroupLeaders.size(); i++)
{
if (m_peerGroupLeaders.elementAt(i).isClosed())
{
m_peerGroupLeaders.removeElementAt(i);
i--;
}
else
{
String peerResults =
getSearchResultsFromPeerGroupLeader(
m_peerGroupLeaders.elementAt(i),
depth-1, query);
results += peerResults;
}
}
}
}
/* now search my own file list */
synchronized (m_clientData)
{
Set<String> clients = m_clientData.keySet();
for (String clientIP : clients)
{
HashMap<String, String> files = m_clientData.get(clientIP).files;
Set<String> 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 + "|" +
m_clientData.get(clientIP).speed + "|" +
fileName + "|" +
files.get(fileName) + "\n";
}
}
}
}
synchronized (m_currentSearches)
{
m_currentSearches.remove(querylc);
}
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 + "\n");
for (;;)
{
String inLine = br.readLine();
if (inLine.equals("."))
break;
searchResults += inLine + "\n";
}
}
catch (Exception e)
{
return "";
}
return searchResults;
}
}