diff options
author | Pierre Langlois <pierre.langlois@arm.com> | 2015-02-12 14:58:43 +0000 |
---|---|---|
committer | Pierre Langlois <pierre.langlois@arm.com> | 2016-03-04 17:39:40 +0000 |
commit | 553cba749ec883222c210290c4e9389618915055 (patch) | |
tree | 50126d3df0a87db3e86bdd54f348c10678749cf0 | |
parent | a7395a1f865863f69f2f5e7b5ce9d095fdd51d46 (diff) | |
download | kdbinder-553cba749ec883222c210290c4e9389618915055.tar.gz |
libkdbinder: kdbus: return Reply objects
This commit changes all the Connection method to return a Reply object
holding the error code and string. For methods that dequeue a message,
we return a DataReply object with the message instead of using output
arguments.
The concerned API is:
~~~
const Reply queue_message(uint64_t dst_id,
const uint8_t *data,
uint64_t size,
uint64_t cookie = 0) const;
const DataReply dequeue_message() const;
const DataReply dequeue_message_blocking(int timeout_ms = -1) const;
const DataReply transact(uint64_t dst_id,
uint64_t cookie,
const uint8_t *data,
uint64_t size,
uint64_t timeout_ms) const;
const Reply reply(uint64_t dst_id,
uint64_t cookie,
const uint8_t *data,
uint64_t size) const;
~~~
Change-Id: I4019ae9f07a248305a8347c87506ef17b65af1d7
-rw-r--r-- | include/kdbinder/kdbus/KDBinder.h | 112 | ||||
-rw-r--r-- | libs/kdbinder/kdbus/cmds.h | 9 | ||||
-rw-r--r-- | libs/kdbinder/kdbus/connection.cpp | 137 | ||||
-rw-r--r-- | libs/kdbinder/tests/kdbus/connection.cpp | 95 |
4 files changed, 175 insertions, 178 deletions
diff --git a/include/kdbinder/kdbus/KDBinder.h b/include/kdbinder/kdbus/KDBinder.h index 971c0c9..108e72f 100644 --- a/include/kdbinder/kdbus/KDBinder.h +++ b/include/kdbinder/kdbus/KDBinder.h @@ -92,6 +92,43 @@ struct NameInfo { const uint64_t owner_id; }; +struct Reply { + Reply(int error_code, const std::string& error_string) + : error_code(error_code), + error_string(error_string) {} + + const int error_code; + const std::string error_string; +}; + +struct DataReply : Reply { + DataReply(const Reply& reply) + : Reply(reply), + data(nullptr), + size(0), + offset(0), + src_id(0), + cookie(0) {} + DataReply(const Reply& reply, + const uint8_t *data, + const uint64_t size, + const uint64_t offset, + const uint64_t src_id, + const uint64_t cookie) + : Reply(reply), + data(data), + size(size), + offset(offset), + src_id(src_id), + cookie(cookie) {} + + const uint8_t *data; + const uint64_t offset; + const uint64_t size; + const uint64_t src_id; + const uint64_t cookie; +}; + class Connection { public: enum NameFlags { @@ -130,55 +167,44 @@ class Connection { Connection(Connection&&) = default; Connection& operator=(Connection&&) = default; - int acquire_name(const std::string& name, uint64_t flags = 0) const; - int release_name(const std::string& name) const; + const Reply acquire_name(const std::string& name, uint64_t flags = 0) const; + const Reply release_name(const std::string& name) const; std::vector<NameInfo> name_list(uint64_t flags = 0) const; - int queue_message(const Connection& dst, - const uint8_t *data, - uint64_t size, - uint64_t cookie = 0) const; - int queue_message(uint64_t dst_id, - const uint8_t *data, - uint64_t size, - uint64_t cookie = 0) const; + const Reply queue_message(const Connection& dst, + const uint8_t *data, + uint64_t size, + uint64_t cookie = 0) const; + const Reply queue_message(uint64_t dst_id, + const uint8_t *data, + uint64_t size, + uint64_t cookie = 0) const; // TODO: Make this API safer. At the moment, the user is required to // copy the chunk of memory returned through the output arguments. The // memory pointed by `data` is owned by the Connection object. - int dequeue_message(uint8_t **data, - uint64_t *size, - uint64_t *src = nullptr, - uint64_t *cookie = nullptr) const; - int dequeue_message_blocking(uint8_t **data, - uint64_t *size, - uint64_t *src = nullptr, - uint64_t *cookie = nullptr, - int timeout_ms = -1) const; - - int transact(const Connection& dst, - uint64_t cookie, - const uint8_t *data_in, - uint64_t size_in, - uint8_t **data_out, - uint64_t *size_out, - uint64_t timeout_ms) const; - int transact(uint64_t dst_id, - uint64_t cookie, - const uint8_t *data_in, - uint64_t size_in, - uint8_t **data_out, - uint64_t *size_out, - uint64_t timeout_ms) const; - - int reply(const Connection& dst, - uint64_t cookie, - const uint8_t *data, - uint64_t size) const; - int reply(uint64_t dst_id, - uint64_t cookie, - const uint8_t *data, - uint64_t size) const; + const DataReply dequeue_message() const; + const DataReply dequeue_message_blocking(int timeout_ms = -1) const; + + const DataReply transact(const Connection& dst, + uint64_t cookie, + const uint8_t *data, + uint64_t size, + uint64_t timeout_ms) const; + const DataReply transact(uint64_t dst_id, + uint64_t cookie, + const uint8_t *data, + uint64_t size, + uint64_t timeout_ms) const; + + const Reply reply(const Connection& dst, + uint64_t cookie, + const uint8_t *data, + uint64_t size) const; + const Reply reply(uint64_t dst_id, + uint64_t cookie, + const uint8_t *data, + uint64_t size) const; const uint64_t id; diff --git a/libs/kdbinder/kdbus/cmds.h b/libs/kdbinder/kdbus/cmds.h index 782a110..54c2f33 100644 --- a/libs/kdbinder/kdbus/cmds.h +++ b/libs/kdbinder/kdbus/cmds.h @@ -31,15 +31,6 @@ namespace android { namespace kdbus { -struct Reply { - Reply(int error_code, const std::string& error_string) - : error_code(error_code), - error_string(error_string) {} - - const int error_code; - const std::string error_string; -}; - template<typename TYPE, typename... ITEMS> const Reply send_command(FILE *file, uint64_t flags, diff --git a/libs/kdbinder/kdbus/connection.cpp b/libs/kdbinder/kdbus/connection.cpp index 6b432b3..65ee566 100644 --- a/libs/kdbinder/kdbus/connection.cpp +++ b/libs/kdbinder/kdbus/connection.cpp @@ -85,7 +85,8 @@ std::unique_ptr<Connection> Connection::hello( return std::unique_ptr<Connection>(new Connection(bus_file, reply.id, buf)); } -int Connection::acquire_name(const std::string& name, uint64_t flags) const { +const Reply Connection::acquire_name(const std::string& name, + uint64_t flags) const { // struct kdbus_cmd_name requires a KDBUS_ITEM_NAME. auto reply = send_command_name_acquire(bus_file_.get(), flags, @@ -98,10 +99,10 @@ int Connection::acquire_name(const std::string& name, uint64_t flags) const { reply.error_string.c_str()); } - return reply.error_code;; + return reply; } -int Connection::release_name(const std::string& name) const { +const Reply Connection::release_name(const std::string& name) const { // struct kdbus_cmd_name requires a KDBUS_ITEM_NAME. auto reply = send_command_name_release(bus_file_.get(), ItemName(name)); @@ -112,7 +113,7 @@ int Connection::release_name(const std::string& name) const { reply.error_string.c_str()); } - return reply.error_code;; + return reply; } std::vector<NameInfo> Connection::name_list(uint64_t flags) const { @@ -160,17 +161,17 @@ std::vector<NameInfo> Connection::name_list(uint64_t flags) const { return list_vector; } -int Connection::queue_message(const Connection& dst, - const uint8_t *data, - uint64_t size, - uint64_t cookie) const { +const Reply Connection::queue_message(const Connection& dst, + const uint8_t *data, + uint64_t size, + uint64_t cookie) const { return queue_message(dst.id, data, size, cookie); } -int Connection::queue_message(uint64_t dst_id, - const uint8_t *data, - uint64_t size, - uint64_t cookie) const { +const Reply Connection::queue_message(uint64_t dst_id, + const uint8_t *data, + uint64_t size, + uint64_t cookie) const { // When sending a asynchronous message, we do not need to use cookies so we // set it to 0. We are using cookies only for messages which expect a reply. Message message(dst_id, id, cookie, 0, ItemPayloadVec(data, size)); @@ -183,48 +184,41 @@ int Connection::queue_message(uint64_t dst_id, reply.error_string.c_str()); } - return reply.error_code; + return reply; } -int Connection::dequeue_message(uint8_t **data, - uint64_t *size, - uint64_t *src, - uint64_t *cookie) const { +const DataReply Connection::dequeue_message() const { auto reply = send_command_receive_message(bus_file_.get()); if (reply.error_code < 0) { ALOGE("ID %d could not dequeue message: %s\n", (int) id, reply.error_string.c_str()); - return reply.error_code; + return DataReply(reply); } struct kdbus_msg *msg = reinterpret_cast<struct kdbus_msg *>( reinterpret_cast<uint8_t *>(buf_.get()) + reply.offset); struct kdbus_item *item = nullptr; - - if (src != nullptr) - *src = msg->src_id; - if (cookie != nullptr) - *cookie = msg->cookie; + uint64_t size; + uint8_t *data; // TODO: parse the rest of the items for extra information. for_each_item(msg, [&data, this, &size](struct kdbus_item *item) { - if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { - // This is potentially unsafe, as we are returning a pointer to the buffer - // owned by the connection. - *size = item->vec.size; - *data = reinterpret_cast<uint8_t *>(buf_.get()) + item->vec.offset; + switch (item->type) { + case KDBUS_ITEM_PAYLOAD_OFF: { + // This is potentially unsafe, as we are returning a pointer to the buffer + // owned by the connection. + size = item->vec.size; + data = reinterpret_cast<uint8_t *>(buf_.get()) + item->vec.offset; + break; + } } }); - return reply.error_code; + return DataReply(reply, data, size, reply.offset, msg->src_id, msg->cookie); } -int Connection::dequeue_message_blocking(uint8_t **data, - uint64_t *size, - uint64_t *src, - uint64_t *cookie, - int timeout_ms) const { +const DataReply Connection::dequeue_message_blocking(int timeout_ms) const { struct pollfd pollfd = { .fd = fileno(bus_file_.get()), .events = POLLIN | POLLPRI | POLLHUP, @@ -237,10 +231,10 @@ int Connection::dequeue_message_blocking(uint8_t **data, ALOGW("ID %d timed out dequeuing a message: timeout of %d ms\n", (int) id, timeout_ms); - return -ETIMEDOUT; + return DataReply(Reply(-ETIMEDOUT, std::string(strerror(-errno)))); } else if (ret > 0) { if (pollfd.revents & POLLIN) { - ret = dequeue_message(data, size, src, cookie); + return dequeue_message(); } if (pollfd.revents & (POLLHUP | POLLERR)) { @@ -248,39 +242,27 @@ int Connection::dequeue_message_blocking(uint8_t **data, } } - rewind(bus_file_.get()); - - return ret; + return DataReply(Reply(ret, std::string(strerror(-errno)))); } -int Connection::transact(const Connection& dst, - uint64_t cookie, - const uint8_t *data_in, - uint64_t size_in, - uint8_t **data_out, - uint64_t *size_out, - uint64_t timeout_ms) const { - return transact(dst.id, - cookie, - data_in, - size_in, - data_out, - size_out, - timeout_ms); +const DataReply Connection::transact(const Connection& dst, + uint64_t cookie, + const uint8_t *data, + uint64_t size, + uint64_t timeout_ms) const { + return transact(dst.id, cookie, data, size, timeout_ms); } -int Connection::transact(uint64_t dst_id, - uint64_t cookie, - const uint8_t *data_in, - uint64_t size_in, - uint8_t **data_out, - uint64_t *size_out, - uint64_t timeout_ms) const { +const DataReply Connection::transact(uint64_t dst_id, + uint64_t cookie, + const uint8_t *data, + uint64_t size, + uint64_t timeout_ms) const { MessageSync message(dst_id, id, cookie, timeout_ms, - ItemPayloadVec(data_in, size_in)); + ItemPayloadVec(data, size)); auto reply = send_command_transact_message(bus_file_.get(), message); @@ -288,35 +270,42 @@ int Connection::transact(uint64_t dst_id, ALOGE("ID %d could not issue transaction: %s\n", (int) id, reply.error_string.c_str()); - return reply.error_code; + return DataReply(reply); } struct kdbus_msg *msg = reinterpret_cast<struct kdbus_msg *>( reinterpret_cast<uint8_t *>(buf_.get()) + reply.offset); struct kdbus_item *item = nullptr; + uint8_t *data_out; + uint64_t size_out; // TODO: parse the rest of the items for extra information. for_each_item(msg, [&data_out, this, &size_out](struct kdbus_item *item) { if (item->type == KDBUS_ITEM_PAYLOAD_OFF) { - *size_out = item->vec.size; - *data_out = reinterpret_cast<uint8_t *>(buf_.get()) + item->vec.offset; + size_out = item->vec.size; + data_out = reinterpret_cast<uint8_t *>(buf_.get()) + item->vec.offset; } }); - return reply.error_code; + return DataReply(reply, + data_out, + size_out, + reply.offset, + msg->src_id, + msg->cookie); } -int Connection::reply(const Connection& dst, - uint64_t cookie, - const uint8_t *data, - uint64_t size) const { +const Reply Connection::reply(const Connection& dst, + uint64_t cookie, + const uint8_t *data, + uint64_t size) const { return reply(dst.id, cookie, data, size); } -int Connection::reply(uint64_t dst_id, - uint64_t cookie, - const uint8_t *data, - uint64_t size) const { +const Reply Connection::reply(uint64_t dst_id, + uint64_t cookie, + const uint8_t *data, + uint64_t size) const { MessageReply message(dst_id, id, cookie, ItemPayloadVec(data, size)); auto reply = send_command_send_message(bus_file_.get(), message); @@ -327,7 +316,7 @@ int Connection::reply(uint64_t dst_id, reply.error_string.c_str()); } - return reply.error_code; + return reply; } } // namespace kdbus diff --git a/libs/kdbinder/tests/kdbus/connection.cpp b/libs/kdbinder/tests/kdbus/connection.cpp index fd09b6f..1d02b4c 100644 --- a/libs/kdbinder/tests/kdbus/connection.cpp +++ b/libs/kdbinder/tests/kdbus/connection.cpp @@ -51,7 +51,7 @@ TEST(Connection, acquire_name) { auto b = Bus::make("test-bus"); auto c = Connection::hello(*b, "test-conn"); - ASSERT_TRUE(c->acquire_name("foo.bar.test") == 0); + ASSERT_TRUE(c->acquire_name("foo.bar.test").error_code == 0); ASSERT_TRUE(connection_owns_name(*c, "foo.bar.test")); } @@ -59,8 +59,8 @@ TEST(Connection, release_name) { auto b = Bus::make("test-bus"); auto c = Connection::hello(*b, "test-conn"); - ASSERT_TRUE(c->acquire_name("foo.bar.test") == 0); - ASSERT_TRUE(c->release_name("foo.bar.test") == 0); + ASSERT_TRUE(c->acquire_name("foo.bar.test").error_code == 0); + ASSERT_TRUE(c->release_name("foo.bar.test").error_code == 0); ASSERT_FALSE(connection_owns_name(*c, "foo.bar.test")); } @@ -70,12 +70,12 @@ TEST(Connection, acquire_name_deny) { auto c1 = Connection::hello(*b, "test-conn"); auto c2 = Connection::hello(*b, "test-conn"); - ASSERT_TRUE(c1->acquire_name("foo.bar.test") == 0); - ASSERT_FALSE(c2->acquire_name("foo.bar.test") == 0); + ASSERT_TRUE(c1->acquire_name("foo.bar.test").error_code == 0); + ASSERT_FALSE(c2->acquire_name("foo.bar.test").error_code == 0); ASSERT_FALSE(connection_owns_name(*c2, "foo.bar.test")); - ASSERT_TRUE(c1->release_name("foo.bar.test") == 0); - ASSERT_TRUE(c2->acquire_name("foo.bar.test") == 0); + ASSERT_TRUE(c1->release_name("foo.bar.test").error_code == 0); + ASSERT_TRUE(c2->acquire_name("foo.bar.test").error_code == 0); ASSERT_TRUE(connection_owns_name(*c2, "foo.bar.test")); } @@ -84,20 +84,20 @@ TEST(Connection, acquire_name_replace) { auto c1 = Connection::hello(*b, "test-conn"); auto c2 = Connection::hello(*b, "test-conn"); - ASSERT_TRUE(c1->acquire_name("foo.bar.test", Connection::AllowReplacement) == 0); - ASSERT_TRUE(c2->acquire_name("foo.bar.test", Connection::ReplaceExisting) == 0); + ASSERT_TRUE(c1->acquire_name("foo.bar.test", Connection::AllowReplacement).error_code == 0); + ASSERT_TRUE(c2->acquire_name("foo.bar.test", Connection::ReplaceExisting).error_code == 0); ASSERT_TRUE(connection_owns_name(*c2, "foo.bar.test")); c2->release_name("foo.bar.test"); - ASSERT_TRUE(c1->acquire_name("foo.bar.test") == 0); - ASSERT_FALSE(c2->acquire_name("foo.bar.test", Connection::ReplaceExisting) == 0); + ASSERT_TRUE(c1->acquire_name("foo.bar.test").error_code == 0); + ASSERT_FALSE(c2->acquire_name("foo.bar.test", Connection::ReplaceExisting).error_code == 0); ASSERT_FALSE(connection_owns_name(*c2, "foo.bar.test")); c1->release_name("foo.bar.test"); - ASSERT_TRUE(c1->acquire_name("foo.bar.test", Connection::AllowReplacement) == 0); - ASSERT_FALSE(c2->acquire_name("foo.bar.test") == 0); + ASSERT_TRUE(c1->acquire_name("foo.bar.test", Connection::AllowReplacement).error_code == 0); + ASSERT_FALSE(c2->acquire_name("foo.bar.test").error_code == 0); ASSERT_FALSE(connection_owns_name(*c2, "foo.bar.test")); } @@ -106,11 +106,11 @@ TEST(Connection, acquire_name_queue) { auto c1 = Connection::hello(*b, "test-conn"); auto c2 = Connection::hello(*b, "test-conn"); - ASSERT_TRUE(c1->acquire_name("foo.bar.test") == 0); - ASSERT_TRUE(c2->acquire_name("foo.bar.test", Connection::Queue) == 0); + ASSERT_TRUE(c1->acquire_name("foo.bar.test").error_code == 0); + ASSERT_TRUE(c2->acquire_name("foo.bar.test", Connection::Queue).error_code == 0); ASSERT_FALSE(connection_owns_name(*c2, "foo.bar.test")); - ASSERT_TRUE(c1->release_name("foo.bar.test") == 0); + ASSERT_TRUE(c1->release_name("foo.bar.test").error_code == 0); ASSERT_TRUE(connection_owns_name(*c2, "foo.bar.test")); } @@ -158,7 +158,7 @@ TEST(Connection, queue_message) { auto c2 = Connection::hello(*b, "test-conn"); uint8_t data = 42; - ASSERT_TRUE(c1->queue_message(*c2, &data, sizeof(uint8_t)) == 0); + ASSERT_TRUE(c1->queue_message(*c2, &data, sizeof(uint8_t)).error_code == 0); } TEST(Connection, dequeue_message_blocking) { @@ -167,14 +167,14 @@ TEST(Connection, dequeue_message_blocking) { auto c2 = Connection::hello(*b, "test-conn"); uint8_t data_in = 42; uint8_t data_out = 0; - uint8_t *connection_buf = nullptr; - uint64_t size_out = 0; - ASSERT_TRUE(c1->queue_message(*c2, &data_in, sizeof(uint8_t)) == 0); - ASSERT_TRUE(c2->dequeue_message_blocking(&connection_buf, &size_out) == 0); - ASSERT_TRUE(size_out == sizeof(uint8_t)); + ASSERT_TRUE(c1->queue_message(*c2, &data_in, sizeof(uint8_t)).error_code == 0); + auto reply = c2->dequeue_message_blocking(); - memcpy(&data_out, connection_buf, size_out); + ASSERT_TRUE(reply.error_code == 0); + ASSERT_TRUE(reply.size == sizeof(uint8_t)); + + memcpy(&data_out, reply.data, reply.size); ASSERT_TRUE(data_in == data_out); } @@ -185,19 +185,16 @@ TEST(Connection, source_id) { auto c2 = Connection::hello(*b, "test-conn"); uint8_t data_in = 42; uint8_t data_out = 0; - uint8_t *connection_buf = nullptr; - uint64_t size_out = 0; - uint64_t src_id; - ASSERT_TRUE(c1->queue_message(*c2, &data_in, sizeof(uint8_t)) == 0); - ASSERT_TRUE(c2->dequeue_message_blocking(&connection_buf, - &size_out, - &src_id) == 0); - ASSERT_TRUE(src_id == c1->id); + ASSERT_TRUE(c1->queue_message(*c2, &data_in, sizeof(uint8_t)).error_code == 0); + auto reply = c2->dequeue_message_blocking(); + + ASSERT_TRUE(reply.error_code == 0); + ASSERT_TRUE(reply.src_id == c1->id); - ASSERT_TRUE(size_out == sizeof(uint8_t)); + ASSERT_TRUE(reply.size == sizeof(uint8_t)); - memcpy(&data_out, connection_buf, size_out); + memcpy(&data_out, reply.data, reply.size); ASSERT_TRUE(data_in == data_out); } @@ -208,30 +205,24 @@ TEST(Connection, transact) { auto c2 = Connection::hello(*b, "test-conn"); uint8_t data_in = 42; uint8_t data_out = 0; - uint8_t *connection_buf = nullptr; - uint64_t size_out = 0; uint64_t cookie = 123456789; - std::thread reply([&c1, &c2, &cookie]{ - uint8_t *connection_buf = nullptr; - uint64_t size_out = 0; - - c2->dequeue_message_blocking(&connection_buf, &size_out); - c2->reply(*c1, cookie, connection_buf, size_out); + std::thread server([&c1, &c2]{ + auto reply = c2->dequeue_message_blocking(); + c2->reply(*c1, reply.cookie, reply.data, reply.size); }); - ASSERT_TRUE(c1->transact(*c2, - cookie, - &data_in, - sizeof(uint8_t), - &connection_buf, - &size_out, - // One second timeout. - 1000) == 0); - ASSERT_TRUE(size_out == sizeof(uint8_t)); + auto reply = c1->transact(*c2, + cookie, + &data_in, + sizeof(uint8_t), + // One second timeout. + 1000); + ASSERT_TRUE(reply.error_code == 0); + ASSERT_TRUE(reply.size == sizeof(uint8_t)); - memcpy(&data_out, connection_buf, size_out); + memcpy(&data_out, reply.data, reply.size); ASSERT_TRUE(data_in == data_out); - reply.join(); + server.join(); } |