1
0
mirror of https://github.com/haiwen/libsearpc.git synced 2025-05-10 16:14:22 +00:00

Remove fcall and fret

This commit is contained in:
plt 2012-06-04 00:19:16 +08:00
parent 4b51d49593
commit 84d8110465
16 changed files with 574 additions and 417 deletions

View File

@ -229,4 +229,4 @@ The following packages are required to build libsearpc:
* glib-2.0 >= 2.16.0
* gobject-2.0 >= 2.16.0
* simplejson (for pysearpc)
* python simplejson (for pysearpc)

View File

@ -24,10 +24,6 @@
#define BUFLEN 256
#define MAGIC_STRING "ABCD"
/* define the client-side function */
SEARPC_CLIENT_ASYNC_DEFUN_INT__STRING(searpc_strlen, 0);
typedef struct {
int fd;
void *rpc_priv;
@ -47,7 +43,7 @@ static int transport_send(void *arg, char *fcall_str,
/* construct the packet */
pac->length = htons((uint16_t)fcall_len);
strncpy(pac->data, fcall_str, fcall_len);
memcpy(pac->data, fcall_str, fcall_len);
/* send the packet */
if ( writen (trans->fd, buf, PACKET_HEADER_LENGTH + fcall_len) == -1) {
@ -138,7 +134,9 @@ main(int argc, char *argv[])
rpc_client->async_arg = (void *)(long)transport;
/* call the client-side funcion */
searpc_strlen_async(rpc_client, "hello searpc", strlen_callback, "user data");
searpc_client_async_call__int(rpc_client, "searpc_strlen",
strlen_callback, "user data",
1, "string", "hello searpc");
/* call the transport to receive response */
transport_read (transport);

View File

@ -3,6 +3,8 @@ import sys
import socket
from struct import pack, unpack
sys.path += ['..']
from pysearpc import SearpcClient, searpc_func
SERVER_ADDR = '127.0.0.1'

View File

@ -25,8 +25,6 @@
#include <arpa/inet.h>
#endif
/* define the client-side function */
SEARPC_CLIENT_DEFUN_INT__STRING(searpc_strlen);
static char *transport_callback(void *arg, const char *fcall_str,
size_t fcall_len, size_t *ret_len)
@ -40,7 +38,7 @@ static char *transport_callback(void *arg, const char *fcall_str,
/* construct the packet */
pac->length = htons((uint16_t)fcall_len);
strncpy(pac->data, fcall_str, fcall_len);
memcpy(pac->data, fcall_str, fcall_len);
/* send the packet */
if ( writen (fd, buf, PACKET_HEADER_LENGTH + fcall_len) == -1) {
@ -104,7 +102,8 @@ main(int argc, char *argv[])
rpc_client->arg = (void *)(long)sockfd;
/* call the client-side funcion */
ret = searpc_strlen(rpc_client, "hello searpc", &error);
ret = searpc_client_call__int(rpc_client, "searpc_strlen", &error,
1, "string", "hello searpc");
if (error != NULL) {
fprintf(stderr, "error: %s\n", error->message);
exit(-1);

View File

@ -4,8 +4,6 @@
#include <errno.h>
#include <unistd.h>
#include <glib.h>
#include <glib-object.h>
@ -122,11 +120,11 @@ main(int argc, char *argv[])
int fcall_len = ntohs(pac->length);
/* Execute the RPC function */
char *res = searpc_server_call_function ("searpc-demo", pac->data, fcall_len,
&ret_len, &error);
&ret_len);
pac_ret = (packet *)buf;
pac_ret->length = htons((uint16_t)ret_len);
strncpy(pac_ret->data, res, ret_len);
memcpy(pac_ret->data, res, ret_len);
/* send the ret packet */
if (writen (connfd, buf, PACKET_HEADER_LENGTH + ret_len) == -1) {

View File

@ -14,8 +14,7 @@
# * searpc-marshal.h: contains functions like `marshal_int__string()`
#
generated_sources = fcall-impr.h searpc-fcall.h searpc-dfun.h \
searpc-signature.h marshal.h
generated_sources = searpc-signature.h marshal.h
# rpc_headers = fcall-impr.h searpc-fcall.h searpc-dfun.h searpc-signature.h searpc-marshal.h
@ -30,14 +29,14 @@ BUILT_SOURCES = gensource
lib_LTLIBRARIES = libsearpc.la
include_HEADERS = searpc-fcall.h searpc-client.h searpc-dfun.h \
include_HEADERS = searpc-client.h \
searpc-server.h searpc-signature.h searpc-utils.h
noinst_HEADERS = searpc-utils.h fcall-impr.h marshal.h
noinst_HEADERS = searpc-utils.h marshal.h
libsearpc_la_SOURCES = searpc-client.c searpc-server.c $(generated_sources)
libsearpc_la_LDFLAGS = -version-info 1:1:0 -no-undefined
libsearpc_la_LDFLAGS = -version-info 1:2:0 -no-undefined
libsearpc_la_LIBADD = @GLIB_LIBS@ \
${top_builddir}/json-glib/json-glib/libsearpc-json-glib.la
@ -50,9 +49,6 @@ gensource: ${generated_sources}
${generated_sources}: gencode.py rpc_table.py
@echo "[libsearpc]: generating rpc header files"
python gencode.py gen-fcall > fcall-impr.h
python gencode.py gen-fcall-declare > searpc-fcall.h
python gencode.py gen-dfun-macro > searpc-dfun.h
python gencode.py gen-signature > searpc-signature.h
python gencode.py gen-marshal > marshal.h
@echo "[libsearpc]: done"

View File

@ -169,219 +169,6 @@ def gen_signature_list():
print generate_signature(item[0], item[1])
fcall_template = r"""
char*
searpc_client_fcall__${suffix} (const char* fname, ${args})
{
JsonArray *array;
g_return_val_if_fail (fname != NULL, NULL);
array = json_array_new ();
json_array_add_string_element (array, fname);
${args_to_array}
return fcall_common(array, len);
}
"""
def gen_fcall(arg_types):
if len(arg_types) == 0:
suffix = "void"
args = "gsize *len"
args_to_array = ""
return string.Template(fcall_template).substitute(suffix=suffix,
args=args, args_to_array=args_to_array)
suffix = "_".join(arg_types)
args = ""
args_to_array = ""
for i, arg_type in enumerate(arg_types):
args += type_table[arg_type][0] + " param" + str(i+1) + ", "
args_to_array += " " + type_table[arg_type][4] + " (array, param" + str(i+1) +");\n"
args += "gsize *len"
return string.Template(fcall_template).substitute(suffix=suffix,
args=args, args_to_array=args_to_array)
def gen_fcall_list():
from rpc_table import func_table
arg_types_list = []
for item in func_table:
if item[1] not in arg_types_list:
arg_types_list.append(item[1])
for item in arg_types_list:
print gen_fcall(item)
fcall_declare_template = r"""
char* searpc_client_fcall__${suffix} (const char* fname, ${args});
"""
def gen_fcall_declare(arg_types):
if len(arg_types) == 0:
suffix = "void"
args = "gsize *len"
return string.Template(fcall_declare_template).substitute(suffix=suffix,
args=args)
suffix = "_".join(arg_types)
args = ""
for i, arg_type in enumerate(arg_types):
args += type_table[arg_type][0] + " param" + str(i+1) + ", "
args += "gsize *len"
return string.Template(fcall_declare_template).substitute(suffix=suffix,
args=args)
def gen_fcall_declare_list():
from rpc_table import func_table
arg_types_list = []
for item in func_table:
if item[1] not in arg_types_list:
arg_types_list.append(item[1])
for item in arg_types_list:
print gen_fcall_declare(item)
dfun_template_with_gtype = r"""
#define SEARPC_CLIENT_DEFUN_${RET_TYPE}__${ARG_TYPES}(funcname, gtype) \
static ${ret_type_in_c} \
funcname (SearpcClient *client, ${args}) \
{ \
char *fcall, *fret; \
size_t fcall_len, ret_len; \
${ret_type_in_c} result; \
\
fcall = searpc_client_fcall__${arg_types} (#funcname, \
${fcall_args}); \
fret = searpc_client_transport_send (client, \
fcall, \
fcall_len, \
&ret_len); \
if (!fret) { \
g_free (fcall); \
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR); \
return ${default_value}; \
} \
result = searpc_client_fret__${ret_type} (gtype, fret, ret_len, error); \
\
g_free (fcall); \
g_free (fret); \
return result; \
}
"""
dfun_template_without_gtype = r"""
#define SEARPC_CLIENT_DEFUN_${RET_TYPE}__${ARG_TYPES}(funcname) \
static ${ret_type_in_c} \
funcname (SearpcClient *client, ${args}) \
{ \
char *fcall, *fret; \
size_t fcall_len, ret_len; \
${ret_type_in_c} result; \
\
fcall = searpc_client_fcall__${arg_types} (#funcname, \
${fcall_args}); \
fret = searpc_client_transport_send (client, \
fcall, \
fcall_len, \
&ret_len); \
if (!fret) { \
g_free (fcall); \
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR); \
return ${default_value}; \
} \
result = searpc_client_fret__${ret_type} (fret, ret_len, error); \
\
g_free (fcall); \
g_free (fret); \
return result; \
}
"""
def gen_dfun_macro(ret_type, arg_types):
if ret_type in ['object', 'objlist']:
template = string.Template(dfun_template_with_gtype)
else:
template = string.Template(dfun_template_without_gtype)
if len(arg_types) == 0:
arg_types_str = "void"
else:
arg_types_str = "_".join(arg_types)
args = ""
for i, arg_type in enumerate(arg_types):
args += type_table[arg_type][0] + " param" + str(i+1) + ", "
args += "GError **error"
fcall_args = ""
for i, arg_type in enumerate(arg_types):
fcall_args += " param" + str(i+1) + ", "
fcall_args += "&fcall_len"
default_value = type_table[ret_type][5]
ret_type_in_c = type_table[ret_type][1]
return template.substitute(ret_type=ret_type, RET_TYPE=ret_type.upper(),
ret_type_in_c=ret_type_in_c,
arg_types=arg_types_str, ARG_TYPES=arg_types_str.upper(),
args=args, fcall_args=fcall_args,
default_value=default_value)
def gen_dfun_macro_list():
from rpc_table import func_table
for item in func_table:
print gen_dfun_macro(item[0], item[1])
async_dfun_template = r"""
#define SEARPC_CLIENT_ASYNC_DEFUN_${RET_TYPE}__${ARG_TYPES}(funcname, gtype) \
static int \
funcname##_async (SearpcClient *client, ${args} \
AsyncCallback callback, void *user_data) \
{ \
char *fcall; \
size_t fcall_len; \
\
fcall = searpc_client_fcall__${arg_types} (#funcname, \
${fcall_args}); \
return searpc_client_async_call (client, fcall, \
fcall_len, callback, "${ret_type}", \
gtype, user_data); \
}
"""
def gen_async_dfun_macro(ret_type, arg_types):
template = string.Template(async_dfun_template)
if len(arg_types) == 0:
arg_types_str = "void"
else:
arg_types_str = "_".join(arg_types)
args = ""
for i, arg_type in enumerate(arg_types):
args += type_table[arg_type][0] + " param" + str(i+1) + ", "
fcall_args = ""
for i, arg_type in enumerate(arg_types):
fcall_args += " param" + str(i+1) + ", "
fcall_args += "&fcall_len"
return template.substitute(ret_type=ret_type, RET_TYPE=ret_type.upper(),
arg_types=arg_types_str,
ARG_TYPES=arg_types_str.upper(),
args=args, fcall_args=fcall_args)
def gen_async_dfun_macro_list():
from rpc_table import func_table
for item in func_table:
print gen_async_dfun_macro(item[0], item[1])
if __name__ == "__main__":
command = sys.argv[1]
if command == "gen-marshal":
@ -389,12 +176,5 @@ if __name__ == "__main__":
gen_marshal_register_function()
elif command == "gen-signature":
gen_signature_list()
elif command == "gen-fcall":
gen_fcall_list()
elif command == "gen-fcall-declare":
gen_fcall_declare_list()
elif command == "gen-dfun-macro":
gen_dfun_macro_list()
gen_async_dfun_macro_list()
else:
print "Unknown command %s" % (command)

View File

@ -17,8 +17,6 @@ func_table = [
[ "int", ["string", "string", "string"] ],
[ "int", ["string", "string", "int", "int"] ],
[ "int", ["string", "string", "string", "string"]],
[ "int64", [] ],
[ "int64", ["string"] ],
[ "string", [] ],
[ "string", ["int"] ],
[ "string", ["string"] ],

View File

@ -32,11 +32,258 @@ searpc_client_transport_send (SearpcClient *client,
fcall_len, ret_len);
}
static char *
fcall_to_str (const char *fname, int n_params, va_list args, gsize *len)
{
JsonArray *array;
array = json_array_new ();
json_array_add_string_element (array, fname);
int i = 0;
for (; i < n_params; i++) {
const char *type = va_arg(args, const char *);
void *value = va_arg(args, void *);
if (strcmp(type, "int") == 0)
json_array_add_int_element (array, (int)value);
else if (strcmp(type, "string") == 0)
json_array_add_string_or_null_element (array, (char *)value);
else {
g_warning ("unrecognized parameter type %s\n", type);
return NULL;
}
}
gchar *data;
JsonGenerator *gen = json_generator_new ();
JsonNode *root;
root = json_node_new (JSON_NODE_ARRAY);
json_node_take_array (root, array);
json_generator_set_root (gen, root);
g_object_set (gen, "pretty", FALSE, NULL);
data = json_generator_to_data (gen, len);
json_node_free (root);
g_object_unref (gen);
return data;
}
void
searpc_client_call (SearpcClient *client, const char *fname,
const char *ret_type, int gobject_type,
void *ret_ptr, GError **error,
int n_params, ...)
{
g_return_if_fail (fname != NULL);
g_return_if_fail (ret_type != NULL);
va_list args;
gsize len, ret_len;
char *fstr;
va_start (args, n_params);
fstr = fcall_to_str (fname, n_params, args, &len);
va_end (args);
if (!fstr) {
g_set_error (error, DFT_DOMAIN, 0, "Invalid Parameter");
return;
}
char *fret = searpc_client_transport_send (client, fstr, len, &ret_len);
if (!fret) {
g_free (fstr);
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR);
return;
}
if (strcmp(ret_type, "int") == 0)
*((int *)ret_ptr) = searpc_client_fret__int (fret, ret_len, error);
else if (strcmp(ret_type, "int64") == 0)
*((gint64 *)ret_ptr) = searpc_client_fret__int64 (fret, ret_len, error);
else if (strcmp(ret_type, "string") == 0)
*((char **)ret_ptr) = searpc_client_fret__string (fret, len, error);
else if (strcmp(ret_type, "object") == 0)
*((GObject **)ret_ptr) = searpc_client_fret__object (gobject_type, fret,
ret_len, error);
else if (strcmp(ret_type, "objlist") == 0)
*((GList **)ret_ptr) = searpc_client_fret__objlist (gobject_type, fret,
ret_len, error);
else
g_warning ("unrecognized return type %s\n", ret_type);
g_free (fstr);
g_free (fret);
}
int
searpc_client_call__int (SearpcClient *client, const char *fname,
GError **error, int n_params, ...)
{
g_return_val_if_fail (fname != NULL, 0);
va_list args;
gsize len, ret_len;
char *fstr;
va_start (args, n_params);
fstr = fcall_to_str (fname, n_params, args, &len);
va_end (args);
if (!fstr) {
g_set_error (error, DFT_DOMAIN, 0, "Invalid Parameter");
return 0;
}
char *fret = searpc_client_transport_send (client, fstr, len, &ret_len);
if (!fret) {
g_free (fstr);
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR);
return 0;
}
int ret = searpc_client_fret__int (fret, ret_len, error);
g_free (fstr);
g_free (fret);
return ret;
}
gint64
searpc_client_call__int64 (SearpcClient *client, const char *fname,
GError **error, int n_params, ...)
{
g_return_val_if_fail (fname != NULL, 0);
va_list args;
gsize len, ret_len;
char *fstr;
va_start (args, n_params);
fstr = fcall_to_str (fname, n_params, args, &len);
va_end (args);
if (!fstr) {
g_set_error (error, DFT_DOMAIN, 0, "Invalid Parameter");
return 0;
}
char *fret = searpc_client_transport_send (client, fstr, len, &ret_len);
if (!fret) {
g_free (fstr);
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR);
return 0;
}
gint64 ret = searpc_client_fret__int64 (fret, ret_len, error);
g_free (fstr);
g_free (fret);
return ret;
}
char *
searpc_client_call__string (SearpcClient *client, const char *fname,
GError **error, int n_params, ...)
{
g_return_val_if_fail (fname != NULL, NULL);
va_list args;
gsize len, ret_len;
char *fstr;
va_start (args, n_params);
fstr = fcall_to_str (fname, n_params, args, &len);
va_end (args);
if (!fstr) {
g_set_error (error, DFT_DOMAIN, 0, "Invalid Parameter");
return NULL;
}
char *fret = searpc_client_transport_send (client, fstr, len, &ret_len);
if (!fret) {
g_free (fstr);
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR);
return NULL;
}
char *ret = searpc_client_fret__string (fret, ret_len, error);
g_free (fstr);
g_free (fret);
return ret;
}
GObject *
searpc_client_call__object (SearpcClient *client, const char *fname,
int object_type,
GError **error, int n_params, ...)
{
g_return_val_if_fail (fname != NULL, NULL);
g_return_val_if_fail (object_type != 0, NULL);
va_list args;
gsize len, ret_len;
char *fstr;
va_start (args, n_params);
fstr = fcall_to_str (fname, n_params, args, &len);
va_end (args);
if (!fstr) {
g_set_error (error, DFT_DOMAIN, 0, "Invalid Parameter");
return NULL;
}
char *fret = searpc_client_transport_send (client, fstr, len, &ret_len);
if (!fret) {
g_free (fstr);
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR);
return NULL;
}
GObject *ret = searpc_client_fret__object (object_type, fret, ret_len, error);
g_free (fstr);
g_free (fret);
return ret;
}
GList*
searpc_client_call__objlist (SearpcClient *client, const char *fname,
int object_type,
GError **error, int n_params, ...)
{
g_return_val_if_fail (fname != NULL, NULL);
g_return_val_if_fail (object_type != 0, NULL);
va_list args;
gsize len, ret_len;
char *fstr;
va_start (args, n_params);
fstr = fcall_to_str (fname, n_params, args, &len);
va_end (args);
if (!fstr) {
g_set_error (error, DFT_DOMAIN, 0, "Invalid Parameter");
return NULL;
}
char *fret = searpc_client_transport_send (client, fstr, len, &ret_len);
if (!fret) {
g_free (fstr);
g_set_error (error, DFT_DOMAIN, TRANSPORT_ERROR_CODE, TRANSPORT_ERROR);
return NULL;
}
GList *ret = searpc_client_fret__objlist (object_type, fret, ret_len, error);
g_free (fstr);
g_free (fret);
return ret;
}
typedef struct {
SearpcClient *client;
AsyncCallback callback;
const gchar *ret_type;
int gtype;
int gtype; /* to specify the specific gobject type
if ret_type is object or objlist */
void *cbdata;
} AsyncCallData;
@ -77,15 +324,24 @@ searpc_client_generic_callback (char *retstr, size_t len,
g_free (data);
}
int
searpc_client_async_call (SearpcClient *client,
gchar *fcall_str,
size_t fcall_len,
AsyncCallback callback,
const gchar *ret_type,
int gtype,
void *cbdata)
searpc_client_async_call_v (SearpcClient *client,
const char *fname,
AsyncCallback callback,
const gchar *ret_type,
int gtype,
void *cbdata,
int n_params,
va_list args)
{
gsize len, ret_len;
char *fstr;
fstr = fcall_to_str (fname, n_params, args, &len);
if (!fstr)
return -1;
int ret;
AsyncCallData *data = g_new0(AsyncCallData, 1);
data->client = client;
@ -94,7 +350,7 @@ searpc_client_async_call (SearpcClient *client,
data->gtype = gtype;
data->cbdata = cbdata;
ret = client->async_send (client->async_arg, fcall_str, fcall_len, data);
ret = client->async_send (client->async_arg, fstr, len, data);
if (ret < 0) {
g_free (data);
return -1;
@ -102,30 +358,99 @@ searpc_client_async_call (SearpcClient *client,
return 0;
}
/*
* serialize function call from array to string
*/
static char *
fcall_common (JsonArray *array, gsize *len)
int
searpc_client_async_call__int (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...)
{
gchar *data;
JsonGenerator *gen = json_generator_new ();
JsonNode *root;
g_return_val_if_fail (fname != NULL, -1);
root = json_node_new (JSON_NODE_ARRAY);
json_node_take_array (root, array);
json_generator_set_root (gen, root);
va_list args;
int ret;
g_object_set (gen, "pretty", FALSE, NULL);
data = json_generator_to_data (gen, len);
json_node_free (root);
g_object_unref (gen);
return data;
va_start (args, n_params);
ret = searpc_client_async_call_v (client, fname, callback, "int", 0, cbdata,
n_params, args);
va_end (args);
return ret;
}
#include "fcall-impr.h"
int
searpc_client_async_call__int64 (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...)
{
g_return_val_if_fail (fname != NULL, -1);
va_list args;
int ret;
va_start (args, n_params);
ret = searpc_client_async_call_v (client, fname, callback, "int64", 0, cbdata,
n_params, args);
va_end (args);
return ret;
}
int
searpc_client_async_call__string (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...)
{
g_return_val_if_fail (fname != NULL, -1);
va_list args;
int ret;
va_start (args, n_params);
ret = searpc_client_async_call_v (client, fname, callback, "string", 0, cbdata,
n_params, args);
va_end (args);
return ret;
}
int
searpc_client_async_call__object (SearpcClient *client,
const char *fname,
AsyncCallback callback,
int object_type, void *cbdata,
int n_params, ...)
{
g_return_val_if_fail (fname != NULL, -1);
va_list args;
int ret;
va_start (args, n_params);
ret = searpc_client_async_call_v (client, fname, callback, "object",
object_type, cbdata,
n_params, args);
va_end (args);
return ret;
}
int
searpc_client_async_call__objlist (SearpcClient *client,
const char *fname,
AsyncCallback callback,
int object_type, void *cbdata,
int n_params, ...)
{
g_return_val_if_fail (fname != NULL, -1);
va_list args;
int ret;
va_start (args, n_params);
ret = searpc_client_async_call_v (client, fname, callback, "objlist",
object_type, cbdata,
n_params, args);
va_end (args);
return ret;
}
/*

View File

@ -34,28 +34,74 @@ SearpcClient *searpc_client_new ();
void searpc_client_free (SearpcClient *client);
void
searpc_client_call (SearpcClient *client, const char *fname,
const char *ret_type, int gobject_type,
void *ret_ptr, GError **error,
int n_params, ...);
int
searpc_client_call__int (SearpcClient *client, const char *fname,
GError **error, int n_params, ...);
gint64
searpc_client_call__int64 (SearpcClient *client, const char *fname,
GError **error, int n_params, ...);
char *
searpc_client_call__string (SearpcClient *client, const char *fname,
GError **error, int n_params, ...);
GObject *
searpc_client_call__object (SearpcClient *client, const char *fname,
int object_type,
GError **error, int n_params, ...);
GList*
searpc_client_call__objlist (SearpcClient *client, const char *fname,
int object_type,
GError **error, int n_params, ...);
char* searpc_client_transport_send (SearpcClient *client,
const gchar *fcall_str,
size_t fcall_len,
size_t *ret_len);
/**
* Send the serialized function call to server.
*
* @fcall_str: the serialized function.
* @ret_type: the return type.
* @gtype: specify the type id if @ret_type is `object` or `objlist`,
* or 0 otherwise.
* @cbdata: the data that will be given to the callback.
*/
int searpc_client_async_call (SearpcClient *client,
gchar *fcall_str,
size_t fcall_len,
AsyncCallback callback,
const gchar *ret_type,
int gtype,
void *cbdata);
int
searpc_client_async_call__int (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...);
int
searpc_client_async_call__int64 (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...);
int
searpc_client_async_call__string (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...);
int
searpc_client_async_call__object (SearpcClient *client,
const char *fname,
AsyncCallback callback,
int object_type, void *cbdata,
int n_params, ...);
int
searpc_client_async_call__objlist (SearpcClient *client,
const char *fname,
AsyncCallback callback,
int object_type, void *cbdata,
int n_params, ...);
/* called by the transport layer, the rpc layer should be able to
* modify the str, but not take ownership of it */
@ -65,7 +111,6 @@ searpc_client_generic_callback (char *retstr, size_t len,
#include <searpc-fcall.h>
char*
searpc_client_fret__string (char *data, size_t len, GError **error);
@ -88,7 +133,5 @@ searpc_client_fret__objlist (GType gtype, char *data,
#define TRANSPORT_ERROR "Transport Error"
#define TRANSPORT_ERROR_CODE 500
#include <searpc-dfun.h>
#endif

View File

@ -158,6 +158,29 @@ marshal_set_ret_common (JsonObject *object, gsize *len, GError *error)
return data;
}
static gchar *
error_to_json (int code, const char *msg, gsize *len)
{
JsonObject *object = json_object_new ();
JsonNode *root = json_node_new (JSON_NODE_OBJECT);
JsonGenerator *generator = json_generator_new ();
gchar *data;
json_object_set_int_member (object, "err_code", code);
json_object_set_string_or_null_member (object, "err_msg", msg);
json_node_take_object (root, object);
json_generator_set_root (generator, root);
g_object_set (generator, "pretty", FALSE, NULL);
data = json_generator_to_data (generator, len);
json_node_free (root);
g_object_unref (generator);
return data;
}
/* include the generated marshal functions */
#include "marshal.h"
@ -235,33 +258,34 @@ searpc_server_register_function (const char *svc_name,
/* Called by RPC transport. */
gchar*
searpc_server_call_function (const char *svc_name,
gchar *func, gsize len, gsize *ret_len, GError **error)
gchar *func, gsize len, gsize *ret_len)
{
SearpcService *service;
JsonParser *parser;
JsonNode *root;
JsonArray *array;
gchar* ret;
GError *error = NULL;
#ifdef PROFILE
struct timeval start, end, intv;
gettimeofday(&start, NULL);
#endif
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
service = g_hash_table_lookup (service_table, svc_name);
if (!service) {
g_warning ("[SeaRPC] cannot find service %s.\n", svc_name);
g_set_error (error, DFT_DOMAIN, 501, "cannot find service %s.", svc_name);
return NULL;
char buf[256];
snprintf (buf, 255, "cannot find service %s.", svc_name);
return error_to_json (501, buf, ret_len);
}
parser = json_parser_new ();
if (!json_parser_load_from_data (parser, func, len, error)) {
g_warning ("[SeaRPC] failed to parse RPC call: %s\n", (*error)->message);
g_object_unref (parser);
return NULL;
if (!json_parser_load_from_data (parser, func, len, &error)) {
char buf[512];
snprintf (buf, 511, "failed to parse RPC call: %s\n", error->message);
g_object_unref (parser);
return error_to_json (511, buf, ret_len);
}
root = json_parser_get_root (parser);
@ -270,12 +294,13 @@ searpc_server_call_function (const char *svc_name,
const char *fname = json_array_get_string_element(array, 0);
FuncItem *fitem = g_hash_table_lookup(service->func_table, fname);
if (!fitem) {
g_warning ("[SeaRPC] cannot find function %s.\n", fname);
g_set_error (error, DFT_DOMAIN, 500, "cannot find function %s.", fname);
return NULL;
char buf[256];
snprintf (buf, 255, "cannot find function %s.", fname);
g_object_unref (parser);
return error_to_json (500, buf, ret_len);
}
gchar* ret = fitem->marshal->mfunc (fitem->func, array, ret_len);
ret = fitem->marshal->mfunc (fitem->func, array, ret_len);
#ifdef PROFILE
gettimeofday(&end, NULL);

View File

@ -78,8 +78,7 @@ gboolean searpc_server_register_function (const char *service,
* Returns the serialized representatio of the returned value.
*/
gchar *searpc_server_call_function (const char *service,
gchar *func, gsize len, gsize *ret_len,
GError **error);
gchar *func, gsize len, gsize *ret_len);
/**
* searpc_compute_signature:

View File

@ -1,33 +1,5 @@
genrpc_files = pygencode.py rpc_table.py
AM_CFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" \
-DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \
@GLIB_CFLAGS@ \
-I/usr/include/python$(PYTHON_VERSION) \
-I${top_builddir}/lib \
-I${top_srcdir}/lib
pysearpcdir=${pyexecdir}/pysearpc
pysearpc_PYTHON = __init__.py client.py
BUILT_SOURCES = fcallfret.h
# generating the fcallfret module
pysearpc_LTLIBRARIES = fcallfret.la
fcallfret_la_LDFLAGS = -module -avoid-version -export-symbols-regex initfcallfret -no-undefined @SERVER_PKG_RPATH@
fcallfret_la_SOURCES = fcallfret.c fcallfret.h
fcallfret_la_LIBADD = @GLIB_LIBS@ $(top_builddir)/lib/libsearpc.la @LIB_PYTHON@
EXTRA_DIST = ${genrpc_files}
fcallfret.h: ${genrpc_files}
python pygencode.py > fcallfret.h
rpc_table.py: ../lib/rpc_table.py
cp -f ../lib/rpc_table.py .
DISTCLEANFILES = fcallfret.h rpc_table.py

View File

@ -1,4 +1,3 @@
import fcallfret
import simplejson as json
class SearpcError(Exception):
@ -9,6 +8,31 @@ class SearpcError(Exception):
def __str__(self):
return self.msg
def _fret_int(ret_str):
try:
dicts = json.loads(ret_str)
except:
raise SearpcError('Invalid response format')
if dicts.has_key('err_code'):
raise SearpcError(dicts['err_msg'])
if dicts['ret']:
return dicts['ret']
def _fret_string(ret_str):
try:
dicts = json.loads(ret_str)
except:
raise SearpcError('Invalid response format')
if dicts.has_key('err_code'):
raise SearpcError(dicts['err_msg'])
if dicts['ret']:
return dicts['ret']
class _SearpcObj(object):
'''A compact class to emulate gobject.GObject
'''
@ -59,40 +83,33 @@ def _fret_objlist(ret_str):
return l
def searpc_func(ret_type, param_types):
def decorate(func):
if len(param_types) == 0:
fcall = getattr(fcallfret, 'fcall__void')
else:
fcall = getattr(fcallfret, 'fcall__' + '_'.join(param_types))
if ret_type == "void":
fret = None
elif ret_type == "object":
fret = _fret_obj
elif ret_type == "objlist":
fret = _fret_objlist
elif ret_type == "int":
fret = _fret_int
elif ret_type == "int64":
fret = _fret_int
elif ret_type == "string":
fret = _fret_string
else:
fret = getattr(fcallfret, 'fret__' + ret_type)
raise SearpcError('Invial return type')
def newfunc(self, *args):
fcall_str = fcall(func.__name__, *args)
array = [func.__name__] + list(args)
fcall_str = json.dumps(array)
ret_str = self.call_remote_func_sync(fcall_str)
if fret:
try:
return fret(ret_str)
except fcallfret.error, e:
raise SearpcError(str(e))
return fret(ret_str)
def newfunc_obj(self, *args):
fcall_str = fcall(func.__name__, *args)
ret_str = self.call_remote_func_sync(fcall_str)
return fret(ret_str)
if ret_type == "objlist" or ret_type == "object":
return newfunc_obj
else:
return newfunc
return newfunc
return decorate

View File

@ -10,6 +10,7 @@
#include "searpc-client.h"
/* sample class */
#define MAMAN_TYPE_BAR (maman_bar_get_type ())
#define MAMAN_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
@ -58,12 +59,10 @@ maman_bar_set_property (GObject *object,
case PROP_MAMAN_NAME:
g_free (self->name);
self->name = g_value_dup_string (value);
g_print ("maman: %s\n", self->name);
break;
case PROP_PAPA_NUMBER:
self->papa_number = g_value_get_uchar (value);
g_print ("papa: %u\n", self->papa_number);
break;
default:
@ -145,13 +144,30 @@ maman_bar_init (MamanBar *self)
}
/* test function define macro */
SEARPC_CLIENT_DEFUN_INT__STRING(func4);
SEARPC_CLIENT_DEFUN_INT__STRING_STRING(func1);
SEARPC_CLIENT_DEFUN_STRING__VOID(func0);
SEARPC_CLIENT_DEFUN_OBJECT__STRING(func2, 0);
SEARPC_CLIENT_DEFUN_OBJLIST__STRING_INT(func3, 0);
/* sample client */
SearpcClient *client;
char *
sample_transport(void *arg, const gchar *fcall_str,
size_t fcall_len, size_t *ret_len)
{
g_assert (strcmp(arg, "test") == 0);
char *ret;
/* directly call in memory, instead of send via network */
gchar *temp = g_strdup(fcall_str);
ret = searpc_server_call_function ("test", temp, fcall_len, ret_len);
g_free (temp);
return ret;
}
void
init_sample_client ()
{
client = searpc_client_new();
client->transport = sample_transport;
client->arg = "test";
}
gchar *
get_substring (const gchar *orig_str, int sub_len, GError **error)
@ -168,32 +184,35 @@ get_substring (const gchar *orig_str, int sub_len, GError **error)
}
void test_simple_call (void *fixture, const void *data)
{
gchar* result;
GError *error = NULL;
result = searpc_client_call__string (client, "get_substring", &error,
2, "string", "hello", "int", 2);
g_assert (error == NULL);
g_assert (strcmp(result, "he") == 0);
g_free (result);
/* error should return */
result = NULL;
result = searpc_client_call__string (client, "get_substring", &error,
2, "string", "hello", "int", 10);
g_assert (error->message);
g_free (result);
}
void
test_invalid_call (void *fixture, const void *data)
{
char *fcall, *fret;
gsize fcall_len, ret_len;
gchar* result;
GError *error = NULL;
fcall = searpc_client_fcall__string_int ("get_substring", "hello", 2,
&fcall_len);
fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error);
g_assert (error == NULL);
result = searpc_client_fret__string (fret, ret_len, &error);
g_assert (strcmp(result, "he") == 0);
g_free (fcall);
g_free (fret);
g_free (result);
/* error should return */
result = NULL;
fcall = searpc_client_fcall__string_int ("get_substring", "hello", 7,
&fcall_len);
fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error);
g_assert (error == NULL);
result = searpc_client_fret__string (fret, ret_len, &error);
g_assert (error->message);
g_free (fcall);
g_free (fret);
result = searpc_client_call__string (client, "nonexist_func", &error,
2, "string", "hello", "int", 2);
g_assert (error != NULL);
g_free (result);
}
@ -205,23 +224,16 @@ get_maman_bar(const char *name, GError **error)
void test_object_call (void *fixture, const void *data)
{
char *fcall, *fret;
gsize fcall_len, ret_len;
GObject *result;
GError *error = NULL;
fcall = searpc_client_fcall__string ("get_maman_bar", "kitty",
&fcall_len);
fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error);
result = searpc_client_call__object (client, "get_maman_bar",
MAMAN_TYPE_BAR, &error,
1, "string", "kitty");
g_assert (error == NULL);
result = searpc_client_fret__object (MAMAN_TYPE_BAR, fret, ret_len, &error);
g_free (fcall);
g_free (fret);
g_object_unref (result);
}
GList *
get_maman_bar_list (const char *name, int num, GError **error)
{
@ -251,30 +263,22 @@ get_maman_bar_list (const char *name, int num, GError **error)
void test_objlist_call (void *fixture, const void *data)
{
char *fcall, *fret;
gsize fcall_len, ret_len;
GList *result, *ptr;
GError *error = NULL;
fcall = searpc_client_fcall__string_int ("get_maman_bar_list", "kitty", 10,
&fcall_len);
fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error);
result = searpc_client_call__objlist (client, "get_maman_bar_list",
MAMAN_TYPE_BAR, &error,
2, "string", "kitty", "int", 10);
g_assert (error == NULL);
result = searpc_client_fret__objlist (MAMAN_TYPE_BAR, fret, ret_len, &error);
g_free (fcall);
g_free (fret);
for (ptr = result; ptr; ptr = ptr->next)
g_object_unref (ptr->data);
g_list_free (result);
fcall = searpc_client_fcall__string_int ("get_maman_bar_list", "kitty", 0,
&fcall_len);
fret = searpc_server_call_function ("test", fcall, fcall_len, &ret_len, &error);
result = searpc_client_call__objlist (client, "get_maman_bar_list",
MAMAN_TYPE_BAR, &error,
2, "string", "kitty", "int", 0);
g_assert (error == NULL);
result = searpc_client_fret__objlist (MAMAN_TYPE_BAR, fret, ret_len, &error);
g_free (fcall);
g_free (fret);
for (ptr = result; ptr; ptr = ptr->next)
g_object_unref (ptr->data);
g_list_free (result);
@ -296,6 +300,9 @@ main (int argc, char *argv[])
searpc_server_register_function ("test", get_maman_bar_list, "get_maman_bar_list",
searpc_signature_objlist__string_int());
/* sample client */
init_sample_client();
g_test_add ("/searpc/simple", void, NULL,
NULL, test_simple_call, NULL);
@ -303,6 +310,9 @@ main (int argc, char *argv[])
g_test_add ("/searpc/simple2", void, NULL,
NULL, test_simple_call, NULL);
g_test_add ("/searpc/invalid_call", void, NULL,
NULL, test_invalid_call, NULL);
g_test_add ("/searpc/object", void, NULL,
NULL, test_object_call, NULL);

View File

@ -1,22 +1,17 @@
import sys
sys.path += ['..', '../pysearpc/.libs']
sys.path += ['..']
from pysearpc import SearpcClient, searpc_func, SearpcError
import fcallfret
class SampleRpcClient(SearpcClient):
def call_remote_func_sync(self, fcall_str):
return ""
@searpc_func("void", ["string"])
@searpc_func("void", ["string", "int"])
def list_peers(self):
pass
fcallfret.fcall__string("list", "hello")
client = SampleRpcClient()
client.list_peers("10")
client.list_peers("id", 10)