bd79353ab1d212477f0be3c24ba3304d4a766fff
[jMoule] / src / DonkeyCore.java
1 import java.io.*;\r
2 import java.net.*;\r
3 import java.util.Hashtable;\r
4 import java.util.Vector;\r
5 import javax.swing.*;\r
6 \r
7 /**\r
8  * This class implements mlDonkey Core/GUI protocol.\r
9  * This is a part of <a href="http://royale.zerezo.com/jmoule/" target="_blank">jMoule</a>.\r
10  * This project is licenced under GPL.\r
11  * @author Antoine Jacquet\r
12  */\r
13 public class DonkeyCore extends Thread\r
14 {\r
15         byte[] buffer=new byte[1024*100];\r
16         int pos;\r
17         int nbsearches=0;\r
18         Socket connection;\r
19         String password;\r
20         \r
21         /**\r
22           * This contains the informations about the files being downloaded.\r
23           * File ID are the hash keys.\r
24           * The values of the hash are vectors containing file informations : filename, size, downloaded, %, rate, ETA and running state.\r
25           */\r
26         public Hashtable fileInfos=new Hashtable();\r
27         \r
28         /**\r
29           * This contains the informations about the results of searches.\r
30           * Files ID are the hash keys.\r
31           * The values of the hash are vectors containing result informations : filename, size, tags and download state.\r
32           */\r
33         public Hashtable resultInfos=new Hashtable();\r
34         \r
35         /**\r
36          * This contains the informations about the donkey servers.\r
37          * Servers ID are the hash keys.\r
38          * The values of the hash are vectors containing server informations : host, users, files, connected state.\r
39          */\r
40         public Hashtable serverInfos=new Hashtable();\r
41         \r
42         /**\r
43          * This contains all the searches results.\r
44          * Each entry is a vector containing a specific search result.\r
45          * Each specific search result contains vectors with same format as resultInfos.\r
46          */\r
47         public Vector searchResults=new Vector();\r
48         \r
49         /**\r
50          * This contains statistics informations.\r
51          * The keys are the variables and the values are numbers.\r
52          */\r
53         public Hashtable statInfos=new Hashtable();\r
54         \r
55         /**\r
56          * This is a text panel containing console messages...\r
57          */\r
58         public JTextArea console=new JTextArea();\r
59         //String console=new String();\r
60         \r
61         /**\r
62          * Constructs an unconnected DonkeyCore.\r
63          */\r
64         public DonkeyCore()\r
65         {\r
66                 /*\r
67                 Vector fileInfo;\r
68                 fileInfo=new Vector();\r
69                 fileInfo.add("a");\r
70                 fileInfo.add("b");\r
71                 fileInfo.add("m");\r
72                 fileInfo.add("x");\r
73                 fileInfo.add("x");\r
74                 fileInfo.add(new Boolean(true));\r
75                 fileInfos.put(new Long(0),fileInfo);\r
76                 fileInfo=new Vector();\r
77                 fileInfo.add("b");\r
78                 fileInfo.add("a");\r
79                 fileInfo.add("d");\r
80                 fileInfo.add("d");\r
81                 fileInfo.add("m");\r
82                 fileInfo.add(new Boolean(true));\r
83                 fileInfos.put(new Long(1),fileInfo);\r
84                 fileInfo=new Vector();\r
85                 fileInfo.add("g");\r
86                 fileInfo.add("a");\r
87                 fileInfo.add("k");\r
88                 fileInfo.add("k");\r
89                 fileInfo.add("i");\r
90                 fileInfo.add(new Boolean(true));\r
91                 fileInfos.put(new Long(2),fileInfo);\r
92                 Vector serverInfo;\r
93                 serverInfo=new Vector();\r
94                 serverInfo.add("a");\r
95                 serverInfo.add("a");\r
96                 serverInfo.add("a");\r
97                 serverInfo.add(Boolean.FALSE);\r
98                 serverInfos.put(new Long(0),serverInfo);\r
99                 serverInfo=new Vector();\r
100                 serverInfo.add("b");\r
101                 serverInfo.add("d");\r
102                 serverInfo.add("e");\r
103                 serverInfo.add(new Boolean(true));\r
104                 serverInfos.put(new Long(1),serverInfo);\r
105                 serverInfo=new Vector();\r
106                 serverInfo.add("e");\r
107                 serverInfo.add("x");\r
108                 serverInfo.add("q");\r
109                 serverInfo.add(new Boolean(false));\r
110                 serverInfos.put(new Long(2),serverInfo);\r
111                 serverInfo=new Vector();\r
112                 serverInfo.add("a");\r
113                 serverInfo.add("b");\r
114                 serverInfo.add("n");\r
115                 serverInfo.add(new Boolean(true));\r
116                 serverInfos.put(new Long(3),serverInfo);\r
117                 */\r
118         }\r
119         \r
120         /**\r
121          * Constructs a connected DonkeyCore.\r
122          * Same parameters as "connect".\r
123          */\r
124         public DonkeyCore(String host,int port,String password)\r
125         {\r
126                 this();\r
127                 connect(host,port,password);\r
128         }\r
129         \r
130         /**\r
131          * Connects an unconnected DonkeyCore.\r
132          * @param host mlDonkey host you wish to connect to.\r
133          * @param port mlDonkey core port.\r
134          * @param password Password if needed.\r
135          */\r
136         public boolean connect(String host,int port,String password)\r
137         {\r
138                 this.password=password;\r
139                 //System.out.println(password);\r
140                 try\r
141                 {\r
142                         connection=new Socket(host,port);\r
143                         start();\r
144                         return true;\r
145                 }\r
146                 catch (Exception e)\r
147                 {\r
148                         e.printStackTrace();\r
149                         return false;\r
150                 }\r
151         }\r
152         \r
153         /**\r
154          * Disconnects this DonkeyCore.\r
155          */\r
156         public void disconnect()\r
157         {\r
158                 try\r
159                 {\r
160                         connection.close();\r
161                         connection=null;\r
162                 }\r
163                 catch (Exception e)\r
164                 {\r
165                         e.printStackTrace();\r
166                 }\r
167         }\r
168         \r
169         /**\r
170           * Tests if this DonkeyCore is already connected.\r
171           * @return true if connected.\r
172           */\r
173         public boolean isConnected()\r
174         {\r
175                 return connection!=null;\r
176         }\r
177 \r
178         void debug(String message)\r
179         {\r
180                 //System.out.println(message);\r
181         }\r
182 \r
183         boolean readMessage()\r
184         {\r
185                 try\r
186                 {\r
187                         InputStream i=connection.getInputStream();\r
188                         // read the length of the message\r
189                         long l=i.read()+256*(i.read()+256*(i.read()+256*i.read()));\r
190                         //System.out.print("size: "+l+" ");\r
191                         pos=0;\r
192                         // read the buffer\r
193                         while (pos<l) pos+=i.read(buffer,pos,(int)l-pos);\r
194                         pos=0;\r
195                         // ok\r
196                         \r
197                         // dump\r
198 /*\r
199                         if (buffer[0]==3)\r
200                         {\r
201                                 System.out.println("Dump: "+new String(buffer,0,(int)l));\r
202                                 for (pos=0;pos<l;pos++)\r
203                                 {\r
204                                         System.out.print(buffer[pos]+",");\r
205                                 }\r
206                         }\r
207                         pos=0;\r
208 */\r
209 \r
210                         return true;\r
211                 }\r
212                 catch (Exception e)\r
213                 {\r
214                         e.printStackTrace();\r
215                         return false;\r
216                 }\r
217         }\r
218         \r
219         int readByte()\r
220         {\r
221                 byte temp=buffer[pos++];\r
222                 return(temp<0?temp+256:temp);\r
223         }\r
224         \r
225         int readInt()\r
226         {\r
227                 return(readByte()+(readByte()<<8));\r
228         }\r
229         \r
230         long readLong()\r
231         {\r
232                 return(readInt()+((long)readInt()<<16));\r
233         }\r
234         \r
235         String readString()\r
236         {\r
237                 int l=readInt();\r
238                 if (l>0)\r
239                 {\r
240                         String temp=new String(buffer,pos,l);\r
241                         pos+=l;\r
242                         return(temp);\r
243                 }\r
244                 else return("");\r
245         }\r
246 \r
247         synchronized boolean sendMessage(byte[] buffer,int l)\r
248         {\r
249                 try\r
250                 {\r
251                         connection.getOutputStream().write(l%256);\r
252                         connection.getOutputStream().write(l/256);\r
253                         connection.getOutputStream().write(0);\r
254                         connection.getOutputStream().write(0);\r
255                         connection.getOutputStream().write(buffer,0,l);\r
256                         return true;\r
257                 }\r
258                 catch (Exception e)\r
259                 {\r
260                         e.printStackTrace();\r
261                         return false;\r
262                 }\r
263         }\r
264         \r
265         /**\r
266          * Asks the mlDonkey core to connect more servers.\r
267          */\r
268         public void connectMore()\r
269         {\r
270         byte[] buffer=new byte[2];\r
271     buffer[0]=1; buffer[1]=0; // function\r
272     sendMessage(buffer,2);\r
273         }\r
274 \r
275         /**\r
276          * Asks the mlDonkey core to clean old servers.\r
277          */\r
278         public void cleanOld()\r
279         {\r
280         byte[] buffer=new byte[2];\r
281     buffer[0]=2; buffer[1]=0; // function\r
282     sendMessage(buffer,2);\r
283         }\r
284 \r
285         /**\r
286          * Asks the mlDonkey core to kill (terminate) itself.\r
287          */\r
288         public void kill()\r
289         {\r
290         byte[] buffer=new byte[2];\r
291     buffer[0]=3; buffer[1]=0; // function\r
292     sendMessage(buffer,2);\r
293         }\r
294 \r
295         /**\r
296          * Extends (redo) the last search.\r
297          */ \r
298         public void extend()\r
299         {\r
300         byte[] buffer=new byte[2];\r
301     buffer[0]=4; buffer[1]=0; // function\r
302     sendMessage(buffer,2);\r
303         }\r
304         \r
305         /**\r
306          * Start a new download.\r
307          * @param fileID ID of the file to download (found in resultInfos key).\r
308          */\r
309         public void download(Long fileID)\r
310         {\r
311                 byte[] buffer=new byte[9];\r
312                 int i=0;\r
313     buffer[i++]=50; buffer[i++]=0; // function\r
314     buffer[i++]=0; buffer[i++]=0; // result_names (empty list)\r
315     long id=fileID.longValue();\r
316     for (int j=0;j<4;j++)\r
317     {\r
318         buffer[i++]=(byte)(id%256);\r
319         id/=256;\r
320     }\r
321     buffer[i++]=0; // force\r
322         sendMessage(buffer,i);\r
323         }\r
324         \r
325         /**\r
326          * Pause/Resume a download.\r
327          * @param fileID ID of the file to switch (found in resultInfos key).\r
328          * @param bool true = resume, false = pause.\r
329          */\r
330         public void switchDownload(Long fileID,boolean bool)\r
331         {\r
332                 byte[] buffer=new byte[9];\r
333                 int i=0;\r
334     buffer[i++]=23; buffer[i++]=0; // function\r
335     long id=fileID.longValue();\r
336     for (int j=0;j<4;j++)\r
337     {\r
338         buffer[i++]=(byte)(id%256);\r
339         id/=256;\r
340     }\r
341     if (bool)\r
342         buffer[i++]=1;\r
343     else\r
344         buffer[i++]=0;\r
345         sendMessage(buffer,i);\r
346         }\r
347         \r
348         /**\r
349          * Asks mlDonkey to connect to a new server.\r
350          * @param serverID ID of the server to connect to (found in serverInfos key).\r
351          */\r
352         public void connectServer(Long serverID)\r
353         {\r
354                 byte[] buffer=new byte[6];\r
355                 int i=0;\r
356     buffer[i++]=21; buffer[i++]=0; // function\r
357     long id=serverID.longValue();\r
358     for (int j=0;j<4;j++)\r
359     {\r
360         buffer[i++]=(byte)(id%256);\r
361         id/=256;\r
362     }\r
363         sendMessage(buffer,i);\r
364         }\r
365         \r
366         /**\r
367          * Asks mlDonkey to disconnect from a server.\r
368          * @param serverID ID of the server to disconnect (found in serverInfos key).\r
369          */\r
370         public void disconnectServer(Long serverID)\r
371         {\r
372                 byte[] buffer=new byte[6];\r
373                 int i=0;\r
374     buffer[i++]=22; buffer[i++]=0; // function\r
375     long id=serverID.longValue();\r
376     for (int j=0;j<4;j++)\r
377     {\r
378         buffer[i++]=(byte)(id%256);\r
379         id/=256;\r
380     }\r
381         sendMessage(buffer,i);\r
382         }\r
383         \r
384         /**\r
385          * Start a new search.\r
386          * @param query A simple string to describe what you want to search.\r
387          * @return A vector of search results (entries of this vector have same structure as resultInfos entries).\r
388          */\r
389         public Vector search(String query)\r
390         {\r
391                 byte[] buffer=new byte[1024*100];\r
392                 int i=0,j;\r
393                 buffer[i++]=42; buffer[i++]=0; // function\r
394                 buffer[i++]=(byte)(nbsearches%256); buffer[i++]=(byte)(nbsearches/256); \r
395                 buffer[i++]=0; buffer[i++]=0; // num\r
396                 buffer[i++]=4; // keywords\r
397                 buffer[i++]=0; buffer[i++]=0; // empty string\r
398                 buffer[i++]=(byte)(query.length()%256);\r
399                 buffer[i++]=(byte)(query.length()/256);\r
400                 for (j=0;j<query.length();j++)\r
401                         buffer[i++]=(byte)query.charAt(j);\r
402                 buffer[i++]=0; buffer[i++]=4; buffer[i++]=0; buffer[i++]=0; // max hits\r
403                 buffer[i++]=1; // type\r
404                 Vector searchResult=new Vector();\r
405                 searchResults.add(searchResult);\r
406                 sendMessage(buffer,i);\r
407                 nbsearches++;\r
408                 /*\r
409                 Vector resultInfo=new Vector();\r
410                 resultInfo.add(new Long(1));\r
411                 resultInfo.add("a");\r
412                 resultInfo.add("a");\r
413                 resultInfo.add("a");\r
414                 resultInfo.add(new Boolean(false));\r
415                 searchResult.add(resultInfo);\r
416                 resultInfo=new Vector();\r
417                 resultInfo.add(new Long(2));\r
418                 resultInfo.add("b");\r
419                 resultInfo.add("b");\r
420                 resultInfo.add("b");\r
421                 resultInfo.add(new Boolean(false));\r
422                 searchResult.add(resultInfo);\r
423                 resultInfo=new Vector();\r
424                 resultInfo.add(new Long(3));\r
425                 resultInfo.add("c");\r
426                 resultInfo.add("c");\r
427                 resultInfo.add("c");\r
428                 resultInfo.add(new Boolean(false));\r
429                 searchResult.add(resultInfo);\r
430                 */\r
431                 return searchResult;\r
432         }\r
433         \r
434         /**\r
435          * This class is a thread.\r
436          */\r
437         public void run()\r
438         {\r
439                 while(readMessage())\r
440                 {\r
441                         //String serverStates[]={"NotConnected -1","Connecting","Connected_initiating","Connected_downloading","Connected -1","Connected n","NewHost","RemovedHost","BlackListedHost","NotConnected n"};\r
442                         Boolean serverStates[]={\r
443                                 Boolean.FALSE, // "NotConnected -1"\r
444                                 Boolean.FALSE, // "Connecting"\r
445                                 Boolean.TRUE,  // "Connected_initiating"\r
446                                 Boolean.TRUE,  // "Connected_downloading"\r
447                                 Boolean.TRUE,  // "Connected -1"\r
448                                 Boolean.TRUE,  // "Connected n"\r
449                                 Boolean.FALSE, // "NewHost"\r
450                                 Boolean.FALSE, // "RemovedHost"\r
451                                 Boolean.FALSE, // "BlackListedHost"\r
452                                 Boolean.FALSE  // "NotConnected n"\r
453                         };\r
454                         Boolean fileStates[]={\r
455                                 Boolean.TRUE,  // FileDownloading\r
456                                 Boolean.FALSE, // FilePaused\r
457                         Boolean.TRUE,  // FileDownloaded\r
458                         Boolean.FALSE, // FileShared\r
459                         Boolean.FALSE, // FileCancelled\r
460                         Boolean.FALSE, // FileNew\r
461                         Boolean.FALSE, // FileAborted s\r
462                                 Boolean.FALSE  // FileQueued\r
463                         };\r
464                         int i,n,f;\r
465                         Long id;\r
466                         String tags;\r
467                         switch(f=readInt()) // fonction\r
468                         {\r
469                                 \r
470                                 // CoreProtocol\r
471                                 case 0:\r
472                                         debug("CoreProtocol: "+readLong());\r
473                                         // (06:00:00:00:) 00:00:10:00:00:00 GuiProtocol\r
474                                         for (i=0;i<6;i++) buffer[i]=0;\r
475                                         buffer[2]=10;\r
476                                         sendMessage(buffer,6);\r
477                                         // (04:00:00:00:) 05:00:00:00 Password (empty)\r
478                                         i=0;\r
479                                         buffer[i++]=5; buffer[i++]=0; // function\r
480                                         buffer[i++]=(byte)(password.length()%256);\r
481                                         buffer[i++]=(byte)(password.length()/256);\r
482                                         for (int j=0;j<password.length();j++)\r
483                                                 buffer[i++]=(byte)password.charAt(j);\r
484                                         sendMessage(buffer,i);\r
485                                         break;\r
486 \r
487                                 // Options_info\r
488                                 case 1:\r
489                                         debug("Options_info:");\r
490                                         n=readInt();\r
491                                         for (i=0;i<n;i++)\r
492                                                 debug(readString()+" = "+readString());\r
493                                         break;\r
494                                         \r
495                                 // DefineSearches\r
496                                 case 3:\r
497                                         n=readInt();\r
498                                         debug("DefineSearches: "+n);\r
499                                         /*for (i=0;i<n;i++)\r
500                                         {\r
501                                                 System.out.println(readString()); // name\r
502                                                 System.out.println(readByte());\r
503                                         }*/\r
504                                         break;\r
505                                         \r
506                                 // Result_info\r
507                                 case 4:\r
508                                         Vector resultInfo=new Vector();\r
509                                         debug("Result_info: ");\r
510                                         id=new Long(readLong());\r
511                                         resultInfo.add(id);\r
512                                         readLong(); // network\r
513                                         n=readInt();\r
514                                         resultInfo.add(readString());\r
515                                         for (i=0;i<n-1;i++) readString(); // names\r
516                                         for (i=0;i<16;i++) readByte(); // hash\r
517                                         resultInfo.add(new Long(readLong())); // Size\r
518                                         readString(); // Format\r
519                                         readString(); // Type\r
520                                         tags=new String();\r
521                                         n=readInt();\r
522                                         for (i=0;i<n;i++)\r
523                                         {\r
524                                                 readString(); // TagName\r
525                                                 switch (readByte()) // TagValue\r
526                                                 {\r
527                                                         case 0:\r
528                                                         case 1:\r
529                                                                 tags=tags.concat(""+readLong()+" ");\r
530                                                                 break;\r
531                                                         case 2:\r
532                                                                 tags=tags.concat(readString()+" ");\r
533                                                                 break;\r
534                                                         case 3:\r
535                                                                 tags=tags.concat(""+readByte()+"."+readByte()+"."+readByte()+"."+readByte()+" ");\r
536                                                                 break;\r
537                                                 }\r
538                                         }\r
539                                         resultInfo.add(tags);\r
540                                         readString(); // Comment\r
541                                         readByte(); // Done (boolean)\r
542                                         resultInfo.add(new Boolean(false)); // download ?\r
543                                         resultInfos.put(id,resultInfo);\r
544                                         break;\r
545 \r
546                                 // Search_result                                        \r
547                                 case 5:\r
548                                         int search=(int)readLong(); // Search\r
549                                         Long info=new Long(readLong()); // Result_Info\r
550                                         ((Vector)searchResults.get(search)).add(resultInfos.get(info));\r
551                                         break;\r
552                                 \r
553                                 // File_info\r
554                                 case 7:\r
555                                 case 40:\r
556                                 case 43: \r
557                                         Vector fileInfo=new Vector();\r
558                                         debug("FileInformation: ");\r
559                                         id=new Long(readLong()); // id\r
560                                         readLong(); // network\r
561                                         n=readInt();\r
562                                         readString();\r
563                                         fileInfo.add(readString());\r
564                                         for (i=0;i<n-2;i++)     debug(readString()); // names\r
565                                         //for (i=0;i<n;i++)     debug(readString()); // names\r
566                                         for (i=0;i<16;i++) readByte(); // hash\r
567                                         //readLong(); // size\r
568                                         //readLong(); // downloaded\r
569                                         long filesize=readLong();\r
570                                         long filedl=readLong();\r
571                                         fileInfo.add(new Long(filesize));\r
572                                         fileInfo.add(new Long(filedl));\r
573                                         fileInfo.add(new Float(Math.round(10000*filedl/filesize)/100.0));\r
574                                         //debug(readLong()+"/"+readLong());\r
575                                         readLong(); // nlocations\r
576                                         readLong(); // nclients\r
577                                         int state=readByte(); // file_state\r
578                                         readString(); // chunks\r
579                                         readString(); // availability\r
580                                         //fileInfo.add(new Float(readString())); // rate\r
581                                         double rate=Math.round(Float.parseFloat(readString()))/1000.0;\r
582                                         fileInfo.add(new Float(rate));\r
583                                         long time=Math.round((filesize-filedl)/(1024*rate));\r
584                                         if (rate>0)\r
585                                                 fileInfo.add(new Float(time/3600.0));\r
586                                         else\r
587                                                 fileInfo.add(new Float(0));\r
588                                         n=readInt();\r
589                                         for (i=0;i<n;i++) readString(); // chunks age\r
590                                         readString(); // age\r
591                                         switch (readByte()) // format\r
592                                         {\r
593                                                 case 0:\r
594                                                         debug("Unknown_format");\r
595                                                         break;\r
596                                                 case 1: // FormatType\r
597                                                         //readString(); readString();\r
598                                                         debug("FormatType: "+readString()+" "+readString());\r
599                                                         break;\r
600                                                 case 2: // AVI\r
601                                                         debug("AVI: ");\r
602                                                         debug("codec: "+readString()); // codec\r
603                                                         debug(readLong()+"x"+readLong()+", "+readLong()+" fps "+readLong()+" rate")     ;\r
604                                                         break;\r
605                                                 case 3: // MP3\r
606                                                         debug("MP3: ");\r
607                                                         debug("title: "+readString()); // title\r
608                                                         debug("artist: "+readString()); // artist\r
609                                                         debug("album: "+readString()); // album\r
610                                                         debug("year: "+readString()); // year\r
611                                                         debug("comment: "+readString()); // comment\r
612                                                         debug("track: "+readLong()); // track number\r
613                                                         debug("genre: "+readLong()); // genre\r
614                                                         break;\r
615                                         }\r
616                                         fileInfo.add(fileStates[state]);\r
617                                         fileInfos.put(id,fileInfo);\r
618                                         break;\r
619                                 \r
620                                 // File_source\r
621                                 case 10:\r
622                                         // file_num f, client_num c\r
623                                         //debug("File_source: "+readInt()+" "+readInt());\r
624                                         break;\r
625                                 \r
626                                 // Server_state\r
627                                 case 13:\r
628                                         //debug("Server_state: "+readLong()+" etat: "+readByte());\r
629                                         id=new Long(readLong());\r
630                                         ((Vector)serverInfos.get(id)).setElementAt(serverStates[readByte()],3); // server_state\r
631                                         //System.out.println(id+" : state changed");\r
632                                         break;\r
633                                         \r
634                                 // Client_state\r
635                                 case 16:\r
636                                         debug("Client_state: "+readLong()+" etat: "+readByte());\r
637                                         break;\r
638                                 \r
639                                 // Client_info\r
640                                 case 15:\r
641                                         /*\r
642                                         debug("Client_info: ");\r
643                                         debug("num: "+readLong());\r
644                                         debug("network: "+readLong());\r
645                                         switch(readByte())\r
646                                         {\r
647                                                 case 0:\r
648                                                         // Known_location\r
649                                                         debug("type: Known_location");\r
650                                                         debug("ip: "+readByte()+"."+readByte()+"."+readByte()+"."+readByte());\r
651                                                         debug("port: "+readInt());\r
652                                                         break;\r
653                                                 case 1:\r
654                                                         // Indirect_location\r
655                                                         debug("type: Indirect_location");\r
656                                                         debug("name: "+readString());\r
657                                                         break;\r
658                                         }\r
659                                         */\r
660                                         break;\r
661                                 \r
662                                 // Console\r
663                                 case 19: \r
664                                         debug("Console: ");\r
665                                         //console=console.concat(readString());\r
666                                         console.append(readString());\r
667                                         break;\r
668                                 \r
669                                 // Network_info\r
670                                 case 20:\r
671                                         n=readInt();\r
672                                         debug("Network_info: "+readString());\r
673                                         break;\r
674                                         \r
675                                 // Server_info\r
676                                 case 26:\r
677                                         Vector serverInfo=new Vector();\r
678                                         debug("Server_info: ");\r
679                                         id=new Long(readLong()); // id\r
680                                         readLong(); // network\r
681                                         // only works if proto>=2\r
682                                         String host=null;\r
683                                         switch(readByte())\r
684                                         {\r
685                                                 case 0:\r
686                                                         //debug("ip: "+readByte()+"."+readByte()+"."+readByte()+"."+readByte());\r
687                                                         host=""+readByte()+"."+readByte()+"."+readByte()+"."+readByte();\r
688                                                         break;\r
689                                                 case 1:\r
690                                                         //debug("name: "+readString());\r
691                                                         host=readString();\r
692                                                         break;\r
693                                         }\r
694                                         //debug("port: "+readInt());\r
695                                         host=host+":"+readInt(); // port\r
696                                         serverInfo.add(host);\r
697                                         readLong(); // score\r
698                                         tags=new String();\r
699                                         n=readInt();\r
700                                         for (i=0;i<n;i++)\r
701                                         {\r
702                                                 readString(); // TagName\r
703                                                 switch (readByte()) // TagValue\r
704                                                 {\r
705                                                         case 0:\r
706                                                         case 1:\r
707                                                                 tags=tags.concat(""+readLong()+" ");\r
708                                                                 break;\r
709                                                         case 2:\r
710                                                                 tags=tags.concat(readString()+" ");\r
711                                                                 break;\r
712                                                         case 3:\r
713                                                                 tags=tags.concat(""+readByte()+"."+readByte()+"."+readByte()+"."+readByte()+" ");\r
714                                                                 break;\r
715                                                 }\r
716                                         }\r
717                                         serverInfo.add(new Long(readLong())); // nusers\r
718                                         serverInfo.add(new Long(readLong())); // nfiles\r
719                                         serverInfo.add(serverStates[readByte()]); // server_state\r
720                                         serverInfos.put(id,serverInfo);\r
721                                         break;\r
722                                                                 \r
723                                 // Add_section_option\r
724                                 case 36:\r
725                                         debug("Add_section_option: "+readString()+" "+readString()+" "+readString());\r
726                                         break;\r
727                                 \r
728                                 // Add_plugin_option\r
729                                 case 38:\r
730                                         debug("Add_plugin_option: "+readString()+" "+readString()+" "+readString());\r
731                                         break;\r
732                                         \r
733                                 // File_downloaded\r
734                                 case 46:\r
735                                         debug("File_downloaded: ");\r
736                                         debug("n: "+readLong());\r
737                                         debug("size: "+readLong());\r
738                                         debug("rate: "+readString());\r
739                                         debug("last_seen: "+readLong());\r
740                                         break;\r
741                                         \r
742                                 // Shared_file_info\r
743                                 case 48:\r
744                                         debug("Shared_file_info: ");\r
745                                         debug("num: "+readLong());\r
746                                         debug("network: "+readLong());\r
747                                         debug("name: "+readString());\r
748                                         debug("size: "+readLong());\r
749                                         // ...                                  \r
750                                         break;\r
751                                         \r
752                                 // Client_stats\r
753                                 case 49:\r
754                                         debug("Client_stats: ");\r
755                                         statInfos.put("upload_counter",new Long(readLong()+(readLong()<<32)));\r
756                                         statInfos.put("download_counter",new Long(readLong()+(readLong()<<32)));\r
757                                         statInfos.put("shared_counter",new Long(readLong()+(readLong()<<32)));\r
758                                         statInfos.put("nshared_files",new Long(readLong()));\r
759                                         statInfos.put("tcp_upload_rate",new Long(readLong()));\r
760                                         statInfos.put("tcp_download_rate",new Long(readLong()));\r
761                                         statInfos.put("udp_upload_rate",new Long(readLong()));\r
762                                         statInfos.put("udp_download_rate",new Long(readLong()));\r
763                                         statInfos.put("ndownloading_files",new Long(readLong()));\r
764                                         statInfos.put("ndownloaded_files",new Long(readLong()));\r
765                                         // ...\r
766                                         break;\r
767 \r
768                                 default:\r
769                                         debug("Fonction: "+f);\r
770                                         break;\r
771                                         \r
772                         }\r
773                         //System.out.println();\r
774                 }\r
775         }\r
776         \r
777 }