Кому-нибудь удалось реализовать команду REST на FTP-сервере twisted? Моя текущая попытка:
from twisted.protocols import ftp
from twisted.internet import defer
class MyFTP(ftp.FTP):
def ftp_REST(self, pos):
try:
pos = int(pos)
except ValueError:
return defer.fail(CmdSyntaxError('Bad argument for REST'))
def all_ok(result):
return ftp.REQ_FILE_ACTN_PENDING_FURTHER_INFO # 350
return self.shell.restart(pos).addCallback(all_ok)
class MyShell(ftp.FTPShell):
def __init__(self, host, auth):
self.position = 0
...
def restart(self, pos):
self.position = pos
print "Restarting at %s"%pos
return defer.succeed(pos)
Когда клиент отправляет команду REST, требуется несколько секунд, прежде чем я увижу это в выводе скрипта:
Traceback (most recent call last):
Failure: twisted.protocols.ftp.PortConnectionError: DTPFactory timeout
Restarting at <pos>
Что я делаю не так? Мне кажется, что ответ должен следовать немедленно из команды REST, почему время ожидания сокета истекло?
Обновление:
После включения ведения журнала, как это было предложено Жаном-Полем Кальдероне, похоже, что команда REST даже не попадает в мой класс FTP до истечения времени соединения DTP из-за отсутствия соединения (для краткости временные метки сокращены до MM: SS) :
09:53 [TrafficLoggingProtocol,1,127.0.0.1] cleanupDTP
09:53 [TrafficLoggingProtocol,1,127.0.0.1] <<class 'twisted.internet.tcp.Port'> of twisted.protocols.ftp.DTPFactory on 37298>
09:53 [TrafficLoggingProtocol,1,127.0.0.1] dtpFactory.stopFactory
09:53 [-] (Port 37298 Closed)
09:53 [-] Stopping factory <twisted.protocols.ftp.DTPFactory instance at 0x8a792ec>
09:53 [-] dtpFactory.stopFactory
10:31 [-] timed out waiting for DTP connection
10:31 [-] Unexpected FTP error
10:31 [-] Unhandled Error
Traceback (most recent call last):
Failure: twisted.protocols.ftp.PortConnectionError: DTPFactory timeout
10:31 [TrafficLoggingProtocol,2,127.0.0.1] Restarting at 1024
Команда ftp_PASV
возвращает DTPFactory.deferred
, который описывается как «отложенный [который] будет срабатывать при подключении экземпляра». Команды RETR проходят нормально (в противном случае ftp.FTP был бы бесполезен).
Это наводит меня на мысль, что здесь есть какая-то операция блокировки, которая не позволит чему-либо еще произойти, пока не будет установлено соединение DTP; тогда и только тогда мы сможем принять дальнейшие команды. К сожалению, похоже, что некоторые (все?) Клиенты (в частности, я тестирую с FileZilla) отправляют команду REST перед подключением при попытке возобновить загрузку.