import java.util.Vector;\r
import javax.swing.*;\r
\r
+/**\r
+ * This class implements mlDonkey Core/GUI protocol.\r
+ * This is a part of <a href="http://royale.zerezo.com/jmoule/" target="_blank">jMoule</a>.\r
+ * This project is licenced under GPL.\r
+ * @author Antoine Jacquet\r
+ */\r
public class DonkeyCore extends Thread\r
{\r
byte[] buffer=new byte[1024*100];\r
int nbsearches=0;\r
Socket connection;\r
String password;\r
- Hashtable fileInfos=new Hashtable();\r
- Hashtable resultInfos=new Hashtable();\r
- Hashtable serverInfos=new Hashtable();\r
- Vector searchResults=new Vector();\r
+ \r
+ /**\r
+ * This contains the informations about the files being downloaded.\r
+ * File ID are the hash keys.\r
+ * The values of the hash are vectors containing file informations : filename, size, downloaded, %, rate, ETA and running state.\r
+ */\r
+ public Hashtable fileInfos=new Hashtable();\r
+ \r
+ /**\r
+ * This contains the informations about the results of searches.\r
+ * Files ID are the hash keys.\r
+ * The values of the hash are vectors containing result informations : filename, size, tags and download state.\r
+ */\r
+ public Hashtable resultInfos=new Hashtable();\r
+ \r
+ /**\r
+ * This contains the informations about the donkey servers.\r
+ * Servers ID are the hash keys.\r
+ * The values of the hash are vectors containing server informations : host, users, files, connected state.\r
+ */\r
+ public Hashtable serverInfos=new Hashtable();\r
+ \r
+ /**\r
+ * This contains all the searches results.\r
+ * Each entry is a vector containing a specific search result.\r
+ * Each specific search result contains vectors with same format as resultInfos.\r
+ */\r
+ public Vector searchResults=new Vector();\r
+ \r
+ /**\r
+ * This contains statistics informations.\r
+ * The keys are the variables and the values are numbers.\r
+ */\r
+ public Hashtable statInfos=new Hashtable();\r
+ \r
+ /**\r
+ * This is a text panel containing console messages...\r
+ */\r
+ public JTextArea console=new JTextArea();\r
//String console=new String();\r
- JTextArea console=new JTextArea();\r
\r
+ /**\r
+ * Constructs an unconnected DonkeyCore.\r
+ */\r
public DonkeyCore()\r
{\r
/*\r
*/\r
}\r
\r
+ /**\r
+ * Constructs a connected DonkeyCore.\r
+ * Same parameters as "connect".\r
+ */\r
public DonkeyCore(String host,int port,String password)\r
{\r
this();\r
connect(host,port,password);\r
}\r
\r
+ /**\r
+ * Connects an unconnected DonkeyCore.\r
+ * @param host mlDonkey host you wish to connect to.\r
+ * @param port mlDonkey core port.\r
+ * @param password Password if needed.\r
+ */\r
public boolean connect(String host,int port,String password)\r
{\r
this.password=password;\r
}\r
}\r
\r
+ /**\r
+ * Disconnects this DonkeyCore.\r
+ */\r
public void disconnect()\r
{\r
try\r
}\r
}\r
\r
+ /**\r
+ * Tests if this DonkeyCore is already connected.\r
+ * @return true if connected.\r
+ */\r
public boolean isConnected()\r
{\r
return connection!=null;\r
\r
int readInt()\r
{\r
- return(readByte()+256*readByte());\r
+ return(readByte()+(readByte()<<8));\r
}\r
\r
long readLong()\r
{\r
- return(readByte()+256*(readByte()+256*(readByte()+256*readByte())));\r
+ return(readInt()+((long)readInt()<<16));\r
}\r
\r
String readString()\r
}\r
}\r
\r
+ /**\r
+ * Asks the mlDonkey core to connect more servers.\r
+ */\r
public void connectMore()\r
{\r
byte[] buffer=new byte[2];\r
sendMessage(buffer,2);\r
}\r
\r
+ /**\r
+ * Asks the mlDonkey core to clean old servers.\r
+ */\r
public void cleanOld()\r
{\r
byte[] buffer=new byte[2];\r
sendMessage(buffer,2);\r
}\r
\r
+ /**\r
+ * Asks the mlDonkey core to kill (terminate) itself.\r
+ */\r
public void kill()\r
{\r
byte[] buffer=new byte[2];\r
sendMessage(buffer,2);\r
}\r
\r
+ /**\r
+ * Extends (redo) the last search.\r
+ */ \r
public void extend()\r
{\r
byte[] buffer=new byte[2];\r
sendMessage(buffer,2);\r
}\r
\r
+ /**\r
+ * Start a new download.\r
+ * @param fileID ID of the file to download (found in resultInfos key).\r
+ */\r
public void download(Long fileID)\r
{\r
byte[] buffer=new byte[9];\r
sendMessage(buffer,i);\r
}\r
\r
+ /**\r
+ * Pause/Resume a download.\r
+ * @param fileID ID of the file to switch (found in resultInfos key).\r
+ * @param bool true = resume, false = pause.\r
+ */\r
public void switchDownload(Long fileID,boolean bool)\r
{\r
byte[] buffer=new byte[9];\r
sendMessage(buffer,i);\r
}\r
\r
+ /**\r
+ * Asks mlDonkey to connect to a new server.\r
+ * @param serverID ID of the server to connect to (found in serverInfos key).\r
+ */\r
public void connectServer(Long serverID)\r
{\r
byte[] buffer=new byte[6];\r
sendMessage(buffer,i);\r
}\r
\r
+ /**\r
+ * Asks mlDonkey to disconnect from a server.\r
+ * @param serverID ID of the server to disconnect (found in serverInfos key).\r
+ */\r
public void disconnectServer(Long serverID)\r
{\r
byte[] buffer=new byte[6];\r
sendMessage(buffer,i);\r
}\r
\r
+ /**\r
+ * Start a new search.\r
+ * @param query A simple string to describe what you want to search.\r
+ * @return A vector of search results (entries of this vector have same structure as resultInfos entries).\r
+ */\r
public Vector search(String query)\r
{\r
- byte[] buffer=new byte[1024*100];\r
- int i=0,j;\r
- buffer[i++]=42; buffer[i++]=0; // function\r
- buffer[i++]=(byte)(nbsearches%256); buffer[i++]=(byte)(nbsearches/256); \r
- buffer[i++]=0; buffer[i++]=0; // num\r
- buffer[i++]=4; // keywords\r
- buffer[i++]=0; buffer[i++]=0; // empty string\r
- buffer[i++]=(byte)(query.length()%256);\r
- buffer[i++]=(byte)(query.length()/256);\r
- for (j=0;j<query.length();j++)\r
- buffer[i++]=(byte)query.charAt(j);\r
- buffer[i++]=50; buffer[i++]=0; buffer[i++]=0; buffer[i++]=0; // max hits\r
- buffer[i++]=1; // type\r
- Vector searchResult=new Vector();\r
- searchResults.add(searchResult);\r
- sendMessage(buffer,i);\r
- nbsearches++;\r
- /*\r
- Vector resultInfo=new Vector();\r
- resultInfo.add(new Long(1));\r
- resultInfo.add("a");\r
- resultInfo.add("a");\r
- resultInfo.add("a");\r
- resultInfo.add(new Boolean(false));\r
- searchResult.add(resultInfo);\r
- resultInfo=new Vector();\r
- resultInfo.add(new Long(2));\r
- resultInfo.add("b");\r
- resultInfo.add("b");\r
- resultInfo.add("b");\r
- resultInfo.add(new Boolean(false));\r
- searchResult.add(resultInfo);\r
- resultInfo=new Vector();\r
- resultInfo.add(new Long(3));\r
- resultInfo.add("c");\r
- resultInfo.add("c");\r
- resultInfo.add("c");\r
- resultInfo.add(new Boolean(false));\r
- searchResult.add(resultInfo);\r
- */\r
- return searchResult;\r
+ byte[] buffer=new byte[1024*100];\r
+ int i=0,j;\r
+ buffer[i++]=42; buffer[i++]=0; // function\r
+ buffer[i++]=(byte)(nbsearches%256); buffer[i++]=(byte)(nbsearches/256); \r
+ buffer[i++]=0; buffer[i++]=0; // num\r
+ buffer[i++]=4; // keywords\r
+ buffer[i++]=0; buffer[i++]=0; // empty string\r
+ buffer[i++]=(byte)(query.length()%256);\r
+ buffer[i++]=(byte)(query.length()/256);\r
+ for (j=0;j<query.length();j++)\r
+ buffer[i++]=(byte)query.charAt(j);\r
+ buffer[i++]=0; buffer[i++]=4; buffer[i++]=0; buffer[i++]=0; // max hits\r
+ buffer[i++]=1; // type\r
+ Vector searchResult=new Vector();\r
+ searchResults.add(searchResult);\r
+ sendMessage(buffer,i);\r
+ nbsearches++;\r
+ /*\r
+ Vector resultInfo=new Vector();\r
+ resultInfo.add(new Long(1));\r
+ resultInfo.add("a");\r
+ resultInfo.add("a");\r
+ resultInfo.add("a");\r
+ resultInfo.add(new Boolean(false));\r
+ searchResult.add(resultInfo);\r
+ resultInfo=new Vector();\r
+ resultInfo.add(new Long(2));\r
+ resultInfo.add("b");\r
+ resultInfo.add("b");\r
+ resultInfo.add("b");\r
+ resultInfo.add(new Boolean(false));\r
+ searchResult.add(resultInfo);\r
+ resultInfo=new Vector();\r
+ resultInfo.add(new Long(3));\r
+ resultInfo.add("c");\r
+ resultInfo.add("c");\r
+ resultInfo.add("c");\r
+ resultInfo.add(new Boolean(false));\r
+ searchResult.add(resultInfo);\r
+ */\r
+ return searchResult;\r
}\r
\r
+ /**\r
+ * This class is a thread.\r
+ */\r
public void run()\r
{\r
while(readMessage())\r
readString(); // chunks\r
readString(); // availability\r
//fileInfo.add(new Float(readString())); // rate\r
- fileInfo.add(new Float(Math.round(Float.parseFloat(readString()))/1000.0));\r
+ double rate=Math.round(Float.parseFloat(readString()))/1000.0;\r
+ fileInfo.add(new Float(rate));\r
+ long time=Math.round((filesize-filedl)/(1024*rate));\r
+ if (rate>0)\r
+ fileInfo.add(new Float(time/3600.0));\r
+ else\r
+ fileInfo.add(new Float(0));\r
n=readInt();\r
for (i=0;i<n;i++) readString(); // chunks age\r
readString(); // age\r
// Client_stats\r
case 49:\r
debug("Client_stats: ");\r
- // stats...\r
+ statInfos.put("upload_counter",new Long(readLong()+(readLong()<<32)));\r
+ statInfos.put("download_counter",new Long(readLong()+(readLong()<<32)));\r
+ statInfos.put("shared_counter",new Long(readLong()+(readLong()<<32)));\r
+ statInfos.put("nshared_files",new Long(readLong()));\r
+ statInfos.put("tcp_upload_rate",new Long(readLong()));\r
+ statInfos.put("tcp_download_rate",new Long(readLong()));\r
+ statInfos.put("udp_upload_rate",new Long(readLong()));\r
+ statInfos.put("udp_download_rate",new Long(readLong()));\r
+ statInfos.put("ndownloading_files",new Long(readLong()));\r
+ statInfos.put("ndownloaded_files",new Long(readLong()));\r
+ // ...\r
break;\r
\r
default:\r
setSize(600,400);\r
windowsize=getSize();\r
setLocation((screensize.width-windowsize.width)/2,(screensize.height-windowsize.height)/2);\r
+ setIconImage(Toolkit.getDefaultToolkit().createImage(getClass().getResource("/icon.gif")));\r
addWindowListener(new WindowAdapter() {\r
public void windowClosing(WindowEvent e)\r
{\r
tabbedPane.add(searchPanel,"Search");\r
\r
// Downloads panel\r
- //tabbedPane.add(new JScrollPane(new JTable(new DownloadTableModel(donkeyCore.fileInfos))),"Downloads");\r
- //DownloadTableModel \r
- dataModel=new DownloadTableModel(donkeyCore.fileInfos,donkeyCore);\r
- //TableSorter \r
- sorter=new TableSorter(dataModel);\r
- //JTable \r
- tableView=new JTable(sorter);\r
- tableView.setColumnSelectionAllowed(false);\r
- tableView.setRowSelectionAllowed(false);\r
- sorter.addMouseListenerToHeaderInTable(tableView);\r
- tabbedPane.add(new JScrollPane(tableView),"Downloads");\r
+ //tabbedPane.add(new JScrollPane(new JTable(new DownloadTableModel(donkeyCore.fileInfos))),"Downloads");\r
+ //DownloadTableModel \r
+ dataModel=new DownloadTableModel(donkeyCore.fileInfos,donkeyCore);\r
+ //TableSorter \r
+ sorter=new TableSorter(dataModel);\r
+ //JTable \r
+ tableView=new JTable(sorter);\r
+ tableView.setColumnSelectionAllowed(false);\r
+ tableView.setRowSelectionAllowed(false);\r
+ sorter.addMouseListenerToHeaderInTable(tableView);\r
+ tabbedPane.add(new JScrollPane(tableView),"Downloads");\r
\r
// Console panel\r
tabbedPane.add(new JScrollPane(donkeyCore.console),"Console");\r
\r
+ // Stats panel\r
+ //tabbedPane.add(new JScrollPane(new JTable(new StatTableModel(donkeyCore.statInfos))),"Stats");\r
+ dataModel=new StatTableModel(donkeyCore.statInfos);\r
+ sorter=new TableSorter(dataModel);\r
+ tableView=new JTable(sorter);\r
+ tableView.setColumnSelectionAllowed(false);\r
+ tableView.setRowSelectionAllowed(false);\r
+ sorter.addMouseListenerToHeaderInTable(tableView);\r
+ tabbedPane.add(new JScrollPane(tableView),"Stats");\r
+\r
try\r
{\r
Thread.sleep(2000);\r