14#if defined(__MOS_KERNEL__)
25#define MOS_LIB_ASSERT_X(cond, msg) assert(cond &&msg)
26#define MOS_LIB_ASSERT(cond) assert(cond)
35#define syscall_ipc_create(server_name, max_pending) ipc_create(server_name, max_pending)
36#define syscall_ipc_accept(server_fd) io_ref(ipc_accept(server_fd))
37#define syscall_ipc_connect(server_name, smh_size) ipc_connect(server_name, smh_size)
38#define start_thread(name, func, arg) kthread_create(func, arg, name)
39#define syscall_io_close(fd) io_unref(fd)
44#if !defined(__MOS_KERNEL__)
48#define memzero(ptr, size) memset(ptr, 0, size)
49#define mutex_acquire(mutex) pthread_mutex_lock(mutex)
50#define mutex_release(mutex) pthread_mutex_unlock(mutex)
51#define mos_warn(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
52#define MOS_LIB_UNREACHABLE() __builtin_unreachable()
58 void *(*func)(
void *);
61 pthread_create(&thread,
NULL, u.func, arg);
62 pthread_setname_np(thread,
name);
66#define RPC_SERVER_MAX_PENDING_CALLS 32
68typedef struct _rpc_server
79typedef struct _rpc_args_iter
110 rpc_context_t *context = (rpc_context_t *) arg;
112 if (context->server->on_connect)
113 context->server->on_connect(context);
123 mos_warn(
"failed to read message from client");
131 mos_warn(
"invalid magic in rpc request: %x", request->
magic);
160 for (
size_t i = 0; i < request->
args_count; i++)
177 context->request = request;
178 context->response =
NULL;
183 if (context->response ==
NULL)
187 context->response->call_id = request->
call_id;
188 context->response->data_size = 0;
191 context->response->result_code = result;
193 const bool written =
ipc_write_as_msg(context->client_fd, (
const char *) context->response,
sizeof(
rpc_response_t) + context->response->data_size);
196 free(context->response);
201 mos_warn(
"failed to write reply to client");
206 if (context->server->on_disconnect)
207 context->server->on_disconnect(context);
219#ifndef __MOS_KERNEL__
227#if !defined(__MOS_KERNEL__)
279 if ((
long) client_fd == -EINTR)
282 if ((
long) client_fd == -ECONNABORTED)
285#if !defined(__MOS_KERNEL__)
291 rpc_context_t *context = malloc(
sizeof(rpc_context_t));
292 memset(context, 0,
sizeof(rpc_context_t));
293 context->server = server;
294 context->client_fd = client_fd;
310 return context->data;
316 __atomic_exchange(&context->data, &data, &old, __ATOMIC_SEQ_CST);
322 return context->server;
327 if (!context->request)
329 return context->request->function_id;
334 if (context->arg_iter.next_arg_index >= context->request->args_count)
345 args->next_arg_index++;
358 if (
size != expected_size)
360 return (
void *) data;
363#define RPC_ARG_NEXT_IMPL(type, TYPE) \
364 type rpc_arg_next_##type(rpc_context_t *context) \
366 return *(type *) rpc_arg_next(context, NULL); \
386 const char *ptr = context->request->args_array;
387 for (
size_t i = 0; i < iarg; i++)
398 *argsize = arg->
size;
402#define RPC_GET_ARG_IMPL(type, TYPE) \
403 type rpc_arg_##type(const rpc_context_t *context, size_t iarg) \
405 return *(type *) rpc_arg(context, iarg, RPC_ARGTYPE_##TYPE, NULL); \
428 response->
call_id = context->request->call_id;
432 context->response = response;
435bool rpc_arg_pb(rpc_context_t *context,
const pb_msgdesc_t *fields,
void *val,
size_t argid)
449 const int retval =
pb_encode(&stream, type_fields, val);
#define RPC_RESPONSE_MAGIC
#define RPC_REQUEST_MAGIC
ipc_msg_t * ipc_read_msg(ipcfd_t fd)
Read an IPC message.
bool ipc_write_as_msg(ipcfd_t fd, const char *data, size_t size)
void ipc_msg_destroy(ipc_msg_t *buffer)
Destroy an IPC message.
bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct)
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen)
bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct)
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
static void * memcpy(void *s1, const void *s2, size_t n)
static void * memset(void *s, int c, size_t n)
const void * rpc_arg_sized_next(rpc_context_t *context, size_t expected_size)
Iterate to the next argument, and check that the size is as expected.
void rpc_server_destroy(rpc_server_t *server)
Destroy the RPC server.
rpc_server_t * rpc_server_create(const char *server_name, void *data)
Create a new RPC server.
#define MOS_LIB_ASSERT_X(cond, msg)
void rpc_server_set_on_disconnect(rpc_server_t *server, rpc_server_on_disconnect_t on_disconnect)
Sets the callback function to be called when a client disconnects from the RPC server.
rpc_server_t * rpc_context_get_server(const rpc_context_t *context)
Get the RPC server instance for an RPC call context.
void rpc_write_result_pb(rpc_context_t *context, const pb_msgdesc_t *type_fields, const void *val)
#define memzero(ptr, size)
void rpc_server_set_data(rpc_server_t *server, void *data)
Set the user data for the server.
const void * rpc_arg(const rpc_context_t *context, size_t iarg, rpc_argtype_t type, size_t *argsize)
bool rpc_server_register_functions(rpc_server_t *server, const rpc_function_info_t *functions, size_t count)
Register multiple functions with the server.
void * rpc_context_get_data(const rpc_context_t *context)
Get the context data for an RPC context.
static void start_thread(const char *name, thread_entry_t entry, void *arg)
void rpc_write_result(rpc_context_t *context, const void *data, size_t size)
Write a result to the reply.
void rpc_server_close(rpc_server_t *server)
Close the RPC server.
#define RPC_ARG_NEXT_IMPL(type, TYPE)
const char * rpc_arg_string(const rpc_context_t *context, size_t iarg)
MOSAPI int rpc_context_get_function_id(const rpc_context_t *context)
Get the function ID for an RPC call context.
static rpc_function_info_t * rpc_server_get_function(rpc_server_t *server, u32 function_id)
const char * rpc_arg_next_string(rpc_context_t *context)
static void rpc_handle_client(void *arg)
#define mos_warn(fmt,...)
bool rpc_arg_pb(rpc_context_t *context, const pb_msgdesc_t *fields, void *val, size_t argid)
const void * rpc_arg_next(rpc_context_t *context, size_t *size)
Iterate to the next argument.
void rpc_server_set_on_connect(rpc_server_t *server, rpc_server_on_connect_t on_connect)
Sets the callback function to be called when a client connects to the RPC server.
void * rpc_context_set_data(rpc_context_t *context, void *data)
Set the context data for an RPC client.
#define RPC_SERVER_MAX_PENDING_CALLS
void rpc_server_exec(rpc_server_t *server)
Run the server, this function will not return until the server is destroyed.
void * rpc_server_get_data(rpc_server_t *server)
Get the user data for the server.
#define RPC_GET_ARG_IMPL(type, TYPE)
#define MOS_LIB_ASSERT(cond)
void(* rpc_server_on_disconnect_t)(rpc_context_t *context)
struct _rpc_server rpc_server_t
void(* rpc_server_on_connect_t)(rpc_context_t *context)
rpc_response_t * response
rpc_response_t * response
rpc_argtype_t args_type[16]
rpc_result_code_t result_code
rpc_function_info_t * functions
rpc_server_on_connect_t on_connect
rpc_server_on_disconnect_t on_disconnect
void(* thread_entry_t)(void *arg)
should_inline fd_t syscall_ipc_create(const char *name, size_t max_pending_connections)
should_inline bool syscall_io_close(fd_t fd)
should_inline fd_t syscall_ipc_accept(fd_t fd)