agent_operation_handler(
service,
user_data,
- [fields](agent::connect_data const & d){
+ [fields, invocation](agent::connect_data const & d){
using ivi::settings::unique_ptr;
// Extract requested mandatory and alternate fields.
gchar * fname = nullptr;
GVariant * fvalue = nullptr;
- JsonReader * const reader = d.reader.get();
/**
* @todo Refactor this GVariant dictionary iteration code.
if (strcmp(argname, "Requirement") == 0
&& strcmp(g_variant_get_string(argvalue, nullptr),
"mandatory") == 0) {
- // Extract required field value from the Settings app
- // request, and add it to the dictionary result.
- char const * supplied_field = nullptr;
- if (json_reader_read_member(reader, fname)) {
+
+ // Check if we were supplied the required field, and add
+ // it to the dictionary result.
+ auto const i = d.info.find(fname);
+ if (i == d.info.end()) {
+ std::string err(
+ std::string("Required connection field \"")
+ + fname
+ + "\" not supplied.");
+
/**
- * @todo Not all fields are strings. In particular,
- * the "Alternates" field is an array of
- * strings.
+ * @todo This send_error() call is probably
+ * redundant. Look into removing it.
*/
- supplied_field =
- json_reader_get_string_value(reader);
- }
- json_reader_end_member(reader);
+ d.response.send_error(err);
- if (supplied_field == nullptr) {
+ /**
+ * @bug Register a settingsd-specific error during
+ * initialization via
+ * @c g_dbus_error_register_error(), and use it
+ * in this call instead.
+ */
+ g_dbus_method_invocation_return_dbus_error(
+ invocation,
+ "net.connman.Agent.Error.Canceled",
+ err.c_str());
+ break; /// @todo Is this correct?
}
-
}
}
bool
ivi::settings::agent::register_connect_data(
char const * service_path,
- JsonReader * reader,
+ std::map<std::string, std::string> && info,
response_callback const & response)
{
- connect_data data(reader, response);
+ connect_data data(std::move(info), response);
std::lock_guard<std::mutex> guard(data_.lock);
return result.second;
}
+bool
+ivi::settings::agent::deregister_connect_data(char const * service_path)
+{
+ std::lock_guard<std::mutex> guard(data_.lock);
+
+ return data_.info.erase(service_path) == 1;
+}
+
// Local Variables:
// mode:c++
{
public:
+ typedef std::map<std::string, std::string> connect_info_map_type;
+
/**
* Constructor.
*
* method calls.
*/
bool register_connect_data(char const * service_path,
- JsonReader * reader,
+ connect_info_map_type && info,
response_callback const & response);
+ /**
+ * Deregister connectio data.
+ */
+ bool deregister_connect_data(char const * service_path);
+
/// Get D-Bus object path for this @c Agent.
char const *
object_path() const
/**
* Constructor.
*
- * @note We bump the reference count on the @c JsonReader
- * object.
+ * @param[in] info_map Map of Connman Agent API field name to
+ * value.
+ * @param[in] resp Callback object through which responses
+ * will be sent to the caller
+ * (e.g. Settings app).
*/
- connect_data(JsonReader * rd,
+ connect_data(connect_info_map_type && info_map,
response_callback const & resp)
- : reader(static_cast<JsonReader *>(g_object_ref(rd)))
+ : info(info_map)
, response(resp)
{
}
/// Move constructor.
connect_data(connect_data && other)
- : reader(std::move(other.reader))
+ : info(std::move(other.info))
, response(other.response)
{
- other.reader.reset();
-
- // Nothing to do with response field.
}
/// Disallow copy construction and assignment.
void operator=(connect_data const &) = delete;
/**
- * Pointer to the @c JsonReader object containing the request
- * information, including arguments.
+ * Map of Connman Agent API field name to value.
*/
- unique_ptr<JsonReader> reader;
+ std::map<std::string, std::string> info;
/**
* The response callback through errors will be sent to the
bool
ivi::settings::connman_manager::register_connect_data(
char const * service_path,
- JsonReader * reader,
+ std::map<std::string, std::string> && info,
response_callback const & response)
{
return agent_.register_connect_data(service_path,
- reader,
+ std::move(info),
response);
}
+bool
+ivi::settings::connman_manager::deregister_connect_data(
+ char const * service_path)
+{
+ return agent_.deregister_connect_data(service_path);
+}
+
GVariant *
ivi::settings::connman_manager::get_properties(
std::string const & technology,
* method calls.
*/
bool register_connect_data(char const * service_path,
- JsonReader * reader,
+ std::map<std::string, std::string> && info,
response_callback const & response);
/**
+ * Deregister connection data.
+ */
+ bool deregister_connect_data(char const * service_path);
+
+ /**
* Get the properties for a specific technology.
*
* @param[in] technology Connman technology for which properties
// ----------------------------------------------------------------------
ivi::settings::connman_service::connman_service(
- GDBusConnection * connection)
+ GDBusConnection * connection,
+ connman_manager & manager)
: connection_(connection)
+ , manager_(manager)
{
}
if (path != nullptr) {
service s(path, connection_);
- s.handle_request(name, reader, response);
+ s.handle_request(name, reader, manager_, response);
}
}
json_reader_end_member(reader);
public:
/// Constructor.
- connman_service(GDBusConnection * connection);
+ connman_service(GDBusConnection * connection,
+ connman_manager & manager);
/// Destructor.
~connman_service();
/// The underlying D-Bus connection.
GDBusConnection * const connection_;
+ /**
+ * The object used to register connection information for use
+ * by the Connman Agent.
+ */
+ connman_manager & manager_;
+
};
}
std::unique_ptr<ivi::settings::plugin> manager(mgr);
std::unique_ptr<ivi::settings::plugin> service(
- new ivi::settings::connman_service(connection));
+ new ivi::settings::connman_service(connection, *mgr));
std::unique_ptr<ivi::settings::plugin> technology(
new ivi::settings::connman_technology(connection, *mgr));
void
ivi::settings::service::handle_request(char const * name,
JsonReader * reader,
+ connman_manager & manager,
response_callback & response)
{
if (name != nullptr) {
if (strcmp(name, "connect") == 0)
- connect(reader, response);
+ connect(reader, manager, response);
else if (strcmp(name, "disconnect") == 0)
- disconnect(reader, response);
+ disconnect(reader, manager, response);
else {
response.send_error(
std::string("Unrecognized connman service request name: ")
}
void
-ivi::settings::service::connect(JsonReader * /* reader */,
+ivi::settings::service::connect(JsonReader * reader,
+ connman_manager & manager,
response_callback response)
{
+ bool successful_parse = false;
+
+ typedef agent::connect_info_map_type map_type;
+ map_type info;
+
+ // The service connection information is found in the second array
+ // element.
+ if (json_reader_read_element(reader, 1)
+ && json_reader_is_object(reader)) {
+ gint const count = json_reader_count_members(reader);
+ for (gint i = 0; i < count; ++i) {
+ if (json_reader_read_element(reader, i)) {
+ char const * const name = json_reader_get_member_name(reader);
+ char const * const value = json_reader_get_string_value(reader);
+
+ if (name != nullptr && value != nullptr)
+ info.insert(std::make_pair(name, value));
+ }
+ json_reader_end_element(reader);
+ }
+
+ // This cast is safe.
+ if (static_cast<gint>(info.size()) == count) {
+ successful_parse = true;
+ }
+ }
+ json_reader_end_element(reader);
+
+ if (!successful_parse) {
+ response.send_error("Unable to parse service connection information.");
+ return;
+ }
+
+ if (!manager.register_connect_data(connman_.object_path(),
+ std::move(info),
+ response)) {
+ response.send_error("Unable to register connection information.");
+ return;
+ }
+
call_method("Connect", response);
}
void
ivi::settings::service::disconnect(JsonReader * reader,
+ connman_manager & manager,
response_callback response)
{
bool null = false;
}
call_method("Disconnect", response);
+
+ manager.deregister_connect_data(connman_.object_path());
}
void
*/
void handle_request(char const * name,
JsonReader * reader,
+ connman_manager & manager,
response_callback & response);
private:
/// Connect to the service.
void connect(JsonReader * reader,
+ connman_manager & manager,
response_callback response);
/// Disconnect from the service.
void disconnect(JsonReader * reader,
+ connman_manager & manager,
response_callback response);
/**