diff --git a/protobuf-c-rpc/protobuf-c-rpc.c b/protobuf-c-rpc/protobuf-c-rpc.c index 09b40cc..fc1b147 100644 --- a/protobuf-c-rpc/protobuf-c-rpc.c +++ b/protobuf-c-rpc/protobuf-c-rpc.c @@ -562,7 +562,6 @@ handle_client_fd_events (int fd, uint32_t header[4]; unsigned status_code, method_index, message_length, request_id; Closure *closure; - uint8_t *packed_data; ProtobufCMessage *msg; protobuf_c_data_buffer_peek (&client->incoming, header, sizeof (header)); status_code = uint32_from_le (header[0]); @@ -583,23 +582,36 @@ handle_client_fd_events (int fd, } closure = client->info.connected.closures + (request_id - 1); - /* read message and unpack */ + /* Discard the RPC header */ protobuf_c_data_buffer_discard (&client->incoming, 16); - packed_data = client->allocator->alloc (client->allocator, message_length); - protobuf_c_data_buffer_read (&client->incoming, packed_data, message_length); - /* TODO: use fast temporary allocator */ - msg = protobuf_c_message_unpack (closure->response_type, - client->allocator, - message_length, - packed_data); - if (msg == NULL) - { - fprintf(stderr, "unable to unpack msg of length %u", message_length); - client_failed (client, "failed to unpack message"); - client->allocator->free (client->allocator, packed_data); - return; - } + if (status_code == PROTOBUF_C_STATUS_CODE_SUCCESS) + { + /* read message and unpack */ + uint8_t *packed_data = + client->allocator->alloc (client->allocator, message_length); + protobuf_c_data_buffer_read (&client->incoming, packed_data, message_length); + + /* TODO: use fast temporary allocator */ + msg = protobuf_c_message_unpack (closure->response_type, + client->allocator, + message_length, + packed_data); + + client->allocator->free (client->allocator, packed_data); + if (msg == NULL) + { + fprintf(stderr, "unable to unpack msg of length %u", message_length); + client_failed (client, "failed to unpack message"); + return; + } + } + else + { + /* Server did not send a response message */ + protobuf_c_assert (message_length == 0); + msg = NULL; + } /* invoke closure */ closure->closure (msg, closure->closure_data); @@ -609,8 +621,8 @@ handle_client_fd_events (int fd, client->info.connected.first_free_request_id = request_id; /* clean up */ - protobuf_c_message_free_unpacked (msg, client->allocator); - client->allocator->free (client->allocator, packed_data); + if (msg) + protobuf_c_message_free_unpacked (msg, client->allocator); } } } diff --git a/protobuf-c-rpc/t/test-rpc.c b/protobuf-c-rpc/t/test-rpc.c index 2bccfd3..2a186d7 100644 --- a/protobuf-c-rpc/t/test-rpc.c +++ b/protobuf-c-rpc/t/test-rpc.c @@ -33,7 +33,10 @@ test__by_name (Foo__DirLookup_Service *service, char *email = NULL; (void) service; if (name->name == NULL) + { closure (NULL, closure_data); + return; + } else if (strcmp (name->name, "dave") == 0) { number = "555-1212"; @@ -130,6 +133,12 @@ test_service (ProtobufCService *service) foo__dir_lookup__by_name (service, &name, test_not_found_closure, &is_done); while (!is_done) protobuf_c_dispatch_run (protobuf_c_dispatch_default ()); + + name.name = NULL; + is_done = 0; + foo__dir_lookup__by_name (service, &name, test_defunct_closure, &is_done); + while (!is_done) + protobuf_c_dispatch_run (protobuf_c_dispatch_default ()); } static void test_defunct_client (ProtobufCService *service)