mirror of
https://github.com/protobuf-c/protobuf-c.git
synced 2024-12-27 13:21:12 +08:00
Work on simplerpc. revisit service api.. may need to rerevisit
git-svn-id: https://protobuf-c.googlecode.com/svn/trunk@46 00440858-1255-0410-a3e6-75ea37f81c3a
This commit is contained in:
parent
a81974883a
commit
c4442d125c
9
TODO
9
TODO
@ -1,15 +1,16 @@
|
||||
- check over documentation again
|
||||
- make services derive from ProtobufCService; be usable with a cast.
|
||||
- provide example rpc
|
||||
- at least include extensions in Descriptor
|
||||
|
||||
- To document:
|
||||
- Documentations:
|
||||
- __INIT macro
|
||||
- service __init function
|
||||
- get rid of docs for create-service; update generally
|
||||
- check over documentation again
|
||||
|
||||
- support Group (whatever it is)
|
||||
- almost no code generator options are obeyed
|
||||
- ISSUE: strings may not contain NULs
|
||||
- generate Init functions / handle default values
|
||||
- at least include extensions in Descriptor
|
||||
- proper support for extensions (not sure i get what's needed)
|
||||
|
||||
- get rid of kThick/ThinSeparator if we decide not to use them
|
||||
|
@ -1534,14 +1534,12 @@ struct _ServiceMachgen
|
||||
typedef void (*DestroyHandler)(void *service);
|
||||
typedef void (*GenericHandler)(void *service,
|
||||
const ProtobufCMessage *input,
|
||||
ProtobufCClosure closure,
|
||||
void *closure_data);
|
||||
ProtobufCClosure *closure);
|
||||
static void
|
||||
service_machgen_invoke(ProtobufCService *service,
|
||||
unsigned method_index,
|
||||
const ProtobufCMessage *input,
|
||||
ProtobufCClosure closure,
|
||||
void *closure_data)
|
||||
ProtobufCClosure *closure)
|
||||
{
|
||||
GenericHandler *handlers;
|
||||
GenericHandler handler;
|
||||
@ -1549,7 +1547,7 @@ service_machgen_invoke(ProtobufCService *service,
|
||||
PROTOBUF_C_ASSERT (method_index < service->descriptor->n_methods);
|
||||
handlers = (GenericHandler *) machgen->service;
|
||||
handler = handlers[method_index];
|
||||
(*handler) (machgen->service, input, closure, closure_data);
|
||||
(*handler) (machgen->service, input, closure);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1564,6 +1562,55 @@ protobuf_c_service_generated_init (ProtobufCService *service,
|
||||
memset (service + 1, 0, descriptor->n_methods * sizeof (GenericHandler));
|
||||
}
|
||||
|
||||
ProtobufCClosure *
|
||||
protobuf_c_closure_new (const ProtobufCMessageDescriptor *descriptor,
|
||||
ProtobufCClosureFunc func,
|
||||
void *closure_data,
|
||||
ProtobufCDestroyFunc destroy)
|
||||
{
|
||||
ProtobufCClosure *rv;
|
||||
rv = protobuf_c_default_allocator.alloc (&protobuf_c_default_allocator,
|
||||
sizeof (ProtobufCClosure));
|
||||
rv->descriptor = descriptor;
|
||||
rv->handle_message = func;
|
||||
rv->handle_error = NULL;
|
||||
rv->closure_data = closure_data;
|
||||
rv->destroy_data = destroy;
|
||||
return rv;
|
||||
}
|
||||
#undef protobuf_c_closure_set_error_handler
|
||||
void
|
||||
protobuf_c_closure_set_error_handler (ProtobufCClosure *closure,
|
||||
ProtobufCClosureErrorFunc func)
|
||||
{
|
||||
closure->handle_error = func;
|
||||
}
|
||||
|
||||
static inline void free_closure (ProtobufCClosure *closure)
|
||||
{
|
||||
if (closure->destroy_data)
|
||||
closure->destroy_data (closure->closure_data);
|
||||
protobuf_c_default_allocator.free (&protobuf_c_default_allocator, closure);
|
||||
}
|
||||
|
||||
void protobuf_c_closure_run (ProtobufCClosure *closure,
|
||||
const ProtobufCMessage *message)
|
||||
{
|
||||
PROTOBUF_C_ASSERT (closure->descriptor == message->descriptor);
|
||||
closure->handle_message (message, closure->closure_data);
|
||||
free_closure (closure);
|
||||
}
|
||||
|
||||
void
|
||||
protobuf_c_closure_error (ProtobufCClosure *closure,
|
||||
const ProtobufCError *error)
|
||||
{
|
||||
if (closure->handle_error != NULL)
|
||||
closure->handle_error (error, closure->closure_data);
|
||||
free_closure (closure);
|
||||
}
|
||||
|
||||
|
||||
void protobuf_c_service_destroy (ProtobufCService *service)
|
||||
{
|
||||
service->destroy (service);
|
||||
|
@ -173,6 +173,23 @@ void protobuf_c_message_free_unpacked (ProtobufCMessage *message,
|
||||
typedef struct _ProtobufCMethodDescriptor ProtobufCMethodDescriptor;
|
||||
typedef struct _ProtobufCServiceDescriptor ProtobufCServiceDescriptor;
|
||||
|
||||
typedef struct _ProtobufCError ProtobufCError;
|
||||
struct _ProtobufCError
|
||||
{
|
||||
const char *domain; /* must be static string */
|
||||
unsigned code;
|
||||
char *message;
|
||||
};
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
|
||||
#define PROTOBUF_C_PRINTF_ATTR( format_idx, arg_idx ) \
|
||||
__attribute__((__format__ (__printf__, format_idx, arg_idx)))
|
||||
#endif
|
||||
ProtobufCError *protobuf_c_error_new (const char *domain,
|
||||
unsigned code,
|
||||
const char *message_format,
|
||||
...) PROTOBUF_C_PRINTF_ATTR(3,4);
|
||||
|
||||
|
||||
struct _ProtobufCMethodDescriptor
|
||||
{
|
||||
const char *name;
|
||||
@ -192,16 +209,45 @@ struct _ProtobufCServiceDescriptor
|
||||
};
|
||||
|
||||
typedef struct _ProtobufCService ProtobufCService;
|
||||
typedef void (*ProtobufCClosure)(const ProtobufCMessage *message,
|
||||
typedef void (*ProtobufCClosureFunc) (const ProtobufCMessage *message,
|
||||
void *closure_data);
|
||||
typedef void (*ProtobufCClosureErrorFunc)(const ProtobufCError *error,
|
||||
void *closure_data);
|
||||
typedef void (*ProtobufCDestroyFunc) (void *closure_data);
|
||||
|
||||
typedef struct _ProtobufCClosure ProtobufCClosure;
|
||||
struct _ProtobufCClosure
|
||||
{
|
||||
const ProtobufCMessageDescriptor *descriptor;
|
||||
ProtobufCClosureFunc handle_message;
|
||||
ProtobufCClosureErrorFunc handle_error;
|
||||
void *closure_data;
|
||||
ProtobufCDestroyFunc destroy_data;
|
||||
};
|
||||
|
||||
ProtobufCClosure *protobuf_c_closure_new (const ProtobufCMessageDescriptor *,
|
||||
ProtobufCClosureFunc func,
|
||||
void *closure_data,
|
||||
ProtobufCDestroyFunc destroy);
|
||||
void protobuf_c_closure_set_error_handler
|
||||
(ProtobufCClosure *closure,
|
||||
ProtobufCClosureErrorFunc func);
|
||||
#define protobuf_c_closure_set_error_handler(closure, func) \
|
||||
do { ((closure)->handle_error) = (func); } while(0)
|
||||
|
||||
/* these functions destroy the closure */
|
||||
void protobuf_c_closure_run (ProtobufCClosure *closure,
|
||||
const ProtobufCMessage *message);
|
||||
void protobuf_c_closure_error(ProtobufCClosure *closure,
|
||||
const ProtobufCError *error);
|
||||
|
||||
struct _ProtobufCService
|
||||
{
|
||||
const ProtobufCServiceDescriptor *descriptor;
|
||||
void (*invoke)(ProtobufCService *service,
|
||||
unsigned method_index,
|
||||
const ProtobufCMessage *input,
|
||||
ProtobufCClosure closure,
|
||||
void *closure_data);
|
||||
ProtobufCClosure *closure);
|
||||
void (*destroy) (ProtobufCService *service);
|
||||
};
|
||||
|
||||
|
@ -120,16 +120,16 @@ GenerateStructDefinition(io::Printer* printer) {
|
||||
}
|
||||
printer->Outdent();
|
||||
|
||||
printer->Print(vars, "};\n\n");
|
||||
printer->Print(vars, "};\n");
|
||||
|
||||
printer->Print(vars, "#define $ucclassname$__INIT \\\n"
|
||||
" { PROTOBUF_C_MESSAGE_INIT (&$lcclassname$__descriptor)");
|
||||
" { PROTOBUF_C_MESSAGE_INIT (&$lcclassname$__descriptor) \\\n ");
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor *field = descriptor_->field(i);
|
||||
printer->Print(", ");
|
||||
field_generators_.get(field).GenerateStaticInit(printer);
|
||||
}
|
||||
printer->Print(" }\n");
|
||||
printer->Print(" }\n\n\n");
|
||||
|
||||
}
|
||||
|
||||
@ -180,10 +180,16 @@ void MessageGenerator::GenerateClosureTypedef(io::Printer* printer)
|
||||
}
|
||||
std::map<string, string> vars;
|
||||
vars["name"] = FullNameToC(descriptor_->full_name());
|
||||
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
||||
printer->Print(vars,
|
||||
"typedef void (*$name$_Closure)\n"
|
||||
"typedef void (*$name$__ClosureFunc)\n"
|
||||
" (const $name$ *message,\n"
|
||||
" void *closure_data);\n");
|
||||
" void *closure_data);\n"
|
||||
"ProtobufCClosure *$lcclassname$__closure_new\n"
|
||||
" ($name$__ClosureFunc func,\n"
|
||||
" void *closure_data,\n"
|
||||
" ProtobufCDestroyFunc destroy);\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -240,6 +246,15 @@ GenerateHelperFunctionDefinitions(io::Printer* printer)
|
||||
" PROTOBUF_C_ASSERT (message->base.descriptor == &$lcclassname$__descriptor);\n"
|
||||
" protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n"
|
||||
"}\n"
|
||||
"ProtobufCClosure *$lcclassname$__closure_new\n"
|
||||
" ($classname$__ClosureFunc func,\n"
|
||||
" void *closure_data,\n"
|
||||
" ProtobufCDestroyFunc destroy)\n"
|
||||
"{\n"
|
||||
" return protobuf_c_closure_new (&$lcclassname$__descriptor,\n"
|
||||
" (ProtobufCClosureFunc) func,\n"
|
||||
" closure_data, destroy);\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -71,8 +71,7 @@ void ServiceGenerator::GenerateVfuncs(io::Printer* printer)
|
||||
printer->Print(vars_,
|
||||
" void (*$method$)($cname$_Service *service,\n"
|
||||
" $metpad$ const $input_typename$ *input,\n"
|
||||
" $metpad$ $output_typename$_Closure closure,\n"
|
||||
" $metpad$ void *closure_data);\n");
|
||||
" $metpad$ ProtobufCClosure *closure);\n");
|
||||
}
|
||||
printer->Print(vars_,
|
||||
"};\n");
|
||||
@ -95,8 +94,7 @@ void ServiceGenerator::GenerateCallersDeclarations(io::Printer* printer)
|
||||
printer->Print(vars_,
|
||||
"void $lcfullname$__$method$(ProtobufCService *service,\n"
|
||||
" $padddddddddddddddddd$ const $input_typename$ *input,\n"
|
||||
" $padddddddddddddddddd$ $output_typename$_Closure closure,\n"
|
||||
" $padddddddddddddddddd$ void *closure_data);\n");
|
||||
" $padddddddddddddddddd$ ProtobufCClosure *closure);\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,17 +165,18 @@ void ServiceGenerator::GenerateCallersImplementations(io::Printer* printer)
|
||||
vars_["metpad"] = ConvertToSpaces(lcname);
|
||||
vars_["input_typename"] = FullNameToC(method->input_type()->full_name());
|
||||
vars_["output_typename"] = FullNameToC(method->output_type()->full_name());
|
||||
vars_["lc_output_typename"] = FullNameToLower(method->output_type()->full_name());
|
||||
vars_["padddddddddddddddddd"] = ConvertToSpaces(lcfullname + "__" + lcname);
|
||||
vars_["index"] = SimpleItoa(i);
|
||||
|
||||
printer->Print(vars_,
|
||||
"void $lcfullname$__$method$(ProtobufCService *service,\n"
|
||||
" $padddddddddddddddddd$ const $input_typename$ *input,\n"
|
||||
" $padddddddddddddddddd$ $output_typename$_Closure closure,\n"
|
||||
" $padddddddddddddddddd$ void *closure_data)\n"
|
||||
" $padddddddddddddddddd$ ProtobufCClosure *closure)\n"
|
||||
"{\n"
|
||||
" PROTOBUF_C_ASSERT (service->descriptor == &$lcfullname$__descriptor);\n"
|
||||
" service->invoke(service, $index$, (const ProtobufCMessage *) input, (ProtobufCClosure) closure, closure_data);\n"
|
||||
" PROTOBUF_C_ASSERT (closure->descriptor == &$lc_output_typename$__descriptor);\n"
|
||||
" service->invoke(service, $index$, (const ProtobufCMessage *) input, closure);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
#include <gsk/gsk.h>
|
||||
#include "generated/simplerpc.pb-c.h"
|
||||
|
||||
/* === server === */
|
||||
|
||||
struct _SimplerpcServerStream
|
||||
{
|
||||
@ -7,20 +10,24 @@ struct _SimplerpcServerStream
|
||||
GskBuffer incoming, outgoing;
|
||||
};
|
||||
|
||||
struct _SimplerpcServer
|
||||
struct _SimplerpcContext
|
||||
{
|
||||
GskStreamListener *listener;
|
||||
GHashTable *domain_to_service;
|
||||
guint ref_count;
|
||||
};
|
||||
|
||||
struct _SimplerpcServer
|
||||
{
|
||||
GskStreamListener *listener;
|
||||
SimplerpcContext *context;
|
||||
};
|
||||
|
||||
static SimplerpcServer *
|
||||
simplerpc_server_from_listener (GskStreamListener *listener)
|
||||
simplerpc_server_from_listener (GskStreamListener *listener,
|
||||
SimplerpcContext *context)
|
||||
{
|
||||
SimplerpcServer *rv = g_slice_new (SimplerpcServer);
|
||||
rv->listener = listener;
|
||||
rv->ref_count = 1;
|
||||
rv->domain_to_service = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free,
|
||||
protobuf_c_server_destroy);
|
||||
@ -30,8 +37,9 @@ simplerpc_server_from_listener (GskStreamListener *listener)
|
||||
}
|
||||
|
||||
SimplerpcServer *
|
||||
simplerpc_bind_ipv4 (int tcp_port,
|
||||
simplerpc_server_bind_ipv4 (int tcp_port,
|
||||
SimplerpcBindIpv4Flags flags,
|
||||
SimplerpcContext *context,
|
||||
ProtobufCError **error)
|
||||
{
|
||||
GskStreamListener *listener;
|
||||
@ -46,33 +54,111 @@ simplerpc_bind_ipv4 (int tcp_port,
|
||||
set_protobuf_c_error_from_gerror (error, ge);
|
||||
return NULL;
|
||||
}
|
||||
return simplerpc_server_from_listener (listener);
|
||||
return simplerpc_server_from_listener (listener, context);
|
||||
}
|
||||
|
||||
SimplerpcServer *
|
||||
simplerpc_bind_local (const char *path,
|
||||
simplerpc_server_bind_local (const char *path,
|
||||
SimplerpcContext *context,
|
||||
ProtobufCError **error)
|
||||
{
|
||||
...
|
||||
return simplerpc_server_from_listener (listener);
|
||||
GskStreamListener *listener;
|
||||
GskSocketAddress *addr;
|
||||
addr = gsk_socket_address_new_local (path);
|
||||
listener = gsk_stream_listener_socket_new_bind (addr, &ge);
|
||||
if (listener == NULL)
|
||||
{
|
||||
set_protobuf_c_error_from_gerror (error, ge);
|
||||
return NULL;
|
||||
}
|
||||
return simplerpc_server_from_listener (listener, context);
|
||||
}
|
||||
|
||||
|
||||
typedef struct _BuiltinService BuiltinService;
|
||||
struct _BuiltinService
|
||||
{
|
||||
Simplerpc__Builtin_Service base;
|
||||
SimplerpcContext *context;
|
||||
};
|
||||
|
||||
static void
|
||||
builtin_service_list_domains (Simplerpc__Builtin_Service *service,
|
||||
const Simplerpc__DomainListRequest *input,
|
||||
ProtobufCClosure *closure)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
static void
|
||||
builtin_service_destroy (Simplerpc__Builtin_Service *ser)
|
||||
{
|
||||
BuiltinService *bs = (BuiltinService *) ser;
|
||||
g_slice_free (BuiltinService, bs);
|
||||
}
|
||||
|
||||
SimplerpcContext *
|
||||
simplerpc_context_new (void)
|
||||
{
|
||||
SimplerpcContext *context = g_slice_new (SimplerpcContext);
|
||||
BuiltinService *service;
|
||||
context->domain_to_service
|
||||
= g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify) protobuf_c_server_destroy);
|
||||
context->ref_count = 1;
|
||||
|
||||
service = g_slice_new (BuiltinService);
|
||||
simplerpc__builtin__init (&service->base);
|
||||
service->base.list_domains = builtin_service_list_domains;
|
||||
service->base.base.destroy = builtin_service_free;
|
||||
service->context = context;
|
||||
simplerpc_context_add_service (context, "simplerpc.builtin",
|
||||
(ProtobufCService *) service);
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
simplerpc_add_service (SimplerpcServer *server,
|
||||
simplerpc_context_add_service (SimplerpcContext *context,
|
||||
const char *domain,
|
||||
ProtobufCService *service)
|
||||
{
|
||||
...
|
||||
g_hash_table_insert (context, g_strdup (domain), service);
|
||||
}
|
||||
|
||||
void
|
||||
simplerpc_server_destroy (SimplerpcServer *server)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
/* === client === */
|
||||
typedef struct _SimplerpcClientRequest SimplerpcClientRequest;
|
||||
typedef struct _SimplerpcClient SimplerpcClient;
|
||||
|
||||
struct _SimplerpcClientRequest
|
||||
{
|
||||
guint64 request_id;
|
||||
gsize request_len;
|
||||
guint8 *request_data;
|
||||
ProtobufCClosure *closure;
|
||||
SimplerpcClientRequest *prev, *next;
|
||||
};
|
||||
|
||||
struct _SimplerpcClient
|
||||
{
|
||||
GskStream *transport;
|
||||
GskBuffer incoming;
|
||||
GskBuffer outgoing;
|
||||
GHashTable *request_id_to_request;
|
||||
|
||||
guint ref_count;
|
||||
SimplerpcClientRequest *first, *last;
|
||||
};
|
||||
|
||||
SimplerpcClient *
|
||||
simplerpc_client_new_ipv4 (const uint8_t *ip_addr,
|
||||
simplerpc_client_new_ipv4 (const char *hostname,
|
||||
uint16_t port,
|
||||
ProtobufCError **error)
|
||||
{
|
||||
|
@ -3,14 +3,19 @@
|
||||
|
||||
#include <google/protobuf-c/protobuf.h>
|
||||
|
||||
SimplerpcServer * simplerpc_bind_ipv4 (int tcp_port,
|
||||
SimplerpcBindIpv4Flags flags,
|
||||
ProtobufCError **error);
|
||||
SimplerpcServer * simplerpc_bind_local (const char *path,
|
||||
ProtobufCError **error);
|
||||
void simplerpc_add_service (SimplerpcServer *server,
|
||||
SimplerpcContext *simplerpc_context_new (void);
|
||||
void simplerpc_context_add_service
|
||||
(SimplerpcServer *server,
|
||||
const char *domain,
|
||||
ProtobufCService *service);
|
||||
|
||||
SimplerpcServer * simplerpc_bind_ipv4 (int tcp_port,
|
||||
SimplerpcBindIpv4Flags flags,
|
||||
SimplerpcContext *context,
|
||||
ProtobufCError **error);
|
||||
SimplerpcServer * simplerpc_bind_local (const char *path,
|
||||
SimplerpcContext *context,
|
||||
ProtobufCError **error);
|
||||
void simplerpc_server_destroy (SimplerpcServer *server);
|
||||
|
||||
|
||||
|
37
src/simplerpc/simplerpc.proto
Normal file
37
src/simplerpc/simplerpc.proto
Normal file
@ -0,0 +1,37 @@
|
||||
package simplerpc;
|
||||
|
||||
message RequestPreamble
|
||||
{
|
||||
required uint32 size = 1;
|
||||
required string domain = 2;
|
||||
required uint64 request_id = 3;
|
||||
}
|
||||
|
||||
message ResponsePreamble
|
||||
{
|
||||
required uint32 size = 1;
|
||||
required uint64 request_id = 2;
|
||||
}
|
||||
|
||||
// builtin services (domain=simplerpc.builtin)
|
||||
message DomainListRequest
|
||||
{
|
||||
required bool get_service_defs = 1;
|
||||
}
|
||||
|
||||
message DomainInfo
|
||||
{
|
||||
required string domain = 1;
|
||||
optional string service = 2;
|
||||
optional bytes service_defs = 3;
|
||||
}
|
||||
|
||||
message DomainListResponse
|
||||
{
|
||||
repeated DomainInfo info = 1;
|
||||
}
|
||||
|
||||
service Builtin
|
||||
{
|
||||
rpc ListDomains(DomainListRequest) returns (DomainListResponse);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user