Thanks for clarifying your requirements.
Does your printer always look for the FTP server on port 21 (the standard port)? Or can you configure that?
This matters due to permissions. macOS (unlike iOS) continues to require root privileges to bind to low-numbered ports (below 1024). If your printer can only connect to the standard FTP port, you’ll have to bind to that port and thus you will need some sort of privilege escalation. This takes a seemingly simple job (run pyftpdlib from inside your app) and turns it into a hard one.
Moreover, it represents a conceptual problem. If there’s a single resource on the system (the FTP port) then their needs to be a single entity responsible for managing it. That means that you really want your FTP server managed by a daemon. If you try to manage it from an app, there’s the possibility that two users on the system might collide.
Thus the architecture I recommend is that you have a launchd daemon that manages your FTP server and you communicate with that daemon to get the server status, start the server, stop the server, and so on. That further breaks down as follows:
You need something to install the daemon. It sounds like you’re in a managed environment, in which case it might be best to push an installer package to the machine to install the daemon. It’s certainly easy to do that. In a consumer-oriented app you might want to use
SMJobBless
to install the daemon, which is a complex exercise.You need a way to communicate between the daemon and the app. For this I recommend
NSXPCConnection
.You need to consider authorisation. The daemon runs as root, so it will be able to do the things it needs to do. How should it react, say, when a user tries to do some destructive action, like stop the server? Is any use allowed to do this? Or is that restricted to some specific users? One way to handle this authorisation is via the Authorisation Services API.
*phew*
A good place to start here is the EvenBetterAuthorizationSample sample code. It does the whole
SMJobBless
thing, which you might want to avoid. But it also shows both
NSXPCConnection
and Authorisation Services, which you will definitely want to look at.
Finally, I want to clarify one thing. You may actually want to use two daemons here:
A launchd daemon you write, that speaks over
NSXPCConnection
and can be used to start and stop the FTP server.A separate launchd daemon that represents the FTP server itself.
There are other ways to structure this (for example, you could have your daemon launch the FTP server as a child process) but, due to the nature of how launchd works, separating them out might be best.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"