The protocol is based on TCP/IP, and servers implementing it are listening on port XYZ.
This is work in progress
XML-RPC was originally built for HTTP, but can also be used on top of other protocols.
In the future, we might decide to use another transfer protocol. This should only require minor changes to clients/servers.
It is legal for the client to have multiple requests running at the same time with the same sessionid.
ret.encode('iso8859-1')
(provided that ret is a
string)
None
is not a legal return value, not even inside a
tuple/dictionary.
encoding='iso8859-1'
to the xmlrpclib.Server
constructor if non-ASCII
characters are used in parameters to method calls. Non-printable
characters must be encoded as binary:
xmlrpclib.Binary('\01')
As the server is extend-able by modules all methods will not be described here. Use the python help function for a list of callable methods in a given module.
When an error occurs, a xmlrpclib.Fault is raised with the message parameter describing the cause of the error.
sessid = testsvr.login(user, passwd)The login method authenticates the user. Upon success, a sessionid is returned which must be used for future communication with the server.
OK, NUMBER, server-version
where
NUMBER currently is 1. This number may be increased at a later time
if the protocol is changed in an uncompatible way.
clientid is a string identifying the client. By requiring this string it is easier to keep track of the number of different clients.
# protocol_command bofh_cmd1 bofh_cmd2 parameter[1..n] #of_loopable_param commands = ( ('get_person', 'person', 'get', 'number', 1), ('add_fg', 'filegroup', 'add', 'string', 'string', 1))Here protocol_command is the name of the function that will be called in the server. bofh_cmd1 and bofh_cmd2 are the keywords that uniqualy identifies this command. parameter[1..n] indicates the expected type of the parameter. Legal types are:
filegroup add user1 user2 group
, the
client should send:
add_fg(user1, group) add_fg(user2, group)
if validate('fodselsnr', 12345678901):Validates that arg is legal for the given argtype, and returns 1 on success, otherwise raises an error. The defined argtypes are:
The usage of run_command() as a wrapper for all other functions allows centralized handling of some authenticaion logic and any server messages (see below). One might argue that the methods should be exported directly, but this will put a greater burden on the server implementator not to accidentaly make it possible to call methods without being authenticated.
server_msg, ret_value = server.function()The legal values for server_msg are:
config.dat
contains a list of the modules that should be
loaded into bofhd. It contains a number of lines of the format:
module_filemodule_file does not have a .py ending, and must contain a class named BofhdExtention.
The following methods must be implemented (see bofhd_module_example.py for an example):
def __init__(self): # The format of the all_commands dict is as follows: # function : (clicmd1, clicmd2, param[1..n]) # # - function is the name of the function that will be called # on the server to execute the command # # - clicmd1 and clicmd2 is the first and second client # command that identifies which function to call # # NOTE: by design the namespace for the above values is the same # for all modules, thus a module may overwrite a previously # defined value by appearing later in the module load sequence. # # - param[1..n] are the parameters that the user must give # in the client. These arguments will be passed, in the # same order, to the function on the server. One, and only # one, parameter may be given a trailing + to indicate that # the parameter is loopable self.all_commands = { 'a_person' : ('person', 'get', 'number+') } def get_commands(self, uname): return {'a_command' : ('person', 'get', 'number+')} def get_format_suggestion(self, cmd): return { 'a_command' : "Name: %s\nPassword: %s\n" }The global dict of all commands is built up by first searching the bofhd module, and then all modules in the configfile. Thus, a command in a module may override the default implementation.