Other chapters give detailed informations about the programming API.
Additional Details:
The FTS C library is a set of C functions allowing an application to communicate with a FTS server, using some kind of bytestream oriented interface; the communication is implemented on a bytestream oriented protocol; while an application is free to interface directly to a server physically accessing the available physical connection (at least, in the cases where this connection is documented, like for sockets and pipes based connections), this library greately simplify the work by providing a higher level framework for handling the client/server interface. This library is written in C, and optimized for interfacing with C or C++ applications.
The idea of this library is to cope essentially with the syntax of the communication, and to avoid dealing with the semantic of the applications implemented with FTS; the basic idea is to provide a way to exchange information between FTS clients and servers, but to make as few assumption as possible on what these messages mean and on their purpose; in this way the library is completely generic, and can be used for any kind of applications.
The basic item of information exchanged between FTS clients and servers is called a message; a message is a command chosen in a predefined set of commands, with as arguments an ordered set of values of type chosen between a predefined set of types, sent to a target subsystem within the destination system (client or server).
The semantic of the command actually depends on the target subsystem; the library itself does not impose any semantic to the messages, but allows the application programmer to define subsystems with their specific semantic; the FTS server, together with the library, provides a number of predefined subsystems, like the Max interpreter, or other subsystem dealing with the configuration and so on; but these predefined subsystems are just installed on top of the library as the other, and future version of FTS will allow to configure which subsystem to install.
The library provides two asynchronous message streams, in the server to client and in the client to server directions.
The library defines also a generic event mechanism, as a client based subsystem, that allows the server to provide information on server's situation and state change without making assumption on the kind of application connected as a client.
The next chapters document the functions used to send and receive messages, and the way to create and access messages, and how to cope with events; in the appendix you will find the description of the bytestream protocol and the predefined subsystems together with their semantic.
The library define an abstraction, the fts_server
that represent
the server and the connection to the server, in the application; this
section document functions dealing with this abstraction.
fts_server *fts_open(int connection_type, char *name, char *options)
It creates a fts_server
structure, and connect it to the server manager;
the server structure is fully initialized; this function can be used to
create connections on multiple servers, with the limit of one server for
each connected machine. The connection_type argument specify how to
connect to the FTS server; some values are strictly architecture
dependent; currently implemented values are as following; other values
can be implemented in future releases, or alternative versions of the
library.
The name argument identify the server to connect to, when it is not completely specified by the connection type; the semantic of the name is actually connection_type dependent, and documented below. The options argument is a string coding a number of server and connection dependent options that are interpreted at the open time; see below for specific semantic.
The possible connection types are:
and are documented below.
A Sink Connection is a fake connection, that throw away all the messages sent thru it; it is provided in order to simplify debugging of applications. The name and options arguments are not used in this case.
A pipe connection connects to the server thru a Unix pipe; the server will run on the same CPU as the client. The name and options arguments are not used in this case.
A pipe connection connects to the server thru a Unix named pipe; the server will run on the same CPU as the client; currently supported only in the DEC Alpha and SGI workstations. The name argument is used to generate two names for the input and output pipes (name.from and name.to). The options argument is not used in this case. Named pipes can be used in order to simplify debugging of user modules added to fts; running FTS directly from a debugger with the -n name option will connect FTS to the named pipe.
An ISPW connection connects to the server running in a ISPW card thru shared memory; supported only on the Next Cube, for NextStep 3.1 and 3.2 only. The name and options arguments are not used in this case.
A socket connection connect to the server thru the FTS daemon, by means of an TCP connection; supported in all the environment with a UNIX like socket interface, and in some other environment supporting sockets, like MacOS with the right extensions. The name argument is the internet name or address of the machine where the daemon reside.
The options argument is interpreted as an unordered set of character; characters have the following meaning:
w
b
a
d
void fts_close(fts_server *server)
Close the connection represented by server; the actual server
may be shutdown or not, depending on the connection and the running
mode of the server and daemon, if any; it will be shutdown for all the
connections type that allow only one client, anyway. Every reference
to the structure pointed by server is illegal after calling
fts_close
on it.
Getting Infos About a Connection
fts_connection_status fts_get_connection_status(fts_server *server)
Return the status of the connection represented by server. The
fts_connection_status
is an enum
with the
following possible values and meanings:
not_connected
output_connected
fts_poll
or the
fts_get_fd
functions; this probabily means that the
server is not yet up and running, or that the connection is not
completely set up, yet.
connected
dead
int fts_have_input_fd(fts_server *server)
int fts_get_input_fd(fts_server *server)
Some kind of connection may use a file descriptor to connect to the server; in this case the file descriptor can be accessed in order to use the select function to decide when to poll the server; this usually avoid an active waiting loop and can spare the client CPU resources w.r.t. a poll loop without select.
The fts_have_input_fd
function return a non-zero value if and only if the
connection represented by server use a file descriptor; it can be
called only if the connection with the server is fully established,
i.e. if the fts_get_connection_status
function return
connected
; programmers are formally discouraged from trying to
infere the result of this function directly from the
connection_type
passed to the fts_open
function; the same
connection type may or not use a file descriptor depending on the
version of the software, and the hardware and software platforms; this
function is the only way to know if a file descriptor can be
obtained.
The fts_get_input_fd
function return the file descriptor that can
be used in select; warning: any other use of this file descriptor is
discouraged, and may bring to unknown results; in particular, the users
should not assume that this file descriptor is the actual
channel between the client and the server and that they can write and
read unparsed messages directly to this file descriptor.
void fts_send(fts_server *server, fts_mess *mess)
Send the mess message to server; the message must be created and filled with the message relative primitives, according to the message protocol defined in the appendix.
void fts_cacheing_on(fts_server *server)
void fts_cacheing_off(fts_server *server)
void fts_flush_cache(fts_server *server)
If cacheing is on, server cache all the messages in an internal buffer up to a certain dimension, and then send the message all together; it may reduce communication overhead on certain kind of connection when there are a lot of messages send, like during a patch loading.
fts_cacheing_on
set on the cacheing, and fts_cacheing_off
disable the cacheing; the fts_flush_cache
forces the server
to send all the messages that are stored in the internal
cache. This feature may be removed in a future release.
void fts_poll(fts_server *server);
void fts_install_subsystem(char type, void (* fun)(fts_server *server, fts_mess *mess)
The input from a server is done by polling; in the case where
server support a file descriptor, the programmer can use a select
to avoid wasting cpu resources polling the server when there are no data
ready; otherwise, the polling should be done regularly; anyway, the
server to client connection is flow controlled, so that if the client
don't poll the connection fast enough, the server will stop to generate
events, without blocking the normal FTS computation.
The fts_poll
function poll the connection represented by
server; for all the correctly formatted messages received,
fts_poll
will call the corresponding subsystem function; as the
protocol specify, the target subsystem is specified by the first
character of the message; the subsystem function is installed at any
time by the fts_install_subsystem
function; the subsystem
function will be called with as argument server, and the message
parsed in a fts_mess
structure and passed in the mess
argument; the function should not free the message, and should copy all
the arguments needed, because the message itself will be freed when the
function return. Uncorrectly formatted messages, or messages for an
uninstalled subsystem will be discarded, without any error signalling.
This group of function allows to create, access and manipulate messages, received or sent thru the server; the representation is unique for outgoing or ingoing messages.
A message is conceptually made of:
The client library is independent from the actual meaning of the messages; for a list of implemented target subsystem, and for the meaning of the commands and argument, see the documentation of the FTS protocol in appendix A.
Creating and Freeing a Message
The following functions are used to get or free a message structure:
fts_mess *fts_mess_new(void)
Create and return an empty message structure.
void fts_mess_free(fts_mess *mess)
Free the mess message structure after its use.
These two functions keep a free list of used messages and optimize
memory allocation; so there is no need to store used messages in the
application to spare a call to fts_mess_new and to fts_mess_free
,
that are very efficient. The only reason to keep a message is when you
want to send it many times, unchanged or almost unchanged.
The following functions are used to fill up a message; there are two kind of functions to add arguments to a message: the first type adds an argument at the end of the already existing arguments, the second set an argument in a specific position; if the second kind is used, the programmer should take care that there are no empty arguments in the middle of the message.
void fts_mess_set_req(fts_mess *mess, int req)
Set the request id; the request id is a reference to this message that the server may use in error messages and such, to identify the original message the error refer to. Setting the request id is optional; if not set, a convenctional value of minus one is used, meaning no request id specified.
void fts_mess_set_type(fts_mess *mess, int type)
Set the type of the message mess to type
void fts_mess_set_cmd(fts_mess *mess, int cmd)
Set the command field of the message mess to cmd.
void fts_mess_add_long(fts_mess *mess, long val)
Add a long argument of value val to the message mess.
void fts_mess_add_float(fts_mess *mess, float val)
Add a float argument of value val to the message mess.
void fts_mess_add_string(fts_mess *mess, char *val)
Add a string argument to the message mess; the val pointer is stored in the message structure, but the string itself is not copied in the message structure; it is the application responsability to not free or change the string until the message has been sent and freed.
void fts_mess_add_string_copy(fts_mess *mess, char *val)
Add a string argument to the message mess; the string val is copied in the message structure; the application is free to reuse the string when this function return. The malloc'ed memory will be freed when the message is freed.
void fts_mess_set_long(fts_mess *mess, long val, int pos)
Set the long value val as the argument in position pos of the message mess.
void fts_mess_set_float(fts_mess *mess, float val, int pos)
Set the float value val as the argument in position pos of the message mess.
void fts_mess_set_string(fts_mess *mess, char *val, int pos)
Set the string value val as the argument in position pos of the message mess. The pointer val is stored in the message structure, but the string itself is not copied in the message structure; the application should not free or change the string until the message has been sent and freed.
void fts_mess_set_string_copy(fts_mess *mess, char *val, int pos)
Set the string value val as the argument in position pos of the message mess. The string is copied in the message structure; the application is free to reuse the string when this function return. The malloc'ed memory will be freed when the message is freed.
void fts_mess_append(fts_mess *mess, fts_value_list *args)
Append the whole content of a value list as arguments to the message. Value list are structures that contain a list of tagged values and are documented below.
The following functions are used to access a message, and to get and check the types of arguments and so on.
int fts_mess_get_req(fts_mess *mess)
Get the request id stored in the message; a value of minus one means that no request id was specified. This function is actually implemented as a macro.
char fts_mess_get_type(fts_mess *mess)
Return the type of the message mess, i.e. the target subsystem. This function is actually implemented as a macro.
char fts_mess_get_cmd(fts_mess *mess)
Return the command of the message mess. This function is actually implemented as a macro.
int fts_mess_get_nargs(fts_mess *mess)
Return the number of arguments stored in the messages mess. This function is actually implemented as a macro.
fts_value_list *fts_mess_get_args(fts_mess *mess)
Get all the arguments of the message as a value list. This function is actually implemented as a macro.
int fts_mess_is_long_arg(fts_mess *mess, int i)
Return non zero if the argument i of mess is of type long. This function is actually implemented as a macro.
int fts_mess_is_float_arg(fts_mess *mess, int i)
Return non zero if the argument i of mess is of type float. This function is actually implemented as a macro.
int fts_mess_is_string_arg(fts_mess *mess, int i)
Return non zero if the argument i of mess is of type string, and the string itself have not been copied in the message structure. This function is actually implemented as a macro.
int fts_mess_is_string_copy_arg(fts_mess *mess, int i)
Return non zero if the argument i of mess is of type string, and the string itself have been copied in the message structure. This function is actually implemented as a macro.
int fts_mess_is_chars_arg(fts_mess *mess, int i)
Return non zero if the argument i of mess is of type string. This function is actually implemented as a macro.
long fts_mess_get_long_arg(fts_mess *mess, int i)
Return the argument i of mess, assuming that it is of type
long; it is an error to apply this function if
fts_mess_is_long_arg(mess, i)
would return 0. This
function is actually implemented as a macro.
float fts_mess_get_float_arg(fts_mess *mess, int i)
Return the argument i of mess, assuming that it is of type
float; it is an error to apply this function if
fts_mess_is_float_arg(mess, i)
would return 0. This
function is actually implemented as a macro.
char *fts_mess_get_string_arg(fts_mess *mess, int i)
Return the argument i of mess, assuming that it is of type
string; it is an error to apply this function if
fts_mess_is_chars_arg(mess, i)
would return 0. This
function is actually implemented as a macro.
An event is the representation of a condition that may occur in the system; raising an event signal to the system that the represented condition actually occurred; the condition can be an error or abnormal condition, but can also be something that occur in the normal behaviour of the system; for example, the MAX subsystem objects signal a change of status to their graphic representation by means of an event.
An event can be raised in the FTS server, in the daemon (if used), in the client library or in the application itself; the client library transparently handles all this cases with a uniform mechanism; anyway, note that if the event is raised in the server, it is sent to the client by means of a message, so it will affect the client only the next time the fts_poll is called; while if the event is raised locally in the application, it is seen immediately.
When an event is raised other arguments may be specified to give more informations about the condition; an event is specified by a pair of integers, called event and tag; the semantic of the tag is event specific; can be used to specialize an event, but also for other purposes.
An handler is a function that is called by the FTS client library when an event is raised; at most one handler is invoked for an event; the association between events and handler to call is called event table; the client library maintain an event table for every fts_server structure instantiated, and one global event table; typically, handlers designed to handle global error conditions are put in the global table, while handlers designed to handle server dependent conditions are installed in the server table.
An handler can be installed for a particular event/tag pair, or for only an event value (and will be called regardless of the tag value), or for any event and any tag; if more than one handler are suitable for the same event, which handler will be called is implementation dependent; so the application should not make assumption on a particular selection criteria in these cases.
When an handler is installed, other two values can be stored in the
event table, two void *
pointers, one called owner and
one called user_data; they are both passed to the handler when called;
the only difference between the two is that handlers to be deinstalled
can be chosen using the owner, and not the user_data value.
Installing and Deinstalling Event Handlers
The handler type is defined as follow:
typedef void (* fts_handler)(fts_server *server, long req, long event,
long tag, fts_value_list *args, void *owner, void *user_data);
The event arguments are passed as fts_value_list; a set of functions and macros are provided to create and access this structure (see Value Lists)
void fts_add_handler(fts_server *server, long req, long event, long tag, fts_handler handler, void *owner, void *user_data)
Install the handler in the server event table, for the request id req, event event and tag tag, with the given owner and used_data values; if any value (tag, event, and request id) is zero, only the other values are used to match the event; if all the values are zero, all the events match.
void fts_remove_handlers(fts_server *server, long req, long event, long tag, fts_handler handler, void *owner)
All the handlers matching the arguments will be removed from the global event table; to match means either that the values are the same, or that the argument passed is 0, or NULL, depending of the type; for example, req, event and tag to zero, and handler to NULL, we can remove all the handlers that were installed for a given owner; while specifing event and leaving tag, handler and owner to zero (or NULL) we can remove all the handlers for a particular event.
void fts_raise_event(fts_server *server, long req, long event, long tag, fts_value_list *args)
Raise a event defined by the req and event/tag pair, with the given arguments; the arguments are specified as an value list (see Value Lists).
void fts_wait_for(fts_server *server, long req, long event, long tag, fts_handler handler, void *owner, void *user_data)
Poll the server until an event, specified by the req and the pair event/tag, is raised; when the event is raised, the specified handler will be invoked, with the event arguments and the owner and user_data specified.
The event we wait for can be raised remotely in the server, or locally as a side effect of the response to some other message.
Note that currently the fts_wait_for
implementation don't use the server file descriptor
if available, so it uses more CPU resources than needed; this will be fixed in some future
release.
Event argument are represented by the fts_value_list
C type;
fts_value_list
is a type defining variable list of type tagged value; these values
are used in events, and internally to represent message arguments; element type
supported are float
, long
, char *
(copied or shared); the copied and
shared string type tag identify both a char *
; by convention they
are used for new copied strings that may/should be freed after the use,
and for pointers to shared/static strings that should not be copied.
The following documents a number of macros to deal with fts_value
values; they are documented as functions.
fts_value_list *fts_value_list_new(void)
Create and return a new, empty value list; the value list module handle a free list of value lists, so freeing and reallocating a value list is usually better and faster than reusing old an existing one.
int fts_value_list_get_size(fts_value_list *list)
Return the number of element in list.
fts_value_list *fts_value_list_copy(fts_value_list *list)
Copy the list, generating a new value list.
void fts_value_list_append(fts_value_list *list, fts_value_list *append)
Append the elements contained in the list append in the list list.
fts_value_list *fts_value_list_sublist(fts_value_list *old, int start, int end)
Generate a new list, containing a sublist of the list old, from the element start, to the element end. The list is a read only list, cannot be modified with the set and add family of functions; it can be copied, if modifications are needed.
fts_value_list *fts_value_list_sublist_copy(fts_value_list *old, int start, int end)
Generate a new list, containing a sublist of the list old, from the element start, to the element end. The list is a newly allocated list, and can be modified.
void fts_value_list_free(fts_value_list *list)
The list list is freed; no further references should be done
on the list.
Setting an element in a list
void fts_value_list_add_long(fts_value_list *list, long val)
Add at the end of list a value of type long, value val.
void fts_value_list_add_float(fts_value_list *list, float val)
Add at the end of list a value of type float, value val.
void fts_value_list_add_string(fts_value_list *list, const char *val)
Add at the end of list a value of type string, value val.
void fts_value_list_add_string_copy(fts_value_list *list, const char *val)
Add at the end of list a value of type string, value val; the value is copied in a private allocated memory.
void fts_value_list_set_long(fts_value_list *list, long val, int pos)
Set the element of list in position pos to type long, value val.
void fts_value_list_set_float(fts_value_list *list, float val, int pos)
Set the element of list in position pos to type float, value val.
void fts_value_list_set_string(fts_value_list *list, const char *val, int pos)
Set the element of list in position pos to type string, value val.
void fts_value_list_set_string_copy(fts_value_list *list, const char *val, int pos)
Set the element of list in position pos to type string, value val;
the value is copied in a private allocated memory.
Accessing an element in a list
long fts_value_list_get_long(fts_value_list *list, int pos)
Return the long value of the element of list in position pos; it is an error getting a long value of a non long element.
float fts_value_list_get_float(fts_value_list *list, int pos)
Return the float value of the element of list in position pos; it is an error getting a float value of a non float element.
char fts_value_list_get_string(fts_value_list *list, int pos)
Return the string value of the element of list in position pos; it is an error getting a string value of a non string element.
Checking an element in a list
int fts_value_list_is_long(fts_value_list *list, int pos)
Return non zero if the value of the element of list in position pos is of type long.
int fts_value_list_is_float(fts_value_list *list, int pos)
Return non zero if the value of the element of list in position pos is of type float.
int fts_value_list_is_chars(fts_value_list *list, int pos)
Return non zero if the value of the element of list in position pos is of type string (either a private copy or not).
int fts_value_list_is_string(fts_value_list *list, int pos)
Return non zero if the value of the element of list in position pos is of type string, and is not a private copy.
int fts_value_list_is_string_copy(fts_value_list *list, int pos)
Return non zero if the value of the element of list in position pos is of type string, and is a private copy.
The FTS C API is defined by the include file ftsapi.h
, that define
prototypes for all the functions documented in this manual, and for
all the constants mentioned.
Protocol constants are defined in the file protocol.h
.
Predefined events and event tags are defined in the file evdefs.h
.
The FTS client and the server communicate by means of messages; a message is a data abstraction, including a message type, a message command, and a number of arguments.
The communication is implemented by means of a secure bidirectional bytestream media, as a TCP connection; this appendix documents the way messages are sent thru the bytestream; it do not document the message semantic, which is partially documented in the next appendixs.
Note that the bytestream protocol is considered documented in the strict sense: it is correct to implement applications that don't use the C client library and access directly to the byte streams, under the condition that comply with this protocol and with the session protocol recomendations; this allow the writing of other client library, for example in other programming languages.
The protocol do not include any kind of error correction; the basic protocol don't include either any kind of flow control; the flow control, when needed, is implemented by means of special messages, and so is not part of the basic protocol definition.
The current version of the protocol send all the data using ASCII characters. The communication is partially human readable.
Future version of the protocol may include a more compact binary version; anyway, it is guaranteed that in all the future version of the protocol:
The protocol is completely asynchronus: i.e. the two directions of the communication are completely independent at this level of abstraction; the representation used for message in both direction is the same.
Constants used here are defined in the protocol.h file.
A message is represented by a ASCII string generated by the following grammar:
<message> ::= <type> <cmd> <arg-list> <end-of-message> <type> ::= <ASCII-char> <cmd> ::= <ASCII-char> <arg-list> ::= <empty-string> | <arg> <arg-list> <arg> ::= <int-arg> | <obj-arg> | <float-arg> | <string-arg> <int-arg> ::= <pos-int-arg> | <neg-int-arg> <pos-int-arg> ::= <pos-int-type-tag> <hex-unsigned-int-representation> <neg-int-arg> ::= <neg-int-type-tag> <hex-unsigned-int-representation> <obj-arg> ::= <obj-type-tag> <hex-unsigned-int-representation> <float-arg> ::= <float-type-tag> <float-representation> <string-arg> ::= <start-string-tag> <string-body> <stop-string-tag>Where:
<ASCII-char>
<empty-string>
<pos-int-type-tag>
<neg-int-type-tag>
<obj-type-tag>
<float-type-tag>
<start-string-tag>
<stop-string-tag>
<end-of-message>
Since messages cannot contain a new-line character in their body, a new-line character can be put in the string as the string ``\n'' (two characters); a double quote can be put in a message content as the string ``\"'' (two characters); the client library, and the FTS message support automatically performs these quoting/dequoting operations when needed.
Since the type tag performs as a token separator in the grammar, the obvious choice of 'f' as type tag for the floating point values would not work, because it would introduce an ambiguity at the end of a int value, sent as hexadecimal.
Longs are sent with a sign-value representation, to avoid introducing dependencies from the word machine size in the protocol; the sign is included in the type tag, so there are two type tag for long, positive long and negative long.
The floats are sent in printf/scanf style representation.
The maximum values for scalar arguments is not specified by the protocol itself, and depend on the connected subsystem.
Arguments are positionals, i.e. first argument in the string is argument 0, second argument in the string is argument 1 and so on.
Messages can include any number tab and blanks; however, unless they occur inside a string, they are considered as lexical token separators.
This grammar do not handle the request ID; actually, the request ID is not a special field of the message, but it is always, for all the subsystems, the first argument of the message; this is left implicit in the documentation of the subsystem.
This appendix document all the defined subsystem for the communication protocol.
The void subsystem is identified by a target subsystem identifier equal to VOID_CODE (currently 'v'). Any message, in both directions, sent to the void subsystem is simply discarded; it can be used for debugging.
The Max subsystem is identified by a target subsystem identifier equal to MAX_CODE (currently 'm'). The Max subsystem correspond to the Max interpreter; messages to this subsystem allow the creation and execution of a Max patch.
Commands, with their relative argument syntax and command semantics are defined as follows:
NEW_OBJ_CODE, long proc, long obj, string class, args ...
Create a new Max object; the object is created in processor number proc; processor are numbered from 0 up to the number of installed processors; if the FTS server is monoprocessor, the proc argument should be zero.
The object is given the identifier obj; it is an error to assign the same identifier to multiple objects; for a multiprocessor server, the identifier space is global to all the processors.
The class argument is the name of the class of the object. All the other args are passed to the class specific new function, so their semantic is class relative.
FREE_OBJ_CODE long obj
Free the object of identifier obj; the object will be immediately destroyed, and the resources used will be returned to FTS.
CONNECT_CODE long obj1, long outlet, long obj2, long inlet
Connect the outlet outlet of obj1 to the inlet inlet of obj2.
DISCONNECT_CODE long obj1, long outlet, long obj2, long inlet
Disconnect the outlet outlet of obj1 from the inlet inlet of obj2.
MESSAGE_CODE long target-obj, string message, long inlet, args ...
MESSAGE_CODE string target-name, string message, long inlet, args ...
Send the Max message message to an object, on the given inlet; the object can be specified either by its object identifier, or by a name; the ability to be identified by name is class specific; currently, only receive objects can be specified by name, but other classes can be built with this ability.
The arguments are passed to the object as they are; object identifier are converted in pointers to the objects themselves.
The Meta Max subsystem is used to get information about objects and object classes, like how many inlets or which kind of message an object accept. The Meta Protocol is not (yet) documented.
The Manager subsystem is the subsystem that takes care of booting the server and of the pre-boot configuration (also of some post-boot configuration paramenters); the actual location of the subsystem depends on the configuration and on the type of connection used; for example, for coprocessor based server the manager is the part of the program that boot the coprocessor, so it must reside on the target machine; in case of a socket connection the manager is remote, while in case of a local connection the manager is local; in order to give a complete transparency to the user application, the communication with the manager is always performed with messages, regardless to the location of the manager; the library will route the messages as needed depending on the configuration.
At the moment, most of the manager messages are server specific; so we document here a manager protocol for each kind of server the library can directly bootstrap; in future releases the manager protocol will evolve in a server independent core, with a few server specific extensions.
The ISPW manager subsystem is charged with all the pre-boot configuration of the ISPW FTS server, and with the bootstrap itself; so many of the supported messages are, at least in the current version, ISPW dependent.
setftsdir
Set the ftsdir; the directory is interpreted locally from the manager.
setsysdir
Set the sysdir, i.e. the directory where some ISPW system file are kept; the directory is interpreted locally from the manager.
setthrottle
Set the three throttles; if the server is running change them dynamically.
setadvances ...
Set the advances values; if the server is running change them dynamically. The values should be more than one, less or equal to the number of processors. Advances should be set after the nproc configuration value.
setcpuslots ...
Set the cpus slot; should be set before the server startup. The values should be equal to the number of processors. This message should be sent after the nproc configuration value.
setmachversion
Set the mach version; should be set before the server startup. Note that in case of non local manager, the manager is free to ignore this message and to use informations locally available on the host.
setnproc
Set the number of processors used; should be set before the server startup.
setnboard
Set the number of ISPW boards installed in the machine; the other pertinent parameters are derived from this one.
opensdserver
Take the directory were to find the sound server executable, the sound server number, and the three throttle values to pass on to the server. Start the sound server with the given identifier.
closesdserver
Close (shutdown) the sound server with given identifier.
start
Boot/start the FTS server, with the previously set up configuration. Send this if the server status is server_down.
shutdown
Shutdown the server.
The Unix manager is used for Unix servers, usually connected to the daemon or the client thru a Unix pipe; the Unix manager handles server booting and shutdown, essentially.
setftsdir
Set the ftsdir; the directory is interpreted locally from the manager.
start
Boot/start the FTS server, with the previously set up configuration. Send this if the server status is server_down.
shutdown
Shutdown the server.
restart
Shutdown the server (if not already dead/down) and reboot it; used for cleanup; Send this is the server status is server_dead.
The Session Manager subsystem is the subsystem that handle a peer-to-peer connection, i.e. the connection between the client and the daemon, or between the client and the server, or between the daemon and the server; its purpose is to handle the connection itself, and not the message content. It provides two messages to initialize and quit the connection, and three message to handle flow control in the server to client direction.
This messages are usually sent and handled directly by the library; anyway, if a client write directly to the bytestream, it should at least send the first two.
INIT_CONNECTION
QUIT_CONNECTION
FLOW_CONTROL_ON
FLOW_CONTROL_OFF
ACK_MESSAGE
The Event subsystem is the subprotocol used to send events to the
clients; the format of the messages is unique, and include a
VOID_COMMAND
command field, the event and the tag coded
as the first two integer argument of the message, and the event
arguments coded as the other message arguments.
The daemon control subsystem is a subsystem that is actually installed in the
daemon itself, and whose purpose is to perform control operations on the daemon
itself; the functionalities offered by this message are currently available
by means of the ftsc
program (see the relative documentation), but can
easily incorporated in any user application.
The defined messages are as following.
DEBUG_LEVEL
ftsd
documentation). The argument
values are int that can go from 0 (completely quiet) to 4; debug level
1 correspond to the normal logging of new clients to the system
administration files; level 4 give an extremely detailed log of the daemon
activities.
RESET_DAEMON
HALT_DAEMON
ATTACH_MODE
ftsd
documentation), otherwise set the detach
mode.
GET_VERSION
The client library define a number of events and the related tags; the numbers below 1024 are reserved for events and tags handled by the library, and cannot be used by the application; FTS itself and the FTS subsystems define a number of events; refer to the FTS documentation for details.
Note that events and tags int, while represented in the client library with the local int type, should have values that can be represented with a 32 bit int.
Tag meaning is event specific; this means that tags are not identified by globally unique numbers, but only unique only w.r.t. events.
Predefined Events are:
FATAL_ERROR
CONNECTION_ERROR
PROGRAM_ERROR
SERVICE_REQUEST
CLIENT_INFO
SERVER_INFO
FIRST_APPLICATION_EV
The predefined tags for each event are documented in the following.
Tags defined for the FATAL_ERROR event.
EXHAUSTED_MEMORY
Tags defined for the CONNECTION_ERROR event.
CONNECTION_DIED
SERVER_DIED
UNKNOWN_SERVER_MESSAGE_CMD
BAD_FTSD_ADDR
UNKNOWN_TCP_SERVICE
CANNOT_CREATE_SOCKET
CANNOT_CONNECT
CONNECTION_CLOSED
Tags defined for the PROGRAM_ERROR event.
MESSAGE_TOO_LONG
INVALID_TH1_VALUE
INVALID_TH2_VALUE
INVALID_TH3_VALUE
INVALID_ADVANCE
INVALID_MNGR_MESSAGE
UNKNOWN_MNGR_MESSAGE
SOUNDDISK_ERROR
Tags defined for the SERVICE_REQUEST event.
PRINT_REQUEST
No tags are currently defined for the CLIENT_INFO event.
Tags defined for the SERVER_INFO event.
No user visible tags are currently defined for the CLIENT_INFO event.
Authors : Maurizio De Cecco, François Déchelle
Copyright © 1995 IRCAM.