summaryrefslogtreecommitdiffstats
path: root/module/network/HTTPChunk.py
diff options
context:
space:
mode:
authorGravatar mkaay <mkaay@mkaay.de> 2010-12-19 14:12:03 +0100
committerGravatar mkaay <mkaay@mkaay.de> 2010-12-19 14:12:03 +0100
commit5120d1a26cac79ab283f38db8d7f18c9c010e786 (patch)
tree219f8874869ac6f9c1656fea9df8db17b55ce034 /module/network/HTTPChunk.py
parentacc manager fix (diff)
downloadpyload-5120d1a26cac79ab283f38db8d7f18c9c010e786.tar.xz
new experimental backend, new gui status (unfinished)
Diffstat (limited to 'module/network/HTTPChunk.py')
-rw-r--r--module/network/HTTPChunk.py201
1 files changed, 201 insertions, 0 deletions
diff --git a/module/network/HTTPChunk.py b/module/network/HTTPChunk.py
new file mode 100644
index 000000000..37c28f685
--- /dev/null
+++ b/module/network/HTTPChunk.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: mkaay
+"""
+
+from HTTPBase import HTTPBase
+from urllib2 import HTTPError
+from threading import Lock
+from helper import *
+from time import sleep
+from traceback import print_exc
+
+class HTTPChunk(HTTPBase):
+ def __init__(self, url, fh, get={}, post={}, referer=None, cookies=True, customHeaders={}, range=None, bucket=None, interface=None, proxies={}):
+ HTTPBase.__init__(self, interface=interface, proxies=proxies)
+
+ self.url = url
+ self.bucket = bucket
+ self.range = range
+ self.noRangeHeader = False
+ self.fh = fh
+
+ self.get = get
+ self.post = post
+ self.referer = referer
+ self.cookies = cookies
+ self.customHeaders = customHeaders
+
+ self.deferred = Deferred()
+
+ self.lock = Lock()
+ self.abort = False
+ self.finished = False
+
+ self.arrived = 0
+
+ self.startTime = None
+ self.endTime = None
+
+ self.speed = 0 #byte/sec
+ self.speedCalcTime = None
+ self.speedCalcLen = 0
+
+ self.bufferSize = 16*1024 #tune if performance is poor
+ self.resp = None
+
+ def getSpeed(self):
+ self.lock.acquire()
+ speed = self.speed
+ self.lock.release()
+ return speed
+
+ @threaded
+ def _download(self, resp):
+ self.arrived = 0
+ self.lastSpeed = self.startTime = inttime()
+
+ if self.noRangeHeader and not self.range[0] == 0:
+ self.deferred.error("range starts not at 0")
+
+ running = True
+ while running:
+ if self.abort:
+ break
+ count = self.bufferSize
+ if self.noRangeHeader:
+ if self.range[1] <= self.arrived+count:
+ count = min(count, self.arrived+count - self.range[1])
+ running = False
+ if self.bucket:
+ count = self.bucket.add(count)
+ if count == 0:
+ sleep(0.01)
+ continue
+
+ try:
+ data = resp.read(count)
+ except:
+ self.deferred.error("timeout")
+ break
+
+ if self.speedCalcTime < inttime():
+ self.lock.acquire()
+ self.speed = self.speedCalcLen
+ self.lock.release()
+ self.speedCalcTime = inttime()
+ self.speedCalcLen = 0
+ size = len(data)
+ self.speedCalcLen += size
+ self.arrived += size
+ if self.noRangeHeader:
+ if self.range[1] <= self.arrived:
+ self.fh.write(data[:-(self.arrived-self.range[1])])
+ break
+
+ if data:
+ self.fh.write(data)
+ else:
+ break
+
+ self.speed = 0
+ self.endTime = inttime()
+ self.finished = True
+ self.fh.close()
+
+ if self.abort:
+ self.deferred.error("abort")
+ elif self.size == self.arrived:
+ self.deferred.callback(resp)
+ else:
+ self.deferred.error("wrong content lenght")
+
+ def getEncoding(self):
+ try:
+ if self.resp.info()["Content-Encoding"] in ("gzip", "deflate"):
+ return self.resp.info()["Content-Encoding"]
+ except:
+ pass
+ return "plain"
+
+ def download(self):
+ if self.range:
+ self.customHeaders["Range"] = "bytes=%i-%i" % self.range
+ try:
+ print "req"
+ resp = self.getResponse(self.url, self.get, self.post, self.referer, self.cookies, self.customHeaders)
+ self.resp = resp
+ except HTTPError, e:
+ print_exc()
+ self.deferred.error(e)
+ return self.deferred
+
+ if (self.range and resp.getcode() == 206) or (not self.range and resp.getcode() == 200):
+ self._download(resp)
+ else:
+ self.deferred.error(resp.getcode(), resp)
+ return self.deferred
+
+if __name__ == "__main__":
+ import sys
+ from Bucket import Bucket
+ bucket = Bucket()
+ #bucket.setRate(200*1000)
+ bucket = None
+
+ url = "http://download.fedoraproject.org/pub/fedora/linux/releases/13/Live/x86_64/Fedora-13-x86_64-Live.iso"
+
+ finished = 0
+ def err(*a, **b):
+ print a, b
+ def callb(*a, **b):
+ global finished
+ finished += 1
+ print a, b
+
+ print "starting"
+
+ conns = 4
+
+ chunks = []
+ for a in range(conns):
+ fh = open("file.part%d" % a, "wb")
+ chunk = HTTPChunk(url, fh, bucket=bucket, range=(a*5*1024*1024, (a+1)*5*1024*1024))
+ print "fireing chunk #%d" % a
+ d = chunk.download()
+ d.addCallback(callb)
+ d.addErrback(err)
+ chunks.append(chunk)
+
+ try:
+ while True:
+ aspeed = 0
+ for a, chunk in enumerate(chunks):
+ if not chunk.finished:
+ print "#%d" % a, chunk.getSpeed()/1024, "kb/s"
+ else:
+ print "#%d" % a, "finished"
+ aspeed += chunk.getSpeed()
+ print "sum", aspeed/1024
+ if finished == conns:
+ print "- finished"
+ break
+ sleep(1)
+ except KeyboardInterrupt:
+ for chunk in chunks:
+ chunk.abort = True
+ sys.exit()