1
0
mirror of https://github.com/haiwen/libsearpc.git synced 2025-06-19 18:31:54 +00:00
libsearpc/README.markdown

225 lines
7.3 KiB
Markdown
Raw Normal View History

2011-04-08 12:27:39 +00:00
Introduction
2011-05-18 03:06:01 +00:00
============
2011-04-08 12:27:39 +00:00
Searpc is a simple C language RPC framework based on GObject system. Searpc
handles the serialization/deserialization part of RPC, the transport
part is left to users.
The serialization/deserialization uses JSON format via json-glib
library. A JsonObject is returned from server to client after
executing the RPC function. Each RPC function defined in the server side should
take an extra GError argument to report error. The returned JsonObject
contains three fields:
* **ret**: the return value of the RPC function
* **err_code**: error code. This field is only set if the RPC function
reports an error.
* **err_msg**: error message. This field is only set if the RPC function
reports an error.
2011-04-09 03:04:02 +00:00
2011-04-08 12:27:39 +00:00
Example
======
Client
------
In the client side, you need to:
2011-05-18 03:06:01 +00:00
* Define your RPC function with our marco.
2011-04-08 12:27:39 +00:00
* write code to send the request to server and get the resonpse from it.
### Define your RPC function ###
The client define RPC functions using macros defined in
2011-05-18 03:06:01 +00:00
`searpc-client.h`. To call the functions, the client needs to create
2011-04-08 12:27:39 +00:00
a SearpcClient object and supply a transport function. For example:
/*
* define a RPC function which takes a string argument and returns
2011-05-18 03:06:01 +00:00
* an integer. The xxx_INT__STRING naming convention is used to
2011-04-08 12:27:39 +00:00
* indicate the types of the param(string) and the return value(int).
*/
2011-05-18 03:06:01 +00:00
SEARPC_CLIENT_DEFUN_INT__STRING(searpc_strlen)
2011-04-08 12:27:39 +00:00
/* create an rpc_client and supply the transport function. */
SearpcClient *rpc_client;
rpc_client = searpc_client_new();
rpc_client->transport = transport_callback;
rpc_client->arg = &sockfd;
2011-05-18 03:06:01 +00:00
The `SEARPC_CLIENT_DEFUN_XXX__YYY` macro defines a client side RPC function.
2011-04-08 12:27:39 +00:00
**XXX** stands for the return type and **YYY** stands for the param type. If there
are multiple params, just append every param type there. For example,
2011-05-18 03:06:01 +00:00
`SEARPC_CLIENT_DEFUN_INT__STRING_STRING` defines a RPC function which takes two
2011-04-08 12:27:39 +00:00
string params and returns an integer value.
### Transport function ###
When the client-side function is called, Searpc does the following work:
* Pack the function name and the params into JSON data format.
* Call your transport function to send the JSON data
to the server, and get the returned data from the server.
* Unpack the returned JSON data and return the value as the return
value of the client-side function.
Your transport function is supposed to:
* Send the request data to the server.
* Receive the returned data from the server.
The prototype of the transport function is:
/*
* arg: rpc_client->arg. Normally a socket number.
* fcall_str: the JSON data stream generated by Searpc.
2011-05-18 03:06:01 +00:00
* fcall_len: the length of `fcall_str`.
2011-04-08 12:27:39 +00:00
* ret_len: place to get the length of the returned json data stream.
2011-05-18 03:06:01 +00:00
* Returns: A newly allocated string stores the JSON data stream.
*/
2011-04-08 12:27:39 +00:00
static char *transport_callback (void *arg, const char *fcall_str, size_t fcall_len, size_t *ret_len);
Server
------
In the server side, you need to:
* Register your function
* write code to receive the request and send the result
And Searpc handles the others for you.
### Concepts ###
2011-05-18 03:06:01 +00:00
* **Marshal**: The process of unpacking the function arguments from
JSON data, call the RPC function and packing the result into JSON
data format is called marshalling. The function used to
pack the result is called a **marshal**.
2011-04-08 12:27:39 +00:00
2011-05-18 03:06:01 +00:00
* **Signature**: Signatures are used to identify different types of
2011-04-08 12:27:39 +00:00
marshals. After the execution of a RPC function on the server side,
different types of results need different marshals.
2011-05-18 03:06:01 +00:00
* **Function table**: The hash table used to store the (funcname, func)
2011-04-08 12:27:39 +00:00
pairs.
2011-05-18 03:06:01 +00:00
* **Marshal table**: The hash table used to store the (signature,
2011-04-08 12:27:39 +00:00
marshal) pairs.
### Register your function ###
2011-05-18 03:06:01 +00:00
The `seaprc_server_register_function` routine registers a function as
2011-04-08 12:27:39 +00:00
a RPC function. It inserts your function into the function table. The
prototype of this function is:
/*
* func: pointer to the function you want to register
* fname: the name of the function. It would be the key of your
* function in the fucntion hash table.
* signature: the identifier used to get the corresponding marshal.
* Returns: a gboolean value indicating success or failure
*/
gboolean searpc_server_register_function (void *func, const gchar *fname, const gchar *signature)
2011-05-18 03:06:01 +00:00
Before calling `searpc_server_register_function`, you need to call
2011-04-08 12:27:39 +00:00
**`searpc_server_init()`** to do the initialization work.
### Call the RPC fucntion ###
After the registration, you should listen to the socket and wait for the
incoming request data stream. Once you get a valid request, call the
2011-05-18 03:06:01 +00:00
`searpc_server_call_function()` routine, which will automatically do the
2011-04-08 12:27:39 +00:00
following work for you:
* Parse the JSON data stream to resolve the function name and the data.
* Lookup the function in the function table according to the funcname.
* If a proper function is found, call the function with the given params.
* Packing the result into a JSON data string.
2011-05-18 03:06:01 +00:00
The prototype of `searpc_server_call_function` is:
2011-04-08 12:27:39 +00:00
/*
* data: The incoming JSON data stream.
* len: The length of **`data`**.
* ret_len: Place to hold the length of the JSON data stream to be returned
* Returns: The JSON data containing the result of the RPC
*/
gchar* searpc_server_call_function (gchar *data, gsize len, gsize *ret_len)
2011-05-18 03:06:01 +00:00
The value returned by `searpc_server_call_function()` is the JSON data
ready to send back to the client.
2011-04-08 12:27:39 +00:00
Pysearpc
2011-05-18 03:06:01 +00:00
========
2011-04-08 12:27:39 +00:00
**Pysearpc** is the Python binding of **Searpc**. Only the client side function is
supported. To use it, simply define a class which inherits **SearpcClient**, and
2011-05-18 03:06:01 +00:00
provide a `call_remote_func_sync` method, which is equivalent to the
`transport_callback`.
2011-04-08 12:27:39 +00:00
2011-05-18 03:06:01 +00:00
To define your RPC funtion, use the `@searpc_func` decorator. It is
equivalent to `SEARPC_CLIENT_DEFUN_XXX__YYY` macro. To define a RPC
2011-04-08 12:27:39 +00:00
function which accepts multiple params, here is an example:
class SampeSearpcClient(SearpcClient):
def call_remote_func_sync(self, fcall_str):
# your transport code here
...
@searpc_func("int", ["string", "string"])
def searpc_demo_func(self):
# this is enough for the client side
pass
See the demo program for a more detailed example.
Demos
======
There are well-commented demos in both C and Python.
* **searpc-demo-server.c**: The server side demo program
* **searpc-demo-client.c**: The client side demo in C
* **pysearpc-demo-client.py**: The client side demo in Python
2011-05-18 03:06:01 +00:00
To run the demo, run the server demo in a shell, and run the client
demo in another. To run the python demo, you should first install the
package and setup the **PYTHONPATH** appropriately.
2011-04-08 12:27:39 +00:00
Thread Safety
2011-05-18 03:06:01 +00:00
=============
2011-04-08 12:27:39 +00:00
Extend Searpc
2011-05-18 03:06:01 +00:00
=============
2011-04-08 12:27:39 +00:00
To support new rpc function types,
1. edit **`rpc_table.py`**,
2. call **make genrpc**.
3. If the return type is not supported yet, you need also define the
corresponding **`searpc_fret_*`** function.
2011-04-09 03:04:02 +00:00
Dependency
2011-05-18 03:06:01 +00:00
==========
2011-04-09 03:04:02 +00:00
The following packages are required to build libsearpc:
2011-04-09 03:53:55 +00:00
* glib-2.0 >= 2.16.0
* gobject-2.0 >= 2.16.0
* json-glib-1.0 >= 0.10.2
* pygobject-2.0 >= 2.0 (if you choose to build pysearpc)
2011-04-09 03:04:02 +00:00