1
0
mirror of https://github.com/haiwen/libsearpc.git synced 2025-08-22 14:15:51 +00:00

Compare commits

..

No commits in common. "master" and "v3.1.0" have entirely different histories.

32 changed files with 218 additions and 950 deletions

View File

@ -1,9 +1,5 @@
sudo: false
language: python
python:
- "2.7"
- "3.5"
- "3.6"
compiler:
- gcc
- clang
@ -11,8 +7,6 @@ addons:
apt:
packages:
- libjansson-dev
install:
- pip install future
before_install:
- git clean -x -f
- ./autogen.sh

View File

@ -18,5 +18,12 @@ endif
SUBDIRS = lib pysearpc ${MAKE_DEMO} tests
install-data-local:
if MACOS
sed -i '' -e "s|(DESTDIR)|${DESTDIR}|g" $(pcfiles)
else
${SED} -i "s|(DESTDIR)|${DESTDIR}|g" $(pcfiles)
endif
dist-hook:
git log -1 > $(distdir)/latest_commit

View File

@ -42,15 +42,6 @@ AC_ARG_ENABLE(server-pkg,
AC_HELP_STRING([--enable-server-pkg], [enable static compile]),
[server_pkg=$enableval],[server_pkg="no"])
# option: compile-universal
# default: no
AC_ARG_ENABLE([compile-universal],
[AS_HELP_STRING([--enable-compile-universal],
[compile seafile universal @<:@default: no@:>@])],
[compile_universal=${enableval}], [compile_universal=no])
AM_CONDITIONAL([COMPILE_UNIVERSAL], [test x${compile_universal} = xyes])
dnl - check if the macro WIN32 is defined on this compiler.
AC_MSG_CHECKING(for WIN32)
@ -78,23 +69,6 @@ fi
AM_CONDITIONAL([MACOS], [test "$bmac" = "yes"])
AC_SUBST(MACOS)
AC_MSG_CHECKING(for FreeBSD)
if test "$(uname -s)" = "FreeBSD"; then
bfbsd=yes
fi
if test x$bfbsd = "xyes"; then
server_pkg=no
AC_MSG_RESULT(compile in FreeBSD)
fi
AM_CONDITIONAL([FBSD], [test "$bfbsd" = "yes"])
AC_SUBST(FBSD)
AC_ARG_WITH([python3], [AS_HELP_STRING([--with-python3], [use python3])],
[with_python3="yes"],[])
# Checks for libraries.
GLIB_REQUIRED=2.26.0
@ -110,12 +84,7 @@ PKG_CHECK_MODULES(JANSSON, [jansson >= $JANSSON_REQUIRED])
AC_SUBST(JANSSON_CFLAGS)
AC_SUBST(JANSSON_LIBS)
if test "$with_python3" = "yes"; then
AM_PATH_PYTHON([3.5])
else
AM_PATH_PYTHON([2.7])
fi
AM_PATH_PYTHON([2.4])
if test "$bwin32" = true; then
if test x$PYTHON_DIR != x; then
# set pyexecdir to somewhere like /c/Python26/Lib/site-packages

6
debian/changelog vendored
View File

@ -1,9 +1,3 @@
libsearpc1 (3.2.0) unstable; urgency=low
* new upstream release
-- Jonathan Xu <jonathan.xu@seafile.com> Thu, 24 Oct 2019 11:05:10 +0800
libsearpc1 (3.1.0) unstable; urgency=low
* new upstream release

7
debian/control vendored
View File

@ -4,11 +4,10 @@ Priority: extra
Maintainer: m.eik michalke <meik.michalke@hhu.de>
Build-Depends:
debhelper (>= 7),
dh-python,
autotools-dev,
intltool,
libglib2.0-dev,
python3 (>= 3.5),
python,
libtool,
libjansson-dev
Standards-Version: 3.9.5
@ -31,7 +30,7 @@ Section: libdevel
Architecture: any
Depends:
${misc:Depends},
python3 (>= 3.5),
python (>= 2.7),
libsearpc1 (= ${binary:Version})
Conflicts: seafile
Description: Development files for the libsearpc1 package.
@ -50,7 +49,7 @@ Package: python-searpc
Section: python
Multi-Arch: foreign
Architecture: all
Depends: ${python3:Depends},
Depends: ${python:Depends},
${shlibs:Depends},
${misc:Depends}
Description: simple and easy-to-use C language RPC framework

View File

@ -1 +1 @@
usr/lib/python3*/site-packages/pysearpc/*.py usr/lib/python3/dist-packages/pysearpc
usr/lib/python*/dist-packages/pysearpc/*.py

4
debian/rules vendored
View File

@ -2,11 +2,11 @@
# -*- makefile -*-
%:
dh $@ --with python3 --with autotools_dev --builddirectory=build
dh $@ --with python2 --with autotools_dev --builddirectory=build
override_dh_auto_configure:
./autogen.sh
dh_auto_configure -- --disable-compile-demo --with-python3
dh_auto_configure -- --disable-compile-demo
override_dh_strip:
# emptying the dependency_libs field in .la files

View File

@ -4,7 +4,6 @@
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#ifdef WIN32

View File

@ -4,8 +4,6 @@
#include <glib.h>
#include <glib-object.h>
GType test_object_get_type (void);
#define TEST_OBJECT_TYPE (test_object_get_type())
#define TEST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_OBJECT_TYPE, TestObject))
#define IS_TEST_OBJCET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_OBJCET_TYPE))

View File

@ -2,13 +2,8 @@
AM_CFLAGS = @GLIB_CFLAGS@ \
@JANSSON_CFLAGS@ \
-I${top_builddir}/lib \
-I${top_srcdir}/lib
if MACOS
if COMPILE_UNIVERSAL
AM_CFLAGS += -arch x86_64 -arch arm64
endif
endif
-I${top_srcdir}/lib \
-DG_LOG_DOMAIN=\"Searpc\"
lib_LTLIBRARIES = libsearpc.la

View File

@ -36,7 +36,7 @@ static void clean_objlist(GList *list)
SearpcClient *
searpc_client_new (void)
searpc_client_new ()
{
return g_new0 (SearpcClient, 1);
}

View File

@ -5,16 +5,6 @@
#include <glib-object.h>
#include <jansson.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LIBSEARPC_EXPORTS
#define LIBSEARPC_API __declspec(dllexport)
#else
#define LIBSEARPC_API
#endif
#ifndef DFT_DOMAIN
#define DFT_DOMAIN g_quark_from_string(G_LOG_DOMAIN)
#endif
@ -41,88 +31,85 @@ struct _SearpcClient {
void *async_arg;
};
typedef struct _SearpcClient LIBSEARPC_API SearpcClient;
typedef struct _SearpcClient SearpcClient;
LIBSEARPC_API
SearpcClient *searpc_client_new (void);
SearpcClient *searpc_client_new ();
LIBSEARPC_API void
searpc_client_free (SearpcClient *client);
void searpc_client_free (SearpcClient *client);
LIBSEARPC_API void
void
searpc_client_call (SearpcClient *client, const char *fname,
const char *ret_type, GType gobject_type,
void *ret_ptr, GError **error,
int n_params, ...);
LIBSEARPC_API int
int
searpc_client_call__int (SearpcClient *client, const char *fname,
GError **error, int n_params, ...);
LIBSEARPC_API gint64
gint64
searpc_client_call__int64 (SearpcClient *client, const char *fname,
GError **error, int n_params, ...);
LIBSEARPC_API char *
char *
searpc_client_call__string (SearpcClient *client, const char *fname,
GError **error, int n_params, ...);
LIBSEARPC_API GObject *
GObject *
searpc_client_call__object (SearpcClient *client, const char *fname,
GType object_type,
GError **error, int n_params, ...);
LIBSEARPC_API GList*
GList*
searpc_client_call__objlist (SearpcClient *client, const char *fname,
GType object_type,
GError **error, int n_params, ...);
LIBSEARPC_API json_t *
json_t *
searpc_client_call__json (SearpcClient *client, const char *fname,
GError **error, int n_params, ...);
LIBSEARPC_API char*
searpc_client_transport_send (SearpcClient *client,
const gchar *fcall_str,
size_t fcall_len,
size_t *ret_len);
char* searpc_client_transport_send (SearpcClient *client,
const gchar *fcall_str,
size_t fcall_len,
size_t *ret_len);
LIBSEARPC_API int
int
searpc_client_async_call__int (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...);
LIBSEARPC_API int
int
searpc_client_async_call__int64 (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...);
LIBSEARPC_API int
int
searpc_client_async_call__string (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
int n_params, ...);
LIBSEARPC_API int
int
searpc_client_async_call__object (SearpcClient *client,
const char *fname,
AsyncCallback callback,
GType object_type, void *cbdata,
int n_params, ...);
LIBSEARPC_API int
int
searpc_client_async_call__objlist (SearpcClient *client,
const char *fname,
AsyncCallback callback,
GType object_type, void *cbdata,
int n_params, ...);
LIBSEARPC_API int
int
searpc_client_async_call__json (SearpcClient *client,
const char *fname,
AsyncCallback callback, void *cbdata,
@ -131,7 +118,7 @@ searpc_client_async_call__json (SearpcClient *client,
/* called by the transport layer, the rpc layer should be able to
* modify the str, but not take ownership of it */
LIBSEARPC_API int
int
searpc_client_generic_callback (char *retstr, size_t len,
void *vdata, const char *errstr);
@ -141,9 +128,5 @@ searpc_client_generic_callback (char *retstr, size_t len,
#define TRANSPORT_ERROR "Transport Error"
#define TRANSPORT_ERROR_CODE 500
#ifdef __cplusplus
}
#endif
#endif

