Skip to content

Broken timeout without datachannel #658

@FedericoHeichou

Description

@FedericoHeichou

If a client connects and does not open the data channel, the timeout polling is not performed.

Example code:

from pyftpdlib.servers import MultiprocessFTPServer
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.log import config_logging

config_logging(level="DEBUG")
authorizer = DummyAuthorizer()
authorizer.add_user("user", "12345", "/tmp", perm="elradfmwMT")
authorizer.add_anonymous("/tmp")
handler = FTPHandler
handler.authorizer = authorizer
handler.dtp_handler.timeout = 10
handler.timeout = 10
server = MultiprocessFTPServer(('127.0.0.1', 21), handler)
server.serve_forever()

If you then connect with a ftp client (like tnftp) that does not automatically execute a data channel command, the channel command will not be closed until a command like EPSV is sent, then the polling starts to run and after the timeout (in my example 10 seconds) any command is good to reset the timeout.

Checking the code, the EPSV command triggers the _on_dtp_close(self), which has a re-set of self._idler.

To enforce the timeout I did the same in the on_login function:

from pyftpdlib.servers import MultiprocessFTPServer
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.log import config_logging


class CustomFTPHandler(FTPHandler):
    def on_login(self, username):
        super().on_login(username)
        if self._idler is not None and not self._idler.cancelled:
            self._idler.cancel()
        self._idler = self.ioloop.call_later(
            self.timeout, self.handle_timeout, _errback=self.handle_error
        )


config_logging(level="DEBUG")
authorizer = DummyAuthorizer()
authorizer.add_user("user", "12345", "/tmp", perm="elradfmwMT")
authorizer.add_anonymous("/tmp")
handler = CustomFTPHandler
handler.authorizer = authorizer
handler.timeout = 10
handler.dtp_handler.timeout = 10
server = MultiprocessFTPServer(('127.0.0.1', 21), handler)
server.serve_forever()

Seems to be a bug... What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions