ProFTPD Developer's Guide: Response Handlers

ProFTPD Version 1.2


Table of Contents

Responding To Client Requests
Whenever the server processes a request from the client, it must generate an appropriate, RFC-compliant response back to the client. There are two main ways of generating these responses, usually done from within a command handler.

Response Chains
The first, and prefered, method of transmitting numeric-plus-text message responses back to clients is via the internal response chains. Using these allows all handlers to add their own individual responses, which will then all be sent en masse after the command successfully completes, or fails.

The engine maintains two such response chains, one chain for success messages, and one for error messages. When all handlers for a given command have been called, the engine evaluates the final condition of the command. If it has failed (signaled by a handler returning one of the available ERROR* macros), all responses pending in the error response chain are sent. If, on the other hand, the command has successfully completed, the success response chain is sent. If a command has neither completed successfully nor resulted in an error, it is assumed to be an invalid command, and the client is informed approppriately. In any case, once the "lifetime" of the command is over, and one (or none) of the response chains has been sent, both chains are destroyed.

The response chain method uses the following functions:

As you can see, with the response chain method, there are no multiline functions for multiline replies, as there are with the second response method. This is because the server automatically generates a multiline formated reply if it detects that there are two or more responses with the same numeric waiting to be sent to the client. In many cases, you may be writing a handler, POST_CMD for example, that neither specifically knows nor cares what numerics other handlers are using during their responses. In this case, you can use the special R_DUP response numeric, which tells the server that your response should be assumed to be part of a multiline response started by another handler.

For example, if the following pr_response_add() calls were made from different modules:

module A:
pr_response_add(R_200, "Command successfully completed");

module B:
pr_response_add(R_DUP, "Statistics for command '%s': none", cmd->argv[0]);

module C:
pr_response_add(R_DUP, "XFOO post_cmd handler ran");

The final output sent to the client, assuming the command was successfully handled, would be (assuming your command is named 'XFOO'):

  200-Command successfully completed.
   Statistics for command 'XFOO': none.
  200 XFOO post_cmd handler ran.

See include/ftp.h for the full listing of response numerics.

Responses to the client should be added using pr_response_add() when the handler is going to return HANDLED or DECLINED; pr_response_add_err() should be used if the handler is going to return ERROR. At least one response in the chain, either "normal" or error chain, should be present in order to return an RFC-compliant response code to the client. This is important; returning the wrong code for a command, or no code at all, can hang the client. Note also that responses may be added to both chains simultaneously, however only one chain of response will be flushed back to the client.

Direct Response
The second way, a direct response method, is incompatible with other handlers, and should be used only if the handler is about to terminate the current connection, and thus kill the fork()ed child server, usually via end_login(). This method must use one of the functions listed below, for the "normal" response chains will never be processed by the core engine.

The direct response method utilizes the following functions:

Response handler macros
The following are some macros specific to response generation, both by modules and by the core engine:

Table of Contents



Author: $Author: castaglia $
Last Updated: $Date: 2003/04/25 15:42:55 $


© Copyright 2000-2003 TJ Saunders
All Rights Reserved