36
template<typename SessionType>
39
typedef std::shared_ptr<SessionStore> Ptr;
41
SessionStore() = default;
42
SessionStore(const SessionStore&) = delete;
43
SessionStore& operator=(const SessionStore&) = delete;
44
virtual ~SessionStore() = default;
46
virtual void remove_session(const std::shared_ptr<SessionType>& session) = 0;
49
struct SessionWrapper : public std::enable_shared_from_this<SessionWrapper>
51
typedef std::shared_ptr<SessionWrapper> Ptr;
53
SessionWrapper(const SessionStore<SessionWrapper>::Ptr& session_store,
54
const culss::Interface::Ptr& session,
55
core::dbus::Service::Ptr service,
56
core::dbus::Object::Ptr object)
57
: session_store(session_store),
59
remote(service, object)
61
session->install_position_updates_handler(std::bind(&SessionWrapper::on_position_update, this, std::placeholders::_1));
62
session->install_velocity_updates_handler(std::bind(&SessionWrapper::on_velocity_update, this, std::placeholders::_1));
63
session->install_heading_updates_handler(std::bind(&SessionWrapper::on_heading_update, this, std::placeholders::_1));
66
const core::dbus::types::ObjectPath& path() const
68
return session->path();
71
void on_session_died() noexcept
73
std::cout << __PRETTY_FUNCTION__ << std::endl;
74
VLOG(1) << "Session died, removing from store and stopping all updates.";
76
auto thiz = shared_from_this();
79
session_store->remove_session(thiz);
80
session->stop_position_updates();
81
session->stop_heading_updates();
82
session->stop_velocity_updates();
83
} catch(const std::runtime_error& e)
85
LOG(ERROR) << "Error while stopping updates for died session: " << e.what();
89
void on_position_update(const cul::Update<cul::Position>& position)
93
auto result = remote.session->transact_method<culs::session::Interface::UpdatePosition, void>(position);
94
if (result.is_error())
96
LOG(ERROR) << result.error().print();
99
} catch(const std::runtime_error& e)
101
// We consider the session to be dead once we hit an exception here.
102
// We thus remove it from the central and end its lifetime.
107
void on_velocity_update(const cul::Update<cul::Velocity>& velocity)
111
auto result = remote.session->transact_method<culs::session::Interface::UpdateVelocity, void>(velocity);
112
if (result.is_error())
114
LOG(ERROR) << result.error().print();
117
} catch(const std::runtime_error& e)
119
// We consider the session to be dead once we hit an exception here.
120
// We thus remove it from the central and end its lifetime.
125
void on_heading_update(const cul::Update<cul::Heading>& heading)
129
auto result = remote.session->transact_method<culs::session::Interface::UpdateHeading, void>(heading);
130
if (result.is_error())
132
LOG(ERROR) << result.error().print();
135
} catch(const std::runtime_error& e)
137
// We consider the session to be dead once we hit an exception here.
138
// We thus remove it from the central and end its lifetime.
143
SessionStore<SessionWrapper>::Ptr session_store;
144
culs::session::Interface::Ptr session;
147
explicit Remote(const dbus::Service::Ptr& service,
148
const dbus::Object::Ptr& session)
154
dbus::Service::Ptr service;
155
dbus::Object::Ptr session;
160
struct culs::Skeleton::Private : public SessionStore<SessionWrapper>, std::enable_shared_from_this<culs::Skeleton::Private>
162
Private(Skeleton* parent, const dbus::Bus::Ptr& connection, const culs::PermissionManager::Ptr& permission_manager)
164
permission_manager(permission_manager),
166
object(parent->access_service()->add_object_for_path(culs::Interface::path()))
168
object->install_method_handler<culs::Interface::CreateSessionForCriteria>(
169
std::bind(&culs::Skeleton::Private::handle_create_session_for_criteria, this, std::placeholders::_1));
172
~Private() noexcept {}
174
void handle_create_session_for_criteria(const core::dbus::Message::Ptr& in);
175
void remove_session(const std::shared_ptr<SessionWrapper>& session);
178
PermissionManager::Ptr permission_manager;
180
dbus::Object::Ptr object;
182
std::map<dbus::types::ObjectPath, std::shared_ptr<SessionWrapper>> session_store;
185
culs::Skeleton::Skeleton(const dbus::Bus::Ptr& connection, const culs::PermissionManager::Ptr& permission_manager)
186
: dbus::Skeleton<culs::Interface>(connection), d{new Private{this, connection, permission_manager}}
33
dbus::Message::Ptr the_empty_reply()
35
return dbus::Message::Ptr{};
39
culs::Skeleton::DBusDaemonCredentialsResolver::DBusDaemonCredentialsResolver(const dbus::Bus::Ptr& bus)
45
culs::Skeleton::DBusDaemonCredentialsResolver::resolve_credentials_for_incoming_message(const dbus::Message::Ptr& msg)
47
return culs::Credentials
49
daemon.get_connection_unix_process_id(msg->sender()),
50
daemon.get_connection_unix_user(msg->sender())
54
core::dbus::types::ObjectPath culs::Skeleton::ObjectPathGenerator::object_path_for_caller_credentials(const culs::Credentials&)
56
static std::uint32_t index{0};
57
std::stringstream ss; ss << "/sessions/" << index++;
59
return core::dbus::types::ObjectPath{ss.str()};
63
culs::Skeleton::Skeleton(const culs::Skeleton::Configuration& configuration)
64
: dbus::Skeleton<culs::Interface>(configuration.incoming),
65
configuration(configuration),
66
object(access_service()->add_object_for_path(culs::Interface::path())),
69
object->get_property<culs::Interface::Properties::DoesSatelliteBasedPositioning>(),
70
object->get_property<culs::Interface::Properties::DoesReportCellAndWifiIds>(),
71
object->get_property<culs::Interface::Properties::IsOnline>(),
72
object->get_property<culs::Interface::Properties::VisibleSpaceVehicles>()
75
object->install_method_handler<culs::Interface::CreateSessionForCriteria>([this](const dbus::Message::Ptr& msg)
77
handle_create_session_for_criteria(msg);
190
81
culs::Skeleton::~Skeleton() noexcept
83
object->uninstall_method_handler<culs::Interface::CreateSessionForCriteria>();
194
void culs::Skeleton::Private::handle_create_session_for_criteria(const core::dbus::Message::Ptr& in)
86
void culs::Skeleton::handle_create_session_for_criteria(const dbus::Message::Ptr& in)
88
VLOG(1) << __PRETTY_FUNCTION__;
196
90
auto sender = in->sender();
91
auto reply = the_empty_reply();
201
in->reader() >> criteria;
203
Credentials credentials
205
static_cast<pid_t>(daemon.get_connection_unix_process_id(sender)),
206
static_cast<uid_t>(daemon.get_connection_unix_user(sender))
209
if (PermissionManager::Result::rejected == permission_manager->check_permission_for_credentials(criteria, credentials))
210
throw std::runtime_error("Client lacks permissions to access the service with the given criteria");
212
auto session = parent->create_session_for_criteria(criteria);
214
auto service = dbus::Service::use_service(parent->access_bus(), in->sender());
215
auto object = service->object_for_path(session->path());
96
in->reader() >> criteria;
99
configuration.credentials_resolver->resolve_credentials_for_incoming_message(in);
102
configuration.permission_manager->check_permission_for_credentials(criteria, credentials);
104
if (PermissionManager::Result::rejected == result) throw std::runtime_error
106
"Client lacks permissions to access the service with the given criteria"
110
configuration.object_path_generator->object_path_for_caller_credentials(credentials);
113
dbus::Service::use_service(configuration.outgoing, sender);
115
culss::Skeleton::Configuration config
118
culss::Skeleton::Local
120
create_session_for_criteria(criteria),
121
configuration.incoming
123
culss::Skeleton::Remote
125
stub->object_for_path(path)
129
culss::Interface::Ptr session
131
new culss::Skeleton{config}
134
if (not add_to_session_store_for_path(path, session))
136
reply = dbus::Message::make_error(
138
culs::Interface::Errors::CreatingSession::name(),
139
"Refused to create second session for same process");
142
reply = dbus::Message::make_method_return(in);
143
reply->writer() << path;
146
} catch(const std::exception& e)
218
std::lock_guard<std::mutex> lg(guard);
220
auto wrapper = SessionWrapper::Ptr{new SessionWrapper{shared_from_this(), session, service, object}};
222
bool inserted = false;
223
std::tie(std::ignore, inserted) = session_store.insert(std::make_pair(session->path(), wrapper));
225
auto reply = dbus::Message::make_method_return(in);
226
reply->writer() << session->path();
227
parent->access_bus()->send(reply);
230
throw std::runtime_error("Could not insert duplicate session into store.");
148
// We only send a very generic error message to the client to avoid
149
// leaking any sort of internal error handling details to untrusted
151
reply = dbus::Message::make_error(
153
culs::Interface::Errors::CreatingSession::name(),
154
"Error creating session");
155
// We log the error for debugging purposes.
156
LOG(ERROR) << "Error creating session: " << e.what();
233
} catch(const std::runtime_error& e)
235
parent->access_bus()->send(
236
dbus::Message::make_error(
238
culs::Interface::Errors::CreatingSession::name(),
241
LOG(ERROR) << "Error creating session: " << e.what();
159
// We are done processing the request and try to send out the result to the client.
162
configuration.incoming->send(reply);
163
} catch(const std::exception& e)
165
// We log the error for debugging purposes.
166
LOG(ERROR) << "Error sending reply to session creation request: " << e.what();
245
void culs::Skeleton::Private::remove_session(const SessionWrapper::Ptr& session)
170
bool culs::Skeleton::add_to_session_store_for_path(
171
const core::dbus::types::ObjectPath& path,
172
const culss::Interface::Ptr& session)
247
174
std::lock_guard<std::mutex> lg(guard);
248
session_store.erase(session->path());
250
VLOG(1) << "# of session in session store: " << session_store.size() << std::endl;
175
bool inserted = false;
176
std::tie(std::ignore, inserted) = session_store.insert(std::make_pair(path, session));
180
core::Property<bool>& culs::Skeleton::does_satellite_based_positioning()
182
return *properties.does_satellite_based_positioning;
185
core::Property<bool>& culs::Skeleton::does_report_cell_and_wifi_ids()
187
return *properties.does_report_cell_and_wifi_ids;
190
core::Property<bool>& culs::Skeleton::is_online()
192
return *properties.is_online;
195
core::Property<std::map<cul::SpaceVehicle::Key, cul::SpaceVehicle>>& culs::Skeleton::visible_space_vehicles()
197
return *properties.visible_space_vehicles;