View File

@ -139,7 +139,7 @@ def generate_marshal_register_item(ret_type, arg_types):
signature_name=signature_name)
def gen_marshal_register_function(f):
write_file(f, "static void register_marshals(void)""")
write_file(f, "static void register_marshals()""")
write_file(f, "{")
for item in func_table:
write_file(f, generate_marshal_register_item(item[0], item[1]))
@ -147,7 +147,7 @@ def gen_marshal_register_function(f):
signature_template = r"""
inline static gchar *
${signature_name}(void)
${signature_name}()
{
return searpc_compute_signature (${args});
}

View File

@ -8,13 +8,8 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#ifdef __linux__
#include <fcntl.h>
#include <sys/epoll.h>
#endif
#endif // !defined(WIN32)
#include <glib.h>
#include <glib/gstdio.h>
#include <jansson.h>
@ -37,9 +32,7 @@ static char* formatErrorMessage();
#endif // defined(WIN32)
static void* named_pipe_listen(void *arg);
static void* handle_named_pipe_client_with_thread (void *arg);
static void handle_named_pipe_client_with_threadpool(void *data, void *user_data);
static void named_pipe_client_handler (void *data);
static void* named_pipe_client_handler(void *arg);
static char* searpc_named_pipe_send(void *arg, const gchar *fcall_str, size_t fcall_len, size_t *ret_len);
static char * request_to_json(const char *service, const char *fcall_str, size_t fcall_len);
@ -47,8 +40,8 @@ static int request_from_json (const char *content, size_t len, char **service, c
static void json_object_set_string_member (json_t *object, const char *key, const char *value);
static const char * json_object_get_string_member (json_t *object, const char *key);
static gssize pipe_write_n(SearpcNamedPipe fd, const void *vptr, size_t n);
static gssize pipe_read_n(SearpcNamedPipe fd, void *vptr, size_t n);
static ssize_t pipe_write_n(SearpcNamedPipe fd, const void *vptr, size_t n);
static ssize_t pipe_read_n(SearpcNamedPipe fd, void *vptr, size_t n);
typedef struct {
SearpcNamedPipeClient* client;
@ -81,33 +74,6 @@ SearpcNamedPipeServer* searpc_create_named_pipe_server(const char *path)
{
SearpcNamedPipeServer *server = g_malloc0(sizeof(SearpcNamedPipeServer));
memcpy(server->path, path, strlen(path) + 1);
return server;
}
SearpcNamedPipeServer* searpc_create_named_pipe_server_with_threadpool (const char *path, int named_pipe_server_thread_pool_size)
{
GError *error = NULL;
SearpcNamedPipeServer *server = g_malloc0(sizeof(SearpcNamedPipeServer));
memcpy(server->path, path, strlen(path) + 1);
server->pool_size = named_pipe_server_thread_pool_size;
server->named_pipe_server_thread_pool = g_thread_pool_new (handle_named_pipe_client_with_threadpool,
NULL,
named_pipe_server_thread_pool_size,
FALSE,
&error);
if (!server->named_pipe_server_thread_pool) {
if (error) {
g_warning ("Falied to create named pipe server thread pool : %s\n", error->message);
g_clear_error (&error);
} else {
g_warning ("Falied to create named pipe server thread pool.\n");
}
g_free (server);
return NULL;
}
return server;
}
@ -133,7 +99,7 @@ int searpc_named_pipe_server_start(SearpcNamedPipeServer *server)
}
if (g_file_test (un_path, G_FILE_TEST_EXISTS)) {
g_message ("socket file exists, delete it anyway\n");
g_debug ("socket file exists, delete it anyway\n");
if (g_unlink (un_path) < 0) {
g_warning ("delete socket file failed : %s\n", strerror(errno));
goto failed;
@ -158,28 +124,6 @@ int searpc_named_pipe_server_start(SearpcNamedPipeServer *server)
goto failed;
}
#ifdef __linux__
if (server->use_epoll) {
int epoll_fd;
struct epoll_event event;
epoll_fd = epoll_create1(0);
if (epoll_fd < 0) {
g_warning ("failed to open an epoll file descriptor: %s\n", strerror(errno));
goto failed;
}
event.events = EPOLLIN;
event.data.fd = pipe_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_fd, &event) == -1) {
g_warning ("failed to add pipe fd to epoll list: %s\n", strerror(errno));
goto failed;
}
server->epoll_fd = epoll_fd;
}
#endif
server->pipe_fd = pipe_fd;
#endif // !defined(WIN32)
@ -196,187 +140,26 @@ failed:
}
typedef struct {
SearpcNamedPipe connfd;
SearpcNamedPipeServer *server;
gboolean use_epoll;
SearpcNamedPipe connfd;
} ServerHandlerData;
// EPOLL
#ifdef __linux__
static void epoll_handler(void *data)
{
ServerHandlerData *handler_data = data;
SearpcNamedPipe connfd = handler_data->connfd;
SearpcNamedPipeServer *server = handler_data->server;
char *buf = NULL;
guint32 len = 0;
char *ret_str = NULL;
int ret = 0;
int n;
if (pipe_read_n(connfd, &len, sizeof(guint32)) < 0) {
g_warning("failed to read rpc request size: %s\n", strerror(errno));
ret = -1;
goto out;
}
if (len <= 0) {
ret = -1;
goto out;
}
buf = g_new0 (char, len);
n = pipe_read_n (connfd, buf, len);
if (n < 0) {
g_warning ("failed to read rpc request: %s\n", strerror(errno));
ret = -1;
goto out;
}
char *service, *body;
if (request_from_json (buf, len, &service, &body) < 0) {
ret = -1;
goto out;
}
gsize ret_len;
ret_str = searpc_server_call_function (service, body, strlen(body), &ret_len);
g_free (service);
g_free (body);
len = (guint32)ret_len;
if (pipe_write_n (connfd, &len, sizeof(guint32)) < 0) {
ret = -1;
goto out;
}
if (pipe_write_n (connfd, ret_str, ret_len) < 0) {
ret = -1;
goto out;
}
struct epoll_event event;
event.events = EPOLLIN | EPOLLRDHUP;
event.data.ptr = (void *)handler_data;
if (epoll_ctl (server->epoll_fd, EPOLL_CTL_ADD, connfd, &event) == -1) {
ret = -1;
g_warning ("failed to add client fd to epoll list: %s\n", strerror(errno));
goto out;
}
out:
g_free (buf);
if (ret < 0) {
close (connfd);
g_free (handler_data);
}
g_free (ret_str);
}
static void
epoll_listen (SearpcNamedPipeServer *server)
{
#define MAX_EVENTS 1000
struct epoll_event event;
struct epoll_event events[MAX_EVENTS];
int connfd;
int n_events;
int i;
while (1) {
n_events = epoll_wait (server->epoll_fd, events, MAX_EVENTS, 1000);
if (n_events <= 0) {
if (n_events < 0) {
g_warning ("Failed to call waits for events on the epoll: %s\n", strerror(errno));
}
continue;
}
for (i = 0; i < n_events; i++) {
if (events[i].data.fd == server->pipe_fd) {
if (!(events[i].events & EPOLLIN)) {
continue;
}
// new client connection
connfd = accept (server->pipe_fd, NULL, 0);
if (connfd < 0) {
g_warning ("Failed to accept new client connection: %s\n", strerror(errno));
continue;
}
event.events = EPOLLIN | EPOLLRDHUP;
ServerHandlerData *data = g_new0(ServerHandlerData, 1);
data->use_epoll = TRUE;
data->connfd = connfd;
data->server = server;
event.data.ptr = (void *)data;
if (epoll_ctl (server->epoll_fd, EPOLL_CTL_ADD, connfd, &event) == -1) {
g_warning ("Failed to add client fd to epoll list: %s\n", strerror(errno));
epoll_ctl(server->epoll_fd, EPOLL_CTL_DEL, connfd, NULL);
close (connfd);
g_free (data);
continue;
}
} else {
ServerHandlerData *data = (ServerHandlerData *)events[i].data.ptr;
connfd = data->connfd;
if (events[i].events & (EPOLLHUP | EPOLLRDHUP)) {
g_free (data);
epoll_ctl(server->epoll_fd, EPOLL_CTL_DEL, connfd, NULL);
close (connfd);
continue;
}
// After socket is readable, remove the socket from the epoll.
// After the worker finishes processing the current request, we will add the socket back into the epoll.
epoll_ctl(server->epoll_fd, EPOLL_CTL_DEL, connfd, NULL);
if (server->named_pipe_server_thread_pool) {
if (g_thread_pool_get_num_threads (server->named_pipe_server_thread_pool) >= server->pool_size) {
g_warning("The rpc server thread pool is full, the maximum number of threads is %d\n", server->pool_size);
}
g_thread_pool_push (server->named_pipe_server_thread_pool, data, NULL);
} else {
pthread_t handler;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&handler, &attr, handle_named_pipe_client_with_thread, data);
}
}
}
}
}
#endif
static void* named_pipe_listen(void *arg)
{
SearpcNamedPipeServer *server = arg;
#if !defined(WIN32)
#ifdef __linux__
if (server->use_epoll) {
epoll_listen (server);
return NULL;
}
#endif
while (1) {
int connfd = accept (server->pipe_fd, NULL, 0);
pthread_t *handler = g_malloc(sizeof(pthread_t));
ServerHandlerData *data = g_malloc(sizeof(ServerHandlerData));
data->server = server;
data->connfd = connfd;
data->use_epoll = FALSE;
if (server->named_pipe_server_thread_pool) {
if (g_thread_pool_get_num_threads (server->named_pipe_server_thread_pool) >= server->pool_size) {
g_warning("The rpc server thread pool is full, the maximum number of threads is %d\n", server->pool_size);
}
g_thread_pool_push (server->named_pipe_server_thread_pool, data, NULL);
} else {
pthread_t handler;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&handler, &attr, handle_named_pipe_client_with_thread, data);
}
// TODO(low priority): Instead of using a thread to handle each client,
// use select(unix)/iocp(windows) to do it.
pthread_create(handler, NULL, named_pipe_client_handler, data);
server->handlers = g_list_append(server->handlers, handler);
}
#else // !defined(WIN32)
while (1) {
HANDLE connfd = INVALID_HANDLE_VALUE;
@ -409,79 +192,53 @@ static void* named_pipe_listen(void *arg)
break;
}
/* g_debug ("Accepted a named pipe client\n"); */
g_debug ("Accepted a named pipe client\n");
pthread_t *handler = g_malloc(sizeof(pthread_t));
ServerHandlerData *data = g_malloc(sizeof(ServerHandlerData));
data->server = server;
data->connfd = connfd;
data->use_epoll = FALSE;
if (server->named_pipe_server_thread_pool)
g_thread_pool_push (server->named_pipe_server_thread_pool, data, NULL);
else {
pthread_t handler;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&handler, &attr, handle_named_pipe_client_with_thread, data);
}
// TODO(low priority): Instead of using a thread to handle each client,
// use select(unix)/iocp(windows) to do it.
pthread_create(handler, NULL, named_pipe_client_handler, data);
server->handlers = g_list_append(server->handlers, handler);
}
#endif // !defined(WIN32)
return NULL;
}
static void* handle_named_pipe_client_with_thread(void *arg)
static void* named_pipe_client_handler(void *arg)
{
#ifdef __linux__
ServerHandlerData *handler_data = arg;
if (handler_data->use_epoll) {
epoll_handler (arg);
return NULL;
}
#endif
named_pipe_client_handler(arg);
ServerHandlerData *data = arg;
// SearpcNamedPipeServer *server = data->server;
SearpcNamedPipe connfd = data->connfd;
return NULL;
}
static void handle_named_pipe_client_with_threadpool(void *data, void *user_data)
{
#ifdef __linux__
ServerHandlerData *handler_data = data;
if (handler_data->use_epoll) {
epoll_handler (data);
return;
}
#endif
named_pipe_client_handler(data);
}
static void named_pipe_client_handler(void *data)
{
ServerHandlerData *handler_data = data;
SearpcNamedPipe connfd = handler_data->connfd;
guint32 len;
guint32 bufsize = 4096;
size_t len;
size_t bufsize = 4096;
char *buf = g_malloc(bufsize);
g_debug ("start to serve on pipe client\n");
while (1) {
len = 0;
if (pipe_read_n(connfd, &len, sizeof(guint32)) < 0) {
g_warning("failed to read rpc request size: %s\n", strerror(errno));
if (pipe_read_n(connfd, &len, sizeof(uint32_t)) < 0) {
g_warning("failed to read rpc request size: %s", strerror(errno));
break;
}
if (len == 0) {
/* g_debug("EOF reached, pipe connection lost"); */
g_debug("EOF reached, pipe connection lost");
break;
}
while (bufsize < len) {
bufsize *= 2;
buf = g_realloc(buf, bufsize);
buf = realloc(buf, bufsize);
}
if (pipe_read_n(connfd, buf, len) < 0 || len == 0) {
g_warning("failed to read rpc request: %s\n", strerror(errno));
g_warning("failed to read rpc request: %s", strerror(errno));
g_free (buf);
break;
}
@ -490,20 +247,19 @@ static void named_pipe_client_handler(void *data)
break;
}
gsize ret_len;
size_t ret_len;
char *ret_str = searpc_server_call_function (service, body, strlen(body), &ret_len);
g_free (service);
g_free (body);
len = (guint32)ret_len;
if (pipe_write_n(connfd, &len, sizeof(guint32)) < 0) {
g_warning("failed to send rpc response(%s): %s\n", ret_str, strerror(errno));
if (pipe_write_n(connfd, &ret_len, sizeof(uint32_t)) < 0) {
g_warning("failed to send rpc response(%s): %s", ret_str, strerror(errno));
g_free (ret_str);
break;
}
if (pipe_write_n(connfd, ret_str, ret_len) < 0) {
g_warning("failed to send rpc response: %s\n", strerror(errno));
g_warning("failed to send rpc response: %s", strerror(errno));
g_free (ret_str);
break;
}
@ -517,10 +273,11 @@ static void named_pipe_client_handler(void *data)
DisconnectNamedPipe(connfd);
CloseHandle(connfd);
#endif // !defined(WIN32)
g_free (data);
g_free (buf);
return NULL;
}
int searpc_named_pipe_client_connect(SearpcNamedPipeClient *client)
{
#if !defined(WIN32)
@ -531,39 +288,29 @@ int searpc_named_pipe_client_connect(SearpcNamedPipeClient *client)
g_strlcpy (servaddr.sun_path, client->path, sizeof(servaddr.sun_path));
if (connect(client->pipe_fd, (struct sockaddr *)&servaddr, (socklen_t)sizeof(servaddr)) < 0) {
g_warning ("pipe client failed to connect to server: %s\n", strerror(errno));
close(client->pipe_fd);
return -1;
}
#else // !defined(WIN32)
SearpcNamedPipe pipe_fd;
pipe_fd = CreateFile(
client->path, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
for (;;) {
pipe_fd = CreateFile(
client->path, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
if (pipe_fd != INVALID_HANDLE_VALUE) {
break;
}
/* wait with default timeout (approx. 50ms) */
if (GetLastError() != ERROR_PIPE_BUSY || !WaitNamedPipe(client->path, NMPWAIT_USE_DEFAULT_WAIT)) {
G_WARNING_WITH_LAST_ERROR("Failed to connect to named pipe");
return -1;
}
if (pipe_fd == INVALID_HANDLE_VALUE) {
G_WARNING_WITH_LAST_ERROR("Failed to connect to named pipe");
return -1;
}
DWORD mode = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(pipe_fd, &mode, NULL, NULL)) {
G_WARNING_WITH_LAST_ERROR("Failed to set named pipe mode");
CloseHandle (pipe_fd);
return -1;
}
@ -571,7 +318,7 @@ int searpc_named_pipe_client_connect(SearpcNamedPipeClient *client)
#endif // !defined(WIN32)
/* g_debug ("pipe client connected to server\n"); */
g_debug ("pipe client connected to server\n");
return 0;
}
@ -585,7 +332,6 @@ void searpc_free_client_with_pipe_transport (SearpcClient *client)
close(pipe_client->pipe_fd);
#endif
g_free (pipe_client);
g_free (data->service);
g_free (data);
searpc_client_free (client);
}
@ -593,36 +339,37 @@ void searpc_free_client_with_pipe_transport (SearpcClient *client)
char *searpc_named_pipe_send(void *arg, const gchar *fcall_str,
size_t fcall_len, size_t *ret_len)
{
/* g_debug ("searpc_named_pipe_send is called\n"); */
g_debug ("searpc_named_pipe_send is called\n");
ClientTransportData *data = arg;
SearpcNamedPipeClient *client = data->client;
char *json_str = request_to_json(data->service, fcall_str, fcall_len);
guint32 len = (guint32)strlen(json_str);
size_t json_len = strlen(json_str);
if (pipe_write_n(client->pipe_fd, &len, sizeof(guint32)) < 0) {
g_warning("failed to send rpc call: %s\n", strerror(errno));
uint32_t len = json_len;
if (pipe_write_n(client->pipe_fd, &len, sizeof(uint32_t)) < 0) {
g_warning("failed to send rpc call: %s", strerror(errno));
free (json_str);
return NULL;
}
if (pipe_write_n(client->pipe_fd, json_str, len) < 0) {
g_warning("failed to send rpc call: %s\n", strerror(errno));
if (pipe_write_n(client->pipe_fd, json_str, json_len) < 0) {
g_warning("failed to send rpc call: %s", strerror(errno));
free (json_str);
return NULL;
}
free (json_str);
if (pipe_read_n(client->pipe_fd, &len, sizeof(guint32)) < 0) {
g_warning("failed to read rpc response: %s\n", strerror(errno));
if (pipe_read_n(client->pipe_fd, &len, sizeof(uint32_t)) < 0) {
g_warning("failed to read rpc response: %s", strerror(errno));
return NULL;
}
char *buf = g_malloc(len);
if (pipe_read_n(client->pipe_fd, buf, len) < 0) {
g_warning("failed to read rpc response: %s\n", strerror(errno));
g_warning("failed to read rpc response: %s", strerror(errno));
g_free (buf);
return NULL;
}
@ -690,11 +437,11 @@ json_object_get_string_member (json_t *object, const char *key)
#if !defined(WIN32)
// Write "n" bytes to a descriptor.
gssize
ssize_t
pipe_write_n(int fd, const void *vptr, size_t n)
{
size_t nleft;
gssize nwritten;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
@ -715,11 +462,11 @@ pipe_write_n(int fd, const void *vptr, size_t n)
}
// Read "n" bytes from a descriptor.
gssize
ssize_t
pipe_read_n(int fd, void *vptr, size_t n)
{
size_t nleft;
gssize nread;
ssize_t nread;
char *ptr;
ptr = vptr;
@ -741,7 +488,7 @@ pipe_read_n(int fd, void *vptr, size_t n)
#else // !defined(WIN32)
gssize pipe_read_n (SearpcNamedPipe fd, void *vptr, size_t n)
ssize_t pipe_read_n (SearpcNamedPipe fd, void *vptr, size_t n)
{
DWORD bytes_read;
BOOL success = ReadFile(
@ -762,7 +509,7 @@ gssize pipe_read_n (SearpcNamedPipe fd, void *vptr, size_t n)
return n;
}
gssize pipe_write_n(SearpcNamedPipe fd, const void *vptr, size_t n)
ssize_t pipe_write_n(SearpcNamedPipe fd, const void *vptr, size_t n)
{
DWORD bytes_written;
BOOL success = WriteFile(
@ -773,14 +520,38 @@ gssize pipe_write_n(SearpcNamedPipe fd, const void *vptr, size_t n)
NULL); // not overlapped I/O
if (!success || bytes_written != (DWORD)n) {
G_WARNING_WITH_LAST_ERROR("failed to write to named pipe");
return -1;
G_WARNING_WITH_LAST_ERROR("failed to read command from the pipe");
}
FlushFileBuffers(fd);
return 0;
}
static char *locale_to_utf8 (const gchar *src)
{
if (!src)
return NULL;
gsize bytes_read = 0;
gsize bytes_written = 0;
GError *error = NULL;
gchar *dst = NULL;
dst = g_locale_to_utf8
(src, /* locale specific string */
strlen(src), /* len of src */
&bytes_read, /* length processed */
&bytes_written, /* output length */
&error);
if (error) {
return NULL;
}
return dst;
}
// http://stackoverflow.com/questions/3006229/get-a-text-from-the-error-code-returns-from-the-getlasterror-function
// The caller is responsible to free the returned message.
char* formatErrorMessage()
@ -793,12 +564,11 @@ char* formatErrorMessage()
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error_code,
/* EN_US */
MAKELANGID(LANG_ENGLISH, 0x01),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buf,
sizeof(buf) - 1,
NULL);
return g_strdup(buf);
return locale_to_utf8(buf);
}
#endif // !defined(WIN32)

View File

@ -10,16 +10,6 @@
#include <windows.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LIBSEARPC_EXPORTS
#define LIBSEARPC_API __declspec(dllexport)
#else
#define LIBSEARPC_API
#endif
// Implementatin of a searpc transport based on named pipe. It uses unix domain
// sockets on linux/osx, and named pipes on windows.
//
@ -40,22 +30,14 @@ typedef int SearpcNamedPipe;
struct _SearpcNamedPipeServer {
char path[4096];
pthread_t listener_thread;
GList *handlers;
SearpcNamedPipe pipe_fd;
gboolean use_epoll;
int epoll_fd;
GThreadPool *named_pipe_server_thread_pool;
int pool_size;
};
typedef struct _SearpcNamedPipeServer LIBSEARPC_API SearpcNamedPipeServer;
typedef struct _SearpcNamedPipeServer SearpcNamedPipeServer;
LIBSEARPC_API
SearpcNamedPipeServer* searpc_create_named_pipe_server(const char *path);
LIBSEARPC_API
SearpcNamedPipeServer* searpc_create_named_pipe_server_with_threadpool(const char *path, int named_pipe_server_thread_pool_size);
LIBSEARPC_API
int searpc_named_pipe_server_start(SearpcNamedPipeServer *server);
// Client side interface.
@ -65,22 +47,14 @@ struct _SearpcNamedPipeClient {
SearpcNamedPipe pipe_fd;
};
typedef struct _SearpcNamedPipeClient LIBSEARPC_API SearpcNamedPipeClient;
typedef struct _SearpcNamedPipeClient SearpcNamedPipeClient;
LIBSEARPC_API
SearpcNamedPipeClient* searpc_create_named_pipe_client(const char *path);
LIBSEARPC_API
SearpcClient * searpc_client_with_named_pipe_transport(SearpcNamedPipeClient *client, const char *service);
LIBSEARPC_API
int searpc_named_pipe_client_connect(SearpcNamedPipeClient *client);
LIBSEARPC_API
void searpc_free_client_with_pipe_transport (SearpcClient *client);
#ifdef __cplusplus
}
#endif
#endif // SEARPC_NAMED_PIPE_TRANSPORT_H

View File

@ -9,10 +9,8 @@
#include "searpc-server.h"
#include "searpc-utils.h"
#ifdef __linux__
#include <sys/time.h>
#include <sys/errno.h>
#include <pthread.h>
#ifdef PROFILE
#include <sys/time.h>
#endif
struct FuncItem;
@ -36,14 +34,6 @@ typedef struct {
static GHashTable *marshal_table;
static GHashTable *service_table;
#ifdef __linux__
static FILE *slow_log_fp = NULL;
static gint64 slow_threshold;
static GList *filtered_funcs;
static pthread_mutex_t slow_log_lock;
static gboolean log_to_stdout = FALSE;
#endif
static void
func_item_free (FuncItem *item)
{
@ -146,10 +136,7 @@ searpc_set_objlist_to_ret_object (json_t *object, GList *ret)
void
searpc_set_json_to_ret_object (json_t *object, json_t *ret)
{
if (ret == NULL)
json_object_set_new(object, "ret", json_null ());
else
json_object_set_new (object, "ret", ret);
json_object_set_new (object, "ret", ret);
}
char *
@ -198,67 +185,8 @@ searpc_server_init (RegisterMarshalFunc register_func)
register_func ();
}
#ifdef __linux__
int
searpc_server_init_with_slow_log (RegisterMarshalFunc register_func,
const char *slow_log_path,
gint64 slow_threshold_in,
GList *filtered_funcs_in)
{
const char *log_to_stdout_env = g_getenv("SEAFILE_LOG_TO_STDOUT");
if (g_strcmp0(log_to_stdout_env, "true") == 0) {
slow_log_fp = stdout;
log_to_stdout = TRUE;
} else if (slow_log_path) {
slow_log_fp = fopen (slow_log_path, "a+");
if (!slow_log_fp) {
g_warning ("Failed to open RPC slow log file %s: %s\n", slow_log_path, strerror(errno));
return -1;
}
}
slow_threshold = slow_threshold_in;
filtered_funcs = filtered_funcs_in;
pthread_mutex_init (&slow_log_lock, NULL);
searpc_server_init (register_func);
return 0;
}
int
searpc_server_reopen_slow_log (const char *slow_log_path)
{
FILE *fp, *oldfp;
if (log_to_stdout) {
return 0;
}
if ((fp = fopen (slow_log_path, "a+")) == NULL) {
g_warning ("Failed to open RPC slow log file %s\n", slow_log_path);
return -1;
}
pthread_mutex_lock (&slow_log_lock);
oldfp = slow_log_fp;
slow_log_fp = fp;
pthread_mutex_unlock (&slow_log_lock);
if (fclose(oldfp) < 0) {
g_warning ("Failed to close old RPC slow log file\n");
return -1;
}
return 0;
}
#endif
void
searpc_server_final(void)
searpc_server_final()
{
g_hash_table_destroy (service_table);
g_hash_table_destroy (marshal_table);
@ -316,53 +244,6 @@ searpc_server_register_function (const char *svc_name,
return TRUE;
}
#ifdef __linux__
static gboolean
rpc_include_passwd (const char *fname) {
GList *ptr;
char *rpc_name;
for (ptr = filtered_funcs; ptr; ptr = ptr->next) {
rpc_name = ptr->data;
if (g_strcmp0 (fname, rpc_name) == 0) {
return TRUE;
}
}
return FALSE;
}
static void
print_slow_log_if_necessary (const char *svc_name, const char *func, gsize len,
const struct timeval *start,
const struct timeval *intv)
{
char time_buf[64];
gint64 intv_in_usec = ((gint64)intv->tv_sec) * G_USEC_PER_SEC + (gint64)intv->tv_usec;
gint64 intv_in_msec = intv_in_usec/1000;
double intv_in_sec = ((double)intv_in_usec)/G_USEC_PER_SEC;
if (intv_in_msec < slow_threshold)
return;
strftime(time_buf, 64, "%Y/%m/%d %H:%M:%S", localtime(&start->tv_sec));
pthread_mutex_lock (&slow_log_lock);
if (log_to_stdout) {
fprintf (slow_log_fp, "[seafile-slow-rpc] ");
}
fprintf (slow_log_fp, "[%s] \"%s\" %.*s %.3f\n",
time_buf, svc_name, (int)len, func, intv_in_sec);
fflush (slow_log_fp);
pthread_mutex_unlock (&slow_log_lock);
}
#endif
/* Called by RPC transport. */
char*
searpc_server_call_function (const char *svc_name,
@ -374,12 +255,10 @@ searpc_server_call_function (const char *svc_name,
json_error_t jerror;
GError *error = NULL;
#ifdef __linux__
#ifdef PROFILE
struct timeval start, end, intv;
if (slow_log_fp) {
gettimeofday(&start, NULL);
}
gettimeofday(&start, NULL);
#endif
service = g_hash_table_lookup (service_table, svc_name);
@ -411,14 +290,11 @@ searpc_server_call_function (const char *svc_name,
ret = fitem->marshal->mfunc (fitem->func, array, ret_len);
#ifdef __linux__
if (slow_log_fp) {
if (!filtered_funcs || !rpc_include_passwd (fitem->fname)) {
gettimeofday(&end, NULL);
timersub(&end, &start, &intv);
print_slow_log_if_necessary (svc_name, func, len, &start, &intv);
}
}
#ifdef PROFILE
gettimeofday(&end, NULL);
timersub(&end, &start, &intv);
g_debug ("[searpc] Time spend in call %s: %ds %dus\n",
fname, intv.tv_sec, intv.tv_usec);
#endif
json_decref(array);

View File

@ -5,16 +5,6 @@
#include <glib-object.h>
#include <jansson.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LIBSEARPC_EXPORTS
#define LIBSEARPC_API __declspec(dllexport)
#else
#define LIBSEARPC_API
#endif
#ifndef DFT_DOMAIN
#define DFT_DOMAIN g_quark_from_string(G_LOG_DOMAIN)
#endif
@ -23,17 +13,11 @@ typedef gchar* (*SearpcMarshalFunc) (void *func, json_t *param_array,
gsize *ret_len);
typedef void (*RegisterMarshalFunc) (void);
LIBSEARPC_API
void searpc_set_string_to_ret_object (json_t *object, char *ret);
LIBSEARPC_API
void searpc_set_int_to_ret_object (json_t *object, json_int_t ret);
LIBSEARPC_API
void searpc_set_object_to_ret_object (json_t *object, GObject *ret);
LIBSEARPC_API
void searpc_set_objlist_to_ret_object (json_t *object, GList *ret);
LIBSEARPC_API
void searpc_set_json_to_ret_object (json_t *object, json_t *ret);
LIBSEARPC_API
char *searpc_marshal_set_ret_common (json_t *object, gsize *len, GError *error);
/**
@ -41,33 +25,14 @@ char *searpc_marshal_set_ret_common (json_t *object, gsize *len, GError *error);
*
* Inititalize searpc server.
*/
LIBSEARPC_API
void searpc_server_init (RegisterMarshalFunc register_func);
/**
* searpc_server_init_with_slow_log:
*
* Inititalize searpc server with slow log file.
*/
LIBSEARPC_API int
searpc_server_init_with_slow_log (RegisterMarshalFunc register_func,
const char *slow_log_path,
gint64 slow_threshold_in,
GList *filtered_funcs_in);
/**
* Used in log rotate.
*/
LIBSEARPC_API int
searpc_server_reopen_slow_log (const char *slow_log_path);
/**
* searpc_server_final:
*
* Free the server structure.
*/
LIBSEARPC_API
void searpc_server_final (void);
void searpc_server_final ();
/**
* searpc_create_service:
@ -77,7 +42,6 @@ void searpc_server_final (void);
*
* @svc_name: Service name.
*/
LIBSEARPC_API
int searpc_create_service (const char *svc_name);
/**
@ -85,7 +49,6 @@ int searpc_create_service (const char *svc_name);
*
* Remove the service from the server.
*/
LIBSEARPC_API
void searpc_remove_service (const char *svc_name);
/**
@ -96,7 +59,6 @@ void searpc_remove_service (const char *svc_name);
* @signature: the signature of the marshal, register_marshal() will take
* owner of this string.
*/
LIBSEARPC_API
gboolean searpc_server_register_marshal (gchar *signature,
SearpcMarshalFunc marshal);
@ -108,7 +70,6 @@ gboolean searpc_server_register_marshal (gchar *signature,
* @signature: the signature of the function, register_function() will take
* owner of this string.
*/
LIBSEARPC_API
gboolean searpc_server_register_function (const char *service,
void* func,
const gchar *fname,
@ -125,7 +86,6 @@ gboolean searpc_server_register_function (const char *service,
*
* Returns the serialized representatio of the returned value.
*/
LIBSEARPC_API
gchar *searpc_server_call_function (const char *service,
gchar *func, gsize len, gsize *ret_len);
@ -136,11 +96,6 @@ gchar *searpc_server_call_function (const char *service,
*
* Compute function signature.
*/
LIBSEARPC_API
char* searpc_compute_signature (const gchar *ret_type, int pnum, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,4 +1,5 @@
#include <errno.h>
#include <unistd.h>
#include <glib.h>
#include <glib-object.h>
#include <jansson.h>

View File

@ -2,23 +2,15 @@
#include <glib-object.h>
#include <jansson.h>
#ifdef LIBSEARPC_EXPORTS
#define LIBSEARPC_API __declspec(dllexport)
#else
#define LIBSEARPC_API
#endif
#define SEARPC_JSON_DOMAIN g_quark_from_string("SEARPC_JSON")
typedef enum {
SEARPC_JSON_ERROR_LOAD,
SEARPC_JSON_ERROR_PACK,
SEARPC_JSON_ERROR_UPACK
} LIBSEARPC_API SEARPCJSONERROR;
} SEARPCJSONERROR;
LIBSEARPC_API
json_t *json_gobject_serialize (GObject *);
LIBSEARPC_API
GObject *json_gobject_deserialize (GType , json_t *);
inline static void setjetoge(const json_error_t *jerror, GError **error)

View File

@ -1,4 +1,4 @@
prefix=@prefix@
prefix=(DESTDIR)@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
@ -8,4 +8,4 @@ Description: Simple C rpc library
Version: @VERSION@
Libs: -L${libdir} -lsearpc
Cflags: -I${includedir} -I${includedir}/searpc
Requires: gobject-2.0 >= 2.26.0 gio-2.0 jansson >= 2.2.1
Requires: gobject-2.0 gio-2.0 jansson

View File

@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29215.179
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsearpc", "libsearpc.vcxproj", "{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Debug|x64.ActiveCfg = Debug|x64
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Debug|x64.Build.0 = Debug|x64
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Debug|x86.ActiveCfg = Debug|Win32
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Debug|x86.Build.0 = Debug|Win32
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Release|x64.ActiveCfg = Release|x64
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Release|x64.Build.0 = Release|x64
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Release|x86.ActiveCfg = Release|Win32
{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {393C05AB-0CCA-4180-93EF-57D9CB079042}
EndGlobalSection
EndGlobal

View File

@ -1,137 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{7E7BDAA2-D61E-466D-B138-CC2454CAB1D3}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>true</VcpkgEnableManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;LIBSEARPC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>LIBSEARPC_EXPORTS;WIN32</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)vcpkg_installed\x64-windows\x64-windows\include\glib-2.0;$(ProjectDir)vcpkg_installed\x64-windows\x64-windows\lib\glib-2.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>LIBSEARPC_EXPORTS;WIN32</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)vcpkg_installed\x64-windows\x64-windows\include\glib-2.0;$(ProjectDir)vcpkg_installed\x64-windows\x64-windows\lib\glib-2.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="lib\searpc-client.c" />
<ClCompile Include="lib\searpc-named-pipe-transport.c" />
<ClCompile Include="lib\searpc-server.c" />
<ClCompile Include="lib\searpc-utils.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="config.h" />
<ClInclude Include="lib\searpc-client.h" />
<ClInclude Include="lib\searpc-named-pipe-transport.h" />
<ClInclude Include="lib\searpc-server.h" />
<ClInclude Include="lib\searpc-utils.h" />
<ClInclude Include="lib\searpc.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,5 +1,5 @@
import json
from .common import SearpcError
from common import SearpcError
def _fret_int(ret_str):
try:
@ -7,10 +7,10 @@ def _fret_int(ret_str):
except:
raise SearpcError('Invalid response format')
if 'err_code' in dicts:
if dicts.has_key('err_code'):
raise SearpcError(dicts['err_msg'])
if 'ret' in dicts:
if dicts.has_key('ret'):
return dicts['ret']
else:
raise SearpcError('Invalid response format')
@ -21,10 +21,10 @@ def _fret_string(ret_str):
except:
raise SearpcError('Invalid response format')
if 'err_code' in dicts:
if dicts.has_key('err_code'):
raise SearpcError(dicts['err_msg'])
if 'ret' in dicts:
if dicts.has_key('ret'):
return dicts['ret']
else:
raise SearpcError('Invalid response format')
@ -61,7 +61,7 @@ def _fret_obj(ret_str):
except:
raise SearpcError('Invalid response format')
if 'err_code' in dicts:
if dicts.has_key('err_code'):
raise SearpcError(dicts['err_msg'])
if dicts['ret']:
@ -75,7 +75,7 @@ def _fret_objlist(ret_str):
except:
raise SearpcError('Invalid response format')
if 'err_code' in dicts:
if dicts.has_key('err_code'):
raise SearpcError(dicts['err_msg'])
l = []
@ -85,19 +85,6 @@ def _fret_objlist(ret_str):
return l
def _fret_json(ret_str):
try:
dicts = json.loads(ret_str)
except:
raise SearpcError('Invalid response format')
if 'err_code' in dicts:
raise SearpcError(dicts['err_msg'])
if dicts['ret']:
return dicts['ret']
else:
return None
def searpc_func(ret_type, param_types):
@ -114,8 +101,6 @@ def searpc_func(ret_type, param_types):
fret = _fret_int
elif ret_type == "string":
fret = _fret_string
elif ret_type == "json":
fret = _fret_json
else:
raise SearpcError('Invial return type')

View File

@ -8,7 +8,6 @@ import os
import socket
import struct
from threading import Thread
import queue
from .client import SearpcClient
from .server import searpc_server
@ -37,67 +36,52 @@ class NamedPipeTransport(SearpcTransport):
def __init__(self, socket_path):
self.socket_path = socket_path
self.pipe = None
self.pipe_fd = None
def connect(self):
self.pipe = socket.socket(socket.AF_UNIX)
self.pipe.connect(self.socket_path)
self.pipe_fd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
make_socket_closeonexec(self.pipe_fd)
self.pipe_fd.connect(self.socket_path)
def stop(self):
if self.pipe:
self.pipe.close()
self.pipe = None
if self.pipe_fd:
self.pipe_fd.close()
self.pipe_fd = None
def send(self, service, fcall_str):
body = json.dumps({
'service': service,
'request': fcall_str,
})
body_utf8 = body.encode(encoding='utf-8')
# "I" for unsiged int
header = struct.pack('=I', len(body_utf8))
sendall(self.pipe, header)
sendall(self.pipe, body_utf8)
header = struct.pack('I', len(body))
sendall(self.pipe_fd, header)
sendall(self.pipe_fd, body)
resp_header = recvall(self.pipe, 4)
resp_header = recvall(self.pipe_fd, 4)
# logger.info('resp_header is %s', resp_header)
resp_size, = struct.unpack('=I', resp_header)
resp_size, = struct.unpack('I', resp_header)
# logger.info('resp_size is %s', resp_size)
resp = recvall(self.pipe, resp_size)
resp = recvall(self.pipe_fd, resp_size)
# logger.info('resp is %s', resp)
return resp.decode(encoding='utf-8')
return resp
class NamedPipeClient(SearpcClient):
def __init__(self, socket_path, service_name, pool_size=5):
def __init__(self, socket_path, service_name):
self.socket_path = socket_path
self.service_name = service_name
self.pool_size = pool_size
self._pool = queue.Queue(pool_size)
self.transport = NamedPipeTransport(socket_path)
self.connected = False
def _create_transport(self):
transport = NamedPipeTransport(self.socket_path)
transport.connect()
return transport
def _get_transport(self):
try:
transport = self._pool.get(False)
except:
transport = self._create_transport()
return transport
def _return_transport(self, transport):
try:
self._pool.put(transport, False)
except queue.Full:
transport.stop()
def stop(self):
self.transport.stop()
def call_remote_func_sync(self, fcall_str):
transport = self._get_transport()
ret_str = transport.send(self.service_name, fcall_str)
self._return_transport(transport)
return ret_str
if not self.connected:
self.transport.connect()
self.connected = True
return self.transport.send(self.service_name, fcall_str)
class NamedPipeServer(object):
@ -107,7 +91,7 @@ class NamedPipeServer(object):
"""
def __init__(self, socket_path):
self.socket_path = socket_path
self.pipe = None
self.pipe_fd = None
self.thread = Thread(target=self.accept_loop)
self.thread.setDaemon(True)
@ -127,40 +111,40 @@ class NamedPipeServer(object):
'Failed to remove existing unix socket {}'.
format(self.socket_path)
)
self.pipe = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
make_socket_closeonexec(self.pipe)
self.pipe.bind(self.socket_path)
self.pipe.listen(10)
self.pipe_fd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
make_socket_closeonexec(self.pipe_fd)
self.pipe_fd.bind(self.socket_path)
self.pipe_fd.listen(10)
logger.info('Server now listening at %s', self.socket_path)
def accept_loop(self):
logger.info('Waiting for clients')
while True:
connfd, _ = self.pipe.accept()
connfd, _ = self.pipe_fd.accept()
logger.info('New pip client')
t = PipeHandlerThread(connfd)
t.start()
class PipeHandlerThread(Thread):
def __init__(self, pipe):
def __init__(self, pipe_fd):
Thread.__init__(self)
self.setDaemon(True)
self.pipe = pipe
self.pipe_fd = pipe_fd
def run(self):
while True:
req_header = recvall(self.pipe, 4)
req_header = recvall(self.pipe_fd, 4)
# logger.info('Got req header %s', req_header)
req_size, = struct.unpack('I', req_header)
# logger.info('req size is %s', req_size)
req = recvall(self.pipe, req_size)
req = recvall(self.pipe_fd, req_size)
# logger.info('req is %s', req)
data = json.loads(req.decode(encoding='utf-8'))
data = json.loads(req)
resp = searpc_server.call_function(data['service'], data['request'])
# logger.info('resp is %s', resp)
resp_header = struct.pack('I', len(resp))
sendall(self.pipe, resp_header)
sendall(self.pipe, resp.encode(encoding='utf-8'))
sendall(self.pipe_fd, resp_header)
sendall(self.pipe_fd, resp)

