<!-- File transfer settings -->
<!-- The maximum size of a file transfer (in bytes). For unlimited, comment out, or set to 0 -->
<ftSizeLimit>524288</ftSizeLimit>
+<!-- The maximum rate for file transfer (in bytes). For unlimited, comment out, or set to 0 -->
+<ftRateLimit>2048</ftRateLimit>
<!-- Please give the port to listen for Jabber socks5 transfers on. -->
<ftJabberPort>8010</ftJabberPort>
<!-- Please give the port to listen for HTTP GETs here (Used in OOB file transfers). -->
# Copyright 2005 James Bunton <james@delx.cjb.net>
# Licensed for distribution under the GPL version 2, check COPYING for details
+from tlib.throttle import Throttler
from tlib.xmlw import Element
from twisted.internet import protocol
import sys
+def doRateLimit(setConsumer, consumer):
+ try:
+ rateLimit = int(config.ftRateLimit)
+ except ValueError:
+ rateLimit = 0
+ if rateLimit > 0:
+ throttler = Throttler(consumer, rateLimit)
+ setConsumer(throttler)
+ else:
+ setConsumer(consumer)
+
def checkSizeOk(size):
try:
size = int(size)
session.legacycon.sendFile(to, self)
def accept(self, legacyFileSend):
- self.startTransfer(legacyFileSend)
+ doRateLimit(self.startTransfer, legacyFileSend)
+ self.cleanup()
def reject(self):
- del self.startTransfer
self.cancelTransfer()
+ self.cleanup()
+
+ def cleanup(self):
+ del self.startTransfer, self.cancelTransfer
try:
assert address not in self.activeConns
self.activeConns[address] = None
- if not isinstance(olist[0], (JEP65ConnectionReceive, JEP65ConnectionSend)):
+ if not isinstance(olist[0], JEP65ConnectionReceive):
legacyftp = olist[0]
connection = olist[1]
- elif not isinstance(olist[1], (JEP65ConnectionReceive, JEP65ConnectionSend)):
+ elif not isinstance(olist[1], JEP65ConnectionReceive):
legacyftp = olist[1]
connection = olist[0]
else:
LogEvent(WARN, '', "No JEP65Connection")
return
- legacyftp.accept(connection.transport)
+ doRateLimit(legacyftp.accept, connection.transport)
else:
LogEvent(WARN, '', "No pending connection.")
class OOBReceiveConnector:
def __init__(self, ftReceive, ftHttpPush):
self.ftReceive, self.ftHttpPush = ftReceive, ftHttpPush
- self.ftReceive.legacyftp.accept(self)
+ doRateLimit(self.ftReceive.legacyftp.accept, self)
def write(self, data):
self.ftHttpPush.write(data)
--- /dev/null
+from twisted.internet import task
+
+
+
+class Throttler:
+ def __init__(self, consumer, speed):
+ self.consumer = consumer
+
+ self.buffer = ""
+ self.speed = speed # Bytes/second
+ self.canClose = False
+
+ self.loopTask = task.LoopingCall(self.loopFunc)
+ self.loopTask.start(1.0)
+
+ def write(self, data):
+ if not self.consumer:
+ raise ValueError, "I/O operation on closed 'file'"
+ self.buffer += data
+
+ def close(self):
+ self.canClose = True
+
+ def loopFunc(self):
+ if self.canClose and len(self.buffer) == 0:
+ self.consumer.close()
+ self.consumer = None
+ self.loopTask.stop()
+
+ else:
+ chunk, self.buffer = self.buffer[:self.speed], self.buffer[self.speed:]
+ self.consumer.write(chunk)
+
+
+