Home » openjdk-7 » net.bonzoun » cocodonkey » [javadoc | source]

    1   //
    2   //  DonkeyTalker.java
    3   //  CocoDonkey
    4   //  $Id: DonkeyTalker.java,v 1.26 2003/01/01 19:27:15 fortun Exp $
    5   //
    6   //  Created by Fred Bonzoun on Sat May 11 2002.
    7   //  Copyright (c) 2002 Bonzoun. All rights reserved.
    8   //
    9   //  This library is free software; you can redistribute it and/or modify
   10   //  it under the terms of the GNU Lesser General Public License as published
   11   //  by the Free Software Foundation; either version 2.1 of the License, or
   12   //  (at your option) any later version.
   13   //
   14   //  This library is distributed in the hope that it will be useful,
   15   //  but WITHOUT ANY WARRANTY; without even the implied warranty of
   16   //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17   //  GNU Lesser General Public License for more details.
   18   //
   19   //  You should have received a copy of the GNU Lesser General Public License
   20   //  along with this program; if not, write to the Free Software
   21   //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   22   //
   23   
   24   package net.bonzoun.cocodonkey;
   25   
   26   import com.apple.cocoa.foundation;
   27   import com.apple.cocoa.application;
   28   
   29   import java.io;
   30   import java.net;
   31   import java.util;
   32   import gnu.regexp;
   33   
   34   public class DonkeyTalker {
   35   
   36       private String hostname;
   37       private SshTunnel tunnel;
   38       private int port;
   39       private Socket socket;
   40       private int defaultTimeout = 30000;
   41       protected BufferedReader in;
   42       protected PrintWriter out;
   43       private long lastCallTime;
   44       private StringBuffer dialog = new StringBuffer();
   45       private int dialogOffset = 0;
   46       private Vector listeners = new Vector();
   47       private boolean isDead = false;
   48       private Logger logger;
   49       private String lastCommand;
   50       private boolean shouldStopCommand = false;
   51   
   52       private CamlFile fileFiles;
   53       private CamlFile fileServers;
   54       private CamlFile fileSharedFiles;
   55       
   56       protected RE reVULine1;
   57       protected RE reVULine2;
   58       protected RE reVDDown0;
   59       protected RE reVDDown0b;
   60       protected RE reVDLine;
   61       protected RE reVDLineb;
   62       protected RE reVDDown1;
   63       protected RE reVDDown;
   64       protected RE reVDEnd;
   65       protected RE reVDNLine1;
   66       protected RE reVDNChunks;
   67       protected RE reVDNSources;
   68       protected RE reS;
   69       protected RE reVRRunning;
   70       protected RE reVRDone;
   71       protected RE reVRTitle;
   72       //protected RE reVRData;
   73       //protected RE reVRSubData;
   74       protected RE reVREnd;
   75       protected RE reCOMMIT;
   76       protected RE reVSTitle;
   77       protected RE reVSLine;
   78       protected RE reVSData;
   79       protected RE reVOData;
   80       protected RE reVMLine;
   81       protected RE reVMALine;
   82       protected RE reUPTitle;
   83       protected RE reUPTitle2;
   84       protected RE reUPLine;
   85       protected RE reUPDone;
   86       protected RE reError;
   87   
   88       public DonkeyTalker(String path, Logger logger) {
   89           this.logger = logger;
   90           port = 4000;
   91           init(path);
   92       }
   93       
   94       public DonkeyTalker(String path, SshTunnel tunnel, Logger logger) {
   95           this.tunnel = tunnel;
   96           this.logger = logger;
   97           port = tunnel.port();
   98           init(path);
   99       }
  100       
  101       public DonkeyTalker(String path, String host, Logger logger) {
  102           hostname = host;
  103           this.logger = logger;
  104           port = 4000;
  105           init(path);
  106       }
  107   
  108       private void init(String path) {
  109           try {
  110               reVULine1 = new RE("credits\\D+(\\d+)\\s*m");
  111               reVULine2 = new RE("disabled\\D+(\\d+)\\s*m");
  112               reVDDown0 = new RE("^Downloaded\\s+(\\d+)/");
  113               reVDDown0b = new RE("^Downloading\\s+(\\d+)");
  114               reVDLine = new RE("\\[\\s*(\\d+)\\s*\\]\\s+(.{1,50})\\s+(\\S+)\\s+(\\d+)\\s+(\\d+)\\s+\\S+\\s+(\\S+)");
  115               reVDLineb = new RE("\\[\\s*(\\d+)\\s*\\]\\s+(.{1,50})(\\s+)(\\d+)\\s+(\\d+)\\s+(\\S+)");
  116               reVDDown1 = new RE("^Downloaded\\s+(\\d+)\\s+files");
  117               reVDDown = new RE("\\[\\s*(\\d+)\\s*\\]\\s+(\\S.*\\S)\\s+(\\d+)\\s+([0-9,A-F]+)");
  118               reVDEnd = new RE("^Use 'commit'");
  119               reVDNLine1 = new RE("\\[\\D*(\\d+)\\s*\\]\\s*(\\S.+\\S)\\s+(\\d+)\\s+(\\d+)");
  120               reVDNChunks = new RE("^Chunks:\\s*\\[(\\d+)\\]");
  121               reVDNSources = new RE("(\\d+)\\s*sources");
  122               reS = new RE("Query\\D+(\\d+)\\D+(\\d+)");
  123               reVRRunning = new RE("(\\d+)\\s+results\\D+(\\d+)\\s+waiting");
  124               reVRDone = new RE("(\\d+)\\s+results.+done");
  125               reVRTitle = new RE("\\[\\s*(\\d+)\\s*\\]\\s*(Donkey )?(.+)");
  126               //reVRData = new RE("(\\d+)\\s+([0-9,A-F]+)\\s+(\\S.*\\S\\s+)?(\\d+)");
  127               //reVRSubData = new RE("^(\\S+)\\s+(\\S+)\\s+((\\S.*\\S)\\s+(\\d+:\\s*\\d+)\\s+((\\d+)\\s+)?)?");
  128               reVREnd = new RE("Bad number of arguments");
  129               reCOMMIT = new RE("commited");
  130               reVSTitle = new RE("Searching\\s+(\\d+)");
  131               reVSLine = new RE("\\[(\\d+)\\s*\\]\\s*(\\S.*\\S)\\s+(\\S+)");
  132               reVSData = new RE("CONTAINS\\[([^\\]]+)\\]");
  133               reVOData = new RE("(\\S+)\\s*=\\s*(\\S+)");
  134               reVMLine = new RE("\\[\\s*(\\d+)\\s*\\]\\s+(\\S+)\\s+(\\S.*\\S)?\\s+(\\d+)\\s+(\\d+)");
  135               reVMALine = new RE("\\[\\s*(\\d+)\\s*\\]\\s+(\\S+)\\s*(\\S.*)?");
  136               reUPTitle = new RE("^Total:\\s+(\\d+).+uploaded");
  137               reUPTitle2 = new RE("^Total:\\s+(\\d+).+bytes.+uploaded");
  138               reUPLine = new RE("^(.+)\\s+requests:\\s+(\\d+)\\s+blocs:\\s+(\\d+)");
  139               reUPDone = new RE("^done$");
  140               reError = new RE("^exception\\s*\\[(.+)\\]");
  141           }
  142           catch(REException e) {
  143               throw new Error("Bad: " + e);
  144           }
  145           fileFiles = new CamlFile(path + "/files.ini");
  146           fileServers = new CamlFile(path + "/servers.ini");
  147           fileSharedFiles = new CamlFile(path + "/shared_files.ini");
  148       }
  149       
  150       public void stopCommandIfCurrent(String cmd) {
  151           if (lastCommand!=null && lastCommand==cmd) {
  152               shouldStopCommand = true;
  153           }
  154       }
  155       
  156       public String hostname() {
  157           return hostname;
  158       }
  159   
  160       public boolean processIsLocal() {
  161           return (hostname==null || hostname.equals("127.0.0.1") || hostname.equals("localhost"))
  162           && tunnel==null;
  163       }
  164   
  165       public synchronized void addListener(Listener listener) {
  166           listeners.add(listener);
  167       }
  168   
  169       public synchronized void removeListener(Listener listener) {
  170           listeners.remove(listener);
  171       }
  172   
  173       public int currentDialogOffset() {
  174           return dialogOffset;
  175       }
  176       
  177       public String dialogSince(int n) {
  178           if (n>=dialogOffset+dialog.length())
  179               return "";
  180           else if (n<=dialogOffset)
  181               return dialog.toString();
  182           else
  183               return dialog.substring(n-dialogOffset);
  184       }
  185       
  186       public synchronized void reconnect() {
  187           Thread.dumpStack();
  188           try {
  189               close();
  190           }
  191           catch(IOException e) {
  192           }
  193           try {
  194               connect();
  195           }
  196           catch(IOException e) {
  197           }
  198       }
  199   
  200       public void connect() throws IOException {
  201           connect(30000);
  202       }
  203       
  204       /*package*/ synchronized void connect(int timeout) throws IOException {
  205           if (isDead)
  206               return;
  207           if (socket!=null)
  208               close();
  209           defaultTimeout = timeout;
  210           InetAddress addr =  InetAddress.getByName(hostname!=null ? hostname : "127.0.0.1");
  211           socket = new Socket(addr, port);
  212           socket.setSoTimeout(timeout);
  213           socket.setSoLinger(true, 20);
  214           in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO8859_1"));
  215           out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "ISO8859_1"));
  216           logCommandln("<<Open connection>>");
  217           testConnection();
  218       }
  219   
  220       public synchronized void finalClose() {
  221           isDead = true;
  222           try {
  223               close();
  224           }
  225           catch (IOException e) {
  226           }
  227           finally {
  228               if (tunnel!=null) {
  229                   tunnel.close();
  230                   tunnel = null;
  231               }
  232           }
  233       }
  234           
  235       public synchronized void close() throws IOException {
  236           if (out!=null) {
  237               out.close();
  238               out = null;
  239           }
  240           if (in!=null) {
  241               in.close();
  242               in = null;
  243           }
  244           if (socket!=null) {
  245               logCommandln("<<Close connection>>");
  246               Socket s = socket;
  247               socket = null;
  248               s.close();
  249           }
  250       }
  251   
  252       public synchronized boolean finalKill() {
  253           isDead = true;
  254           for(int i=0; i<listeners.size(); i++)
  255               ((Listener)listeners.elementAt(i)).stopListening();
  256           boolean cr = kill();
  257           finalClose();
  258           return cr;
  259       }
  260   
  261       public synchronized boolean kill() {
  262           if (socket==null)
  263               return true;
  264           // sendNoWait("kill");
  265           try {
  266               socket.setSoTimeout(10000);
  267               sendNoWait("kill");
  268               String line = readLine();
  269               if (line!=null && reError.getMatch(line)!=null)
  270                   return false;
  271               else
  272                   return true;
  273           }
  274           catch(IOException e) {
  275               return true;
  276           }
  277           finally {
  278               try {
  279                   socket.setSoTimeout(defaultTimeout);
  280               } catch(IOException e) {}
  281           }
  282       }
  283   
  284       public synchronized void quit() {
  285           if (socket==null)
  286               return;
  287           try {
  288               socket.setSoTimeout(2000);
  289               sendNoWait("q");
  290               sendNoWait("");
  291               finalClose();
  292           }
  293           catch(IOException e) {
  294               e.printStackTrace();
  295           }
  296       }
  297       
  298       public synchronized void testConnection() throws IOException {
  299           send("");
  300           if (socket==null)
  301               return;
  302           while (in.ready() && !shouldStopCommand)
  303               readLine();
  304       }
  305       
  306       public synchronized void addServers() {
  307           sendNoFail("c");
  308       }
  309   
  310       public synchronized void addAServer(String host, String port) {
  311           if (port==null)
  312               port = "";
  313           sendNoFail("n " + host + " " + port);
  314       }
  315   
  316       public synchronized void addServerMet(String file) {
  317           sendNoFail("servers " + file);
  318       }
  319       
  320       public synchronized void connectToServer(String id) {
  321           sendNoFail("c " + id);
  322       }
  323       
  324       public synchronized void closeFds() {
  325           sendNoFail("close_fds");
  326       }
  327   
  328       public synchronized void reshare() {
  329           sendNoFail("reshare");
  330       }
  331       
  332       public synchronized void recoverTrash() {
  333           sendNoFail("recover_temp");
  334       }
  335   
  336       public synchronized void removeOldServers() {
  337           sendNoFail("remove_old_servers");
  338       }
  339       
  340       public synchronized void download(GenericItem item) {
  341           sendNoFail("d " + item.size() + " " + item.hash());
  342           // Addition for mldonkey version > 1.16
  343           sendNoFail("dd " + item.size() + " " + item.hash());
  344       }
  345   
  346       public synchronized void download(String link) {
  347           sendNoFail("dllink " + link);
  348       }
  349       
  350       public synchronized int uploadCredit() {
  351           String result = sendAndSearchResult("vu", reVULine1, "$1");
  352           if (result!=null)
  353               return Integer.parseInt(result);
  354           else
  355               return -1;
  356       }
  357   
  358       public synchronized int uploadDisabledTime() {
  359           String result = sendAndSearchResult("vu", reVULine2, "$1");
  360           if (result!=null)
  361               return Integer.parseInt(result);
  362           else
  363               return -1;
  364       }
  365   
  366       public synchronized void disableUploadFor(int n) {
  367           sendAndSearchResult("nu " + n, reVULine2, "$1");
  368       }
  369       
  370       public synchronized NSArray downloadItems() {
  371           NSMutableArray liste = new NSMutableArray();
  372           int state = 0;
  373           try {
  374               send("vd");
  375               if (socket==null)
  376                   return new NSArray();
  377               while(state<3 && !shouldStopCommand) {
  378                   String line = readLine();
  379                   if (line==null)
  380                       break;
  381                   switch (state) {
  382                       case 0: {
  383                           REMatch result = reVDDown0.getMatch(line);
  384                           if (result==null)
  385                               result = reVDDown0b.getMatch(line);
  386                           if (result!=null) {
  387                               state = 1;
  388                           }
  389                           else {
  390                               result = reVDDown1.getMatch(line);
  391                               if (result!=null) {
  392                                   int n = strongParseInt(result.substituteInto("$1"), -1);
  393                                   if (n<=0)
  394                                       state = 3;
  395                                   else
  396                                       state = 2;
  397                               }
  398                           }
  399                           break;
  400                       }
  401                       case 1: {
  402                           StringParser parser = new StringParser(line);
  403                           if (parser.goAfter('[')) {
  404                               parser.getNextStringUntil(StringParser.INTEGER);
  405                               int n = parser.getNextIntUntil("]", -1);
  406                               parser.goAfter(']');
  407                               String r = parser.getLastString();
  408                               float rate;
  409                               if (r.equalsIgnoreCase("paused"))
  410                                   rate = -2;
  411                               else
  412                                   rate = strongParseFloat(r, -1);
  413                               int total = parser.getLastInt(-1);
  414                               int downloaded;
  415                               float percent;
  416                               if (total<0) {
  417                                   total = parser.getLastInt(-1);
  418                                   downloaded = parser.getLastInt(-1);
  419                                   percent = parser.getLastFloat(-1);
  420                               } else {
  421                                   downloaded = parser.getLastInt(-1);
  422                                   percent = -1;
  423                               }
  424                               String name = parser.getRemainingString();
  425                               if (n>=0)
  426                                   liste.addObject(new DownloadItem(n, name, percent, downloaded, total, rate));
  427                           }
  428                           
  429                           /*REMatch result = reVDLine.getMatch(line);
  430                           if (result==null)
  431                               result = reVDLineb.getMatch(line);
  432                           if (result!=null) {
  433                               int n = strongParseInt(result.substituteInto("$1"), -1);
  434                               String name = result.substituteInto("$2");
  435                               float percent = strongParseFloat(result.substituteInto("$3"), -1);
  436                               int downloaded = strongParseInt(result.substituteInto("$4"), -1);
  437                               int total = strongParseInt(result.substituteInto("$5"), -1);
  438                               String r = result.substituteInto("$6");
  439                               float rate;
  440                               if (r.equalsIgnoreCase("paused"))
  441                                   rate = -2;
  442                               else
  443                                   rate = strongParseFloat(r, -1);
  444                               liste.addObject(new DownloadItem(n, name, percent, downloaded, total, rate));
  445                           }*/
  446                           else {
  447                               REMatch result = reVDDown1.getMatch(line);
  448                               if (result!=null) {
  449                                   int n = strongParseInt(result.substituteInto("$1"), -1);
  450                                   if (n<=0)
  451                                       state = 3;
  452                                   else
  453                                       state = 2;
  454                               }
  455                           }
  456                           break;
  457                       }
  458                       case 2: {
  459                           StringParser parser = new StringParser(line);
  460                           if (parser.goAfter('[')) {
  461                               parser.getNextStringUntil(StringParser.INTEGER + ']');
  462                               int n = parser.getNextIntUntil("]", -1);
  463                               parser.goAfter(']');
  464                               String hash = parser.getLastString();
  465                               int size = parser.getLastInt(-1);
  466                               String name = parser.getRemainingString();
  467                               if (n>=0)
  468                                   liste.addObject(new DownloadItem(n, name, size, hash));
  469                           }
  470                           /*REMatch result = reVDDown.getMatch(line);
  471                           if (result!=null) {
  472                               int n = strongParseInt(result.substituteInto("$1"), -1);
  473                               String name = result.substituteInto("$2");
  474                               int size = strongParseInt(result.substituteInto("$3"), -1);
  475                               String hash = result.substituteInto("$4");
  476                               liste.addObject(new DownloadItem(n, name, size, hash));
  477                           }*/
  478                           else {
  479                               REMatch result = reVDEnd.getMatch(line);
  480                               if (result!=null) {
  481                                   state = 3;
  482                               }
  483                           }
  484                           break;
  485                       }
  486                   }
  487               }
  488           }
  489           catch(IOException e) {
  490               e.printStackTrace();
  491               reconnect();
  492           }
  493           return liste;
  494       }
  495   
  496       public synchronized void fillItemDetails(DownloadItem item) {
  497           /*int nbLines = 0;
  498           int nbConn = 0;
  499           CamlData files = fileFiles.data().get("files");
  500           String shortName = (item.name().length()>30 ? item.name().substring(0, 30) : item.name());
  501           for(int i=0; i<files.size(); i++) {
  502               CamlData file = files.get(i);
  503               if (file.getInt("file_size")==item.size()
  504                   && file.get("file_filenames").getString(0).startsWith(shortName)) {
  505                   String name = file.get("file_filenames").getString(0);
  506                   int total = file.getInt("file_size");
  507                   int downloaded = file.getInt("file_downloaded");
  508                   String hash = file.getString("file_md4");
  509                   item.completeData(name, total, hash, downloaded);
  510                   CamlData clients = file.get("file_locations");
  511                   nbLines = clients.size();
  512                   for(int j=0; j<nbLines; j++) {
  513                       if (clients.get(j).getBoolean("client_checked"))
  514                           nbConn++;
  515                   }
  516                   item.setNbClients(nbLines);
  517                   item.setNbConn(nbConn);
  518                   String chunks = file.getString("file_all_chunks");
  519                   item.setChunks(chunks.replace('0', '_').replace('1', 'V'));
  520                   return;
  521               }
  522           }*/
  523           long t0 = System.currentTimeMillis();
  524           int state = 0;
  525           try {
  526               send("vd " + item.id());
  527               if (socket==null)
  528                   return;
  529               String name = "", hash = "";
  530               int n = 0, total = 0, downloaded = 0;
  531               int nbConn = 0, nbClients = 0, nbClientsSeen = 0;
  532               while(state<5 && !shouldStopCommand) {
  533                   String line = readLine();
  534                   if (line==null)
  535                       break;
  536                   switch (state) {
  537                       case 0: {
  538                           REMatch result = reVDNLine1.getMatch(line);
  539                           if (result!=null) {
  540                               n = strongParseInt(result.substituteInto("$1"), -1);
  541                               hash = result.substituteInto("$2");
  542                               if (hash.length()!=32 || !StringParser.stringContainsOnly(hash, StringParser.HEXA)) {
  543                                   name = hash;
  544                                   hash = "";
  545                               }
  546                               total = strongParseInt(result.substituteInto("$3"), -1);
  547                               downloaded = strongParseInt(result.substituteInto("$4"), -1);
  548                               state = 1;
  549                          }
  550                           break;
  551                       }
  552                       case 1: {
  553                           REMatch result = reVDNChunks.getMatch(line);
  554                           if (result!=null) {
  555                               item.setChunks(result.substituteInto("$1"));
  556                               state = 2;
  557                           }
  558                           break;
  559                       }
  560                       case 2: {
  561                           StringParser parser = new StringParser(line);
  562                           if (parser.goAfter('(')) {
  563                               String s = parser.getRemainingString();
  564                               if (s.length()>0 && s.charAt(s.length()-1)==')')
  565                                   s = s.substring(0, s.length()-1);
  566                               if (hash.length()==0 && s.length()==32 && StringParser.stringContainsOnly(s, StringParser.HEXA)) {
  567                                   hash = s;
  568                               } else {
  569                                   // We look for the name of the file
  570                                   if (!StringParser.stringContainsOnly(s, StringParser.HEXA))
  571                                       name = s;
  572                               }
  573                               if (hash.length()>0 && name.length()>0) {
  574                                   if (n==item.id()) {
  575                                       item.completeData(name, total, hash, downloaded);
  576                                   } else {
  577                                       System.out.println("## Bad id: got " + n + " for " + name + " instead of " + item.id());
  578                                   }
  579                                   state = 3;
  580                               }
  581                               break;
  582                           }
  583                           // No break, we want to go through case 3 by default
  584                       }
  585                       case 3: {
  586                           REMatch result = reVDNSources.getMatch(line);
  587                           if (result!=null) {
  588                               nbClients = strongParseInt(result.substituteInto("$1"), 0);
  589                               item.setNbClients(nbClients);
  590                               state = 4;
  591                           }
  592                           break;
  593                       }
  594                       case 4: {
  595                           if (line.indexOf("onlist true")>=0)
  596                               nbConn++;
  597                           if (++nbClientsSeen >= nbClients)
  598                               state = 5;
  599                           break;
  600                       }
  601                   }
  602               }
  603               if (nbConn>0)
  604                   item.setNbConn(nbConn);
  605               else
  606                   item.setNbConn(nbClients);
  607           }
  608           catch(IOException e) {
  609               e.printStackTrace();
  610               reconnect();
  611           }
  612       }
  613   
  614       public synchronized void uploadStats(UploadSpeed generalSpeed) {
  615           int state = 0;
  616           try {
  617               send("upstats");
  618               if (socket==null)
  619                   return;
  620               while(state<2 && !shouldStopCommand) {
  621                   String line = readLine();
  622                   if (line==null)
  623                       break;
  624                   switch (state) {
  625                       case 0: {
  626                           REMatch result = reUPTitle2.getMatch(line);
  627                           if (result!=null) {
  628                               int n = strongParseInt(result.substituteInto("$1"), -1);
  629                               generalSpeed.setBytesCount(n);
  630                               state = 1;
  631                           } else {
  632                               result = reUPTitle.getMatch(line);
  633                               if (result!=null) {
  634                                   int n = strongParseInt(result.substituteInto("$1"), -1);
  635                                   generalSpeed.setBlocCount(n);
  636                                   state = 1;
  637                               }
  638                           }
  639                           break;
  640                       }
  641                       case 1: {
  642                           /*REMatch result = reUPLine.getMatch(line);
  643                           if (result!=null) {
  644                               String name = result.substituteInto("$1");
  645                               int nbClients = strongParseInt(result.substituteInto("$2"), -1);
  646                               int nbBlocs = strongParseInt(result.substituteInto("$3"), -1);
  647                               DownloadItem item = dataSource.item(name);
  648                               if (item!=null)
  649                                   item.setBlocsCount(nbBlocs);
  650                           } else {*/
  651                           REMatch result = reUPDone.getMatch(line);
  652                           if (result!=null) {
  653                               state = 2;
  654                           }
  655                           /*}*/
  656                           break;
  657                       }
  658                   }
  659               }
  660           }
  661           catch(IOException e) {
  662               e.printStackTrace();
  663               reconnect();
  664           }
  665       }
  666   
  667       public synchronized int[] startQuery(String pattern) {
  668           return startQuery(pattern, 0, 0, null, null, null, null, null, 0);
  669       }
  670   
  671       private String commandFor(String prefix, String data) {
  672           String out = "";
  673           java.util.StringTokenizer st = new java.util.StringTokenizer(data);
  674           while (st.hasMoreTokens()) {
  675               out = out + prefix + st.nextToken();
  676           }
  677           return out;
  678       }
  679       
  680       public synchronized int[] startQuery(String pattern, int minSize, int maxSize, String media, String format, String artist, String album, String title, int minBitRate) {
  681           try {
  682               String cmd = "s " + pattern;
  683               // We get the extended options
  684               if (minSize>0)
  685                   cmd += " -minsize " + minSize;
  686               if (maxSize>0)
  687                   cmd += " -maxsize " + maxSize;
  688               if (media!=null && media.length()>0)
  689                   cmd += commandFor(" -media ", media);
  690               if (format!=null && format.length()>0)
  691                   cmd += commandFor(" -format ", format);
  692               if (artist!=null && artist.length()>0)
  693                   cmd += commandFor(" -artist ", artist);
  694               if (album!=null && album.length()>0)
  695                   cmd += commandFor(" -album ", album);
  696               if (title!=null && title.length()>0)
  697                   cmd += commandFor(" -title ", title);
  698               if (minBitRate>0)
  699                   cmd += " -minbitrate " + minBitRate;
  700               // Run !
  701               send(cmd);
  702               if (socket==null)
  703                   return new int[0];
  704               while(in.ready() && !shouldStopCommand) {
  705                   String line = readLine();
  706                   if (line==null)
  707                       break;
  708                   REMatch result = reS.getMatch(line);
  709                   if (result!=null) {
  710                       int[] res = new int[2];
  711                       res[0] = strongParseInt(result.substituteInto("$1"), -1);
  712                       res[1] = strongParseInt(result.substituteInto("$2"), 0);
  713                       return res;
  714                   }
  715               }
  716           }
  717           catch(IOException e) {
  718               e.printStackTrace();
  719               reconnect();
  720           }
  721           return null;
  722       }
  723   
  724       public synchronized Object[] queryResult(int resNb) {
  725           ArrayList liste = new ArrayList();
  726           int state = 0;
  727           int toGo = 0;
  728           SearchedItem currentItem = null;
  729           try {
  730               send("vr " + resNb);
  731               if (socket==null)
  732                   return new Object[0];
  733               while(state<2 && !shouldStopCommand) {
  734                   String line = readLine();
  735                   if (line==null || line.length()==0)
  736                       break;
  737                   switch (state) {
  738                       case 0: {
  739                           REMatch result = reVRRunning.getMatch(line);
  740                           if (result!=null) {
  741                               toGo = strongParseInt(result.substituteInto("$2"), -1);
  742                               state = 1;
  743                           }
  744                           else {
  745                               result = reVRDone.getMatch(line);
  746                               if (result!=null) {
  747                                   toGo = 0;
  748                                   int nb = strongParseInt(result.substituteInto("$1"), 0);
  749                                   if (nb>0)
  750                                       state = 1;
  751                                   else
  752                                       state = 2;
  753                               }
  754                           }
  755                           break;
  756                       }
  757                       case 1: {
  758                           REMatch result = reVRTitle.getMatch(line);
  759                           if (result!=null) {
  760                               int n = strongParseInt(result.substituteInto("$1"), -1);
  761                               String name = result.substituteInto("$3");
  762                               currentItem = new SearchedItem(n, name);
  763                               liste.add(currentItem);
  764                           }
  765                           else {
  766                               StringParser parser = new StringParser(line);
  767                               // We are looking for "size hash ..."
  768                               int size = parser.getNextInt(-1);
  769                               String hash = parser.getNextString();
  770                               if (size>=0 && StringParser.stringContainsOnly(hash, StringParser.HEXA)) {
  771                                   // Last element can be "nb" or "type"
  772                                   String type = parser.getLastString();
  773                                   int nb = 0;
  774                                   if (StringParser.stringContainsOnly(type, StringParser.INTEGER)) {
  775                                       nb = StringParser.parseInt(type, 0);
  776                                       type = parser.getLastString();
  777                                   }
  778                                   // Then comes the extension (avi, mp3, ...)
  779                                   String ext = parser.getLastString();
  780                                   String length = parser.getNextString();
  781                                   // Did we read the quality instead of the length ?
  782                                   if (length.length()>0 && StringParser.stringContainsOnly(length, StringParser.INTEGER)) {
  783                                       // Maybe that we did not read the quality but nb ?
  784                                       int i = StringParser.parseInt(length, -1);
  785                                       length = parser.getNextString();
  786                                       if ( ! (i!=0 && ((i%64)==0 || ((i%32)==0 && i>=64))) ) {
  787                                           // We read nb
  788                                           nb = i;
  789                                           // We skip "quality"
  790                                           if (StringParser.stringContainsOnly(length, StringParser.INTEGER))
  791                                               length = parser.getNextString();
  792                                       }
  793                                   }
  794                                   if (length.length()>0 && length.charAt(length.length()-1)==':') {
  795                                       length += parser.getNextString();
  796                                   }
  797                                   String codec = parser.getRemainingString();
  798                                   currentItem.addBasicInfo(size, hash, nb);
  799                                   currentItem.addExtendedInfo(type, ext, codec, length);
  800                               }
  801                               /*result = reVRData.getMatch(line);
  802                               if (result!=null) {
  803                                   int size = strongParseInt(result.substituteInto("$1"), -1);
  804                                   String hash = result.substituteInto("$2");
  805                                   int nb = strongParseInt(result.substituteInto("$4"), -1);
  806                                   currentItem.addBasicInfo(size, hash, nb);
  807                                   result = reVRSubData.getMatch(result.substituteInto("$3"));
  808                                   if (result!=null) {
  809                                       String type = result.substituteInto("$1");
  810                                       String ext = result.substituteInto("$2");
  811                                       String codec = result.substituteInto("$4");
  812                                       String length = result.substituteInto("$5");
  813                                       currentItem.addExtendedInfo(type, ext, codec, length);
  814                                   }
  815                               }*/
  816                               else {
  817                                   result = reVREnd.getMatch(line);
  818                                   if (result!=null) {
  819                                       state = 2;
  820                                   }
  821                                   else if (line.length()>0) {
  822                                       currentItem.addAlias(line);
  823                                   }
  824                                   else {
  825                                       state = 2;
  826                                   }
  827                               }
  828                           }
  829                           break;
  830                       }
  831                   }
  832               }
  833           }
  834           catch(IOException e) {
  835               e.printStackTrace();
  836               reconnect();
  837           }
  838           return new Object[]{new Integer(toGo), liste};
  839       }
  840   
  841       public synchronized void extendSearch() {
  842           sendNoFail("xs");
  843       }
  844       
  845       public synchronized NSArray serversList() {
  846           NSMutableArray liste = new NSMutableArray();
  847           int state = 0;
  848           try {
  849               send("vm");
  850               if (socket==null)
  851                   return new NSArray();
  852               while(state<2 && !shouldStopCommand) {
  853                   String line = readLine();
  854                   if (line==null || line.length()==0)
  855                       break;
  856                   switch (state) {
  857                       case 0:
  858                       case 1: {
  859                           StringParser parser = new StringParser(line);
  860                           if (parser.goAfter('[')) {
  861                               parser.getNextStringUntil(StringParser.INTEGER);
  862                               int id = parser.getNextIntUntil("]", -1);
  863                               parser.goAfter(']');
  864                               String ip = parser.getNextString();
  865                               parser.getLastStringUntil(StringParser.INTEGER);
  866                               int n2 = parser.getLastInt(-1);
  867                               int n1 = parser.getLastInt(-1);
  868                               String name = parser.getRemainingString();
  869                               liste.addObject(new ServerItem(id, ip, name, n1, n2));
  870                               state = 1;
  871                           }
  872                           /*REMatch result = reVMLine.getMatch(line);
  873                           if (result!=null) {
  874                               int id = strongParseInt(result.substituteInto("$1"), -1);
  875                               String ip = result.substituteInto("$2");
  876                               String name;
  877   							if (result.getStartIndex(3)>0)
  878   								name = result.substituteInto("$3");
  879   							else
  880   								name = "";
  881                               int n1 = strongParseInt(result.substituteInto("$4"), -1);
  882                               int n2 = strongParseInt(result.substituteInto("$5"), -1);
  883                               liste.addObject(new ServerItem(id, ip, name, n1, n2));
  884                               state = 1;
  885                           }*/
  886                           else if (state==1) {
  887                               state = 2;
  888                           }
  889                           break;
  890                       }
  891                   }
  892               }
  893           }
  894           catch(IOException e) {
  895               e.printStackTrace();
  896               reconnect();
  897           }
  898           return liste;
  899       }
  900   
  901       public synchronized List allServersList() {
  902           ArrayList liste = new ArrayList();
  903           CamlData servers = fileServers.data().get("known_servers");
  904           int nb = servers.size();
  905           for(int i=0; i<nb; i++) {
  906               CamlData server = servers.get(i);
  907               int id = i+1;
  908               String ip = server.get("server_addr").getString(0) + ':' + server.get("server_addr").getString(1);
  909               String name = server.getString("server_name") + " - " + server.getString("server_desc");
  910               if (ip.length()>0)
  911                   liste.add(new ServerItem(id, ip, name, 0, 0));
  912           }
  913           return liste;
  914           /*int state = 0;
  915           try {
  916               send("vma");
  917               if (socket==null)
  918                   return new ArrayList();
  919               while(state<2 && !shouldStopCommand) {
  920                   String line = readLine();
  921                   if (line==null || line.length()==0)
  922                       break;
  923                   switch (state) {
  924                       case 0:
  925                       case 1: {
  926                           StringParser parser = new StringParser(line);
  927                           parser.goAfter('[');
  928                           int id = parser.getNextIntUntil("]", -1);
  929                           parser.goAfter(']');
  930                           String ip = parser.getNextString();
  931                           String name = parser.getRemainingString();
  932                           if (ip.length()>0) {
  933                               liste.add(new ServerItem(id, ip, name, 0, 0));
  934                               state = 1;
  935                           }
  936                           else if (state==1) {
  937                               state = 2;
  938                           }
  939                           break;
  940                       }
  941                   }
  942               }
  943           }
  944           catch(IOException e) {
  945               e.printStackTrace();
  946               reconnect();
  947           }
  948           return liste;*/
  949       }
  950       
  951       public synchronized NSDictionary options() {
  952           NSMutableDictionary options = new NSMutableDictionary();
  953           try {
  954               send("vo");
  955               if (socket==null)
  956                   return new NSDictionary();
  957               while(!shouldStopCommand) {
  958                   String line = readLine();
  959                   if (line==null)
  960                       break;
  961                   REMatch result = reVOData.getMatch(line);
  962                   if (result!=null) {
  963                       String key = result.substituteInto("$1");
  964                       if (key.length()>0) {
  965                           String value = result.substituteInto("$2");
  966                           options.setObjectForKey(value, key);
  967                           if (key.equals("client_md4"))
  968                               break;
  969                       }
  970                   }
  971               }
  972           }
  973           catch(IOException e) {
  974               e.printStackTrace();
  975               reconnect();
  976           }
  977           return options;
  978       }
  979   
  980       public synchronized void setOption(String option, String value) {
  981           sendNoFail("set " + option + " " + value);
  982       }
  983       
  984       public synchronized void pause(DownloadItem item) {
  985           sendNoFail("pause " + item.id());
  986       }
  987   
  988       public synchronized void resume(DownloadItem item) {
  989           sendNoFail("resume " + item.id());
  990       }
  991   
  992       public synchronized void cancel(DownloadItem item) {
  993           sendNoFail("cancel " + item.id());
  994           // sendNoFail("close_fds");
  995       }
  996       
  997       public synchronized void forget(int nb) {
  998           sendNoFail("forget " + nb);
  999       }
 1000       
 1001       public synchronized void commit() {
 1002           try {
 1003               send("commit");
 1004               if (socket==null)
 1005                   return;
 1006               while(in.ready() && !shouldStopCommand) {
 1007                   String line = readLine();
 1008                   if (line==null)
 1009                       break;
 1010                   REMatch result = reCOMMIT.getMatch(line);
 1011                   if (result!=null)
 1012                       return;
 1013               }
 1014           }
 1015           catch(IOException e) {
 1016               e.printStackTrace();
 1017               reconnect();
 1018           }
 1019       }
 1020   
 1021       public synchronized NSArray queryList() {
 1022           NSMutableArray liste = new NSMutableArray();
 1023           int state = 0;
 1024           try {
 1025               send("vs");
 1026               if (socket==null)
 1027                   return new NSArray();
 1028               while(state<2 && !shouldStopCommand) {
 1029                   String line = readLine();
 1030                   if (line==null)
 1031                       break;
 1032                   switch(state) {
 1033                       case 0: {
 1034                           REMatch result = reVSTitle.getMatch(line);
 1035                           if (result!=null) {
 1036                               int nb = strongParseInt(result.substituteInto("$1"), -1);
 1037                               if (nb==0)
 1038                                   state = 2;
 1039                               else
 1040                                   state = 1;
 1041                           }
 1042                           break;
 1043                       }
 1044                       case 1: {
 1045                           SearchParser parser = new SearchParser(line);
 1046                           if (parser.searchNumber()>=0) {
 1047                               liste.addObject(parser);
 1048                           }
 1049                           /*REMatch result = reVSLine.getMatch(line);
 1050                           if (result!=null) {
 1051                               int id = strongParseInt(result.substituteInto("$1"), -1);
 1052                               String data = result.substituteInto("$2");
 1053                               int toGo = strongParseInt(result.substituteInto("$3"), -1);
 1054                               StringBuffer query = new StringBuffer();
 1055                               REMatch[] results = reVSData.getAllMatches(data);
 1056                               for(int i=0; i<results.length; i++) {
 1057                                   if (i>0)
 1058                                       query.append(" ");
 1059                                   query.append(results[i].substituteInto("$1"));
 1060                               }
 1061                               liste.addObject(new QueryItem(id, query.toString(), toGo));
 1062                           }*/
 1063                           else {
 1064                               state = 2;
 1065                           }
 1066                           break;
 1067                       }
 1068                   }
 1069               }
 1070           }
 1071           catch(IOException e) {
 1072               e.printStackTrace();
 1073               reconnect();
 1074           }
 1075           return liste;
 1076       }
 1077       
 1078       protected synchronized String sendAndSearchResult(String command, RE match, String substitute) {
 1079           String res = null;
 1080           try {
 1081               send(command);
 1082               if (socket==null)
 1083                   return null;
 1084               while(in.ready() && !shouldStopCommand) {
 1085                   String line = readLine();
 1086                   if (line==null)
 1087                       break;
 1088                   REMatch result = match.getMatch(line);
 1089                   if (result!=null)
 1090                       res = result.substituteInto(substitute);
 1091               }
 1092           }
 1093           catch(IOException e) {
 1094               e.printStackTrace();
 1095               reconnect();
 1096           }
 1097           return res;
 1098       }
 1099   
 1100       protected synchronized void sendNoFail(String command) {
 1101           try {
 1102               send(command);
 1103           }
 1104           catch(IOException e) {
 1105               e.printStackTrace();
 1106               reconnect();
 1107           }
 1108       }
 1109   
 1110       protected synchronized void send(String command) throws IOException {
 1111           sendNoWait(command);
 1112           if (socket==null)
 1113               return;
 1114           // We wait until we get an answer or 10s have elapsed
 1115           for(int i=0; i<100 && !in.ready(); i++) {
 1116               try {
 1117                   Thread.sleep(100);
 1118               }
 1119               catch(InterruptedException e) {
 1120               }
 1121           }
 1122       }
 1123   
 1124       protected synchronized void sendNoWait(String command) throws IOException {
 1125           lastCommand = command; // Very soon because of the stopCommandIfCurrent() method
 1126           // We guaranty that we don't send requests faster than one evry 50ms, just to quiet the core
 1127           long t = System.currentTimeMillis();
 1128           if (t-lastCallTime<50) {
 1129               try {
 1130                   Thread.sleep(t-lastCallTime);
 1131               } catch(InterruptedException e) {}
 1132           }
 1133           lastCallTime = t;
 1134           // We send the command
 1135           finishRead();
 1136           if (socket==null)
 1137               return;
 1138           shouldStopCommand = false; // distant from "lastCommand=command" to avoid multithreading problems
 1139           out.println(command);
 1140           logCommandln(command);
 1141           out.flush();
 1142       }
 1143       
 1144       protected synchronized void finishRead() throws IOException {
 1145           if (socket==null)
 1146               connect();
 1147           if (socket==null)
 1148               return;
 1149           socket.setSoTimeout(5000);
 1150           try {
 1151               while (in.ready())
 1152                   readLine();
 1153           }
 1154           catch(IOException e) {
 1155               e.printStackTrace();
 1156               reconnect();
 1157           }
 1158           finally {
 1159               socket.setSoTimeout(defaultTimeout);
 1160           }
 1161       }
 1162   
 1163       protected int strongParseInt(String value, int def) {
 1164           try {
 1165               return Integer.parseInt(value);
 1166           }
 1167           catch(NumberFormatException e) {
 1168               return def;
 1169           }
 1170       }
 1171   
 1172       protected float strongParseFloat(String value, float def) {
 1173           try {
 1174               return Float.parseFloat(value);
 1175           }
 1176           catch(NumberFormatException e) {
 1177               return def;
 1178           }
 1179       }
 1180   
 1181       private String readLine() throws IOException {
 1182           if (socket==null)
 1183               return null;
 1184           String s = in.readLine();
 1185           if (s!=null)
 1186               s = s.trim();
 1187           logln(s);
 1188           return s;
 1189       }
 1190   
 1191       private void logCommandln(String s) {
 1192           logln("[" + new java.util.Date() + "] " + s);
 1193       }
 1194       
 1195       private void logln(String s) {
 1196           if (s==null)
 1197               return;
 1198           dialog.append(s);
 1199           dialog.append('\n');
 1200           if (dialog.length()>60000) {
 1201               dialogOffset += dialog.length()-30000;
 1202               dialog.delete(0, dialog.length()-30000);
 1203           }
 1204           logger.log(s);
 1205       }
 1206   
 1207       public interface Listener extends Runnable {
 1208           public void stopListening();
 1209       }
 1210   
 1211       public interface Logger {
 1212           public void log(String s);
 1213       }
 1214   }
 1215   
 1216   // $Log: DonkeyTalker.java,v $
 1217   // Revision 1.26  2003/01/01 19:27:15  fortun
 1218   // Delay in the full update of the screen
 1219   //
 1220   // Revision 1.25  2003/01/01 17:34:28  fortun
 1221   // Bug in the downloadItems() and queryRsult() parsing
 1222   //
 1223   // Revision 1.24  2002/08/21 21:47:46  fortun
 1224   // Adaptation for mldonkey v1.19
 1225   // Reads servers list and file detail in the files instead of the telnet connection (does not work in v1.19)
 1226   //
 1227   // Revision 1.23  2002/08/10 12:20:35  fortun
 1228   // Memory leak in the logln() function corrected
 1229   //
 1230   // Revision 1.22  2002/07/30 00:17:58  fortun
 1231   // New extendSearch() method
 1232   //
 1233   // Revision 1.21  2002/07/28 19:45:10  fortun
 1234   // allServersList() now returns a List instead of a NSArray
 1235   //
 1236   // Revision 1.20  2002/07/28 19:33:51  fortun
 1237   // New addServerMet method
 1238   //
 1239   // Revision 1.19  2002/07/22 00:28:13  fortun
 1240   // Acceleration for the queryResult() method
 1241   // NSArrays are now Lists
 1242   //
 1243   // Revision 1.18  2002/07/21 18:38:25  fortun
 1244   // Extended search implemented
 1245   //
 1246   // Revision 1.17  2002/07/21 15:16:02  fortun
 1247   // Right creator set
 1248   //
 1249   // Revision 1.16  2002/07/14 22:40:21  fortun
 1250   // New stopCommandIfCurrent() method to stop the current command
 1251   // New reshare command
 1252   // Bugs when getting the id in a line like [ddd] solved
 1253   //
 1254   // Revision 1.15  2002/07/09 22:12:34  fortun
 1255   // kill() should now be faster
 1256   // new connectToServer() method
 1257   // downloadItems(), fillItemDetails() and allServersList() methods optimized with the new StringParser class
 1258   // new allServersList() method
 1259   //
 1260   // Revision 1.14  2002/07/07 12:38:26  fortun
 1261   // Several little enhancements in stability
 1262   //
 1263   // Revision 1.13  2002/07/05 00:01:08  fortun
 1264   // Uses a logger to log the output
 1265   // Better notion of a local core
 1266   //
 1267   // Revision 1.12  2002/06/30 21:08:53  fortun
 1268   // Uses SO_LINGER option, to better quit from the daemon
 1269   //
 1270   // Revision 1.11  2002/06/29 17:59:07  fortun
 1271   // Bug in the serversList if the server has no name
 1272   //
 1273   // Revision 1.10  2002/06/29 11:17:34  fortun
 1274   // Socket is now 'KeepAlive' enabled
 1275   // Better closing sequence
 1276   //
 1277   // Revision 1.9  2002/06/14 00:41:38  fortun
 1278   // New finalClose and finalKill that marks the talker as dead (cannot be reconnected)
 1279   // Better handling of the 'no connection' state
 1280   // Handles a dialog log
 1281   // Handles listener threads, and stops them when needed
 1282   //
 1283   // Revision 1.8  2002/06/09 15:41:42  fortun
 1284   // Crash avoided when killing the core
 1285   //
 1286   // Revision 1.7  2002/06/08 12:19:28  fortun
 1287   // Added "sendNoWait" that ensures a 50ms delay between calls to the core
 1288   // Bug in finishRead() if not connected
 1289   //
 1290   // Revision 1.6  2002/06/02 18:09:26  fortun
 1291   // Bug in connected servers list if server has no name
 1292   //
 1293   // Revision 1.5  2002/06/02 17:55:31  fortun
 1294   // New "quit" function
 1295   // "Kill" waits less than before
 1296   // "send" should not be stuck anymore (timeout implemented)
 1297   //
 1298   // Revision 1.4  2002/06/02 12:05:22  fortun
 1299   // Timeout shortened in finishRead
 1300   //
 1301   // Revision 1.3  2002/05/27 22:06:56  fortun
 1302   // 'addAServer' method added
 1303   //
 1304   // Revision 1.2  2002/05/25 23:40:47  fortun
 1305   // launchLocalDonkey has been moved to DonkeyLauncher
 1306   // More connection options
 1307   // kill now returns a state
 1308   //
 1309   // Revision 1.1.1.1  2002/05/21 21:26:13  fortun
 1310   //
 1311   //

Home » openjdk-7 » net.bonzoun » cocodonkey » [javadoc | source]