aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Langlois <pierre.langlois@arm.com>2015-02-12 14:58:43 +0000
committerPierre Langlois <pierre.langlois@arm.com>2016-03-04 17:39:40 +0000
commit553cba749ec883222c210290c4e9389618915055 (patch)
tree50126d3df0a87db3e86bdd54f348c10678749cf0
parenta7395a1f865863f69f2f5e7b5ce9d095fdd51d46 (diff)
downloadkdbinder-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.h112
-rw-r--r--libs/kdbinder/kdbus/cmds.h9
-rw-r--r--libs/kdbinder/kdbus/connection.cpp137
-rw-r--r--libs/kdbinder/tests/kdbus/connection.cpp95
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();
}