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:
lahiker42 2008-08-25 17:50:52 +00:00
parent a81974883a
commit c4442d125c
8 changed files with 283 additions and 47 deletions

9
TODO
View File

@ -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

View File

@ -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);

View File

@ -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,
void *closure_data);
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);
};

View File

@ -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"
);
}

View File

@ -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");
}
}

View File

@ -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,9 +37,10 @@ simplerpc_server_from_listener (GskStreamListener *listener)
}
SimplerpcServer *
simplerpc_bind_ipv4 (int tcp_port,
SimplerpcBindIpv4Flags flags,
ProtobufCError **error)
simplerpc_server_bind_ipv4 (int tcp_port,
SimplerpcBindIpv4Flags flags,
SimplerpcContext *context,
ProtobufCError **error)
{
GskStreamListener *listener;
GskSocketAddress *addr;
@ -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,
ProtobufCError **error)
simplerpc_server_bind_local (const char *path,
SimplerpcContext *context,
ProtobufCError **error)
{
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)
{
...
return simplerpc_server_from_listener (listener);
}
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,
const char *domain,
ProtobufCService *service)
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)
{

View File

@ -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);

View 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);
}