/** * Created : May 26, 2012 * * @author pquiring */ import java.io.*; import java.net.*; import java.util.*; import javaforce.*; /** Listens on a port and send peers to registered TorrentClients */ public class TorrentServer extends Thread { private static Vector<TorrentClient> clients = new Vector<TorrentClient>(); private String status = "?"; public static int port = 6881; private ServerSocket ss; public static void register(TorrentClient client) { clients.add(client); } public static void unregister(TorrentClient client) { clients.remove(client); } public TorrentServer(int port) { TorrentServer.port = port; } public void run() { while (true) { try { ss = new ServerSocket(port); while (true) { Socket s = ss.accept(); new PeerListener(s).start(); } } catch (Exception e) { JF.sleep(1000); } } } public String getStatus() { return status; } public void changePort(int port) { TorrentServer.port = port; status = "?"; try {ss.close();} catch (Exception e) {} } private class PeerListener extends Thread { private Socket s; private InputStream is; private OutputStream os; private String ip, id; public PeerListener(Socket s) { this.s = s; } public void run() { try { is = s.getInputStream(); os = s.getOutputStream(); ip = s.getInetAddress().toString().substring(1); } catch (Exception e) { close(); return; } if (!getHandshake()) { close(); return; } if (status.equals("?")) { status = "Ok"; MainPanel.This.setStatus(status); } } private void close() { try { s.close(); } catch (Exception e) {} } private boolean getHandshake() { byte buf[] = new byte[1024]; byte handshake[] = new byte[68]; byte info_hash[] = new byte[20]; int toRead = 68; int pos = 0; JFLog.log("Waiting for handshake:" + ip); try { while (toRead > 0) { int read = is.read(buf, 0, toRead); if (read <= 0) throw new Exception("read error:" + ip); System.arraycopy(buf, 0, handshake, pos, read); pos += read; toRead -= read; } if (handshake[0] != 19) throw new Exception("bad handshake (protocol.len!=19):" + ip); if (!new String(handshake, 1, 19).equals("BitTorrent protocol")) throw new Exception("bad handshake (unknown protocol):" + ip); id = new String(handshake, 48, 20); System.arraycopy(handshake, 28, info_hash, 0, 20); JFLog.log("info_hash=" + escape(info_hash)); for(int a=0;a<clients.size();a++) { TorrentClient client = clients.get(a); if (Arrays.equals(info_hash, client.getHash())) { client.addPeer(s, id); return true; } } JFLog.log("unknown info_hash:drop peer"); return false; } catch (Exception e) { // JFLog.log("getHandshake Exception:" + ip); JFLog.log(e); } return false; } } private static String escape(byte[] hash) { StringBuilder str = new StringBuilder(); for(int a=0;a<hash.length;a++) { if ((hash[a] >= '0') && (hash[a] <= '9')) { str.append((char)hash[a]); continue; } if ((hash[a] >= 'a') && (hash[a] <= 'z')) { str.append((char)hash[a]); continue; } if ((hash[a] >= 'A') && (hash[a] <= 'Z')) { str.append((char)hash[a]); continue; } switch (hash[a]) { case '.': case '-': case '_': case '~': str.append((char)hash[a]); continue; } str.append("%" + String.format("%02x", (((int)hash[a]) & 0xff))); } return str.toString(); } }