Changeset e8712a3


Ignore:
Timestamp:
Oct 15, 2011 5:20:30 PM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
3dbefa8d
Parents:
104594e
Message:
  • EepGet?:
    • Add gunzip support (nonproxied only)
    • Clean up progress formatting
  • SSLEepGet:
    • Add gunzip support
    • Increase buffer size
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketEepGet.java

    r104594e re8712a3  
    7575        }
    7676        return rv;
     77    }
     78
     79    /**
     80     *  Overridden to disable inline gunzipping
     81     *  @since 0.8.10
     82     */
     83    @Override
     84    protected void readHeaders() throws IOException {
     85        try {
     86            super.readHeaders();
     87        } finally {
     88            _isGzippedResponse = false;
     89        }
    7790    }
    7891
  • core/java/src/net/i2p/util/EepGet.java

    r104594e re8712a3  
    55import java.io.IOException;
    66import java.io.InputStream;
     7import java.io.PipedInputStream;
     8import java.io.PipedOutputStream;
    79import java.io.OutputStream;
    810import java.net.MalformedURLException;
     
    1214import java.util.ArrayList;
    1315import java.util.Date;
     16import java.util.Formatter;
    1417import java.util.List;
    1518import java.util.StringTokenizer;
     
    7376    protected int _redirects;
    7477    protected String _redirectLocation;
     78    protected boolean _isGzippedResponse;
     79    protected IOException _decompressException;
     80
    7581    /** this will be replaced by the HTTP Proxy if we are using it */
    7682    protected static final String USER_AGENT = "Wget/1.11.4";
     
    8389        this(ctx, true, proxyHost, proxyPort, numRetries, outputFile, url);
    8490    }
     91
    8592    public EepGet(I2PAppContext ctx, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching) {
    8693        this(ctx, true, proxyHost, proxyPort, numRetries, outputFile, url, allowCaching, null);
    8794    }
     95
    8896    public EepGet(I2PAppContext ctx, int numRetries, String outputFile, String url) {
    8997        this(ctx, false, null, -1, numRetries, outputFile, url);
    9098    }
     99
    91100    public EepGet(I2PAppContext ctx, int numRetries, String outputFile, String url, boolean allowCaching) {
    92101        this(ctx, false, null, -1, numRetries, outputFile, url, allowCaching, null);
    93102    }
     103
    94104    public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url) {
    95105        this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, outputFile, url, true, null);
    96106    }
     107
    97108    public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, String postData) {
    98109        this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, true, null, postData);
    99110    }
     111
    100112    public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag) {
    101113        this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, allowCaching, etag, null);
    102114    }
     115
    103116    public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, String outputFile, String url, boolean allowCaching, String etag, String lastModified) {
    104117        this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, -1, -1, outputFile, null, url, allowCaching, etag, lastModified, null);
    105118    }
     119
    106120    public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) {
    107121        this(ctx, shouldProxy, proxyHost, proxyPort, numRetries, minSize, maxSize, outputFile, outputStream, url, allowCaching, etag, null, postData);
    108122    }
     123
    109124    public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize,
    110125                  String outputFile, OutputStream outputStream, String url, boolean allowCaching,
     
    150165            for (int i = 0; i < args.length; i++) {
    151166                if (args[i].equals("-p")) {
    152                     proxyHost = args[i+1].substring(0, args[i+1].indexOf(':'));
    153                     String port = args[i+1].substring(args[i+1].indexOf(':')+1);
     167                    proxyHost = args[++i].substring(0, args[i].indexOf(':'));
     168                    String port = args[i].substring(args[i].indexOf(':')+1);
    154169                    proxyPort = Integer.parseInt(port);
    155                     i++;
    156170                } else if (args[i].equals("-n")) {
    157171                    numRetries = Integer.parseInt(args[i+1]);
     
    240254   
    241255    private static void usage() {
    242         System.err.println("EepGet [-p 127.0.0.1:4444] [-n #retries] [-o outputFile] " +
    243                            "[-m markSize lineLen] [-t timeout] [-h headerKey headerValue] " +
    244                            "[-u username password] url");
     256        System.err.println("EepGet [-p 127.0.0.1:4444] [-n #retries] [-o outputFile]\n" +
     257                           "       [-m markSize lineLen] [-t timeout] [-h headerKey headerValue]\n" +
     258                           "       [-u username password] url]\n" +
     259                           "       (use -p :0 for no proxy)");
    245260    }
    246261   
     
    324339                        if (timeToSend > 0) {
    325340                            StringBuilder buf = new StringBuilder(50);
     341                            Formatter fmt = new Formatter(buf);
    326342                            buf.append(" ");
    327343                            if ( bytesRemaining > 0 ) {
    328                                 double pct = ((double)_written + _previousWritten) /
     344                                double pct = 100 * ((double)_written + _previousWritten) /
    329345                                             ((double)alreadyTransferred + (double)currentWrite + (double)bytesRemaining);
    330                                 synchronized (_pct) {
    331                                     buf.append(_pct.format(pct));
    332                                 }
    333                                 buf.append(": ");
     346                                fmt.format("%4.1f", Double.valueOf(pct));
     347                                buf.append("%: ");
    334348                            }
    335                             buf.append(_written);
     349                            fmt.format("%8d", Long.valueOf(_written));
    336350                            buf.append(" @ ");
    337351                            double lineKBytes = ((double)_markSize * (double)_lineSize)/1024.0d;
    338352                            double kbps = lineKBytes/((double)timeToSend/1000.0d);
    339                             synchronized (_kbps) {
    340                                 buf.append(_kbps.format(kbps));
    341                             }
    342                             buf.append("KBps");
     353                            fmt.format("%7.2f", Double.valueOf(kbps));
     354                            buf.append(" KBps");
    343355                           
    344356                            buf.append(" / ");
    345357                            long lifetime = _context.clock().now() - _startedOn;
    346358                            double lifetimeKBps = (1000.0d*(double)(_written)/((double)lifetime*1024.0d));
    347                             synchronized (_kbps) {
    348                                 buf.append(_kbps.format(lifetimeKBps));
    349                             }
    350                             buf.append("KBps");
     359                            fmt.format("%7.2f", Double.valueOf(lifetimeKBps));
     360                            buf.append(" KBps");
    351361                            System.out.println(buf.toString());
    352362                        }
     
    590600            throw new IOException("HTTP response size " + _bytesRemaining + " violates maximum of " + _maxSize + " bytes");
    591601
     602        Thread pusher = null;
     603        _decompressException = null;
     604        if (_isGzippedResponse) {
     605            PipedInputStream pi = BigPipedInputStream.getInstance();
     606            PipedOutputStream po = new PipedOutputStream(pi);
     607            pusher = new I2PAppThread(new Gunzipper(pi, _out), "EepGet Decompressor");
     608            _out = po;
     609            pusher.start();
     610        }
     611
    592612        int remaining = (int)_bytesRemaining;
    593         byte buf[] = new byte[8*1024];
     613        byte buf[] = new byte[16*1024];
    594614        while (_keepFetching && ( (remaining > 0) || !strictSize ) && !_aborted) {
    595615            int toRead = buf.length;
     
    649669        _out = null;
    650670       
     671        if (_isGzippedResponse) {
     672            try {
     673                pusher.join();
     674            } catch (InterruptedException ie) {}
     675            pusher = null;
     676            if (_decompressException != null) {
     677                // we can't resume from here
     678                _keepFetching = false;
     679                throw _decompressException;
     680            }
     681        }
     682
    651683        if (_aborted)
    652684            throw new IOException("Timed out reading the HTTP data");
     
    786818        }
    787819
     820        _isGzippedResponse = false;
    788821        // clear out the arguments, as we use the same variables for return values
    789822        _etag = null;
     
    899932
    900933    private void handle(String key, String val) {
     934        key = key.trim();
     935        val = val.trim();
    901936        for (int i = 0; i < _listeners.size(); i++)
    902             _listeners.get(i).headerReceived(_url, _currentAttempt, key.trim(), val.trim());
     937            _listeners.get(i).headerReceived(_url, _currentAttempt, key, val);
    903938       
    904939        if (_log.shouldLog(Log.DEBUG))
     
    906941        if (key.equalsIgnoreCase("Content-length")) {
    907942            try {
    908                 _bytesRemaining = Long.parseLong(val.trim());
     943                _bytesRemaining = Long.parseLong(val);
    909944            } catch (NumberFormatException nfe) {
    910945                nfe.printStackTrace();
    911946            }
    912947        } else if (key.equalsIgnoreCase("ETag")) {
    913             _etag = val.trim();
     948            _etag = val;
    914949        } else if (key.equalsIgnoreCase("Last-Modified")) {
    915             _lastModified = val.trim();
     950            _lastModified = val;
    916951        } else if (key.equalsIgnoreCase("Transfer-encoding")) {
    917             if (val.indexOf("chunked") != -1)
    918                 _encodingChunked = true;
     952            _encodingChunked = val.toLowerCase().contains("chunked");
     953        } else if (key.equalsIgnoreCase("Content-encoding")) {
     954            // This is kindof a hack, but if we are downloading a gzip file
     955            // we don't want to transparently gunzip it and save it as a .gz file.
     956            // A query string will also mess this up
     957            if ((!_actualURL.endsWith(".gz")) && (!_actualURL.endsWith(".tgz")))
     958                _isGzippedResponse = val.toLowerCase().contains("gzip");
    919959        } else if (key.equalsIgnoreCase("Content-Type")) {
    920             _contentType=val.trim();
     960            _contentType=val;
    921961        } else if (key.equalsIgnoreCase("Location")) {
    922             _redirectLocation=val.trim();
     962            _redirectLocation=val;
    923963        } else {
    924964            // ignore the rest
     
    10421082            buf.append("Content-length: ").append(_postData.length()).append("\r\n");
    10431083        // This will be replaced if we are going through I2PTunnelHTTPClient
    1044         buf.append("User-Agent: " + USER_AGENT + "\r\n" +
    1045                    "Accept-Encoding: \r\n" +
     1084        buf.append("Accept-Encoding: ");
     1085        if ((!_shouldProxy) &&
     1086            // This is kindof a hack, but if we are downloading a gzip file
     1087            // we don't want to transparently gunzip it and save it as a .gz file.
     1088            (!path.endsWith(".gz")) && (!path.endsWith(".tgz")))
     1089            buf.append("gzip");
     1090        buf.append("\r\nUser-Agent: " + USER_AGENT + "\r\n" +
    10461091                   "Connection: close\r\n");
    10471092        if (_extraHeaders != null) {
     
    11281173                      "Basic " + Base64.encode((userName + ':' + password).getBytes(), true));  // true = use standard alphabet
    11291174    }
     1175
     1176    /**
     1177     *  Decompressor thread.
     1178     *  Copied / modified from i2ptunnel HTTPResponseOutputStream (GPL)
     1179     *
     1180     *  @since 0.8.10
     1181     */
     1182    protected class Gunzipper implements Runnable {
     1183        private final InputStream _inRaw;
     1184        private final OutputStream _out;
     1185
     1186        public Gunzipper(InputStream in, OutputStream out) {
     1187            _inRaw = in;
     1188            _out = out;
     1189        }
     1190
     1191        public void run() {
     1192            ReusableGZIPInputStream in = null;
     1193            long written = 0;
     1194            try {
     1195                in = ReusableGZIPInputStream.acquire();
     1196                // blocking
     1197                in.initialize(_inRaw);
     1198                byte buf[] = new byte[8*1024];
     1199                int read = -1;
     1200                while ( (read = in.read(buf)) != -1) {
     1201                    _out.write(buf, 0, read);
     1202                }
     1203            } catch (IOException ioe) {
     1204                _decompressException = ioe;
     1205                if (_log.shouldLog(Log.WARN))
     1206                    _log.warn("Error decompressing: " + written + ", " + (in != null ? in.getTotalRead() + "/" + in.getTotalExpanded() : ""), ioe);
     1207            } catch (OutOfMemoryError oom) {
     1208                _decompressException = new IOException("OOM in HTTP Decompressor");
     1209                _log.error("OOM in HTTP Decompressor", oom);
     1210            } finally {
     1211                if (_out != null) try {
     1212                    _out.close();
     1213                } catch (IOException ioe) {}
     1214                if (in != null)
     1215                    ReusableGZIPInputStream.release(in);
     1216            }
     1217        }
     1218    }
    11301219}
  • core/java/src/net/i2p/util/SSLEepGet.java

    r104594e re8712a3  
    4444import java.io.InputStream;
    4545import java.io.OutputStream;
     46import java.io.PipedInputStream;
     47import java.io.PipedOutputStream;
    4648import java.io.PrintWriter;
    4749import java.net.MalformedURLException;
     
    500502        boolean strictSize = (_bytesRemaining >= 0);
    501503
     504        Thread pusher = null;
     505        _decompressException = null;
     506        if (_isGzippedResponse) {
     507            PipedInputStream pi = BigPipedInputStream.getInstance();
     508            PipedOutputStream po = new PipedOutputStream(pi);
     509            pusher = new I2PAppThread(new Gunzipper(pi, _out), "EepGet Decompressor");
     510            _out = po;
     511            pusher.start();
     512        }
     513
    502514        int remaining = (int)_bytesRemaining;
    503         byte buf[] = new byte[1024];
     515        byte buf[] = new byte[16*1024];
    504516        while (_keepFetching && ( (remaining > 0) || !strictSize ) && !_aborted) {
    505517            int toRead = buf.length;
     
    558570        _out = null;
    559571       
     572        if (_isGzippedResponse) {
     573            try {
     574                pusher.join();
     575            } catch (InterruptedException ie) {}
     576            pusher = null;
     577            if (_decompressException != null) {
     578                // we can't resume from here
     579                _keepFetching = false;
     580                throw _decompressException;
     581            }
     582        }
     583
    560584        if (_aborted)
    561585            throw new IOException("Timed out reading the HTTP data");
Note: See TracChangeset for help on using the changeset viewer.