View File

@ -1,5 +1,6 @@
#!/usr/bin/python
import string
import sys
@ -28,7 +29,7 @@ def gen_fcall_funcs_array(arg_types):
pyfuncname = "fcall__" + "_".join(arg_types)
tmplist = []
for arg in arg_types:
tmplist.append(arg.capitalize())
tmplist.append(string.capitalize(arg))
cfuncname = "SearpcClient_Fcall__" + "_".join(tmplist)
@ -46,7 +47,7 @@ def gen_fret_funcs_array(ret_type):
cfuncname = "SearpcClient_Fret__Void"
else:
pyfuncname = "fret__" + ret_type
cfuncname = "SearpcClient_Fret__" + ret_type.capitalize()
cfuncname = "SearpcClient_Fret__" + string.capitalize(ret_type)
return string.Template(func_item_template)\
.substitute(pyfuncname=pyfuncname,
@ -78,8 +79,8 @@ def gen_module_funcs_array():
array = fcall_array
array += fret_array
print(string.Template(module_func_array_template)\
.substitute(array=array))
print string.Template(module_func_array_template)\
.substitute(array=array)
type_table = {
@ -127,7 +128,7 @@ def gen_fcall_func(arg_types):
tmplist = []
for arg in arg_types:
tmplist.append(arg.capitalize())
tmplist.append(string.capitalize(arg))
Suffix = "_".join(tmplist)
suffix = "_".join(arg_types)
def_args = ""
@ -160,7 +161,7 @@ def gen_fcall_list():
arg_types_list.append(item[1])
for item in arg_types_list:
print(gen_fcall_func(item))
print gen_fcall_func(item)
if __name__ == "__main__":

View File

@ -1,6 +1,6 @@
import json
from .common import SearpcError
from common import SearpcError
class SearpcService(object):
def __init__(self, name):
@ -25,7 +25,7 @@ class SearpcServer(object):
"""input str -> output str"""
try:
argv = json.loads(fcallstr)
except Exception as e:
except Exception, e:
raise SearpcError('bad call str: ' + str(e))
service = self.services[svcname]
@ -41,7 +41,7 @@ class SearpcServer(object):
def call_function(self, svcname, fcallstr):
try:
retVal = self._call_function(svcname, fcallstr)
except Exception as e:
except Exception, e:
ret = {'err_code': 555, 'err_msg': str(e)}
else:
ret = {'ret': retVal}

View File

@ -22,14 +22,6 @@ def init_server():
searpc_server.create_service(SVCNAME)
searpc_server.register_function(SVCNAME, add, 'add')
searpc_server.register_function(SVCNAME, mul, 'multi')
searpc_server.register_function(SVCNAME, json_func, 'json_func')
searpc_server.register_function(SVCNAME, get_str, 'get_str')
def json_func(a, b):
return {'a': a, 'b': b}
def get_str():
return u'这是一个测试'
class DummyTransport(SearpcTransport):
@ -48,14 +40,6 @@ class RpcMixin(object):
def multi(self, x, y):
pass
@searpc_func("json", ["string", "int"])
def json_func(self, x, y):
pass
@searpc_func("string", [])
def get_str(self):
pass
class DummyRpcClient(SearpcClient, RpcMixin):
def __init__(self):
self.transport = DummyTransport()
@ -82,6 +66,7 @@ class SearpcTest(unittest.TestCase):
@classmethod
def tearDownClass(cls):
cls.named_pipe_client.stop()
cls.named_pipe_server.stop()
def test_normal_transport(self):
@ -101,12 +86,6 @@ class SearpcTest(unittest.TestCase):
v = client.multi('abc', 2)
self.assertEqual(v, 'abcabc')
v = client.json_func(1, 2)
self.assertEqual(v, json_func(1, 2))
v = client.get_str()
self.assertEqual(v, u'这是一个测试')
def setup_logging(level=logging.INFO):
kw = {
# 'format': '[%(asctime)s][%(pathname)s]: %(message)s',

View File

@ -1,3 +1,4 @@
class SearpcTransport(object):
"""
A transport is repsonsible to send the serialized request to the

View File

@ -5,7 +5,7 @@ from pysearpc.errors import NetworkError
def recvall(fd, total):
remain = total
data = bytearray()
data = ''
while remain > 0:
try:
new = fd.recv(remain)
@ -16,10 +16,10 @@ def recvall(fd, total):
if n <= 0:
raise NetworkError("Failed to read from socket")
else:
data.extend(new)
data += new
remain -= n
return bytes(data)
return data
def sendall(fd, data):
total = len(data)

View File

@ -371,7 +371,7 @@ clar_test_init(int argc, char **argv)
}
int
clar_test_run(void)
clar_test_run()
{
if (_clar.argc > 1)
clar_parse_args(_clar.argc, _clar.argv);
@ -386,7 +386,7 @@ clar_test_run(void)
}
void
clar_test_shutdown(void)
clar_test_shutdown()
{
clar_print_shutdown(
_clar.tests_ran,

View File

@ -27,8 +27,6 @@ static const char *pipe_path = "\\\\.\\pipe\\libsearpc-test";
#define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
#define MAMAN_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))
#define NAMED_PIPE_SERVER_THREAD_POOL_SIZE 50
typedef struct _MamanBar MamanBar;
typedef struct _MamanBarClass MamanBarClass;
@ -204,7 +202,7 @@ get_substring (const gchar *orig_str, int sub_len, GError **error)
}
static SearpcClient *
do_create_client_with_pipe_transport(void)
do_create_client_with_pipe_transport()
{
SearpcNamedPipeClient *pipe_client = searpc_create_named_pipe_client(pipe_path);
cl_must_pass_(searpc_named_pipe_client_connect(pipe_client), "named pipe client failed to connect");
@ -547,7 +545,7 @@ test_searpc__initialize (void)
client->async_send = sample_async_send;
client->async_arg = "test_async";
SearpcNamedPipeServer *pipe_server = searpc_create_named_pipe_server_with_threadpool(pipe_path, NAMED_PIPE_SERVER_THREAD_POOL_SIZE);
SearpcNamedPipeServer *pipe_server = searpc_create_named_pipe_server(pipe_path);
cl_must_pass_(searpc_named_pipe_server_start(pipe_server), "named pipe server failed to start");
#if defined(WIN32)
// Wait for the server thread to start

View File

@ -1,18 +0,0 @@
{
"builtin-baseline": "f63682b9182187131b564c1395e4ac8ecb0c5ea8",
"dependencies": [
"glib",
"jansson",
"pthreads"
],
"overrides": [
{
"name": "jansson",
"version": "2.12-1"
},
{
"name": "pthreads",
"version": "3.0.0-4"
}
]
}