diff --git a/src/google/protobuf-c/protobuf-c-private.h b/src/google/protobuf-c/protobuf-c-private.h index 80e51d3..4b505ed 100644 --- a/src/google/protobuf-c/protobuf-c-private.h +++ b/src/google/protobuf-c/protobuf-c-private.h @@ -34,3 +34,11 @@ int protobuf_c_int_ranges_lookup (unsigned n_ranges, #define PROTOBUF_C_SERVICE_DESCRIPTOR_MAGIC 0x14159bc3 #define PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9 #define PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC 0x114315af + +/* === behind the scenes on the generated service's __init functions */ +typedef void (*ProtobufCServiceDestroy) (ProtobufCService *service); +void +protobuf_c_service_generated_init (ProtobufCService *service, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCServiceDestroy destroy); + diff --git a/src/google/protobuf-c/protobuf-c.c b/src/google/protobuf-c/protobuf-c.c index 9afe844..cb61e44 100644 --- a/src/google/protobuf-c/protobuf-c.c +++ b/src/google/protobuf-c/protobuf-c.c @@ -35,6 +35,15 @@ #define TRUE 1 #define FALSE 0 +#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC) +#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC) +#define ASSERT_IS_MESSAGE(message) \ + ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor) +#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C_SERVICE_DESCRIPTOR_MAGIC) + /* --- allocator --- */ static void protobuf_c_out_of_memory_default (void) @@ -354,6 +363,7 @@ size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) { unsigned i; size_t rv = 0; + ASSERT_IS_MESSAGE (message); for (i = 0; i < message->descriptor->n_fields; i++) { const ProtobufCFieldDescriptor *field = message->descriptor->fields + i; @@ -662,6 +672,7 @@ size_t protobuf_c_message_pack (const ProtobufCMessage *message, { unsigned i; size_t rv = 0; + ASSERT_IS_MESSAGE (message); for (i = 0; i < message->descriptor->n_fields; i++) { const ProtobufCFieldDescriptor *field = message->descriptor->fields + i; @@ -839,6 +850,7 @@ protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message, { unsigned i; size_t rv = 0; + ASSERT_IS_MESSAGE (message); for (i = 0; i < message->descriptor->n_fields; i++) { const ProtobufCFieldDescriptor *field = message->descriptor->fields + i; @@ -1266,6 +1278,8 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc, unsigned f; unsigned i_slab; + ASSERT_IS_MESSAGE_DESCRIPTOR (desc); + if (allocator == NULL) allocator = &protobuf_c_default_allocator; rv = ALLOC (allocator, desc->sizeof_message); @@ -1455,8 +1469,10 @@ protobuf_c_message_free_unpacked (ProtobufCMessage *message, { const ProtobufCMessageDescriptor *desc = message->descriptor; unsigned f; + ASSERT_IS_MESSAGE (message); if (allocator == NULL) allocator = &protobuf_c_default_allocator; + message->descriptor = NULL; for (f = 0; f < desc->n_fields; f++) { if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) @@ -1536,30 +1552,16 @@ service_machgen_invoke(ProtobufCService *service, (*handler) (machgen->service, input, closure, closure_data); } -static void -service_machgen_destroy (ProtobufCService *service) +void +protobuf_c_service_generated_init (ProtobufCService *service, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCServiceDestroy destroy) { - /* destroy function always follows the methods. - we assume these function pointers are the same size. */ - DestroyHandler *handlers; - DestroyHandler handler; - ServiceMachgen *machgen = (ServiceMachgen *) service; - handlers = (DestroyHandler *) machgen->service; - handler = handlers[service->descriptor->n_methods]; - (*handler) (machgen->service); - FREE (&protobuf_c_default_allocator, service); -} -ProtobufCService * -protobuf_c_create_service_from_vfuncs - (const ProtobufCServiceDescriptor *descriptor, - void *service) -{ - ServiceMachgen *rv = ALLOC (&protobuf_c_default_allocator, sizeof (ServiceMachgen)); - rv->base.descriptor = descriptor; - rv->base.invoke = service_machgen_invoke; - rv->base.destroy = service_machgen_destroy; - rv->service = service; - return &rv->base; + ASSERT_IS_SERVICE_DESCRIPTOR(descriptor); + service->descriptor = descriptor; + service->destroy = destroy; + service->invoke = service_machgen_invoke; + memset (service + 1, 0, descriptor->n_methods * sizeof (GenericHandler)); } void protobuf_c_service_destroy (ProtobufCService *service) diff --git a/src/google/protobuf-c/protobuf-c.h b/src/google/protobuf-c/protobuf-c.h index 12a1e49..6062d82 100644 --- a/src/google/protobuf-c/protobuf-c.h +++ b/src/google/protobuf-c/protobuf-c.h @@ -205,12 +205,11 @@ struct _ProtobufCService void (*destroy) (ProtobufCService *service); }; -ProtobufCService *protobuf_c_create_service_from_vfuncs - (const ProtobufCServiceDescriptor *descriptor, - void *service); + void protobuf_c_service_destroy (ProtobufCService *); + /* --- wire format enums --- */ typedef enum { diff --git a/src/google/protobuf/compiler/c/c_service.cc b/src/google/protobuf/compiler/c/c_service.cc index b3fe2a2..f8a67b9 100644 --- a/src/google/protobuf/compiler/c/c_service.cc +++ b/src/google/protobuf/compiler/c/c_service.cc @@ -36,6 +36,7 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor, vars_["fullname"] = descriptor_->full_name(); vars_["cname"] = FullNameToC(descriptor_->full_name()); vars_["lcfullname"] = FullNameToLower(descriptor_->full_name()); + vars_["lcfullpadd"] = ConvertToSpaces(vars_["lcfullname"]); vars_["package"] = descriptor_->file()->package(); if (dllexport_decl.empty()) { vars_["dllexport"] = ""; @@ -58,7 +59,8 @@ void ServiceGenerator::GenerateVfuncs(io::Printer* printer) printer->Print(vars_, "typedef struct _$cname$_Service $cname$_Service;\n" "struct _$cname$_Service\n" - "{\n"); + "{\n" + " ProtobufCService base;\n"); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor *method = descriptor_->method(i); string lcname = CamelToLower(method->name()); @@ -72,10 +74,12 @@ void ServiceGenerator::GenerateVfuncs(io::Printer* printer) " $metpad$ $output_typename$_Closure closure,\n" " $metpad$ void *closure_data);\n"); } - printer->Print(vars_, - " void (*destroy) ($cname$_Service *service);\n"); printer->Print(vars_, "};\n"); + printer->Print(vars_, + "typedef void (*$cname$_ServiceDestroy)($cname$_Service);\n" + "void $lcfullname$__init ($cname$_Service *service,\n" + " $lcfullpadd$ $cname$_ServiceDestroy destroy);\n"); } void ServiceGenerator::GenerateCallersDeclarations(io::Printer* printer) { @@ -111,9 +115,21 @@ void ServiceGenerator::GenerateDescriptorDeclarations(io::Printer* printer) void ServiceGenerator::GenerateCFile(io::Printer* printer) { GenerateServiceDescriptor(printer); - GenerateCreateService(printer); GenerateCallersImplementations(printer); + GenerateInit(printer); } +void ServiceGenerator::GenerateInit(io::Printer* printer) +{ + printer->Print(vars_, + "void $lcfullname$__init ($cname$_Service *service,\n" + " $lcfullpadd$ $cname$_ServiceDestroy destroy)\n" + "{\n" + " protobuf_c_service_generated_init (&service->base,\n" + " &$lcfullname$__descriptor,\n" + " (ProtobufCServiceDestroy) destroy);\n" + "}\n"); +} + void ServiceGenerator::GenerateServiceDescriptor(io::Printer* printer) { int n_methods = descriptor_->method_count(); @@ -141,14 +157,6 @@ void ServiceGenerator::GenerateServiceDescriptor(io::Printer* printer) "};\n"); } -void ServiceGenerator::GenerateCreateService(io::Printer* printer) -{ - printer->Print(vars_, "ProtobufCService *\n" - "$lcfullname$__create_service ($cname$_Service *service)\n" - "{\n" - " return protobuf_c_create_service_from_vfuncs (&$lcfullname$__descriptor, service);\n" - "}\n"); -} void ServiceGenerator::GenerateCallersImplementations(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { diff --git a/src/google/protobuf/compiler/c/c_service.h b/src/google/protobuf/compiler/c/c_service.h index d20d457..7beb074 100644 --- a/src/google/protobuf/compiler/c/c_service.h +++ b/src/google/protobuf/compiler/c/c_service.h @@ -56,7 +56,7 @@ class ServiceGenerator { // Source file stuff. void GenerateCFile(io::Printer* printer); void GenerateServiceDescriptor(io::Printer* printer); - void GenerateCreateService(io::Printer* printer); + void GenerateInit(io::Printer* printer); void GenerateCallersImplementations(io::Printer* printer); const ServiceDescriptor* descriptor_; diff --git a/src/simplerpc/simplerpc.c b/src/simplerpc/simplerpc.c new file mode 100644 index 0000000..751617c --- /dev/null +++ b/src/simplerpc/simplerpc.c @@ -0,0 +1,89 @@ +#include + +struct _SimplerpcServerStream +{ + SimplerpcServer *server; + GskStream *connection; + GskBuffer incoming, outgoing; +}; + +struct _SimplerpcServer +{ + GskStreamListener *listener; + GHashTable *domain_to_service; + guint ref_count; +}; + + +static SimplerpcServer * +simplerpc_server_from_listener (GskStreamListener *listener) +{ + 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); + gsk_stream_listener_handle_accept (listener, handle_accept, + handle_listener_error, + rv, NULL); +} + +SimplerpcServer * +simplerpc_bind_ipv4 (int tcp_port, + SimplerpcBindIpv4Flags flags, + ProtobufCError **error) +{ + GskStreamListener *listener; + GskSocketAddress *addr; + const guint8 *ipaddr = (flags & SIMPLERPC_BIND_IPV4_LOCALHOST) + ? gsk_ipv4_ip_address_localhost + : gsk_ipv4_ip_address_any; + addr = gsk_socket_address_new_ipv4 (ipaddr, tcp_port); + 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); +} + +SimplerpcServer * +simplerpc_bind_local (const char *path, + ProtobufCError **error) +{ + ... + return simplerpc_server_from_listener (listener); +} +void +simplerpc_add_service (SimplerpcServer *server, + const char *domain, + ProtobufCService *service) +{ + ... +} +void +simplerpc_server_destroy (SimplerpcServer *server) +{ + ... +} + + + +SimplerpcClient * +simplerpc_client_new_ipv4 (const uint8_t *ip_addr, + uint16_t port, + ProtobufCError **error) +{ + ... +} + +ProtobufCService * +simplerpc_client_new_service (SimplerpcClient *client, + const char *domain, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCError **error) +{ + ... +} diff --git a/src/simplerpc/simplerpc.h b/src/simplerpc/simplerpc.h new file mode 100644 index 0000000..6bf839f --- /dev/null +++ b/src/simplerpc/simplerpc.h @@ -0,0 +1,27 @@ +#ifndef __PROTOBUF_SIMPLERPC_H_ +#ifndef __PROTOBUF_SIMPLERPC_H_ + +#include + +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, + const char *domain, + ProtobufCService *service); +void simplerpc_server_destroy (SimplerpcServer *server); + + + +SimplerpcClient *simplerpc_client_new_ipv4 (const uint8_t *ip_addr, + uint16_t port, + ProtobufCError **error); + +ProtobufCService *simplerpc_client_new_service (SimplerpcClient *client, + const char *domain, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCError **error); + +#endif