"libtmssl.a" contains a set of functions to make generation of Tsimmis translators and mediators easier. The format and structure "libtmssl.a" is similiar to the original ssl library. "libtmssl.a" is a client to "libtmcomm.a".
"libtmssl.a" provides a default server and a set of "hooks" allowing user to attach translator specific functions to the default server.
Figure 1 shows the interaction between the default server defined in "libtmssl.a" and the functions in "libtmcomm.a". The default server receives requests via "TM_RecvData()". It process the request by calling the hooks that point to user defined functions. The result is send back using "TM_SendObject()" and "TM_SendData()". Then the default server loops back to listen for next request.
| ^
=======================|=========================|=======
|| | | |
|| "libtmcomm.a" | TM_SendObject() |
|| TM_RecvData() TM_SendData() |
|| | | |
|| | | |
|| ++========|=========================|======+
|| || V | |
|| || listen for request <---\ | |
|| || | | | |
|| || V | | |
||============. decode request | | |
hooks <---- tmInit . | | | |
point <---- tmQuery . V | | |
to user <---- tmConvert . call hook send result -/ |
defined <---- tmFetchObj <---- functions | |
functions <---- tmFetchRef . | |
<---- tmShutdown . | |
<---- tmCreateRef . | |
<---- tmFindObj . | |
|| | . | |
|| \-----------> get result ---------/ "libtmssl.a" |
|| . |
+=======================================================+
Figure 1, Interaction Between "libtmssl.a" and "libtmcomm.a"
The user defined functions have full access to all the functions and
data types defined in "libtmcomm.a". These user functions can send
results back to the requester directly if they choose to do so.
However, the return result must follow the partial fetch protocol (see
FETCH.PROTOCOL).
When using the default server in "libtmssl.a", it is very easy to
write a new translator. The user need only to provide the functions
for the hooks and call default server loop. A typical main.c for a
translator looks like this:
void main (int argc, char **argv) {
/* assign my functions to hooks in tmssl */
tmQuery = MyQuery;
tmConvert = MyConvert;
tmFetchObj = MyFetchObj;
tmFetchRef = MyFetchRef;
tmInit = MyInit;
tmShutdown = MyShutdown;
/* call default server loop */
TM_DefaultServer(argc, argv);
}
*************
* INTERFACE *
*************
* NORMAL INTERFACE *
"libssl.a" contains the following function variables. These function
variables are "hooks" allowing user to plug in translator/mediator
specific code to the default server.
TM_InitHandler tmInit;
TM_ShutdownHandler tmShutdown;
TM_QueryHandler tmQuery;
TM_ConvertHandler tmConvert;
TM_FetchHandler tmFetchObj;
TM_FetchHandler tmFetchRef;
TM_FindObjectHandler tmFindObj;
TM_CreateRefHandler tmCreateRef;
In addition, this flag variable can be set (see 'tmCreateRef'):
int tmRecomputeReference (default value is 1)
--
tmInit
tmInit points to a user function of following type:
TM_Error (*) (TM_Data *option);
This function performs Tsimmis server specific initialization
routines. For example, if the Tsimmis server is a translator, this
user routine may open a connection with the native source. 'option'
contains generic server options. The exact content and format have
yet to be determined.
This function should return:
TM_NO_ERROR - init successful, no error
TM_INIT_FAILED - init failed
TM_INIT_TWICE - init called twice
--
tmShutdown
tmShutdown points to a user function of following type:
TM_Error (*) (TM_Data *option)
This function performs Tsimmis server specific shutdown routines.
'option' contains generic shutdown options. The format and content
have yet to be determined.
This function should return:
TM_NO_ERROR - no error
--
tmConvert
tmConvert points to a user function of following type:
TM_Error (*) (TM_Data *query, char **result)
This function converts a Tsimmis client query in OEM_QL into a
native source query. Tsimmis client query is given in 'query' which
is a TM_Data. This TM_Data normally encodes the client query in a
string. The resulting native source query should be a string
returned in the parameter 'result'.
This function should return:
TM_NO_ERROR - no error
TM_CONVERT_FAILED - unable to convert query to native query
--
tmQuery
tmQuery points to a user function of following type:
TM_Error (*) (char *query)
This function executes a native query in string format in the native
source. The function can return:
TM_NO_ERROR - no error
TM_QUERY_FAILED - general query error
TM_QUERY_SYNTAXERROR - query failed at the source due to syntax error
TM_QUERY_UNSUPPORTED - query is not supported at source
--
tmCreateRef
tmCreateRef points to a user function of following type:
TM_Data *(*) (TM_Object *object, void *userData)
This function creates a object reference given a pointer to an object.
The parameter 'userData' can be used to send any additional data used
by the user that is needed to create the reference. An object reference
is used during partial fetch to quickly locate an object with the
reference. Object reference is always treated local to the process.
It is not meant to be persistant and process independent.
There is a default function in the SSL library that provides object
reference creation. You can use the default function or use your
own function. Note that if you use your own object reference, you
must write your own function for 'tmFindObj' (see below) as well.
A global variable 'tmRecomputeReference' controls the scope of the
object reference created by the default function within a process.
If 'tmRecomputeReference' is set to 1 (the default setting), the
object reference computed by the default function of SSL library
is only valid after the last call to 'tmQuery' and before the next
call 'tmQuery'. This method helps to detect stale references that
are passed to the server asking for objects that may no longer exist
after a new query is submitted. The drawback is that you will need
to recompute object references for all your objects after every
'tmQuery' even the object already has a reference from being part
of a result from a previous query.
This function should return:
(TM_Data *) - pointer to a TM_Data that encodes a reference
NULL - object pointer is NULL
--
tmFindObj
tmFindObj points to a user function of the following type:
TM_Object *(*) (TM_Object *root, TM_Data *reference, void *userData)
This function treats the given TM_Data as an object reference. It
returns the object pointed to by the reference. 'userData' can be
used by the user to pass in any additional information that may
be helpful in locating the object. By convension, 'root' object
should be returned if 'reference' is NULL or contains a NULL reference.
There is a default function in the SSL library that provides the
ability to location object given a reference. However, this default
function only understands object references generated by the default
object reference creation function provided in the SSL library (see
above).
This function should return:
'root' - 'reference' is NULL or 'reference' contains NULL
(TM_Object *) - pointer to object referenced
NULL - 'reference' is invalid
--
tmFetchObj
tmFetchRef
tmFetchObj and tmFetchRef are user functions of following type:
TM_Error (*) (TM_ConnEnd *conn,
uint8 fetchType,
TM_Data *objRef,
TM_Object **result)
tmFetchObj and tmFetchRef retrieves OEM objects or object references
that are result of the latest query.
'conn' points to the TM_ConnEnd from which the fetch request
originates. This function can send the result directly through
'conn' to the requestor following the appropriate partial fetch
protocol.
'objRef' points to a TM_Data that encodes a "object reference" that
is implementation specific. The fetch function can use this "object
reference" to locate the "root" object of the result.
'fetchType' can be:
TM_FETCH_ALL - fetch all objects/references
TM_FETCH_ONE - fetch only the root object/reference
TM_FETCH_CHILDREN - fetch the root plus first level children
'result' is where the root of the return object should placed. The
result is always an TM_Object with zero or more child TM_Object.
Returning object in 'result' is optional. The user may decide to
directly send resulting objects to the requestor by calling
"libtmcomm.a" functions. If the user does this, there is no need to
return anything in 'result'. When finished, the user can simply
return TM_NO_ERROR.
If the user does not send results directly to the requestor, it must
return the "root" result object in 'result'. The default server
will then send the result to the requestor for the user. In this
mode, the user sets the 'result' and return TM_NEED_SEND to signal
the default server that the returned object needs to be send to the
requestor.
The fetch function normally work like this if it does not send
objects directly to the requestor:
1. Locate the object referenced by "object reference" encoded in
'refObj'. If there is no support for "object reference", just
pick a default object (usually the root object of the entire
result). This object is the result object and should be placed
in 'result'.
2. Depending on the 'fetchType' flag, attach zero or more child
objects of the result object to the result object.
In case of tmFetchObj, if 'fetchType' is TM_FETCH_ONE, there is no
need to attach any child object. If 'fetchType' is TM_FETCH_ALL,
all child objects of the result object must be attached. If
'fetchType' is TM_FETCH_CHLIDREN, only the first level children of
the result object are required to be attached.
In case of tmFetchRef, instead of returning objects that are result
of some previous query, the result object contains "object
reference". The corresponding child objects contains "object
reference"s of the child objects to the object referenced by
'objRef'. Support for tmFetchRef is optional. If there is no good
notion of "object reference", there is no need to support
tmFetchRef. Then when calling fetch function, pass in NULL as
'objRef'.
This function should return:
TM_NO_ERROR - no error
TM_FETCH_FAILED - unable to fetch result
TM_INVALID_REFERENCE - reference invalid
TM_NULL_RESULT - result is NULL
TM_NEED_SEND - let default server sends the result
TM_NO_SUPPORT - fetch option is not supported
* POWER USER INTERFACE *
A simple "libtmssl.a" client does not need to call any functions in
"libtmssl.a" directly. The client simply setup the 6 hooks mentioned
above and let the default server handles everything. However, to
provide maximum flexibility, a user may decide to bypass the default
server and write his own server. In that case, the functions provided
in "libtmssl.a" may be called directly by the user.
To access the default server and functions defined in "libtmssl.a",
include the header file
tmssl.h
Inclusion of "tmssl.h" automatically includes "tmconnend.h" and
"tmtypes.h".
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tmssl.h functions:
TM_DefaultServer - starts default server
TM_SendResult - send a result using partial fetch protocol
TM_SendCode - send a partial fetch protocol code
TM_DefaultSendOne - send one object using partial fetch protocol
TM_DefaultSendChildren - send one object and its 1st level children
TM_DefaultSendAll - send one object and all its children
TM_DefaultFetchRef - default tmFetchRef function
TM_DefaultFetchObj - default tmFetchObj function
TM_DefaultFetchOne - default function to fetch one object
TM_DefaultFetchAll - default function to fetch all objects
TM_DefaultFetchChildren - default function to fetch children objects
TM_CreateObjectReference - create a default "object reference"
TM_FindObject - find an object given default "object ref."
TM_DefaultInit - default tmInit function
TM_DefaultShutdown - default tmShutdown function
TM_DefaultQuery - default tmQuery function
TM_DefaultConvert - defualt tmConvert function
TM_ListenForConnection - default function that listens for connection
on a TCP port
## More detailed explaination ##
* consult tmssl.c for now *
--
void TM_DefaultServer(int argc, char **argv)
Starts the default server in "libtmssl.a". 'argc' and 'argv' should
contain command line options. The following options are understood
by the default server:
-p port_number - starts server using port_number
-n - do not fork any child process, useful for debugging
-v - verbose mode
The default server listens on a TCP port for connection. When a
connection is requested from a client, the server forks off a new
process to process request by the client. (Forking may be disabled
using "-n" command line option.) The port on which the server
listens for connection is determined by the following priority
rules:
1. Check for command line optione "-p port_number". If a port
number is given, use that port number.
2. If no command line option, check environment variable
"TSIMMIS_PORT". If the environment variable is present, use
the port number stored in the environment variable as the
listening port.
3. If no command line option and no environment variable, use the
compiled default port number 6666.
RETURNS:
--
TM_Error TM_SendResult(TM_ConnEnd *conn, TM_Error error)
Sends a TM_Error code to the remote end using partial fetch protocol.
'conn' is a valid TM_ConnEnd. 'error' is the error code to be send.
This function executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - unable to send message
--
TM_Error TM_SendCode(TM_ConnEnd *conn, uint32 code, uint32 option)
Sends a partial fetch protocol pair to the remote end.
This function executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - unable to send message
--
TM_Error TM_DefaultSendOne(TM_ConnEnd *conn, TM_Object *object)
Sends one TM_Object to the remote end using partial fetch protocol.
'conn' is a valid TM_ConnEnd. 'object' points to the object to be
send. This function executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Error TM_DefaultSendChildren(TM_ConnEnd *conn, TM_Object *object)
Sends one TM_Object and all its first level child objects to the
remote end using partial fetch protocol. 'conn' is a valid
TM_ConnEnd. 'object' points to the root object to be send. This
function executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Error TM_DefaultSendAll(TM_ConnEnd *conn, TM_Object *object)
Sends one TM_Object and all its child objects to the remote end
using partial fetch protocol. 'conn' is a valid TM_ConnEnd.
'object' points to the root object to be send. This function
executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Error TM_DefaultFetchRef(TM_ConnEnd *conn,
uint8 fetchType,
TM_Data *objRefData,
TM_Object **result)
Sends TM_NO_SUPPORT to the remote end. This function does not do
anything interesting. It can be used as a dummy function for the
'tmFetchRef' hook when the user does not want to support object
references.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Error TM_DefaultFetchObj(TM_ConnEnd *conn,
uint8 fetchType,
TM_Data *objRefData,
TM_Object **result)
Default function for 'tmFetchObj' hook. Sends objects stored in
"libtmssl.a" object cache to the remote end. 'conn' is a valid
TM_ConnEnd. 'fetchType' determines how to fetch the objects.
'objRefData' points to a TM_Data containing an "object reference"
produced by TM_CreateObjectReference(). 'result' is not used. This
function executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Error TM_DefaultFetchOne(TM_ConnEnd *conn, TM_Data *objRefData)
Sends one object referenced by "object reference" contained in
'objRefData' to the remote end. This function executes
synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Error TM_DefaultFetchAll(TM_ConnEnd *conn, TM_Data *objRefData)
Sends one object and all its child objects referenced by "object
reference" contained in 'objRefData' to the remote end. This
function executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Error TM_DefaultFetchChildren(TM_ConnEnd *conn, TM_Data *objRefData)
Sends one object and all its first level child objects referenced by
"object reference" contained in 'objRefData' to the remote end.
This function executes synchronously.
RETURNS:
TM_NO_ERROR - no error
TM_ERR_SEND - a network error has occured
--
TM_Data *TM_CreateObjectReference(TM_Data *parentRef, uint32 index)
Creates an object reference based on an existing object reference
and an integer. If the given 'parentRef' is NULL, this routine
returns an object reference that is appropriate for a root object.
For example, if you want to create an object reference using this
function for a TM_Object "Oa" whose parent is another TM_Object
"Op". Then, 'parentRef' should be the object reference of "Op".
'index' is the intiger indicating which child of "Op" "Oa" is. This
number can be obtain as the return value from a call to
TM_ObjectAppendChild(Op, Oa).
RETURNS:
- a pointer to TM_Data that encodes object ref.
NULL - unable to assign object reference
--
TM_Object *TM_FindObject(TM_Object *startObj, TM_Data *objRef)
Finds object with given object reference pointed by 'objRef'. The
search starts with 'startObj' as the root object. 'objRef' must
point to an object reference created by TM_CreateObjectReference().
RETURNS:
- pointer to found object
NULL - object with reference not found
--
TM_Error TM_DefaultInit(TM_Data *option)
Default function for 'tmInit' hook. Does nothing.
RETURN:
TM_INIT_FAILED - don't know how to perform init
--
TM_Error TM_DefaultShutdown(TM_Data *option)
Default function for 'tmShutdown" hook. Does nothing
RETURN:
TM_NO_ERROR - no error
--
TM_Error TM_DefaultQuery(char *query)
Default function for 'tmQuery' hook. Does nothing
RETURN:
TM_QUERY_FAILED - don't know how to handle the query
--
TM_Error TM_DefaultConvert(TM_Data *original, char **result)
Default function for 'tmConvert' hook. This function just extracts
the string from the 'orginal' and return the string in 'result'.
This function can be used if the input query is in native form
already.
RETURNS:
TM_NO_ERROR - no error
TM_CONVERT_FAILED - unable to convert
--
int TM_ListenForConnection(int portNumber, int dynamic)
Creates a TCP stream socket for listening incoming connections.
This procedure attempts to use portNumber given for listening. If
that port is in use and dynamic flag is 1, it dynamically searches
for an open port to bind. If dynamic flag is 0 and portNumber if in
use, it will exit with -1.
Upon receiving a connection request, this function normally forks
another process. The new process will return with an integer
greater than 0. This integer is the new socket that is connected
with the remote end. The original process will continue listen for
more connections until an interrupt from the user.
If the global variable 'tmFork' is 0, this function does not fork
any new process. Upon receiving a connection request, it will
return with a new socket that is connected with the remote end.
Setting 'tmFork' to 0 is very useful during debugging.
RETURNS:
= 0 - finished listening
> 0 - a client is connected via returned socket number
< 0 - a network related error occured
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~