Merge lp:~thomas-voss/location-service/introduce-locationd into lp:location-service
- introduce-locationd
- Merge into next
Proposed by
Thomas Voß
Status: | Merged |
---|---|
Approved by: | Thomas Voß |
Approved revision: | 262 |
Merged at revision: | 261 |
Proposed branch: | lp:~thomas-voss/location-service/introduce-locationd |
Merge into: | lp:location-service |
Diff against target: |
3200 lines (+2854/-50) 35 files modified
src/location/CMakeLists.txt (+60/-0) src/location/cmds/list.cpp (+36/-0) src/location/cmds/list.h (+41/-0) src/location/cmds/provider.cpp (+83/-0) src/location/cmds/provider.h (+52/-0) src/location/cmds/run.cpp (+109/-0) src/location/cmds/run.h (+55/-0) src/location/cmds/status.cpp (+69/-0) src/location/cmds/status.h (+49/-0) src/location/cmds/test.cpp (+32/-0) src/location/cmds/test.h (+41/-0) src/location/daemon.cpp (+54/-0) src/location/daemon.h (+49/-0) src/location/daemon_main.cpp (+26/-0) src/location/dbus/skeleton/service.cpp (+45/-20) src/location/dbus/skeleton/service.h (+32/-28) src/location/dummy_service.cpp (+55/-0) src/location/dummy_service.h (+55/-0) src/location/permission_manager.h (+73/-0) src/location/providers/gps/sntp_reference_time_source.cpp (+2/-2) src/location/runtime.cpp (+107/-0) src/location/runtime.h (+81/-0) src/location/runtime_tests.cpp (+185/-0) src/location/runtime_tests.h (+30/-0) src/location/service_with_engine.cpp (+129/-0) src/location/service_with_engine.h (+61/-0) src/location/session_with_provider.cpp (+111/-0) src/location/session_with_provider.h (+60/-0) src/location/trust_store_permission_manager.cpp (+179/-0) src/location/trust_store_permission_manager.h (+76/-0) src/location/util/cli.cpp (+301/-0) src/location/util/cli.h (+387/-0) src/location/util/do_not_copy_or_move.h (+44/-0) src/location/util/well_known_bus.cpp (+48/-0) src/location/util/well_known_bus.h (+37/-0) |
To merge this branch: | bzr merge lp:~thomas-voss/location-service/introduce-locationd |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Simon Fels (community) | Approve | ||
Thomas Voß | Pending | ||
Review via email: mp+298744@code.launchpad.net |
Commit message
Introduce locationd, featuring the following cmds:
- list: list all known provider implementations
- provider: run a known provider implementation out of process.
- run: execute locationd.
- status: query the status of a locationd instance.
- test: execute runtime tests.
Description of the change
Introduce locationd, featuring the following cmds:
- list: list all known provider implementations
- provider: run a known provider implementation out of process.
- run: execute locationd.
- status: query the status of a locationd instance.
- test: execute runtime tests.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'build' |
2 | === added directory 'build/src' |
3 | === modified file 'src/location/CMakeLists.txt' |
4 | --- src/location/CMakeLists.txt 2016-06-28 11:53:34 +0000 |
5 | +++ src/location/CMakeLists.txt 2016-06-30 09:21:49 +0000 |
6 | @@ -39,8 +39,43 @@ |
7 | |
8 | boost_ptree_settings.cpp |
9 | |
10 | + daemon.h |
11 | + daemon.cpp |
12 | service.cpp |
13 | |
14 | + dummy_service.h |
15 | + dummy_service.cpp |
16 | + |
17 | + permission_manager.h |
18 | + runtime.h |
19 | + runtime.cpp |
20 | + runtime_tests.h |
21 | + runtime_tests.cpp |
22 | + service_with_engine.h |
23 | + service_with_engine.cpp |
24 | + session_with_provider.h |
25 | + session_with_provider.cpp |
26 | + |
27 | + trust_store_permission_manager.h |
28 | + trust_store_permission_manager.cpp |
29 | + |
30 | + cmds/list.h |
31 | + cmds/list.cpp |
32 | + cmds/provider.h |
33 | + cmds/provider.cpp |
34 | + cmds/run.h |
35 | + cmds/run.cpp |
36 | + cmds/status.h |
37 | + cmds/status.cpp |
38 | + cmds/test.h |
39 | + cmds/test.cpp |
40 | + |
41 | + util/cli.h |
42 | + util/cli.cpp |
43 | + util/do_not_copy_or_move.h |
44 | + util/well_known_bus.h |
45 | + util/well_known_bus.cpp |
46 | + |
47 | dbus/skeleton/service.h |
48 | dbus/skeleton/service.cpp |
49 | dbus/skeleton/session.h |
50 | @@ -190,6 +225,12 @@ |
51 | service/daemon_cli_main.cpp |
52 | ) |
53 | |
54 | +add_executable( |
55 | + locationd |
56 | + |
57 | + daemon_main.cpp |
58 | +) |
59 | + |
60 | target_link_libraries( |
61 | ubuntu-location-service-provider-daemon |
62 | |
63 | @@ -244,6 +285,20 @@ |
64 | ${GFlags_LIBRARY} |
65 | ) |
66 | |
67 | +target_link_libraries( |
68 | + locationd |
69 | + |
70 | + ubuntu-location-service |
71 | + |
72 | + ${ENABLED_PROVIDER_TARGETS} |
73 | + |
74 | +# ${Boost_LIBRARIES} |
75 | +# ${DBUS_LIBRARIES} |
76 | +# ${DBUS_CPP_LIBRARIES} |
77 | +# ${GLog_LIBRARY} |
78 | +# ${GFlags_LIBRARY} |
79 | +) |
80 | + |
81 | install( |
82 | TARGETS ubuntu-location-service-providerd |
83 | DESTINATION ${CMAKE_INSTALL_BINDIR} |
84 | @@ -258,3 +313,8 @@ |
85 | TARGETS ubuntu-location-serviced-cli |
86 | DESTINATION ${CMAKE_INSTALL_BINDIR} |
87 | ) |
88 | + |
89 | +install( |
90 | + TARGETS locationd |
91 | + DESTINATION ${CMAKE_INSTALL_BINDIR} |
92 | +) |
93 | |
94 | === added directory 'src/location/cmds' |
95 | === added file 'src/location/cmds/list.cpp' |
96 | --- src/location/cmds/list.cpp 1970-01-01 00:00:00 +0000 |
97 | +++ src/location/cmds/list.cpp 2016-06-30 09:21:49 +0000 |
98 | @@ -0,0 +1,36 @@ |
99 | +/* |
100 | + * Copyright (C) 2016 Canonical, Ltd. |
101 | + * |
102 | + * This program is free software; you can redistribute it and/or modify |
103 | + * it under the terms of the GNU Lesser General Public License as published by |
104 | + * the Free Software Foundation; version 3. |
105 | + * |
106 | + * This program is distributed in the hope that it will be useful, |
107 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
108 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
109 | + * GNU Lesser General Public License for more details. |
110 | + * |
111 | + * You should have received a copy of the GNU Lesser General Public License |
112 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
113 | + * |
114 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
115 | + * |
116 | + */ |
117 | + |
118 | +#include <location/cmds/list.h> |
119 | +#include <location/provider_factory.h> |
120 | + |
121 | +namespace cli = location::util::cli; |
122 | + |
123 | +location::cmds::List::List() |
124 | + : CommandWithFlagsAndAction{cli::Name{"list"}, cli::Usage{"list"}, cli::Description{"lists known provider implementations"}} |
125 | +{ |
126 | + action([this](const Context& ctxt) |
127 | + { |
128 | + location::ProviderFactory::instance().enumerate([&ctxt](const std::string& name, const location::ProviderFactory::Factory&) |
129 | + { |
130 | + ctxt.cout << " - " << name << std::endl; |
131 | + }); |
132 | + return EXIT_SUCCESS; |
133 | + }); |
134 | +} |
135 | |
136 | === added file 'src/location/cmds/list.h' |
137 | --- src/location/cmds/list.h 1970-01-01 00:00:00 +0000 |
138 | +++ src/location/cmds/list.h 2016-06-30 09:21:49 +0000 |
139 | @@ -0,0 +1,41 @@ |
140 | +/* |
141 | + * Copyright (C) 2016 Canonical, Ltd. |
142 | + * |
143 | + * This program is free software; you can redistribute it and/or modify |
144 | + * it under the terms of the GNU Lesser General Public License as published by |
145 | + * the Free Software Foundation; version 3. |
146 | + * |
147 | + * This program is distributed in the hope that it will be useful, |
148 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
149 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
150 | + * GNU Lesser General Public License for more details. |
151 | + * |
152 | + * You should have received a copy of the GNU Lesser General Public License |
153 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
154 | + * |
155 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
156 | + * |
157 | + */ |
158 | + |
159 | +#ifndef LOCATION_CMDS_LIST_H_ |
160 | +#define LOCATION_CMDS_LIST_H_ |
161 | + |
162 | +#include <location/util/cli.h> |
163 | + |
164 | +#include <iosfwd> |
165 | + |
166 | +namespace location |
167 | +{ |
168 | +namespace cmds |
169 | +{ |
170 | +// List lists all known provider implementations |
171 | +class List : public util::cli::CommandWithFlagsAndAction |
172 | +{ |
173 | +public: |
174 | + // List initializes a new instance. |
175 | + List(); |
176 | +}; |
177 | +} |
178 | +} |
179 | + |
180 | +#endif // LOCATION_CMDS_LIST_H_ |
181 | |
182 | === added file 'src/location/cmds/provider.cpp' |
183 | --- src/location/cmds/provider.cpp 1970-01-01 00:00:00 +0000 |
184 | +++ src/location/cmds/provider.cpp 2016-06-30 09:21:49 +0000 |
185 | @@ -0,0 +1,83 @@ |
186 | +/* |
187 | + * Copyright (C) 2016 Canonical, Ltd. |
188 | + * |
189 | + * This program is free software; you can redistribute it and/or modify |
190 | + * it under the terms of the GNU Lesser General Public License as published by |
191 | + * the Free Software Foundation; version 3. |
192 | + * |
193 | + * This program is distributed in the hope that it will be useful, |
194 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
195 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
196 | + * GNU Lesser General Public License for more details. |
197 | + * |
198 | + * You should have received a copy of the GNU Lesser General Public License |
199 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
200 | + * |
201 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
202 | + * |
203 | + */ |
204 | + |
205 | +#include <location/cmds/provider.h> |
206 | + |
207 | +#include <location/provider_factory.h> |
208 | +#include <location/runtime.h> |
209 | + |
210 | +#include <location/providers/remote/skeleton.h> |
211 | + |
212 | +#include <core/dbus/service.h> |
213 | +#include <core/dbus/asio/executor.h> |
214 | +#include <core/posix/signal.h> |
215 | + |
216 | +namespace cli = location::util::cli; |
217 | + |
218 | +namespace |
219 | +{ |
220 | +void die_if(bool b, std::ostream& out, const std::string& message) |
221 | +{ |
222 | + if (b) { out << message << std::endl; std::exit(EXIT_FAILURE); } |
223 | +} |
224 | +} |
225 | + |
226 | +location::cmds::Provider::Provider() |
227 | + : CommandWithFlagsAndAction{cli::Name{"provider"}, cli::Usage{"provider"}, cli::Description{"executes a built-in provider"}}, |
228 | + bus{core::dbus::WellKnownBus::system} |
229 | +{ |
230 | + flag(cli::make_flag(cli::Name{"bus"}, cli::Description{"bus instance to connect to, defaults to system"}, bus)); |
231 | + flag(cli::make_flag(cli::Name{"service"}, cli::Description{"name of the service hosting the provider."}, service)); |
232 | + flag(cli::make_flag(cli::Name{"path"}, cli::Description{"dbus object path hosting the provider."}, path)); |
233 | + flag(cli::make_flag(cli::Name{"id"}, cli::Description{"id of the actual provider implementation."}, id)); |
234 | + |
235 | + action([this](const Context& ctxt) |
236 | + { |
237 | + die_if(not service, ctxt.cout, "service name is missing"); |
238 | + die_if(not path, ctxt.cout, "object path is missing"); |
239 | + die_if(not id, ctxt.cout, "name of actual provider implementation is missing"); |
240 | + |
241 | + // We exit cleanly for SIGINT and SIGTERM. |
242 | + auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_int, core::posix::Signal::sig_term}); |
243 | + trap->signal_raised().connect([trap](core::posix::Signal) |
244 | + { |
245 | + trap->stop(); |
246 | + }); |
247 | + |
248 | + auto impl = location::ProviderFactory::instance().create_provider_for_name_with_config(*id, location::Configuration{}); |
249 | + |
250 | + auto rt = location::Runtime::create(); |
251 | + rt->start(); |
252 | + |
253 | + auto incoming = std::make_shared<core::dbus::Bus>(bus); |
254 | + incoming->install_executor(core::dbus::asio::make_executor(incoming, rt->service())); |
255 | + auto object = core::dbus::Service::add_service(incoming, *service) |
256 | + ->add_object_for_path(core::dbus::types::ObjectPath{*path}); |
257 | + |
258 | + location::providers::remote::skeleton::Configuration config{object, incoming, impl}; |
259 | + auto skeleton = location::providers::remote::skeleton::create_with_configuration(config); |
260 | + |
261 | + trap->run(); |
262 | + |
263 | + incoming->stop(); rt->stop(); |
264 | + |
265 | + return EXIT_SUCCESS; |
266 | + }); |
267 | +} |
268 | + |
269 | |
270 | === added file 'src/location/cmds/provider.h' |
271 | --- src/location/cmds/provider.h 1970-01-01 00:00:00 +0000 |
272 | +++ src/location/cmds/provider.h 2016-06-30 09:21:49 +0000 |
273 | @@ -0,0 +1,52 @@ |
274 | +/* |
275 | + * Copyright (C) 2016 Canonical, Ltd. |
276 | + * |
277 | + * This program is free software; you can redistribute it and/or modify |
278 | + * it under the terms of the GNU Lesser General Public License as published by |
279 | + * the Free Software Foundation; version 3. |
280 | + * |
281 | + * This program is distributed in the hope that it will be useful, |
282 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
283 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
284 | + * GNU Lesser General Public License for more details. |
285 | + * |
286 | + * You should have received a copy of the GNU Lesser General Public License |
287 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
288 | + * |
289 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
290 | + * |
291 | + */ |
292 | + |
293 | +#ifndef LOCATION_CMDS_PROVIDER_H_ |
294 | +#define LOCATION_CMDS_PROVIDER_H_ |
295 | + |
296 | +#include <location/optional.h> |
297 | +#include <location/util/cli.h> |
298 | + |
299 | +#include <location/util/well_known_bus.h> |
300 | + |
301 | +#include <boost/filesystem.hpp> |
302 | + |
303 | +#include <iosfwd> |
304 | + |
305 | +namespace location |
306 | +{ |
307 | +namespace cmds |
308 | +{ |
309 | +// Provider executes an in-tree provider out-of-process. |
310 | +class Provider : public util::cli::CommandWithFlagsAndAction |
311 | +{ |
312 | +public: |
313 | + // Run initializes a new instance. |
314 | + Provider(); |
315 | + |
316 | +private: |
317 | + core::dbus::WellKnownBus bus; // The bus we should connect to. |
318 | + Optional<std::string> service; // The name of the service under which the provider should be exposed. |
319 | + Optional<std::string> path; // The dbus object path under which the provider is known. |
320 | + Optional<std::string> id; // The id of the actual provider implementation. |
321 | +}; |
322 | +} |
323 | +} |
324 | + |
325 | +#endif // LOCATION_CMDS_PROVIDER_H_ |
326 | |
327 | === added file 'src/location/cmds/run.cpp' |
328 | --- src/location/cmds/run.cpp 1970-01-01 00:00:00 +0000 |
329 | +++ src/location/cmds/run.cpp 2016-06-30 09:21:49 +0000 |
330 | @@ -0,0 +1,109 @@ |
331 | +/* |
332 | + * Copyright (C) 2016 Canonical, Ltd. |
333 | + * |
334 | + * This program is free software; you can redistribute it and/or modify |
335 | + * it under the terms of the GNU Lesser General Public License as published by |
336 | + * the Free Software Foundation; version 3. |
337 | + * |
338 | + * This program is distributed in the hope that it will be useful, |
339 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
340 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
341 | + * GNU Lesser General Public License for more details. |
342 | + * |
343 | + * You should have received a copy of the GNU Lesser General Public License |
344 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
345 | + * |
346 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
347 | + * |
348 | + */ |
349 | + |
350 | +#include <location/cmds/run.h> |
351 | + |
352 | +#include <location/boost_ptree_settings.h> |
353 | +#include <location/fusion_provider_selection_policy.h> |
354 | +#include <location/service_with_engine.h> |
355 | +#include <location/settings.h> |
356 | +#include <location/trust_store_permission_manager.h> |
357 | + |
358 | +#include <location/dbus/skeleton/service.h> |
359 | +#include <location/runtime.h> |
360 | + |
361 | +#include <location/util/well_known_bus.h> |
362 | + |
363 | +#include <core/dbus/asio/executor.h> |
364 | +#include <core/posix/signal.h> |
365 | + |
366 | +namespace cli = location::util::cli; |
367 | + |
368 | +location::cmds::Run::Run() |
369 | + : CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"}, cli::Description{"runs the daemon"}}, |
370 | + bus{core::dbus::WellKnownBus::system}, |
371 | + settings{"/var/lib/ubuntu-location-service/config.ini"} |
372 | +{ |
373 | + flag(cli::make_flag(cli::Name{"bus"}, cli::Description{"bus instance to connect to, defaults to system"}, bus)); |
374 | + flag(cli::make_flag(cli::Name{"config"}, cli::Description{"daemon configuration"}, config)); |
375 | + flag(cli::make_flag(cli::Name{"settings"}, cli::Description{"path to runtime persistent state data"}, settings)); |
376 | + |
377 | + action([this](const Context& ctxt) |
378 | + { |
379 | + account_for_lp1447110(); |
380 | + |
381 | + // We exit cleanly for SIGINT and SIGTERM. |
382 | + auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_int, core::posix::Signal::sig_term}); |
383 | + trap->signal_raised().connect([trap](core::posix::Signal) |
384 | + { |
385 | + trap->stop(); |
386 | + }); |
387 | + |
388 | + // The engine instance is the core piece of functionality. |
389 | + auto engine = std::make_shared<location::Engine>( |
390 | + // We default to a fusion provider selection policy, providing |
391 | + // fusioned and filtered updates to sessions. |
392 | + std::make_shared<location::FusionProviderSelectionPolicy>(), |
393 | + // We default to a location::Settings implementation that reads state from |
394 | + // an ini file, immediately syncing back changes to the underlying file whenever |
395 | + // parameters change. |
396 | + std::make_shared<location::SyncingSettings>(std::make_shared<location::BoostPtreeSettings>(settings.string()))); |
397 | + |
398 | + auto rt = location::Runtime::create(); |
399 | + |
400 | + auto incoming = std::make_shared<core::dbus::Bus>(bus); |
401 | + auto outgoing = std::make_shared<core::dbus::Bus>(bus); |
402 | + |
403 | + incoming->install_executor(core::dbus::asio::make_executor(incoming, rt->service())); |
404 | + outgoing->install_executor(core::dbus::asio::make_executor(outgoing, rt->service())); |
405 | + |
406 | + auto service = core::dbus::Service::add_service<location::dbus::Service>(incoming); |
407 | + |
408 | + location::dbus::skeleton::Service::Configuration config |
409 | + { |
410 | + std::make_shared<location::ServiceWithEngine>(engine), |
411 | + incoming, |
412 | + outgoing, |
413 | + service, |
414 | + // We resolve credentials of incoming calls by talking back to the dbus daemon and subsequently |
415 | + // querying apparmor for the confinement profile. |
416 | + std::make_shared<location::dbus::skeleton::Service::DBusDaemonCredentialsResolver>(outgoing), |
417 | + std::make_shared<location::dbus::skeleton::Service::ObjectPathGenerator>(), |
418 | + // Incoming requests are verified by talking to a trust-store instance. |
419 | + location::TrustStorePermissionManager::create_default_instance_with_bus(outgoing) |
420 | + }; |
421 | + |
422 | + rt->start(); |
423 | + |
424 | + auto skeleton = std::make_shared<location::dbus::skeleton::Service>(config); |
425 | + |
426 | + trap->run(); |
427 | + |
428 | + incoming->stop(); outgoing->stop(); rt->stop(); |
429 | + |
430 | + return EXIT_SUCCESS; |
431 | + }); |
432 | +} |
433 | + |
434 | +void location::cmds::Run::account_for_lp1447110() const |
435 | +{ |
436 | + static const boost::filesystem::path old_log_dir{"/var/log/ubuntu-location-service"}; |
437 | + boost::system::error_code ec; |
438 | + boost::filesystem::remove_all(old_log_dir, ec); |
439 | +} |
440 | |
441 | === added file 'src/location/cmds/run.h' |
442 | --- src/location/cmds/run.h 1970-01-01 00:00:00 +0000 |
443 | +++ src/location/cmds/run.h 2016-06-30 09:21:49 +0000 |
444 | @@ -0,0 +1,55 @@ |
445 | +/* |
446 | + * Copyright (C) 2016 Canonical, Ltd. |
447 | + * |
448 | + * This program is free software; you can redistribute it and/or modify |
449 | + * it under the terms of the GNU Lesser General Public License as published by |
450 | + * the Free Software Foundation; version 3. |
451 | + * |
452 | + * This program is distributed in the hope that it will be useful, |
453 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
454 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
455 | + * GNU Lesser General Public License for more details. |
456 | + * |
457 | + * You should have received a copy of the GNU Lesser General Public License |
458 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
459 | + * |
460 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
461 | + * |
462 | + */ |
463 | + |
464 | +#ifndef LOCATION_CMDS_RUN_H_ |
465 | +#define LOCATION_CMDS_RUN_H_ |
466 | + |
467 | +#include <location/optional.h> |
468 | +#include <location/util/cli.h> |
469 | + |
470 | +#include <location/util/well_known_bus.h> |
471 | + |
472 | +#include <boost/filesystem.hpp> |
473 | + |
474 | +#include <iosfwd> |
475 | + |
476 | +namespace location |
477 | +{ |
478 | +namespace cmds |
479 | +{ |
480 | +// Run executes locationd, exposing the service via DBus. |
481 | +class Run : public util::cli::CommandWithFlagsAndAction |
482 | +{ |
483 | +public: |
484 | + // Run initializes a new instance. |
485 | + Run(); |
486 | + |
487 | +private: |
488 | + // Ensure that log files dating back to before the fix |
489 | + // for lp:1447110 are removed and do not waste space. |
490 | + void account_for_lp1447110() const; |
491 | + |
492 | + core::dbus::WellKnownBus bus; // The bus we should connect to. |
493 | + Optional<boost::filesystem::path> config; // Optionally load configuration from this config file. |
494 | + boost::filesystem::path settings; // Runtime persistent state settings are loaded from this file. |
495 | +}; |
496 | +} |
497 | +} |
498 | + |
499 | +#endif // LOCATION_CMDS_RUN_H_ |
500 | |
501 | === added file 'src/location/cmds/status.cpp' |
502 | --- src/location/cmds/status.cpp 1970-01-01 00:00:00 +0000 |
503 | +++ src/location/cmds/status.cpp 2016-06-30 09:21:49 +0000 |
504 | @@ -0,0 +1,69 @@ |
505 | +/* |
506 | + * Copyright (C) 2016 Canonical, Ltd. |
507 | + * |
508 | + * This program is free software; you can redistribute it and/or modify |
509 | + * it under the terms of the GNU Lesser General Public License as published by |
510 | + * the Free Software Foundation; version 3. |
511 | + * |
512 | + * This program is distributed in the hope that it will be useful, |
513 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
514 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
515 | + * GNU Lesser General Public License for more details. |
516 | + * |
517 | + * You should have received a copy of the GNU Lesser General Public License |
518 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
519 | + * |
520 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
521 | + * |
522 | + */ |
523 | + |
524 | +#include <location/cmds/status.h> |
525 | +#include <location/dbus/stub/service.h> |
526 | +#include <location/service/runtime.h> |
527 | +#include <location/util/well_known_bus.h> |
528 | + |
529 | +#include <core/dbus/asio/executor.h> |
530 | + |
531 | +namespace cli = location::util::cli; |
532 | + |
533 | +location::cmds::Status::Status() |
534 | + : CommandWithFlagsAndAction{cli::Name{"status"}, cli::Usage{"status"}, cli::Description{"queries the status of the daemon"}}, |
535 | + bus{core::dbus::WellKnownBus::system} |
536 | +{ |
537 | + flag(cli::make_flag(cli::Name{"bus"}, cli::Description{"bus instance to connect to, defaults to system"}, bus)); |
538 | + action([this](const Context& ctxt) |
539 | + { |
540 | + auto rt = location::service::Runtime::create(); |
541 | + |
542 | + auto conn = std::make_shared<core::dbus::Bus>(bus); |
543 | + |
544 | + conn->install_executor(core::dbus::asio::make_executor(conn, rt->service())); |
545 | + |
546 | + auto service = core::dbus::Service::use_service<location::dbus::Service>(conn); |
547 | + auto stub = std::make_shared<location::dbus::stub::Service>(conn, service, service->object_for_path(core::dbus::types::ObjectPath{location::dbus::Service::path()})); |
548 | + |
549 | + rt->start(); |
550 | + |
551 | + ctxt.cout << " is online: " << std::boolalpha << stub->is_online() << std::endl |
552 | + << " state: " << stub->state() << std::endl |
553 | + << " satellite based positioning: " << std::boolalpha << stub->does_satellite_based_positioning() << std::endl |
554 | + << " reports cell & wifi ids: " << std::boolalpha << stub->does_report_cell_and_wifi_ids() << std::endl; |
555 | + auto svs = stub->visible_space_vehicles().get(); |
556 | + if (svs.size() > 0) |
557 | + { |
558 | + ctxt.cout << " svs:" << std::endl; |
559 | + for (const auto& pair : svs) |
560 | + ctxt.cout << " " << pair.second << std::endl; |
561 | + } |
562 | + else |
563 | + { |
564 | + ctxt.cout << " svs: " << "none"; |
565 | + } |
566 | + |
567 | + ctxt.cout << std::endl; |
568 | + |
569 | + conn->stop(); rt->stop(); |
570 | + |
571 | + return EXIT_SUCCESS; |
572 | + }); |
573 | +} |
574 | |
575 | === added file 'src/location/cmds/status.h' |
576 | --- src/location/cmds/status.h 1970-01-01 00:00:00 +0000 |
577 | +++ src/location/cmds/status.h 2016-06-30 09:21:49 +0000 |
578 | @@ -0,0 +1,49 @@ |
579 | +/* |
580 | + * Copyright (C) 2016 Canonical, Ltd. |
581 | + * |
582 | + * This program is free software; you can redistribute it and/or modify |
583 | + * it under the terms of the GNU Lesser General Public License as published by |
584 | + * the Free Software Foundation; version 3. |
585 | + * |
586 | + * This program is distributed in the hope that it will be useful, |
587 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
588 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
589 | + * GNU Lesser General Public License for more details. |
590 | + * |
591 | + * You should have received a copy of the GNU Lesser General Public License |
592 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
593 | + * |
594 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
595 | + * |
596 | + */ |
597 | + |
598 | +#ifndef LOCATION_CMDS_STATUS_H_ |
599 | +#define LOCATION_CMDS_STATUS_H_ |
600 | + |
601 | +#include <location/optional.h> |
602 | +#include <location/util/cli.h> |
603 | + |
604 | +#include <core/dbus/well_known_bus.h> |
605 | + |
606 | +#include <boost/filesystem.hpp> |
607 | + |
608 | +#include <iosfwd> |
609 | + |
610 | +namespace location |
611 | +{ |
612 | +namespace cmds |
613 | +{ |
614 | +// Status queries the status of the daemon |
615 | +class Status : public util::cli::CommandWithFlagsAndAction |
616 | +{ |
617 | +public: |
618 | + // Status initializes a new instance. |
619 | + Status(); |
620 | + |
621 | +private: |
622 | + core::dbus::WellKnownBus bus; // The bus we should connect to. |
623 | +}; |
624 | +} |
625 | +} |
626 | + |
627 | +#endif // LOCATION_CMDS_STATUS_H_ |
628 | |
629 | === added file 'src/location/cmds/test.cpp' |
630 | --- src/location/cmds/test.cpp 1970-01-01 00:00:00 +0000 |
631 | +++ src/location/cmds/test.cpp 2016-06-30 09:21:49 +0000 |
632 | @@ -0,0 +1,32 @@ |
633 | +/* |
634 | + * Copyright (C) 2016 Canonical, Ltd. |
635 | + * |
636 | + * This program is free software; you can redistribute it and/or modify |
637 | + * it under the terms of the GNU Lesser General Public License as published by |
638 | + * the Free Software Foundation; version 3. |
639 | + * |
640 | + * This program is distributed in the hope that it will be useful, |
641 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
642 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
643 | + * GNU Lesser General Public License for more details. |
644 | + * |
645 | + * You should have received a copy of the GNU Lesser General Public License |
646 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
647 | + * |
648 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
649 | + * |
650 | + */ |
651 | + |
652 | +#include <location/cmds/test.h> |
653 | +#include <location/runtime_tests.h> |
654 | + |
655 | +namespace cli = location::util::cli; |
656 | + |
657 | +location::cmds::Test::Test() |
658 | + : CommandWithFlagsAndAction{cli::Name{"test"}, cli::Usage{"test"}, cli::Description{"executes runtime tests against the gps provider."}} |
659 | +{ |
660 | + action([this](const Context& ctxt) |
661 | + { |
662 | + return location::execute_runtime_tests(ctxt.cout, ctxt.cout); |
663 | + }); |
664 | +} |
665 | |
666 | === added file 'src/location/cmds/test.h' |
667 | --- src/location/cmds/test.h 1970-01-01 00:00:00 +0000 |
668 | +++ src/location/cmds/test.h 2016-06-30 09:21:49 +0000 |
669 | @@ -0,0 +1,41 @@ |
670 | +/* |
671 | + * Copyright (C) 2016 Canonical, Ltd. |
672 | + * |
673 | + * This program is free software; you can redistribute it and/or modify |
674 | + * it under the terms of the GNU Lesser General Public License as published by |
675 | + * the Free Software Foundation; version 3. |
676 | + * |
677 | + * This program is distributed in the hope that it will be useful, |
678 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
679 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
680 | + * GNU Lesser General Public License for more details. |
681 | + * |
682 | + * You should have received a copy of the GNU Lesser General Public License |
683 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
684 | + * |
685 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
686 | + * |
687 | + */ |
688 | + |
689 | +#ifndef LOCATION_CMDS_TEST_H_ |
690 | +#define LOCATION_CMDS_TEST_H_ |
691 | + |
692 | +#include <location/util/cli.h> |
693 | + |
694 | +#include <iosfwd> |
695 | + |
696 | +namespace location |
697 | +{ |
698 | +namespace cmds |
699 | +{ |
700 | +// Test executes runtime tests against the gps provider. |
701 | +class Test : public util::cli::CommandWithFlagsAndAction |
702 | +{ |
703 | +public: |
704 | + // List initializes a new instance. |
705 | + Test(); |
706 | +}; |
707 | +} |
708 | +} |
709 | + |
710 | +#endif // LOCATION_CMDS_TEST_H_ |
711 | |
712 | === added file 'src/location/daemon.cpp' |
713 | --- src/location/daemon.cpp 1970-01-01 00:00:00 +0000 |
714 | +++ src/location/daemon.cpp 2016-06-30 09:21:49 +0000 |
715 | @@ -0,0 +1,54 @@ |
716 | +/* |
717 | + * Copyright (C) 2016 Canonical, Ltd. |
718 | + * |
719 | + * This program is free software; you can redistribute it and/or modify |
720 | + * it under the terms of the GNU Lesser General Public License as published by |
721 | + * the Free Software Foundation; version 3. |
722 | + * |
723 | + * This program is distributed in the hope that it will be useful, |
724 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
725 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
726 | + * GNU Lesser General Public License for more details. |
727 | + * |
728 | + * You should have received a copy of the GNU Lesser General Public License |
729 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
730 | + * |
731 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
732 | + * |
733 | + */ |
734 | + |
735 | +#include <location/daemon.h> |
736 | + |
737 | +#include <location/cmds/list.h> |
738 | +#include <location/cmds/provider.h> |
739 | +#include <location/cmds/run.h> |
740 | +#include <location/cmds/status.h> |
741 | +#include <location/cmds/test.h> |
742 | + |
743 | +#include <glog/logging.h> |
744 | + |
745 | +#include <iostream> |
746 | + |
747 | +namespace cli = location::util::cli; |
748 | + |
749 | +location::Daemon::Daemon() |
750 | + : cmd{cli::Name{"locationd"}, cli::Usage{"locationd"}, cli::Description{"locationd"}} |
751 | +{ |
752 | + cmd.command(std::make_shared<location::cmds::List>()); |
753 | + cmd.command(std::make_shared<location::cmds::Provider>()); |
754 | + cmd.command(std::make_shared<location::cmds::Run>()); |
755 | + cmd.command(std::make_shared<location::cmds::Status>()); |
756 | + cmd.command(std::make_shared<location::cmds::Test>()); |
757 | +} |
758 | + |
759 | +int location::Daemon::run(const std::vector<std::string> &args) |
760 | +{ |
761 | + // Setup logging for the daemon. |
762 | + FLAGS_logtostderr = true; |
763 | + FLAGS_stop_logging_if_full_disk = true; |
764 | + FLAGS_max_log_size = 5; |
765 | + |
766 | + google::InitGoogleLogging("locationd"); |
767 | + |
768 | + return cmd.run(cli::Command::Context{std::cin, std::cout, args}); |
769 | +} |
770 | |
771 | === added file 'src/location/daemon.h' |
772 | --- src/location/daemon.h 1970-01-01 00:00:00 +0000 |
773 | +++ src/location/daemon.h 2016-06-30 09:21:49 +0000 |
774 | @@ -0,0 +1,49 @@ |
775 | +/* |
776 | + * Copyright (C) 2016 Canonical, Ltd. |
777 | + * |
778 | + * This program is free software; you can redistribute it and/or modify |
779 | + * it under the terms of the GNU Lesser General Public License as published by |
780 | + * the Free Software Foundation; version 3. |
781 | + * |
782 | + * This program is distributed in the hope that it will be useful, |
783 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
784 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
785 | + * GNU Lesser General Public License for more details. |
786 | + * |
787 | + * You should have received a copy of the GNU Lesser General Public License |
788 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
789 | + * |
790 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
791 | + * |
792 | + */ |
793 | + |
794 | +#ifndef LOCATION_DAEMON_H_ |
795 | +#define LOCATION_DAEMON_H_ |
796 | + |
797 | +#include <location/util/cli.h> |
798 | +#include <location/util/do_not_copy_or_move.h> |
799 | + |
800 | +#include <memory> |
801 | +#include <set> |
802 | +#include <sstream> |
803 | +#include <string> |
804 | +#include <vector> |
805 | + |
806 | +namespace location |
807 | +{ |
808 | +/// @brief Daemon implements biometryd. |
809 | +class Daemon : private util::DoNotCopyOrMove |
810 | +{ |
811 | +public: |
812 | + /// @brief Daemon creates a new instance, populating the map of known commands. |
813 | + Daemon(); |
814 | + |
815 | + /// @brief run executes the daemon. |
816 | + int run(const std::vector<std::string>& args); |
817 | + |
818 | +private: |
819 | + util::cli::CommandWithSubcommands cmd; |
820 | +}; |
821 | +} |
822 | + |
823 | +#endif // LOCATION_DAEMON_H_ |
824 | |
825 | === added file 'src/location/daemon_main.cpp' |
826 | --- src/location/daemon_main.cpp 1970-01-01 00:00:00 +0000 |
827 | +++ src/location/daemon_main.cpp 2016-06-30 09:21:49 +0000 |
828 | @@ -0,0 +1,26 @@ |
829 | +/* |
830 | + * Copyright (C) 2016 Canonical, Ltd. |
831 | + * |
832 | + * This program is free software; you can redistribute it and/or modify |
833 | + * it under the terms of the GNU Lesser General Public License as published by |
834 | + * the Free Software Foundation; version 3. |
835 | + * |
836 | + * This program is distributed in the hope that it will be useful, |
837 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
838 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
839 | + * GNU Lesser General Public License for more details. |
840 | + * |
841 | + * You should have received a copy of the GNU Lesser General Public License |
842 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
843 | + * |
844 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
845 | + * |
846 | + */ |
847 | + |
848 | +#include <location/daemon.h> |
849 | + |
850 | +int main(int argc, char** argv) |
851 | +{ |
852 | + location::Daemon daemon; |
853 | + return daemon.run(location::util::cli::args(argc, argv)); |
854 | +} |
855 | |
856 | === modified file 'src/location/dbus/skeleton/service.cpp' |
857 | --- src/location/dbus/skeleton/service.cpp 2016-06-28 11:53:34 +0000 |
858 | +++ src/location/dbus/skeleton/service.cpp 2016-06-30 09:21:49 +0000 |
859 | @@ -42,17 +42,17 @@ |
860 | { |
861 | } |
862 | |
863 | -location::service::Credentials |
864 | +location::Credentials |
865 | location::dbus::skeleton::Service::DBusDaemonCredentialsResolver::resolve_credentials_for_incoming_message(const core::dbus::Message::Ptr& msg) |
866 | { |
867 | - return location::service::Credentials |
868 | + return location::Credentials |
869 | { |
870 | static_cast<pid_t>(daemon.get_connection_unix_process_id(msg->sender())), |
871 | static_cast<uid_t>(daemon.get_connection_unix_user(msg->sender())) |
872 | }; |
873 | } |
874 | |
875 | -core::dbus::types::ObjectPath location::dbus::skeleton::Service::ObjectPathGenerator::object_path_for_caller_credentials(const location::service::Credentials&) |
876 | +core::dbus::types::ObjectPath location::dbus::skeleton::Service::ObjectPathGenerator::object_path_for_caller_credentials(const location::Credentials&) |
877 | { |
878 | static std::uint32_t index{0}; |
879 | std::stringstream ss; ss << "/sessions/" << index++; |
880 | @@ -76,22 +76,42 @@ |
881 | }, |
882 | connections |
883 | { |
884 | - properties.state->changed().connect([this](State state) |
885 | - { |
886 | - on_state_changed(state); |
887 | - }), |
888 | - properties.does_satellite_based_positioning->changed().connect([this](bool value) |
889 | - { |
890 | - on_does_satellite_based_positioning_changed(value); |
891 | - }), |
892 | - properties.does_report_cell_and_wifi_ids->changed().connect([this](bool value) |
893 | - { |
894 | - on_does_report_cell_and_wifi_ids_changed(value); |
895 | - }), |
896 | - properties.is_online->changed().connect([this](bool value) |
897 | - { |
898 | - on_is_online_changed(value); |
899 | - }) |
900 | + { |
901 | + properties.state->changed().connect([this](State state) |
902 | + { |
903 | + on_state_changed(state); |
904 | + }), |
905 | + properties.does_satellite_based_positioning->changed().connect([this](bool value) mutable |
906 | + { |
907 | + on_does_satellite_based_positioning_changed(value); Service::configuration.impl->does_satellite_based_positioning() = value; |
908 | + }), |
909 | + properties.does_report_cell_and_wifi_ids->changed().connect([this](bool value) mutable |
910 | + { |
911 | + on_does_report_cell_and_wifi_ids_changed(value); Service::configuration.impl->does_report_cell_and_wifi_ids() = value; |
912 | + }), |
913 | + properties.is_online->changed().connect([this](bool value) mutable |
914 | + { |
915 | + on_is_online_changed(value); Service::configuration.impl->is_online() = value; |
916 | + }) |
917 | + }, |
918 | + { |
919 | + Service::configuration.impl->state().changed().connect([this](State state) mutable |
920 | + { |
921 | + properties.state->set(state); |
922 | + }), |
923 | + Service::configuration.impl->does_satellite_based_positioning().changed().connect([this](bool value) mutable |
924 | + { |
925 | + properties.does_satellite_based_positioning->set(value); |
926 | + }), |
927 | + Service::configuration.impl->does_report_cell_and_wifi_ids().changed().connect([this](bool value) mutable |
928 | + { |
929 | + properties.does_report_cell_and_wifi_ids->set(value); |
930 | + }), |
931 | + Service::configuration.impl->is_online().changed().connect([this](bool value) mutable |
932 | + { |
933 | + properties.is_online->set(value); |
934 | + }) |
935 | + } |
936 | } |
937 | { |
938 | object->install_method_handler<location::dbus::Service::CreateSessionForCriteria>([this](const core::dbus::Message::Ptr& msg) |
939 | @@ -129,7 +149,7 @@ |
940 | auto result = |
941 | configuration.permission_manager->check_permission_for_credentials(criteria, credentials); |
942 | |
943 | - if (service::PermissionManager::Result::rejected == result) throw std::runtime_error |
944 | + if (PermissionManager::Result::rejected == result) throw std::runtime_error |
945 | { |
946 | "Client lacks permissions to access the service with the given criteria" |
947 | }; |
948 | @@ -306,3 +326,8 @@ |
949 | { |
950 | return *properties.visible_space_vehicles; |
951 | } |
952 | + |
953 | +location::Service::Session::Ptr location::dbus::skeleton::Service::create_session_for_criteria(const Criteria& criteria) |
954 | +{ |
955 | + return configuration.impl->create_session_for_criteria(criteria); |
956 | +} |
957 | |
958 | === modified file 'src/location/dbus/skeleton/service.h' |
959 | --- src/location/dbus/skeleton/service.h 2016-06-28 11:53:34 +0000 |
960 | +++ src/location/dbus/skeleton/service.h 2016-06-30 09:21:49 +0000 |
961 | @@ -20,11 +20,10 @@ |
962 | #define LOCATION_DBUS_SKELETON_SERVICE_H_ |
963 | |
964 | #include <location/service.h> |
965 | +#include <location/permission_manager.h> |
966 | |
967 | #include <location/dbus/service.h> |
968 | |
969 | -#include <location/service/permission_manager.h> |
970 | - |
971 | #include <core/dbus/dbus.h> |
972 | #include <core/dbus/object.h> |
973 | #include <core/dbus/property.h> |
974 | @@ -55,7 +54,7 @@ |
975 | virtual ~CredentialsResolver() = default; |
976 | |
977 | // Resolves the sender of msg to the respective credentials. |
978 | - virtual service::Credentials resolve_credentials_for_incoming_message(const core::dbus::Message::Ptr& msg) = 0; |
979 | + virtual Credentials resolve_credentials_for_incoming_message(const core::dbus::Message::Ptr& msg) = 0; |
980 | }; |
981 | |
982 | // Implements CredentialsResolver by reaching out to the dbus daemon and |
983 | @@ -68,7 +67,7 @@ |
984 | DBusDaemonCredentialsResolver(const core::dbus::Bus::Ptr& bus); |
985 | |
986 | // Resolves the sender of msg to pid, uid by calling out to the dbus daemon. |
987 | - service::Credentials resolve_credentials_for_incoming_message(const core::dbus::Message::Ptr& msg); |
988 | + Credentials resolve_credentials_for_incoming_message(const core::dbus::Message::Ptr& msg); |
989 | |
990 | // Stub for accessing the dbus daemon. |
991 | core::dbus::DBus daemon; |
992 | @@ -90,36 +89,30 @@ |
993 | // [1.] Query the AppArmor profile name for pid in credentials. |
994 | // [1.1] If the process is running unconfined, rely on a counter to assemble the session name. |
995 | // [1.2] If the process is confined, use the AppArmor profile name to generate the path. |
996 | - virtual core::dbus::types::ObjectPath object_path_for_caller_credentials(const service::Credentials& credentials); |
997 | + virtual core::dbus::types::ObjectPath object_path_for_caller_credentials(const Credentials& credentials); |
998 | }; |
999 | |
1000 | struct Configuration |
1001 | { |
1002 | - // DBus connection set up for handling requests to the service. |
1003 | - core::dbus::Bus::Ptr incoming; |
1004 | - // DBus connection for reaching out to other services in a non-blocking way. |
1005 | - core::dbus::Bus::Ptr outgoing; |
1006 | - // Service instance that the skeleton should be exposed upon. |
1007 | - core::dbus::Service::Ptr service; |
1008 | - // An implementation of CredentialsResolver for resolving incoming message sender |
1009 | - // to Credentials = uid, pid. |
1010 | - CredentialsResolver::Ptr credentials_resolver; |
1011 | - // An implementation of ObjectPathGenerator for generating session names. |
1012 | - ObjectPathGenerator::Ptr object_path_generator; |
1013 | - // Permission manager implementation for verifying incoming requests. |
1014 | - service::PermissionManager::Ptr permission_manager; |
1015 | + location::Service::Ptr impl; // The actual service implementation. |
1016 | + core::dbus::Bus::Ptr incoming; // DBus connection set up for handling requests to the service. |
1017 | + core::dbus::Bus::Ptr outgoing; // DBus connection for reaching out to other services in a non-blocking way. |
1018 | + core::dbus::Service::Ptr service; // Service instance that the skeleton should be exposed upon. |
1019 | + CredentialsResolver::Ptr credentials_resolver; // An implementation of CredentialsResolver. |
1020 | + ObjectPathGenerator::Ptr object_path_generator; // An implementation of ObjectPathGenerator. |
1021 | + PermissionManager::Ptr permission_manager; // A permission manager implementation. |
1022 | }; |
1023 | |
1024 | Service(const Configuration& configuration); |
1025 | ~Service() noexcept; |
1026 | |
1027 | // From location::service::Interface |
1028 | - const core::Property<State>& state() const; |
1029 | - core::Property<bool>& does_satellite_based_positioning(); |
1030 | - core::Property<bool>& does_report_cell_and_wifi_ids(); |
1031 | - core::Property<bool>& is_online(); |
1032 | - core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles(); |
1033 | - |
1034 | + const core::Property<State>& state() const override; |
1035 | + core::Property<bool>& does_satellite_based_positioning() override; |
1036 | + core::Property<bool>& does_report_cell_and_wifi_ids() override; |
1037 | + core::Property<bool>& is_online() override; |
1038 | + core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles() override; |
1039 | + Session::Ptr create_session_for_criteria(const Criteria& criteria) override; |
1040 | protected: |
1041 | // Enable subclasses to alter the state. |
1042 | core::Property<State>& mutable_state(); |
1043 | @@ -172,10 +165,21 @@ |
1044 | // We sign up to property changes here, to be able to report them to the bus |
1045 | struct |
1046 | { |
1047 | - core::ScopedConnection state; |
1048 | - core::ScopedConnection does_satellite_based_positioning; |
1049 | - core::ScopedConnection does_report_cell_and_wifi_ids; |
1050 | - core::ScopedConnection is_online; |
1051 | + struct |
1052 | + { |
1053 | + core::ScopedConnection state; |
1054 | + core::ScopedConnection does_satellite_based_positioning; |
1055 | + core::ScopedConnection does_report_cell_and_wifi_ids; |
1056 | + core::ScopedConnection is_online; |
1057 | + } dbus; |
1058 | + |
1059 | + struct |
1060 | + { |
1061 | + core::ScopedConnection state; |
1062 | + core::ScopedConnection does_satellite_based_positioning; |
1063 | + core::ScopedConnection does_report_cell_and_wifi_ids; |
1064 | + core::ScopedConnection is_online; |
1065 | + } impl; |
1066 | } connections; |
1067 | // Guards the session store. |
1068 | std::mutex guard; |
1069 | |
1070 | === added file 'src/location/dummy_service.cpp' |
1071 | --- src/location/dummy_service.cpp 1970-01-01 00:00:00 +0000 |
1072 | +++ src/location/dummy_service.cpp 2016-06-30 09:21:49 +0000 |
1073 | @@ -0,0 +1,55 @@ |
1074 | +/* |
1075 | + * Copyright (C) 2016 Canonical, Ltd. |
1076 | + * |
1077 | + * This program is free software; you can redistribute it and/or modify |
1078 | + * it under the terms of the GNU Lesser General Public License as published by |
1079 | + * the Free Software Foundation; version 3. |
1080 | + * |
1081 | + * This program is distributed in the hope that it will be useful, |
1082 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1083 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1084 | + * GNU Lesser General Public License for more details. |
1085 | + * |
1086 | + * You should have received a copy of the GNU Lesser General Public License |
1087 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1088 | + * |
1089 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1090 | + * |
1091 | + */ |
1092 | + |
1093 | +#include <location/dummy_service.h> |
1094 | + |
1095 | +location::Service::Session::Updates& location::DummyService::Session::updates() |
1096 | +{ |
1097 | + return updates_; |
1098 | +} |
1099 | + |
1100 | +const core::Property<location::Service::State>& location::DummyService::state() const |
1101 | +{ |
1102 | + return state_; |
1103 | +} |
1104 | + |
1105 | +core::Property<bool>& location::DummyService::does_satellite_based_positioning() |
1106 | +{ |
1107 | + return does_satellite_based_positioning_; |
1108 | +} |
1109 | + |
1110 | +core::Property<bool>& location::DummyService::is_online() |
1111 | +{ |
1112 | + return is_online_; |
1113 | +} |
1114 | + |
1115 | +core::Property<bool>& location::DummyService::does_report_cell_and_wifi_ids() |
1116 | +{ |
1117 | + return does_report_cell_and_wifi_ids_; |
1118 | +} |
1119 | + |
1120 | +core::Property<std::map<location::SpaceVehicle::Key, location::SpaceVehicle>>& location::DummyService::visible_space_vehicles() |
1121 | +{ |
1122 | + return visible_space_vehicles_; |
1123 | +} |
1124 | + |
1125 | +location::Service::Session::Ptr location::DummyService::create_session_for_criteria(const Criteria&) |
1126 | +{ |
1127 | + return std::make_shared<DummyService::Session>(); |
1128 | +} |
1129 | |
1130 | === added file 'src/location/dummy_service.h' |
1131 | --- src/location/dummy_service.h 1970-01-01 00:00:00 +0000 |
1132 | +++ src/location/dummy_service.h 2016-06-30 09:21:49 +0000 |
1133 | @@ -0,0 +1,55 @@ |
1134 | +/* |
1135 | + * Copyright (C) 2016 Canonical, Ltd. |
1136 | + * |
1137 | + * This program is free software; you can redistribute it and/or modify |
1138 | + * it under the terms of the GNU Lesser General Public License as published by |
1139 | + * the Free Software Foundation; version 3. |
1140 | + * |
1141 | + * This program is distributed in the hope that it will be useful, |
1142 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1143 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1144 | + * GNU Lesser General Public License for more details. |
1145 | + * |
1146 | + * You should have received a copy of the GNU Lesser General Public License |
1147 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1148 | + * |
1149 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1150 | + * |
1151 | + */ |
1152 | + |
1153 | +#ifndef LOCATION_DUMMY_SERVICE_H_ |
1154 | +#define LOCATION_DUMMY_SERVICE_H_ |
1155 | + |
1156 | +#include <location/service.h> |
1157 | + |
1158 | +namespace location |
1159 | +{ |
1160 | +class DummyService : public Service |
1161 | +{ |
1162 | +public: |
1163 | + class Session : public Service::Session |
1164 | + { |
1165 | + public: |
1166 | + Updates& updates() override; |
1167 | + |
1168 | + private: |
1169 | + Updates updates_; |
1170 | + }; |
1171 | + |
1172 | + const core::Property<State>& state() const override; |
1173 | + core::Property<bool>& does_satellite_based_positioning() override; |
1174 | + core::Property<bool>& is_online() override; |
1175 | + core::Property<bool>& does_report_cell_and_wifi_ids() override; |
1176 | + core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles() override; |
1177 | + Session::Ptr create_session_for_criteria(const Criteria& criteria) override; |
1178 | + |
1179 | +private: |
1180 | + core::Property<State> state_; |
1181 | + core::Property<bool> does_satellite_based_positioning_; |
1182 | + core::Property<bool> is_online_; |
1183 | + core::Property<bool> does_report_cell_and_wifi_ids_; |
1184 | + core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>> visible_space_vehicles_; |
1185 | +}; |
1186 | +} |
1187 | + |
1188 | +#endif // LOCATION_DUMMY_SERVICE_H_ |
1189 | |
1190 | === added file 'src/location/permission_manager.h' |
1191 | --- src/location/permission_manager.h 1970-01-01 00:00:00 +0000 |
1192 | +++ src/location/permission_manager.h 2016-06-30 09:21:49 +0000 |
1193 | @@ -0,0 +1,73 @@ |
1194 | +/* |
1195 | + * Copyright © 2012-2013 Canonical Ltd. |
1196 | + * |
1197 | + * This program is free software: you can redistribute it and/or modify it |
1198 | + * under the terms of the GNU Lesser General Public License version 3, |
1199 | + * as published by the Free Software Foundation. |
1200 | + * |
1201 | + * This program is distributed in the hope that it will be useful, |
1202 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1203 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1204 | + * GNU Lesser General Public License for more details. |
1205 | + * |
1206 | + * You should have received a copy of the GNU Lesser General Public License |
1207 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1208 | + * |
1209 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1210 | + */ |
1211 | +#ifndef LOCATION_PERMISSION_MANAGER_H_ |
1212 | +#define LOCATION_PERMISSION_MANAGER_H_ |
1213 | + |
1214 | +#include <memory> |
1215 | + |
1216 | +namespace location |
1217 | +{ |
1218 | +struct Criteria; |
1219 | +/** @brief Credentials of a remote session. */ |
1220 | +struct Credentials |
1221 | +{ |
1222 | + /** @brief The process id of the remote peer. */ |
1223 | + pid_t pid; |
1224 | + /** @brief The user id the remote peer runs under. */ |
1225 | + uid_t uid; |
1226 | +}; |
1227 | + |
1228 | +/** |
1229 | + * @brief The PermissionManager class is an interface to check whether an application |
1230 | + * is allowed to access the location services. |
1231 | + */ |
1232 | +class PermissionManager |
1233 | +{ |
1234 | +public: |
1235 | + /** Manager pointer type. */ |
1236 | + typedef std::shared_ptr<PermissionManager> Ptr; |
1237 | + |
1238 | + /** |
1239 | + * @brief The Result enum summarizes the results of a query for permissions. |
1240 | + */ |
1241 | + enum class Result |
1242 | + { |
1243 | + granted, ///< The app is allowed to access the location service. |
1244 | + rejected ///< The app is not allowed to access the location service. |
1245 | + }; |
1246 | + |
1247 | + virtual ~PermissionManager() = default; |
1248 | + PermissionManager(const PermissionManager&) = delete; |
1249 | + PermissionManager& operator=(const PermissionManager&) = delete; |
1250 | + |
1251 | + /** |
1252 | + * @brief Checks whether the app with the given credentials is allowed to access the service for the given criteria. |
1253 | + * @param criteria The requirements of the remote peer. |
1254 | + * @param credentials The credentials identifying the remote peer. |
1255 | + * @return Result::granted if the remote peer is allowed to access the location service, Result::rejected otherwise. |
1256 | + */ |
1257 | + virtual Result check_permission_for_credentials( |
1258 | + const Criteria& criteria, |
1259 | + const Credentials& credentials) = 0; |
1260 | + |
1261 | +protected: |
1262 | + PermissionManager() = default; |
1263 | +}; |
1264 | +} |
1265 | + |
1266 | +#endif // LOCATION_PERMISSION_MANAGER_H_ |
1267 | |
1268 | === modified file 'src/location/providers/gps/sntp_reference_time_source.cpp' |
1269 | --- src/location/providers/gps/sntp_reference_time_source.cpp 2016-06-26 21:17:03 +0000 |
1270 | +++ src/location/providers/gps/sntp_reference_time_source.cpp 2016-06-30 09:21:49 +0000 |
1271 | @@ -19,7 +19,7 @@ |
1272 | #include <location/providers/gps/sntp_reference_time_source.h> |
1273 | |
1274 | #include <location/configuration.h> |
1275 | -#include <location/service/runtime.h> |
1276 | +#include <location/runtime.h> |
1277 | |
1278 | #include <boost/property_tree/ini_parser.hpp> |
1279 | |
1280 | @@ -46,7 +46,7 @@ |
1281 | |
1282 | gps::HardwareAbstractionLayer::ReferenceTimeSample gps::SntpReferenceTimeSource::sample() |
1283 | { |
1284 | - auto rt = location::service::Runtime::create(); |
1285 | + auto rt = location::Runtime::create(); |
1286 | rt->start(); |
1287 | |
1288 | location::providers::gps::sntp::Client sntp_client; |
1289 | |
1290 | === added file 'src/location/runtime.cpp' |
1291 | --- src/location/runtime.cpp 1970-01-01 00:00:00 +0000 |
1292 | +++ src/location/runtime.cpp 2016-06-30 09:21:49 +0000 |
1293 | @@ -0,0 +1,107 @@ |
1294 | +/* |
1295 | + * Copyright © 2015 Canonical Ltd. |
1296 | + * |
1297 | + * This program is free software: you can redistribute it and/or modify it |
1298 | + * under the terms of the GNU Lesser General Public License version 3, |
1299 | + * as published by the Free Software Foundation. |
1300 | + * |
1301 | + * This program is distributed in the hope that it will be useful, |
1302 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1303 | + * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the |
1304 | + * GNU Lesser General Public License for more details. |
1305 | + * |
1306 | + * You should have received a copy of the GNU Lesser General Public License |
1307 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1308 | + * |
1309 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1310 | + */ |
1311 | +#include <location/runtime.h> |
1312 | + |
1313 | +#include <location/logging.h> |
1314 | + |
1315 | +namespace |
1316 | +{ |
1317 | +// exception_safe_run runs service, catching all exceptions and |
1318 | +// restarting operation until an explicit shutdown has been requested. |
1319 | +// |
1320 | +// TODO(tvoss): Catching all exceptions is risky as they might signal unrecoverable |
1321 | +// errors. We should enable calling code to decide whether an exception should be considered |
1322 | +// fatal or not. |
1323 | +void exception_safe_run(boost::asio::io_service& service) |
1324 | +{ |
1325 | + while (true) |
1326 | + { |
1327 | + try |
1328 | + { |
1329 | + service.run(); |
1330 | + // a clean return from run only happens in case of |
1331 | + // stop() being called (we are keeping the service alive with |
1332 | + // a service::work instance). |
1333 | + break; |
1334 | + } |
1335 | + catch (const std::exception& e) |
1336 | + { |
1337 | + LOG(WARNING) << e.what(); |
1338 | + } |
1339 | + catch (...) |
1340 | + { |
1341 | + LOG(WARNING) << "Unknown exception caught while executing boost::asio::io_service"; |
1342 | + } |
1343 | + } |
1344 | +} |
1345 | +} |
1346 | + |
1347 | +std::shared_ptr<location::Runtime> location::Runtime::create(std::uint32_t pool_size) |
1348 | +{ |
1349 | + return std::shared_ptr<location::Runtime>(new location::Runtime(pool_size)); |
1350 | +} |
1351 | + |
1352 | +location::Runtime::Runtime(std::uint32_t pool_size) |
1353 | + : pool_size_{pool_size}, |
1354 | + service_{pool_size_}, |
1355 | + strand_{service_}, |
1356 | + keep_alive_{service_} |
1357 | +{ |
1358 | +} |
1359 | + |
1360 | +location::Runtime::~Runtime() |
1361 | +{ |
1362 | + try |
1363 | + { |
1364 | + stop(); |
1365 | + } catch(...) |
1366 | + { |
1367 | + // Dropping all exceptions to satisfy the nothrow guarantee. |
1368 | + } |
1369 | +} |
1370 | + |
1371 | +void location::Runtime::start() |
1372 | +{ |
1373 | + for (unsigned int i = 0; i < pool_size_; i++) |
1374 | + workers_.push_back(std::thread{exception_safe_run, std::ref(service_)}); |
1375 | +} |
1376 | + |
1377 | +void location::Runtime::stop() |
1378 | +{ |
1379 | + service_.stop(); |
1380 | + |
1381 | + for (auto& worker : workers_) |
1382 | + if (worker.joinable()) |
1383 | + worker.join(); |
1384 | +} |
1385 | + |
1386 | +std::function<void(std::function<void()>)> location::Runtime::to_dispatcher_functional() |
1387 | +{ |
1388 | + // We have to make sure that we stay alive for as long as |
1389 | + // calling code requires the dispatcher to work. |
1390 | + auto sp = shared_from_this(); |
1391 | + return [sp](std::function<void()> task) |
1392 | + { |
1393 | + sp->strand_.post(task); |
1394 | + }; |
1395 | +} |
1396 | + |
1397 | +boost::asio::io_service& location::Runtime::service() |
1398 | +{ |
1399 | + return service_; |
1400 | +} |
1401 | |
1402 | === added file 'src/location/runtime.h' |
1403 | --- src/location/runtime.h 1970-01-01 00:00:00 +0000 |
1404 | +++ src/location/runtime.h 2016-06-30 09:21:49 +0000 |
1405 | @@ -0,0 +1,81 @@ |
1406 | +/* |
1407 | + * Copyright © 2015 Canonical Ltd. |
1408 | + * |
1409 | + * This program is free software: you can redistribute it and/or modify it |
1410 | + * under the terms of the GNU Lesser General Public License version 3, |
1411 | + * as published by the Free Software Foundation. |
1412 | + * |
1413 | + * This program is distributed in the hope that it will be useful, |
1414 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1415 | + * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the |
1416 | + * GNU Lesser General Public License for more details. |
1417 | + * |
1418 | + * You should have received a copy of the GNU Lesser General Public License |
1419 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1420 | + * |
1421 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1422 | + */ |
1423 | +#ifndef LOCATION_RUNTIME_H_ |
1424 | +#define LOCATION_RUNTIME_H_ |
1425 | + |
1426 | +#include <boost/asio.hpp> |
1427 | + |
1428 | +#include <functional> |
1429 | +#include <memory> |
1430 | +#include <thread> |
1431 | +#include <vector> |
1432 | + |
1433 | +#include <cstdint> |
1434 | + |
1435 | +namespace location |
1436 | +{ |
1437 | +// We bundle our "global" runtime dependencies here, specifically |
1438 | +// a dispatcher to decouple multiple in-process providers from one |
1439 | +// another , forcing execution to a well known set of threads. |
1440 | +class Runtime : public std::enable_shared_from_this<Runtime> |
1441 | +{ |
1442 | +public: |
1443 | + // Our default concurrency setup. |
1444 | + static constexpr const std::uint32_t worker_threads = 4; |
1445 | + |
1446 | + // create returns a Runtime instance with pool_size worker threads |
1447 | + // executing the underlying service. |
1448 | + static std::shared_ptr<Runtime> create(std::uint32_t pool_size = worker_threads); |
1449 | + |
1450 | + Runtime(const Runtime&) = delete; |
1451 | + Runtime(Runtime&&) = delete; |
1452 | + // Tears down the runtime, stopping all worker threads. |
1453 | + ~Runtime() noexcept(true); |
1454 | + Runtime& operator=(const Runtime&) = delete; |
1455 | + Runtime& operator=(Runtime&&) = delete; |
1456 | + |
1457 | + // start executes the underlying io_service on a thread pool with |
1458 | + // the size configured at creation time. |
1459 | + void start(); |
1460 | + |
1461 | + // stop cleanly shuts down a Runtime instance, |
1462 | + // joining all worker threads. |
1463 | + void stop(); |
1464 | + |
1465 | + // to_dispatcher_functional returns a function for integration |
1466 | + // with components that expect a dispatcher for operation. |
1467 | + std::function<void(std::function<void()>)> to_dispatcher_functional(); |
1468 | + |
1469 | + // service returns the underlying boost::asio::io_service that is executed |
1470 | + // by the Runtime. |
1471 | + boost::asio::io_service& service(); |
1472 | + |
1473 | +private: |
1474 | + // Runtime constructs a new instance, firing up pool_size |
1475 | + // worker threads. |
1476 | + Runtime(std::uint32_t pool_size); |
1477 | + |
1478 | + std::uint32_t pool_size_; |
1479 | + boost::asio::io_service service_; |
1480 | + boost::asio::io_service::strand strand_; |
1481 | + boost::asio::io_service::work keep_alive_; |
1482 | + std::vector<std::thread> workers_; |
1483 | +}; |
1484 | +} |
1485 | + |
1486 | +#endif // LOCATION_RUNTIME_H_ |
1487 | |
1488 | === added file 'src/location/runtime_tests.cpp' |
1489 | --- src/location/runtime_tests.cpp 1970-01-01 00:00:00 +0000 |
1490 | +++ src/location/runtime_tests.cpp 2016-06-30 09:21:49 +0000 |
1491 | @@ -0,0 +1,185 @@ |
1492 | +/* |
1493 | + * Copyright © 2015 Canonical Ltd. |
1494 | + * |
1495 | + * This program is free software: you can redistribute it and/or modify it |
1496 | + * under the terms of the GNU Lesser General Public License version 3, |
1497 | + * as published by the Free Software Foundation. |
1498 | + * |
1499 | + * This program is distributed in the hope that it will be useful, |
1500 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1501 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1502 | + * GNU Lesser General Public License for more details. |
1503 | + * |
1504 | + * You should have received a copy of the GNU Lesser General Public License |
1505 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1506 | + * |
1507 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1508 | + */ |
1509 | + |
1510 | +#include <location/runtime.h> |
1511 | +#include <location/runtime_tests.h> |
1512 | + |
1513 | +#include <location/clock.h> |
1514 | +#include <location/providers/gps/hardware_abstraction_layer.h> |
1515 | + |
1516 | +#include <boost/accumulators/accumulators.hpp> |
1517 | +#include <boost/accumulators/statistics/stats.hpp> |
1518 | +#include <boost/accumulators/statistics/mean.hpp> |
1519 | +#include <boost/accumulators/statistics/variance.hpp> |
1520 | + |
1521 | +#include <cstdlib> |
1522 | + |
1523 | +#include <chrono> |
1524 | +#include <condition_variable> |
1525 | +#include <iostream> |
1526 | +#include <mutex> |
1527 | +#include <thread> |
1528 | + |
1529 | +namespace gps = location::providers::gps; |
1530 | + |
1531 | +namespace |
1532 | +{ |
1533 | +template<bool expected, typename Exception> |
1534 | +void expect(bool value, const std::string& what) |
1535 | +{ |
1536 | + if (value != expected) throw Exception{what}; |
1537 | +} |
1538 | + |
1539 | +// Poor man's testing fixture, taking care of shutting down the currently |
1540 | +// running service instance and restarting it after the tests have been run. |
1541 | +struct Fixture |
1542 | +{ |
1543 | + Fixture() |
1544 | + { |
1545 | + // We need to make sure that we are running as root. In addition, we will stop |
1546 | + // any running location service instance prior to executing the test. |
1547 | + expect<true, std::logic_error>(::getuid() == 0, "This test has to be run as root."); |
1548 | + |
1549 | + int rc = ::system("service ubuntu-location-service stop"); |
1550 | + // We consciously ignore any issues and assume that we are good to go. |
1551 | + (void) rc; |
1552 | + } |
1553 | + |
1554 | + ~Fixture() |
1555 | + { |
1556 | + int rc = ::system("service ubuntu-location-service start"); |
1557 | + // We consciously ignore any issues reported by the call to system |
1558 | + // as we would make an otherwise fine test-suite failing just because |
1559 | + // an "uninteresting" post-condition is not satisfied. |
1560 | + (void) rc; |
1561 | + } |
1562 | +}; |
1563 | + |
1564 | +#if defined(LOCATION_PROVIDERS_GPS) |
1565 | +int snr_and_ttff(std::ostream& cout, std::ostream& cerr) |
1566 | +{ |
1567 | + typedef boost::accumulators::accumulator_set< |
1568 | + double, |
1569 | + boost::accumulators::stats< |
1570 | + boost::accumulators::tag::mean, |
1571 | + boost::accumulators::tag::variance |
1572 | + > |
1573 | + > Statistics; |
1574 | + |
1575 | + using boost::accumulators::mean; |
1576 | + using boost::accumulators::variance; |
1577 | + |
1578 | + static const unsigned int trials = 3; |
1579 | + |
1580 | + Statistics stats; |
1581 | + auto hal = gps::HardwareAbstractionLayer::create_default_instance(); |
1582 | + |
1583 | + struct State |
1584 | + { |
1585 | + State() : fix_received(false) |
1586 | + { |
1587 | + } |
1588 | + |
1589 | + bool wait_for_fix_for(const std::chrono::seconds& seconds) |
1590 | + { |
1591 | + std::unique_lock<std::mutex> ul(guard); |
1592 | + return wait_condition.wait_for( |
1593 | + ul, |
1594 | + seconds, |
1595 | + [this]() {return fix_received == true;}); |
1596 | + } |
1597 | + |
1598 | + void on_position_updated(const location::Position&) |
1599 | + { |
1600 | + fix_received = true; |
1601 | + wait_condition.notify_all(); |
1602 | + } |
1603 | + |
1604 | + void reset() |
1605 | + { |
1606 | + fix_received = false; |
1607 | + } |
1608 | + |
1609 | + std::mutex guard; |
1610 | + std::condition_variable wait_condition; |
1611 | + bool fix_received; |
1612 | + } state; |
1613 | + |
1614 | + // We want to run in standalone mode |
1615 | + hal->set_assistance_mode(gps::AssistanceMode::standalone); |
1616 | + |
1617 | + // We wire up our state to position updates from the hal. |
1618 | + hal->position_updates().connect([&state](const location::Position& pos) |
1619 | + { |
1620 | + state.on_position_updated(pos); |
1621 | + }); |
1622 | + |
1623 | + // We report updates to the visible space vehicles here. |
1624 | + hal->space_vehicle_updates().connect([&cout](const std::set<location::SpaceVehicle>& svs) |
1625 | + { |
1626 | + cout << std::scientific; |
1627 | + cout << "key snr has_almanac_data has_ephimeris_data used_in_fix azimuth elevation" << std::endl; |
1628 | + for (const auto& sv : svs) |
1629 | + cout << sv.key.id << " " << sv.snr << " " << sv.has_almanac_data << " " << sv.has_ephimeris_data << " " << sv.used_in_fix << " " << sv.azimuth.value() << " " << sv.elevation.value() << std::endl; |
1630 | + }); |
1631 | + |
1632 | + for (unsigned int i = 0; i < trials; i++) |
1633 | + { |
1634 | + // We want to force a cold start per trial. |
1635 | + hal->delete_all_aiding_data(); |
1636 | + |
1637 | + state.reset(); |
1638 | + auto start = std::chrono::duration_cast<std::chrono::microseconds>(location::Clock::now().time_since_epoch()); |
1639 | + { |
1640 | + hal->start_positioning(); |
1641 | + // We expect a maximum cold start time of 15 minutes. The theoretical |
1642 | + // limit is 12.5 minutes, and we add up some grace period to make the |
1643 | + // test more robust (see http://en.wikipedia.org/wiki/Time_to_first_fix). |
1644 | + expect<true, std::runtime_error>(state.wait_for_fix_for(std::chrono::seconds{15 * 60}), "Wait for fix timed out."); |
1645 | + hal->stop_positioning(); |
1646 | + } |
1647 | + auto stop = std::chrono::duration_cast<std::chrono::microseconds>(location::Clock::now().time_since_epoch()); |
1648 | + |
1649 | + stats((stop - start).count()); |
1650 | + } |
1651 | + |
1652 | + cout << "Mean time to first fix in [ms]: " |
1653 | + << std::chrono::duration_cast<std::chrono::milliseconds>( |
1654 | + std::chrono::microseconds( |
1655 | + static_cast<std::uint64_t>(mean(stats)))).count() |
1656 | + << std::endl; |
1657 | + cout << "Variance in time to first fix in [ms]: " |
1658 | + << std::chrono::duration_cast<std::chrono::milliseconds>( |
1659 | + std::chrono::microseconds( |
1660 | + static_cast<std::uint64_t>(variance(stats)))).count() |
1661 | + << std::endl; |
1662 | + |
1663 | + return 0; |
1664 | +} |
1665 | +#else |
1666 | +int snr_and_ttff(std::ostream&, std::ostream&) { return 0; } |
1667 | +#endif // LOCATION_PROVIDERS_GPS |
1668 | +} |
1669 | + |
1670 | +int location::execute_runtime_tests(std::ostream& cout, std::ostream& cerr) |
1671 | +{ |
1672 | + Fixture fixture; // This throws in case of issues. |
1673 | + auto rc = snr_and_ttff(cout, cerr); if (rc != 0) return rc; |
1674 | + // Other runtime tests go here; |
1675 | + return rc; |
1676 | +} |
1677 | |
1678 | === added file 'src/location/runtime_tests.h' |
1679 | --- src/location/runtime_tests.h 1970-01-01 00:00:00 +0000 |
1680 | +++ src/location/runtime_tests.h 2016-06-30 09:21:49 +0000 |
1681 | @@ -0,0 +1,30 @@ |
1682 | +/* |
1683 | + * Copyright © 2015 Canonical Ltd. |
1684 | + * |
1685 | + * This program is free software: you can redistribute it and/or modify it |
1686 | + * under the terms of the GNU Lesser General Public License version 3, |
1687 | + * as published by the Free Software Foundation. |
1688 | + * |
1689 | + * This program is distributed in the hope that it will be useful, |
1690 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1691 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1692 | + * GNU Lesser General Public License for more details. |
1693 | + * |
1694 | + * You should have received a copy of the GNU Lesser General Public License |
1695 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1696 | + * |
1697 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1698 | + */ |
1699 | +#ifndef LOCATION_RUNTIME_TESTS_H_ |
1700 | +#define LOCATION_RUNTIME_TESTS_H_ |
1701 | + |
1702 | +#include <iosfwd> |
1703 | + |
1704 | +namespace location |
1705 | +{ |
1706 | +// execute_runtime_tests runs all configured runtime tests. |
1707 | +// Returns 0 if successful. |
1708 | +int execute_runtime_tests(std::ostream& cout, std::ostream& cerr); |
1709 | +} |
1710 | + |
1711 | +#endif // LOCATION_RUNTIME_TESTS_H_ |
1712 | |
1713 | === added file 'src/location/service_with_engine.cpp' |
1714 | --- src/location/service_with_engine.cpp 1970-01-01 00:00:00 +0000 |
1715 | +++ src/location/service_with_engine.cpp 2016-06-30 09:21:49 +0000 |
1716 | @@ -0,0 +1,129 @@ |
1717 | +/* |
1718 | + * Copyright © 2016 Canonical Ltd. |
1719 | + * |
1720 | + * This program is free software: you can redistribute it and/or modify it |
1721 | + * under the terms of the GNU Lesser General Public License version 3, |
1722 | + * as published by the Free Software Foundation. |
1723 | + * |
1724 | + * This program is distributed in the hope that it will be useful, |
1725 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1726 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1727 | + * GNU Lesser General Public License for more details. |
1728 | + * |
1729 | + * You should have received a copy of the GNU Lesser General Public License |
1730 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1731 | + * |
1732 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1733 | + */ |
1734 | + |
1735 | +#include <location/proxy_provider.h> |
1736 | +#include <location/service_with_engine.h> |
1737 | +#include <location/session_with_provider.h> |
1738 | + |
1739 | +location::ServiceWithEngine::ServiceWithEngine(const Engine::Ptr& engine) |
1740 | + : engine{engine}, |
1741 | + connections |
1742 | + { |
1743 | + is_online_.changed().connect( |
1744 | + [this](bool value) |
1745 | + { |
1746 | + ServiceWithEngine::engine->configuration.engine_state |
1747 | + = value ? |
1748 | + Engine::Status::on : |
1749 | + Engine::Status::off; |
1750 | + }), |
1751 | + does_report_cell_and_wifi_ids_.changed().connect( |
1752 | + [this](bool value) |
1753 | + { |
1754 | + ServiceWithEngine::engine->configuration.wifi_and_cell_id_reporting_state |
1755 | + = value ? |
1756 | + location::WifiAndCellIdReportingState::on : |
1757 | + location::WifiAndCellIdReportingState::off; |
1758 | + }), |
1759 | + does_satellite_based_positioning_.changed().connect( |
1760 | + [this](bool value) |
1761 | + { |
1762 | + ServiceWithEngine::engine->configuration.satellite_based_positioning_state |
1763 | + = value ? |
1764 | + location::SatelliteBasedPositioningState::on : |
1765 | + location::SatelliteBasedPositioningState::off; |
1766 | + }), |
1767 | + engine->configuration.engine_state.changed().connect( |
1768 | + [this](Engine::Status status) |
1769 | + { |
1770 | + switch (status) |
1771 | + { |
1772 | + case Engine::Status::off: |
1773 | + is_online_ = false; |
1774 | + state_ = State::disabled; |
1775 | + break; |
1776 | + case Engine::Status::on: |
1777 | + is_online_ = true; |
1778 | + state_ = State::enabled; |
1779 | + break; |
1780 | + case Engine::Status::active: |
1781 | + is_online_ = true; |
1782 | + state_ = State::active; |
1783 | + break; |
1784 | + } |
1785 | + }), |
1786 | + engine->configuration.satellite_based_positioning_state.changed().connect( |
1787 | + [this](location::SatelliteBasedPositioningState state) |
1788 | + { |
1789 | + does_satellite_based_positioning_ = |
1790 | + state == location::SatelliteBasedPositioningState::on; |
1791 | + }), |
1792 | + engine->updates.visible_space_vehicles.changed().connect( |
1793 | + [this](const std::map<location::SpaceVehicle::Key, location::SpaceVehicle>&svs) |
1794 | + { |
1795 | + visible_space_vehicles_ = svs; |
1796 | + }) |
1797 | + } |
1798 | +{ |
1799 | +} |
1800 | + |
1801 | +const core::Property<location::Service::State>& location::ServiceWithEngine::state() const |
1802 | +{ |
1803 | + return state_; |
1804 | +} |
1805 | + |
1806 | +core::Property<bool>& location::ServiceWithEngine::does_satellite_based_positioning() |
1807 | +{ |
1808 | + return does_satellite_based_positioning_; |
1809 | +} |
1810 | + |
1811 | +core::Property<bool>& location::ServiceWithEngine::is_online() |
1812 | +{ |
1813 | + return is_online_; |
1814 | +} |
1815 | + |
1816 | +core::Property<bool>& location::ServiceWithEngine::does_report_cell_and_wifi_ids() |
1817 | +{ |
1818 | + return does_report_cell_and_wifi_ids_; |
1819 | +} |
1820 | + |
1821 | +core::Property<std::map<location::SpaceVehicle::Key, location::SpaceVehicle>>& location::ServiceWithEngine::visible_space_vehicles() |
1822 | +{ |
1823 | + return visible_space_vehicles_; |
1824 | +} |
1825 | + |
1826 | +location::Service::Session::Ptr location::ServiceWithEngine::create_session_for_criteria(const Criteria& criteria) |
1827 | +{ |
1828 | + auto proxy_provider = std::make_shared<ProxyProvider>(engine->determine_provider_selection_for_criteria(criteria)); |
1829 | + auto session = std::make_shared<SessionWithProvider>(proxy_provider); |
1830 | + std::weak_ptr<Session> wp{session}; |
1831 | + |
1832 | + session->updates().position_status.changed().connect([this, wp](const Session::Updates::Status& status) |
1833 | + { |
1834 | + location::Optional<location::Update<location::Position>> last_known_position = engine->updates.last_known_location.get(); |
1835 | + bool has_last_known_position = last_known_position ? true : false; |
1836 | + bool is_session_enabled = status == Session::Updates::Status::enabled; |
1837 | + bool is_session_on_or_active = engine->configuration.engine_state != Engine::Status::off; |
1838 | + |
1839 | + if (has_last_known_position && is_session_enabled && is_session_on_or_active) |
1840 | + if (auto sp = wp.lock()) // Immediately send the last known position to the client |
1841 | + sp->updates().position = last_known_position.get(); |
1842 | + }); |
1843 | + |
1844 | + return session; |
1845 | +} |
1846 | |
1847 | === added file 'src/location/service_with_engine.h' |
1848 | --- src/location/service_with_engine.h 1970-01-01 00:00:00 +0000 |
1849 | +++ src/location/service_with_engine.h 2016-06-30 09:21:49 +0000 |
1850 | @@ -0,0 +1,61 @@ |
1851 | +/* |
1852 | + * Copyright © 2016 Canonical Ltd. |
1853 | + * |
1854 | + * This program is free software: you can redistribute it and/or modify it |
1855 | + * under the terms of the GNU Lesser General Public License version 3, |
1856 | + * as published by the Free Software Foundation. |
1857 | + * |
1858 | + * This program is distributed in the hope that it will be useful, |
1859 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1860 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1861 | + * GNU Lesser General Public License for more details. |
1862 | + * |
1863 | + * You should have received a copy of the GNU Lesser General Public License |
1864 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1865 | + * |
1866 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1867 | + */ |
1868 | +#ifndef LOCATION_SERVICE_WITH_ENGINE_H_ |
1869 | +#define LOCATION_SERVICE_WITH_ENGINE_H_ |
1870 | + |
1871 | +#include <location/engine.h> |
1872 | +#include <location/service.h> |
1873 | + |
1874 | +namespace location |
1875 | +{ |
1876 | +class ServiceWithEngine : public Service |
1877 | +{ |
1878 | +public: |
1879 | + ServiceWithEngine(const Engine::Ptr& engine); |
1880 | + |
1881 | + // From Service |
1882 | + const core::Property<State>& state() const override; |
1883 | + core::Property<bool>& does_satellite_based_positioning() override; |
1884 | + core::Property<bool>& is_online() override; |
1885 | + core::Property<bool>& does_report_cell_and_wifi_ids() override; |
1886 | + core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>>& visible_space_vehicles() override; |
1887 | + Session::Ptr create_session_for_criteria(const Criteria& criteria) override; |
1888 | + |
1889 | +private: |
1890 | + Engine::Ptr engine; // The engine instance we use for positioning. |
1891 | + |
1892 | + // Properties of the service implementation. |
1893 | + core::Property<State> state_; |
1894 | + core::Property<bool> does_satellite_based_positioning_; |
1895 | + core::Property<bool> is_online_; |
1896 | + core::Property<bool> does_report_cell_and_wifi_ids_; |
1897 | + core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>> visible_space_vehicles_; |
1898 | + |
1899 | + struct |
1900 | + { |
1901 | + core::ScopedConnection is_online; |
1902 | + core::ScopedConnection does_report_cell_and_wifi_ids; |
1903 | + core::ScopedConnection does_satellite_based_positioning; |
1904 | + core::ScopedConnection engine_state; |
1905 | + core::ScopedConnection satellite_based_positioning_state; |
1906 | + core::ScopedConnection visible_space_vehicles; |
1907 | + } connections; // All event connections are automatically cut on destruction. |
1908 | +}; |
1909 | +} |
1910 | + |
1911 | +#endif // LOCATION_SERVICE_WITH_ENGINE_H_ |
1912 | |
1913 | === added file 'src/location/session_with_provider.cpp' |
1914 | --- src/location/session_with_provider.cpp 1970-01-01 00:00:00 +0000 |
1915 | +++ src/location/session_with_provider.cpp 2016-06-30 09:21:49 +0000 |
1916 | @@ -0,0 +1,111 @@ |
1917 | +/* |
1918 | + * Copyright © 2016 Canonical Ltd. |
1919 | + * |
1920 | + * This program is free software: you can redistribute it and/or modify it |
1921 | + * under the terms of the GNU Lesser General Public License version 3, |
1922 | + * as published by the Free Software Foundation. |
1923 | + * |
1924 | + * This program is distributed in the hope that it will be useful, |
1925 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1926 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1927 | + * GNU Lesser General Public License for more details. |
1928 | + * |
1929 | + * You should have received a copy of the GNU Lesser General Public License |
1930 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1931 | + * |
1932 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1933 | + */ |
1934 | + |
1935 | +#include <location/session_with_provider.h> |
1936 | + |
1937 | +location::SessionWithProvider::SessionWithProvider(const Provider::Ptr& provider) |
1938 | + : provider_{provider}, |
1939 | + connections_ |
1940 | + { |
1941 | + provider_->updates().position.connect( |
1942 | + [this](const Update<Position>& update) |
1943 | + { |
1944 | + updates().position = update; |
1945 | + }), |
1946 | + provider_->updates().heading.connect( |
1947 | + [this](const Update<Heading>& update) |
1948 | + { |
1949 | + updates().heading = update; |
1950 | + }), |
1951 | + provider_->updates().velocity.connect( |
1952 | + [this](const Update<Velocity>& update) |
1953 | + { |
1954 | + updates().velocity = update; |
1955 | + }), |
1956 | + updates().position_status.changed().connect( |
1957 | + [this](const Updates::Status& status) |
1958 | + { |
1959 | + switch(status) |
1960 | + { |
1961 | + case Updates::Status::enabled: |
1962 | + start_position_updates(); break; |
1963 | + case Updates::Status::disabled: |
1964 | + stop_position_updates(); break; |
1965 | + } |
1966 | + }), |
1967 | + updates().velocity_status.changed().connect( |
1968 | + [this](const Updates::Status& status) |
1969 | + { |
1970 | + switch(status) |
1971 | + { |
1972 | + case Updates::Status::enabled: |
1973 | + start_velocity_updates(); break; |
1974 | + case Updates::Status::disabled: |
1975 | + stop_velocity_updates(); break; |
1976 | + } |
1977 | + }), |
1978 | + updates().heading_status.changed().connect( |
1979 | + [this](const Updates::Status& status) |
1980 | + { |
1981 | + switch(status) |
1982 | + { |
1983 | + case Updates::Status::enabled: |
1984 | + start_heading_updates(); break; |
1985 | + case Updates::Status::disabled: |
1986 | + stop_heading_updates(); break; |
1987 | + } |
1988 | + }) |
1989 | + } |
1990 | +{ |
1991 | +} |
1992 | + |
1993 | +location::Service::Session::Updates& location::SessionWithProvider::updates() |
1994 | +{ |
1995 | + return updates_; |
1996 | +} |
1997 | + |
1998 | +void location::SessionWithProvider::start_position_updates() |
1999 | +{ |
2000 | + provider_->state_controller()->start_position_updates(); |
2001 | +} |
2002 | + |
2003 | +void location::SessionWithProvider::stop_position_updates() |
2004 | +{ |
2005 | + provider_->state_controller()->stop_position_updates(); |
2006 | +} |
2007 | + |
2008 | +void location::SessionWithProvider::start_velocity_updates() |
2009 | +{ |
2010 | + provider_->state_controller()->start_velocity_updates(); |
2011 | +} |
2012 | + |
2013 | +void location::SessionWithProvider::stop_velocity_updates() |
2014 | +{ |
2015 | + provider_->state_controller()->stop_velocity_updates(); |
2016 | +} |
2017 | + |
2018 | +void location::SessionWithProvider::start_heading_updates() |
2019 | +{ |
2020 | + provider_->state_controller()->start_heading_updates(); |
2021 | +} |
2022 | + |
2023 | +void location::SessionWithProvider::stop_heading_updates() |
2024 | +{ |
2025 | + provider_->state_controller()->stop_heading_updates(); |
2026 | +} |
2027 | + |
2028 | |
2029 | === added file 'src/location/session_with_provider.h' |
2030 | --- src/location/session_with_provider.h 1970-01-01 00:00:00 +0000 |
2031 | +++ src/location/session_with_provider.h 2016-06-30 09:21:49 +0000 |
2032 | @@ -0,0 +1,60 @@ |
2033 | +/* |
2034 | + * Copyright © 2016 Canonical Ltd. |
2035 | + * |
2036 | + * This program is free software: you can redistribute it and/or modify it |
2037 | + * under the terms of the GNU Lesser General Public License version 3, |
2038 | + * as published by the Free Software Foundation. |
2039 | + * |
2040 | + * This program is distributed in the hope that it will be useful, |
2041 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2042 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2043 | + * GNU Lesser General Public License for more details. |
2044 | + * |
2045 | + * You should have received a copy of the GNU Lesser General Public License |
2046 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2047 | + * |
2048 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
2049 | + */ |
2050 | +#ifndef LOCATION_SESSION_WITH_PROVIDER_H_ |
2051 | +#define LOCATION_SESSION_WITH_PROVIDER_H_ |
2052 | + |
2053 | +#include <location/provider.h> |
2054 | +#include <location/service.h> |
2055 | + |
2056 | +namespace location |
2057 | +{ |
2058 | +class SessionWithProvider : public Service::Session |
2059 | +{ |
2060 | +public: |
2061 | + SessionWithProvider(const Provider::Ptr& provider); |
2062 | + |
2063 | + // From Session::Service. |
2064 | + Updates& updates() override; |
2065 | + |
2066 | +private: |
2067 | + void start_position_updates(); |
2068 | + void stop_position_updates(); |
2069 | + |
2070 | + void start_velocity_updates(); |
2071 | + void stop_velocity_updates(); |
2072 | + |
2073 | + void start_heading_updates(); |
2074 | + void stop_heading_updates(); |
2075 | + |
2076 | + Updates updates_; |
2077 | + Provider::Ptr provider_; |
2078 | + |
2079 | + struct |
2080 | + { |
2081 | + core::ScopedConnection position_updates; |
2082 | + core::ScopedConnection velocity_updates; |
2083 | + core::ScopedConnection heading_updates; |
2084 | + |
2085 | + core::ScopedConnection position_status_updates; |
2086 | + core::ScopedConnection heading_status_updates; |
2087 | + core::ScopedConnection velocity_status_updates; |
2088 | + } connections_; |
2089 | +}; |
2090 | +} |
2091 | + |
2092 | +#endif // LOCATION_SESSION_WITH_PROVIDER_H_ |
2093 | |
2094 | === added file 'src/location/trust_store_permission_manager.cpp' |
2095 | --- src/location/trust_store_permission_manager.cpp 1970-01-01 00:00:00 +0000 |
2096 | +++ src/location/trust_store_permission_manager.cpp 2016-06-30 09:21:49 +0000 |
2097 | @@ -0,0 +1,179 @@ |
2098 | +/* |
2099 | + * Copyright © 2012-2013 Canonical Ltd. |
2100 | + * |
2101 | + * This program is free software: you can redistribute it and/or modify it |
2102 | + * under the terms of the GNU Lesser General Public License version 3, |
2103 | + * as published by the Free Software Foundation. |
2104 | + * |
2105 | + * This program is distributed in the hope that it will be useful, |
2106 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2107 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2108 | + * GNU Lesser General Public License for more details. |
2109 | + * |
2110 | + * You should have received a copy of the GNU Lesser General Public License |
2111 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2112 | + * |
2113 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
2114 | + */ |
2115 | + |
2116 | +#include <location/trust_store_permission_manager.h> |
2117 | +#include <location/logging.h> |
2118 | + |
2119 | +#include <core/trust/dbus_agent.h> |
2120 | + |
2121 | +#include <core/dbus/bus.h> |
2122 | +#include <core/dbus/asio/executor.h> |
2123 | + |
2124 | +#include <core/posix/this_process.h> |
2125 | + |
2126 | +#include <boost/format.hpp> |
2127 | + |
2128 | +#include <sys/apparmor.h> |
2129 | + |
2130 | +namespace |
2131 | +{ |
2132 | +bool is_running_under_testing() |
2133 | +{ |
2134 | + return core::posix::this_process::env::get( |
2135 | + "TRUST_STORE_PERMISSION_MANAGER_IS_RUNNING_UNDER_TESTING", |
2136 | + "0") == "1"; |
2137 | + |
2138 | +} |
2139 | + |
2140 | +namespace i18n |
2141 | +{ |
2142 | +// We only tag strings that should be translated but do not do the actual translation. |
2143 | +// Point is: The service might run in a system context, without correct locale information. |
2144 | +// We leave the translation to in-session trust-store instances. |
2145 | +std::string tr(const std::string& msg) |
2146 | +{ |
2147 | + return msg; |
2148 | +} |
2149 | +} |
2150 | + |
2151 | +// At least make the name a constant, no need to expose it, though. |
2152 | +static constexpr const char* trust_store_service_name{"UbuntuLocationService"}; |
2153 | +} |
2154 | + |
2155 | +location::TrustStorePermissionManager::AppArmorProfileResolver location::TrustStorePermissionManager::libapparmor_profile_resolver() |
2156 | +{ |
2157 | + return [](core::trust::Pid pid) |
2158 | + { |
2159 | + static const int app_armor_error{-1}; |
2160 | + |
2161 | + // We make sure to clean up the returned string. |
2162 | + struct Scope |
2163 | + { |
2164 | + ~Scope() |
2165 | + { |
2166 | + if (con) ::free(con); |
2167 | + } |
2168 | + |
2169 | + char* con{nullptr}; |
2170 | + char* mode{nullptr}; |
2171 | + } scope; |
2172 | + |
2173 | + // Reach out to apparmor |
2174 | + auto rc = aa_gettaskcon(pid.value, &scope.con, &scope.mode); |
2175 | + |
2176 | + // From man aa_gettaskcon: |
2177 | + // On success size of data placed in the buffer is returned, this includes the mode if |
2178 | + //present and any terminating characters. On error, -1 is returned, and errno(3) is |
2179 | + //set appropriately. |
2180 | + if (rc == app_armor_error) throw std::system_error |
2181 | + { |
2182 | + errno, |
2183 | + std::system_category() |
2184 | + }; |
2185 | + |
2186 | + // Safely construct the string |
2187 | + return std::string |
2188 | + { |
2189 | + scope.con ? scope.con : "" |
2190 | + }; |
2191 | + }; |
2192 | +} |
2193 | + |
2194 | +core::trust::Feature location::TrustStorePermissionManager::default_feature() |
2195 | +{ |
2196 | + return core::trust::Feature{0}; |
2197 | +} |
2198 | + |
2199 | +location::TrustStorePermissionManager::Ptr location::TrustStorePermissionManager::create_default_instance_with_bus(const std::shared_ptr<core::dbus::Bus>& bus) |
2200 | +{ |
2201 | + return Ptr |
2202 | + { |
2203 | + new TrustStorePermissionManager |
2204 | + { |
2205 | + core::trust::dbus::create_multi_user_agent_for_bus_connection( |
2206 | + bus, |
2207 | + trust_store_service_name), |
2208 | + TrustStorePermissionManager::libapparmor_profile_resolver() |
2209 | + } |
2210 | + }; |
2211 | +} |
2212 | + |
2213 | +location::TrustStorePermissionManager::TrustStorePermissionManager( |
2214 | + const std::shared_ptr<core::trust::Agent>& agent, |
2215 | + location::TrustStorePermissionManager::AppArmorProfileResolver app_armor_profile_resolver) |
2216 | + : agent{agent}, |
2217 | + app_armor_profile_resolver{app_armor_profile_resolver} |
2218 | +{ |
2219 | +} |
2220 | + |
2221 | +location::PermissionManager::Result location::TrustStorePermissionManager::check_permission_for_credentials( |
2222 | + const location::Criteria&, |
2223 | + const location::Credentials& credentials) |
2224 | +{ |
2225 | + // This is ugly and we should get rid of it. Ideally, we would be able |
2226 | + // inject a mocked trust-store into our acceptance testing. |
2227 | + if (is_running_under_testing()) |
2228 | + return Result::granted; |
2229 | + |
2230 | + std::string profile; |
2231 | + try |
2232 | + { |
2233 | + profile = app_armor_profile_resolver(core::trust::Pid{credentials.pid}); |
2234 | + } catch(const std::exception& e) |
2235 | + { |
2236 | + SYSLOG(ERROR) << "Could not resolve PID " << credentials.pid << " to apparmor profile: " << e.what(); |
2237 | + return location::PermissionManager::Result::rejected; |
2238 | + } catch(...) |
2239 | + { |
2240 | + SYSLOG(ERROR) << "Could not resolve PID " << credentials.pid << " to apparmor profile."; |
2241 | + return location::PermissionManager::Result::rejected; |
2242 | + } |
2243 | + |
2244 | + std::string description = i18n::tr("wants to access your current location."); |
2245 | + |
2246 | + core::trust::Agent::RequestParameters params |
2247 | + { |
2248 | + core::trust::Uid{credentials.uid}, |
2249 | + core::trust::Pid{credentials.pid}, |
2250 | + profile, |
2251 | + TrustStorePermissionManager::default_feature(), |
2252 | + description |
2253 | + }; |
2254 | + |
2255 | + Result result{Result::rejected}; |
2256 | + |
2257 | + try |
2258 | + { |
2259 | + auto answer = agent->authenticate_request_with_parameters(params); |
2260 | + switch(answer) |
2261 | + { |
2262 | + case core::trust::Request::Answer::granted: |
2263 | + result = Result::granted; |
2264 | + break; |
2265 | + case core::trust::Request::Answer::denied: |
2266 | + result = Result::rejected; |
2267 | + break; |
2268 | + } |
2269 | + } catch(...) |
2270 | + { |
2271 | + // We silently drop all issues here and return rejected. |
2272 | + result = Result::rejected; |
2273 | + } |
2274 | + |
2275 | + return result; |
2276 | +} |
2277 | |
2278 | === added file 'src/location/trust_store_permission_manager.h' |
2279 | --- src/location/trust_store_permission_manager.h 1970-01-01 00:00:00 +0000 |
2280 | +++ src/location/trust_store_permission_manager.h 2016-06-30 09:21:49 +0000 |
2281 | @@ -0,0 +1,76 @@ |
2282 | +/* |
2283 | + * Copyright © 2012-2013 Canonical Ltd. |
2284 | + * |
2285 | + * This program is free software: you can redistribute it and/or modify it |
2286 | + * under the terms of the GNU Lesser General Public License version 3, |
2287 | + * as published by the Free Software Foundation. |
2288 | + * |
2289 | + * This program is distributed in the hope that it will be useful, |
2290 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2291 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2292 | + * GNU Lesser General Public License for more details. |
2293 | + * |
2294 | + * You should have received a copy of the GNU Lesser General Public License |
2295 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2296 | + * |
2297 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
2298 | + */ |
2299 | +#ifndef LOCATION_SERVICE_TRUST_STORE_PERMISSION_MANAGER_H_ |
2300 | +#define LOCATION_SERVICE_TRUST_STORE_PERMISSION_MANAGER_H_ |
2301 | + |
2302 | +#include <location/permission_manager.h> |
2303 | + |
2304 | +#include <core/trust/agent.h> |
2305 | + |
2306 | +namespace core |
2307 | +{ |
2308 | +namespace dbus |
2309 | +{ |
2310 | +class Bus; |
2311 | +} |
2312 | +} |
2313 | + |
2314 | +namespace location |
2315 | +{ |
2316 | +// A PermmissionManager implementation leveraging the trust-store |
2317 | +// infrastructure to cache a user's answer and to dispatch |
2318 | +// to user-specific trust-store instances. |
2319 | +class TrustStorePermissionManager : public PermissionManager |
2320 | +{ |
2321 | +public: |
2322 | + // Just a convenience typedef. |
2323 | + typedef std::shared_ptr<TrustStorePermissionManager> Ptr; |
2324 | + |
2325 | + // Functor for resolving a process id to an app-armor profile name. |
2326 | + typedef std::function<std::string(const core::trust::Pid&)> AppArmorProfileResolver; |
2327 | + |
2328 | + // Returns an AppArmorProfileResolver leveraging libapparmor. |
2329 | + static AppArmorProfileResolver libapparmor_profile_resolver(); |
2330 | + |
2331 | + // The default feature tag we use when calling out to the agent. |
2332 | + static core::trust::Feature default_feature(); |
2333 | + |
2334 | + // Creates a default instance, initializing the agent and resolver |
2335 | + // fields to sensible default choices. |
2336 | + static Ptr create_default_instance_with_bus(const std::shared_ptr<core::dbus::Bus>& bus); |
2337 | + |
2338 | + // Sets up the manager for operation and stores the agent and resolver |
2339 | + // instances given to the ctor. |
2340 | + TrustStorePermissionManager( |
2341 | + const std::shared_ptr<core::trust::Agent>& agent, |
2342 | + AppArmorProfileResolver app_armor_profile_resolver); |
2343 | + |
2344 | + // From PermissionManager |
2345 | + Result check_permission_for_credentials(const Criteria&, const Credentials& credentials) override; |
2346 | + |
2347 | +private: |
2348 | + // The agent instance we leverage to authenticate |
2349 | + // permission requests. |
2350 | + std::shared_ptr<core::trust::Agent> agent; |
2351 | + |
2352 | + // Helper to resolve an application's pid to an app-armor profile name. |
2353 | + AppArmorProfileResolver app_armor_profile_resolver; |
2354 | +}; |
2355 | +} |
2356 | + |
2357 | +#endif // LOCATION_SERVICE_TRUST_STORE_PERMISSION_MANAGER_H_ |
2358 | |
2359 | === added directory 'src/location/util' |
2360 | === added file 'src/location/util/cli.cpp' |
2361 | --- src/location/util/cli.cpp 1970-01-01 00:00:00 +0000 |
2362 | +++ src/location/util/cli.cpp 2016-06-30 09:21:49 +0000 |
2363 | @@ -0,0 +1,301 @@ |
2364 | +/* |
2365 | + * Copyright (C) 2016 Canonical, Ltd. |
2366 | + * |
2367 | + * This program is free software; you can redistribute it and/or modify |
2368 | + * it under the terms of the GNU Lesser General Public License as published by |
2369 | + * the Free Software Foundation; version 3. |
2370 | + * |
2371 | + * This program is distributed in the hope that it will be useful, |
2372 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2373 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2374 | + * GNU Lesser General Public License for more details. |
2375 | + * |
2376 | + * You should have received a copy of the GNU Lesser General Public License |
2377 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2378 | + * |
2379 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
2380 | + * |
2381 | + */ |
2382 | + |
2383 | +#include <location/util/cli.h> |
2384 | + |
2385 | +#include <boost/format.hpp> |
2386 | +#include <boost/program_options.hpp> |
2387 | + |
2388 | +#include <iomanip> |
2389 | + |
2390 | +namespace cli = location::util::cli; |
2391 | +namespace po = boost::program_options; |
2392 | + |
2393 | +namespace |
2394 | +{ |
2395 | +namespace pattern |
2396 | +{ |
2397 | +static constexpr const char* help_for_command_with_subcommands = |
2398 | +"NAME:\n" |
2399 | +" %1% - %2%\n" |
2400 | +"\n" |
2401 | +"USAGE:\n" |
2402 | +" %3% [command options] [arguments...]"; |
2403 | + |
2404 | +static constexpr const char* commands = "COMMANDS:"; |
2405 | +static constexpr const char* command = " %1% %2%"; |
2406 | + |
2407 | +static constexpr const char* options = "OPTIONS:"; |
2408 | +static constexpr const char* option = " --%1% %2%"; |
2409 | +} |
2410 | + |
2411 | +void add_to_desc_for_flags(po::options_description& desc, const std::set<cli::Flag::Ptr>& flags) |
2412 | +{ |
2413 | + for (auto flag : flags) |
2414 | + { |
2415 | + auto v = po::value<std::string>()->notifier([flag](const std::string& s) |
2416 | + { |
2417 | + flag->notify(s); |
2418 | + }); |
2419 | + desc.add_options()(flag->name().as_string().c_str(), v, flag->description().as_string().c_str()); |
2420 | + } |
2421 | +} |
2422 | +} |
2423 | + |
2424 | +location::util::cli::ProgressBar::ProgressBar(std::ostream& out, const std::string& prefix, std::uint32_t width) |
2425 | + : prefix{prefix}, width{width}, out{out} |
2426 | +{ |
2427 | +} |
2428 | + |
2429 | +location::util::cli::ProgressBar::~ProgressBar() |
2430 | +{ |
2431 | + out << std::endl; |
2432 | +} |
2433 | + |
2434 | +void location::util::cli::ProgressBar::update(double percentage) |
2435 | +{ |
2436 | + struct CursorState |
2437 | + { |
2438 | + CursorState(std::ostream& out) : out{out} { out << "\33[?25l"; } |
2439 | + ~CursorState() { out << "\33[?25h"; } |
2440 | + std::ostream& out; |
2441 | + } cs{out}; |
2442 | + |
2443 | + out << "\r" << prefix << "[" << std::setw(width) << std::left << std::setfill(' ') << std::string(percentage * width, '=') << "] " << std::setw(5) << std::fixed << std::setprecision(2) << percentage * 100 << " %" << std::flush; |
2444 | +} |
2445 | + |
2446 | +std::vector<std::string> cli::args(int argc, char **argv) |
2447 | +{ |
2448 | + std::vector<std::string> result; |
2449 | + for (int i = 1; i < argc; i++) result.push_back(argv[i]); |
2450 | + return result; |
2451 | +} |
2452 | + |
2453 | +const cli::Name& cli::Flag::name() const |
2454 | +{ |
2455 | + return name_; |
2456 | +} |
2457 | + |
2458 | +const cli::Description& cli::Flag::description() const |
2459 | +{ |
2460 | + return description_; |
2461 | +} |
2462 | + |
2463 | +cli::Flag::Flag(const Name& name, const Description& description) |
2464 | + : name_{name}, |
2465 | + description_{description} |
2466 | +{ |
2467 | +} |
2468 | + |
2469 | +cli::Command::FlagsWithInvalidValue::FlagsWithInvalidValue() : std::runtime_error{"Flags with invalid value"} |
2470 | +{ |
2471 | +} |
2472 | + |
2473 | +cli::Command::FlagsMissing::FlagsMissing() : std::runtime_error{"Flags are missing in command invocation"} |
2474 | +{ |
2475 | +} |
2476 | + |
2477 | +cli::Name cli::Command::name() const |
2478 | +{ |
2479 | + return name_; |
2480 | +} |
2481 | + |
2482 | +cli::Usage cli::Command::usage() const |
2483 | +{ |
2484 | + return usage_; |
2485 | +} |
2486 | + |
2487 | +cli::Description cli::Command::description() const |
2488 | +{ |
2489 | + return description_; |
2490 | +} |
2491 | + |
2492 | +cli::Command::Command(const cli::Name& name, const cli::Usage& usage, const cli::Description& description) |
2493 | + : name_(name), |
2494 | + usage_(usage), |
2495 | + description_(description) |
2496 | +{ |
2497 | +} |
2498 | + |
2499 | +cli::CommandWithSubcommands::CommandWithSubcommands(const Name& name, const Usage& usage, const Description& description) |
2500 | + : Command{name, usage, description} |
2501 | +{ |
2502 | + command(std::make_shared<cmd::Help>(*this)); |
2503 | +} |
2504 | + |
2505 | +cli::CommandWithSubcommands& cli::CommandWithSubcommands::command(const Command::Ptr& command) |
2506 | +{ |
2507 | + commands_[command->name().as_string()] = command; |
2508 | + return *this; |
2509 | +} |
2510 | + |
2511 | +cli::CommandWithSubcommands& cli::CommandWithSubcommands::flag(const Flag::Ptr& flag) |
2512 | +{ |
2513 | + flags_.insert(flag); |
2514 | + return *this; |
2515 | +} |
2516 | + |
2517 | +void cli::CommandWithSubcommands::help(std::ostream& out) |
2518 | +{ |
2519 | + out << boost::format(pattern::help_for_command_with_subcommands) |
2520 | + % name().as_string() % usage().as_string() |
2521 | + % name().as_string() << std::endl; |
2522 | + |
2523 | + if (flags_.size() > 0) |
2524 | + { |
2525 | + out << std::endl << pattern::options << std::endl; |
2526 | + for (const auto& flag : flags_) |
2527 | + out << boost::format(pattern::option) % flag->name() % flag->description() << std::endl; |
2528 | + } |
2529 | + |
2530 | + if (commands_.size() > 0) |
2531 | + { |
2532 | + out << std::endl << pattern::commands << std::endl; |
2533 | + for (const auto& cmd : commands_) |
2534 | + out << boost::format(pattern::command) % cmd.second->name() % cmd.second->description() << std::endl; |
2535 | + } |
2536 | +} |
2537 | + |
2538 | +int cli::CommandWithSubcommands::run(const cli::Command::Context& ctxt) |
2539 | +{ |
2540 | + po::positional_options_description pdesc; |
2541 | + pdesc.add("command", 1); |
2542 | + |
2543 | + po::options_description desc("Options"); |
2544 | + desc.add_options()("command", po::value<std::string>()->required(), "the command to be executed"); |
2545 | + |
2546 | + add_to_desc_for_flags(desc, flags_); |
2547 | + |
2548 | + try |
2549 | + { |
2550 | + po::variables_map vm; |
2551 | + auto parsed = po::command_line_parser(ctxt.args) |
2552 | + .options(desc) |
2553 | + .positional(pdesc) |
2554 | + .style(po::command_line_style::unix_style) |
2555 | + .allow_unregistered() |
2556 | + .run(); |
2557 | + |
2558 | + po::store(parsed, vm); |
2559 | + po::notify(vm); |
2560 | + |
2561 | + return commands_[vm["command"].as<std::string>()]->run(cli::Command::Context |
2562 | + { |
2563 | + ctxt.cin, |
2564 | + ctxt.cout, |
2565 | + po::collect_unrecognized(parsed.options, po::include_positional) |
2566 | + }); |
2567 | + } |
2568 | + catch (const po::error& e) |
2569 | + { |
2570 | + ctxt.cout << e.what() << std::endl; |
2571 | + help(ctxt.cout); |
2572 | + return EXIT_FAILURE; |
2573 | + } |
2574 | + |
2575 | + return EXIT_FAILURE; |
2576 | +} |
2577 | + |
2578 | +cli::CommandWithFlagsAndAction::CommandWithFlagsAndAction(const Name& name, const Usage& usage, const Description& description) |
2579 | + : Command{name, usage, description} |
2580 | +{ |
2581 | +} |
2582 | + |
2583 | +cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::flag(const Flag::Ptr& flag) |
2584 | +{ |
2585 | + flags_.insert(flag); |
2586 | + return *this; |
2587 | +} |
2588 | + |
2589 | +cli::CommandWithFlagsAndAction& cli::CommandWithFlagsAndAction::action(const Action& action) |
2590 | +{ |
2591 | + action_ = action; |
2592 | + return *this; |
2593 | +} |
2594 | + |
2595 | +int cli::CommandWithFlagsAndAction::run(const Context& ctxt) |
2596 | +{ |
2597 | + po::options_description cd(name().as_string()); |
2598 | + |
2599 | + bool help_requested{false}; |
2600 | + cd.add_options()("help", po::bool_switch(&help_requested), "produces a help message"); |
2601 | + |
2602 | + add_to_desc_for_flags(cd, flags_); |
2603 | + |
2604 | + try |
2605 | + { |
2606 | + po::variables_map vm; |
2607 | + auto parsed = po::command_line_parser(ctxt.args).options(cd).style(po::command_line_style::unix_style).allow_unregistered().run(); |
2608 | + po::store(parsed, vm); |
2609 | + po::notify(vm); |
2610 | + |
2611 | + if (help_requested) |
2612 | + { |
2613 | + help(ctxt.cout); |
2614 | + return EXIT_SUCCESS; |
2615 | + } |
2616 | + |
2617 | + return action_(cli::Command::Context |
2618 | + { |
2619 | + ctxt.cin, |
2620 | + ctxt.cout, |
2621 | + po::collect_unrecognized(parsed.options, po::exclude_positional) |
2622 | + }); |
2623 | + } |
2624 | + catch (const po::error& e) |
2625 | + { |
2626 | + ctxt.cout << e.what() << std::endl; |
2627 | + help(ctxt.cout); |
2628 | + return EXIT_FAILURE; |
2629 | + } |
2630 | + |
2631 | + return EXIT_FAILURE; |
2632 | +} |
2633 | + |
2634 | +void cli::CommandWithFlagsAndAction::help(std::ostream& out) |
2635 | +{ |
2636 | + out << boost::format(pattern::help_for_command_with_subcommands) |
2637 | + % name().as_string() % description().as_string() |
2638 | + % name().as_string() << std::endl; |
2639 | + |
2640 | + if (flags_.size() > 0) |
2641 | + { |
2642 | + out << std::endl << boost::format(pattern::options) << std::endl; |
2643 | + for (const auto& flag : flags_) |
2644 | + out << boost::format(pattern::option) % flag->name() % flag->description() << std::endl; |
2645 | + } |
2646 | +} |
2647 | + |
2648 | +cli::cmd::Help::Help(Command& cmd) |
2649 | + : Command{cli::Name{"help"}, cli::Usage{"prints a short help message"}, cli::Description{"prints a short help message"}}, |
2650 | + command{cmd} |
2651 | +{ |
2652 | +} |
2653 | + |
2654 | +// From Command |
2655 | +int cli::cmd::Help::run(const Context &context) |
2656 | +{ |
2657 | + command.help(context.cout); |
2658 | + return EXIT_FAILURE; |
2659 | +} |
2660 | + |
2661 | +void cli::cmd::Help::help(std::ostream &out) |
2662 | +{ |
2663 | + command.help(out); |
2664 | +} |
2665 | |
2666 | === added file 'src/location/util/cli.h' |
2667 | --- src/location/util/cli.h 1970-01-01 00:00:00 +0000 |
2668 | +++ src/location/util/cli.h 2016-06-30 09:21:49 +0000 |
2669 | @@ -0,0 +1,387 @@ |
2670 | +/* |
2671 | + * Copyright (C) 2016 Canonical, Ltd. |
2672 | + * |
2673 | + * This program is free software; you can redistribute it and/or modify |
2674 | + * it under the terms of the GNU Lesser General Public License as published by |
2675 | + * the Free Software Foundation; version 3. |
2676 | + * |
2677 | + * This program is distributed in the hope that it will be useful, |
2678 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2679 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2680 | + * GNU Lesser General Public License for more details. |
2681 | + * |
2682 | + * You should have received a copy of the GNU Lesser General Public License |
2683 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2684 | + * |
2685 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
2686 | + * |
2687 | + */ |
2688 | +#ifndef LOCATION_UTIL_CLI_H_ |
2689 | +#define LOCATION_UTIL_CLI_H_ |
2690 | + |
2691 | +#include <location/util/do_not_copy_or_move.h> |
2692 | +#include <location/optional.h> |
2693 | + |
2694 | +// TODO(tvoss): Reenable once we introduce visibility of symbols |
2695 | +// #include <biometry/visibility.h> |
2696 | +#define LOCATION_DLL_PUBLIC |
2697 | + |
2698 | +#include <iomanip> |
2699 | +#include <iostream> |
2700 | +#include <memory> |
2701 | +#include <set> |
2702 | +#include <sstream> |
2703 | +#include <stdexcept> |
2704 | +#include <string> |
2705 | +#include <unordered_map> |
2706 | +#include <vector> |
2707 | + |
2708 | +namespace location |
2709 | +{ |
2710 | +namespace util |
2711 | +{ |
2712 | +namespace cli |
2713 | +{ |
2714 | +/// @brief ProgressBar prints a progress bar on the terminal. |
2715 | +/// |
2716 | +/// Looks like: |
2717 | +/// Prefix[===============----------] xxx.xx % |
2718 | +/// |--------------- width ------------| |
2719 | +class LOCATION_DLL_PUBLIC ProgressBar |
2720 | +{ |
2721 | +public: |
2722 | + /// @brief ProgressBar initializes an instance with out, prefix and width. |
2723 | + ProgressBar(std::ostream& out, const std::string& prefix = std::string{}, std::uint32_t width = 80); |
2724 | + /// @brief ~ProgressBar cleans up and inserts a std::endl into out. |
2725 | + ~ProgressBar(); |
2726 | + |
2727 | + /// @brief update updates the terminal output for the given percentage. |
2728 | + void update(double percentage); |
2729 | + |
2730 | +private: |
2731 | + /// @cond |
2732 | + std::string prefix; |
2733 | + std::uint32_t width; |
2734 | + std::ostream& out; |
2735 | + /// @endcond |
2736 | +}; |
2737 | + |
2738 | +template<std::size_t max> |
2739 | +class LOCATION_DLL_PUBLIC SizeConstrainedString |
2740 | +{ |
2741 | +public: |
2742 | + SizeConstrainedString(const std::string& s) : s{s} |
2743 | + { |
2744 | + if(s.size() > max) |
2745 | + throw std::logic_error{"Max size exceeded " + std::to_string(max)}; |
2746 | + } |
2747 | + |
2748 | + const std::string& as_string() const |
2749 | + { |
2750 | + return s; |
2751 | + } |
2752 | + |
2753 | + operator std::string() const |
2754 | + { |
2755 | + return s; |
2756 | + } |
2757 | + |
2758 | +private: |
2759 | + std::string s; |
2760 | +}; |
2761 | + |
2762 | +template<std::size_t max> |
2763 | +LOCATION_DLL_PUBLIC bool operator<(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs) |
2764 | +{ |
2765 | + return lhs.as_string() < rhs.as_string(); |
2766 | +} |
2767 | + |
2768 | +template<std::size_t max> |
2769 | +LOCATION_DLL_PUBLIC bool operator==(const SizeConstrainedString<max>& lhs, const SizeConstrainedString<max>& rhs) |
2770 | +{ |
2771 | + return lhs.as_string() == rhs.as_string(); |
2772 | +} |
2773 | + |
2774 | +template<std::size_t max> |
2775 | +LOCATION_DLL_PUBLIC std::ostream& operator<<(std::ostream& out, const SizeConstrainedString<max>& scs) |
2776 | +{ |
2777 | + return out << std::setw(max) << std::left << scs.as_string(); |
2778 | +} |
2779 | + |
2780 | +// We are imposing size constraints to ensure a consistent CLI layout. |
2781 | +typedef SizeConstrainedString<15> Name; |
2782 | +typedef SizeConstrainedString<60> Usage; |
2783 | +typedef SizeConstrainedString<60> Description; |
2784 | + |
2785 | +/// @brief Flag models an input parameter to a command. |
2786 | +class LOCATION_DLL_PUBLIC Flag : public DoNotCopyOrMove |
2787 | +{ |
2788 | +public: |
2789 | + // Safe us some typing. |
2790 | + typedef std::shared_ptr<Flag> Ptr; |
2791 | + |
2792 | + /// @brief notify announces a new value to the flag. |
2793 | + virtual void notify(const std::string& value) = 0; |
2794 | + /// @brief name returns the name of the Flag. |
2795 | + const Name& name() const; |
2796 | + /// @brief description returns a human-readable description of the flag. |
2797 | + const Description& description() const; |
2798 | + |
2799 | +protected: |
2800 | + /// @brief Flag creates a new instance, initializing name and description |
2801 | + /// from the given values. |
2802 | + Flag(const Name& name, const Description& description); |
2803 | + |
2804 | +private: |
2805 | + Name name_; |
2806 | + Description description_; |
2807 | +}; |
2808 | + |
2809 | +/// @brief TypedFlag implements Flag relying on operator<< and operator>> to read/write values to/from strings. |
2810 | +template<typename T> |
2811 | +class LOCATION_DLL_PUBLIC TypedFlag : public Flag |
2812 | +{ |
2813 | +public: |
2814 | + typedef std::shared_ptr<TypedFlag<T>> Ptr; |
2815 | + |
2816 | + TypedFlag(const Name& name, const Description& description) : Flag{name, description} |
2817 | + { |
2818 | + } |
2819 | + |
2820 | + /// @brief value installs the given value in the flag. |
2821 | + TypedFlag& value(const T& value) |
2822 | + { |
2823 | + value_ = value; |
2824 | + return *this; |
2825 | + } |
2826 | + |
2827 | + /// @brief value returns the optional value associated with the flag. |
2828 | + const Optional<T>& value() const |
2829 | + { |
2830 | + return value_; |
2831 | + } |
2832 | + |
2833 | + /// @brief notify tries to unwrap a value of type T from value. |
2834 | + void notify(const std::string& s) override |
2835 | + { |
2836 | + std::stringstream ss{s}; |
2837 | + T value; ss >> value; |
2838 | + value_ = value; |
2839 | + } |
2840 | + |
2841 | +private: |
2842 | + Optional<T> value_; |
2843 | +}; |
2844 | + |
2845 | +/// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to convert to/from string representations, |
2846 | +/// updating the given mutable reference to a value of type T. |
2847 | +template<typename T> |
2848 | +class LOCATION_DLL_PUBLIC TypedReferenceFlag : public Flag |
2849 | +{ |
2850 | +public: |
2851 | + // Safe us some typing. |
2852 | + typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr; |
2853 | + |
2854 | + /// @brief TypedReferenceFlag initializes a new instance with name, description and value. |
2855 | + TypedReferenceFlag(const Name& name, const Description& description, T& value) |
2856 | + : Flag{name, description}, |
2857 | + value_{value} |
2858 | + { |
2859 | + } |
2860 | + |
2861 | + /// @brief notify tries to unwrap a value of type T from value, |
2862 | + /// relying on operator>> to read from given string s. |
2863 | + void notify(const std::string& s) override |
2864 | + { |
2865 | + std::stringstream ss{s}; |
2866 | + ss >> value_.get(); |
2867 | + } |
2868 | + |
2869 | +private: |
2870 | + std::reference_wrapper<T> value_; |
2871 | +}; |
2872 | + |
2873 | +/// @brief OptionalTypedReferenceFlag handles Optional<T> references, making sure that |
2874 | +/// a value is always read on notify, even if the Optional<T> wasn't initialized previously. |
2875 | +template<typename T> |
2876 | +class LOCATION_DLL_PUBLIC OptionalTypedReferenceFlag : public Flag |
2877 | +{ |
2878 | +public: |
2879 | + typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr; |
2880 | + |
2881 | + OptionalTypedReferenceFlag(const Name& name, const Description& description, Optional<T>& value) |
2882 | + : Flag{name, description}, |
2883 | + value_{value} |
2884 | + { |
2885 | + } |
2886 | + |
2887 | + /// @brief notify tries to unwrap a value of type T from value. |
2888 | + void notify(const std::string& s) override |
2889 | + { |
2890 | + std::stringstream ss{s}; T value; ss >> value; |
2891 | + value_.get() = value; |
2892 | + } |
2893 | + |
2894 | +private: |
2895 | + std::reference_wrapper<Optional<T>> value_; |
2896 | +}; |
2897 | + |
2898 | +/// @brief Command abstracts an individual command available from the daemon. |
2899 | +class LOCATION_DLL_PUBLIC Command : public DoNotCopyOrMove |
2900 | +{ |
2901 | +public: |
2902 | + // Safe us some typing |
2903 | + typedef std::shared_ptr<Command> Ptr; |
2904 | + |
2905 | + /// @brief FlagsMissing is thrown if at least one required flag is missing. |
2906 | + struct FlagsMissing : public std::runtime_error |
2907 | + { |
2908 | + /// @brief FlagsMissing initializes a new instance. |
2909 | + FlagsMissing(); |
2910 | + }; |
2911 | + |
2912 | + /// @brief FlagsWithWrongValue is thrown if a value passed on the command line is invalid. |
2913 | + struct FlagsWithInvalidValue : public std::runtime_error |
2914 | + { |
2915 | + /// @brief FlagsWithInvalidValue initializes a new instance. |
2916 | + FlagsWithInvalidValue(); |
2917 | + }; |
2918 | + |
2919 | + /// @brief Context bundles information passed to Command::run invocations. |
2920 | + struct Context |
2921 | + { |
2922 | + std::istream& cin; ///< The std::istream that should be used for reading. |
2923 | + std::ostream& cout; ///< The std::ostream that should be used for writing. |
2924 | + std::vector<std::string> args; ///< The command line args. |
2925 | + }; |
2926 | + |
2927 | + /// @brief name returns the Name of the command. |
2928 | + virtual Name name() const; |
2929 | + |
2930 | + /// @brief usage returns a short usage string for the command. |
2931 | + virtual Usage usage() const; |
2932 | + |
2933 | + /// @brief description returns a longer string explaining the command. |
2934 | + virtual Description description() const; |
2935 | + |
2936 | + /// @brief run puts the command to execution. |
2937 | + virtual int run(const Context& context) = 0; |
2938 | + |
2939 | + /// @brief help prints information about a command to out. |
2940 | + virtual void help(std::ostream& out) = 0; |
2941 | + |
2942 | +protected: |
2943 | + /// @brief Command initializes a new instance with the given name, usage and description. |
2944 | + Command(const Name& name, const Usage& usage, const Description& description); |
2945 | + |
2946 | + /// @brief name adjusts the name of the command to n. |
2947 | + // virtual void name(const Name& n); |
2948 | + /// @brief usage adjusts the usage string of the comand to u. |
2949 | + // virtual void usage(const Usage& u); |
2950 | + /// @brief description adjusts the description string of the command to d. |
2951 | + // virtual void description(const Description& d); |
2952 | + |
2953 | +private: |
2954 | + Name name_; |
2955 | + Usage usage_; |
2956 | + Description description_; |
2957 | +}; |
2958 | + |
2959 | +/// @brief CommandWithSubcommands implements Command, selecting one of a set of actions. |
2960 | +class LOCATION_DLL_PUBLIC CommandWithSubcommands : public Command |
2961 | +{ |
2962 | +public: |
2963 | + typedef std::shared_ptr<CommandWithSubcommands> Ptr; |
2964 | + typedef std::function<int(const Context&)> Action; |
2965 | + |
2966 | + /// @brief CommandWithSubcommands initializes a new instance with the given name, usage and description |
2967 | + CommandWithSubcommands(const Name& name, const Usage& usage, const Description& description); |
2968 | + |
2969 | + /// @brief command adds the given command to the set of known commands. |
2970 | + CommandWithSubcommands& command(const Command::Ptr& command); |
2971 | + |
2972 | + /// @brief flag adds the given flag to the set of known flags. |
2973 | + CommandWithSubcommands& flag(const Flag::Ptr& flag); |
2974 | + |
2975 | + // From Command |
2976 | + int run(const Context& context) override; |
2977 | + void help(std::ostream &out) override; |
2978 | + |
2979 | +private: |
2980 | + std::unordered_map<std::string, Command::Ptr> commands_; |
2981 | + std::set<Flag::Ptr> flags_; |
2982 | +}; |
2983 | + |
2984 | +/// @brief CommandWithFlagsAction implements Command, executing an Action after handling |
2985 | +class LOCATION_DLL_PUBLIC CommandWithFlagsAndAction : public Command |
2986 | +{ |
2987 | +public: |
2988 | + typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr; |
2989 | + typedef std::function<int(const Context&)> Action; |
2990 | + |
2991 | + /// @brief CommandWithFlagsAndAction initializes a new instance with the given name, usage and description |
2992 | + CommandWithFlagsAndAction(const Name& name, const Usage& usage, const Description& description); |
2993 | + |
2994 | + /// @brief flag adds the given flag to the set of known flags. |
2995 | + CommandWithFlagsAndAction& flag(const Flag::Ptr& flag); |
2996 | + |
2997 | + /// @brief action installs the given action. |
2998 | + CommandWithFlagsAndAction& action(const Action& action); |
2999 | + |
3000 | + // From Command |
3001 | + int run(const Context& context) override; |
3002 | + void help(std::ostream &out) override; |
3003 | + |
3004 | +private: |
3005 | + std::set<Flag::Ptr> flags_; |
3006 | + Action action_; |
3007 | +}; |
3008 | + |
3009 | +namespace cmd |
3010 | +{ |
3011 | +/// @brief HelpFor prints a help message for the given command on execution. |
3012 | +class Help : public Command |
3013 | +{ |
3014 | +public: |
3015 | + /// @brief HelpFor initializes a new instance with the given reference to a cmd. |
3016 | + explicit Help(Command& cmd); |
3017 | + |
3018 | + // From Command |
3019 | + int run(const Context &context) override; |
3020 | + void help(std::ostream &out) override; |
3021 | + |
3022 | +private: |
3023 | + /// @cond |
3024 | + Command& command; |
3025 | + /// @endcond |
3026 | +}; |
3027 | +} |
3028 | + |
3029 | +/// @brief args returns a vector of strings assembled from argc and argv. |
3030 | +LOCATION_DLL_PUBLIC std::vector<std::string> args(int argc, char** argv); |
3031 | + |
3032 | +/// @brief make_flag returns a flag with the given name and description. |
3033 | +template<typename T> |
3034 | +LOCATION_DLL_PUBLIC typename TypedFlag<T>::Ptr make_flag(const Name& name, const Description& description) |
3035 | +{ |
3036 | + return std::make_shared<TypedFlag<T>>(name, description); |
3037 | +} |
3038 | + |
3039 | +/// @brief make_flag returns a flag with the given name and description, notifying updates to value. |
3040 | +template<typename T> |
3041 | +LOCATION_DLL_PUBLIC typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, T& value) |
3042 | +{ |
3043 | + return std::make_shared<TypedReferenceFlag<T>>(name, desc, value); |
3044 | +} |
3045 | + |
3046 | +/// @brief make_flag returns a flag with the given name and description, updating the given optional value. |
3047 | +template<typename T> |
3048 | +LOCATION_DLL_PUBLIC typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name, const Description& desc, Optional<T>& value) |
3049 | +{ |
3050 | + return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value); |
3051 | +} |
3052 | +} |
3053 | +} |
3054 | +} |
3055 | + |
3056 | +#endif // LOCATION_UTIL_CLI_H_ |
3057 | |
3058 | === added file 'src/location/util/do_not_copy_or_move.h' |
3059 | --- src/location/util/do_not_copy_or_move.h 1970-01-01 00:00:00 +0000 |
3060 | +++ src/location/util/do_not_copy_or_move.h 2016-06-30 09:21:49 +0000 |
3061 | @@ -0,0 +1,44 @@ |
3062 | +/* |
3063 | + * Copyright (C) 2016 Canonical, Ltd. |
3064 | + * |
3065 | + * This program is free software; you can redistribute it and/or modify |
3066 | + * it under the terms of the GNU Lesser General Public License as published by |
3067 | + * the Free Software Foundation; version 3. |
3068 | + * |
3069 | + * This program is distributed in the hope that it will be useful, |
3070 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3071 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3072 | + * GNU Lesser General Public License for more details. |
3073 | + * |
3074 | + * You should have received a copy of the GNU Lesser General Public License |
3075 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3076 | + * |
3077 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
3078 | + * |
3079 | + */ |
3080 | + |
3081 | +#ifndef LOCATION_UTIL_DO_NOT_COPY_OR_MOVE_H_ |
3082 | +#define LOCATION_UTIL_DO_NOT_COPY_OR_MOVE_H_ |
3083 | + |
3084 | +namespace location |
3085 | +{ |
3086 | +namespace util |
3087 | +{ |
3088 | +/// @cond |
3089 | +class DoNotCopyOrMove |
3090 | +{ |
3091 | +public: |
3092 | + DoNotCopyOrMove(const DoNotCopyOrMove&) = delete; |
3093 | + DoNotCopyOrMove(DoNotCopyOrMove&&) = delete; |
3094 | + virtual ~DoNotCopyOrMove() = default; |
3095 | + DoNotCopyOrMove& operator=(const DoNotCopyOrMove&) = delete; |
3096 | + DoNotCopyOrMove& operator=(DoNotCopyOrMove&&) = delete; |
3097 | + |
3098 | +protected: |
3099 | + DoNotCopyOrMove() = default; |
3100 | +}; |
3101 | +/// @endcond |
3102 | +} |
3103 | +} |
3104 | + |
3105 | +#endif // LOCATION_UTIL_DO_NOT_COPY_OR_MOVE_H_ |
3106 | |
3107 | === added file 'src/location/util/well_known_bus.cpp' |
3108 | --- src/location/util/well_known_bus.cpp 1970-01-01 00:00:00 +0000 |
3109 | +++ src/location/util/well_known_bus.cpp 2016-06-30 09:21:49 +0000 |
3110 | @@ -0,0 +1,48 @@ |
3111 | +/* |
3112 | + * Copyright (C) 2016 Canonical, Ltd. |
3113 | + * |
3114 | + * This program is free software; you can redistribute it and/or modify |
3115 | + * it under the terms of the GNU Lesser General Public License as published by |
3116 | + * the Free Software Foundation; version 3. |
3117 | + * |
3118 | + * This program is distributed in the hope that it will be useful, |
3119 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3120 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3121 | + * GNU Lesser General Public License for more details. |
3122 | + * |
3123 | + * You should have received a copy of the GNU Lesser General Public License |
3124 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3125 | + * |
3126 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
3127 | + * |
3128 | + */ |
3129 | + |
3130 | +#include <location/util/well_known_bus.h> |
3131 | + |
3132 | +#include <boost/assign/list_of.hpp> |
3133 | +#include <boost/bimap.hpp> |
3134 | + |
3135 | +namespace |
3136 | +{ |
3137 | +typedef boost::bimap<std::string, core::dbus::WellKnownBus> Lut; |
3138 | +const Lut& lut() |
3139 | +{ |
3140 | + static Lut instance = boost::assign::list_of<Lut::relation> |
3141 | + ("session", core::dbus::WellKnownBus::session) |
3142 | + ("system", core::dbus::WellKnownBus::system) |
3143 | + ("starter", core::dbus::WellKnownBus::starter); |
3144 | + |
3145 | + return instance; |
3146 | +} |
3147 | +} |
3148 | + |
3149 | +std::ostream& core::dbus::operator<<(std::ostream& out, core::dbus::WellKnownBus bus) |
3150 | +{ |
3151 | + return out << lut().right.at(bus); |
3152 | +} |
3153 | + |
3154 | +std::istream& core::dbus::operator>>(std::istream& in, core::dbus::WellKnownBus& bus) |
3155 | +{ |
3156 | + std::string s; in >> s; bus = lut().left.at(s); |
3157 | + return in; |
3158 | +} |
3159 | |
3160 | === added file 'src/location/util/well_known_bus.h' |
3161 | --- src/location/util/well_known_bus.h 1970-01-01 00:00:00 +0000 |
3162 | +++ src/location/util/well_known_bus.h 2016-06-30 09:21:49 +0000 |
3163 | @@ -0,0 +1,37 @@ |
3164 | +/* |
3165 | + * Copyright (C) 2016 Canonical, Ltd. |
3166 | + * |
3167 | + * This program is free software; you can redistribute it and/or modify |
3168 | + * it under the terms of the GNU Lesser General Public License as published by |
3169 | + * the Free Software Foundation; version 3. |
3170 | + * |
3171 | + * This program is distributed in the hope that it will be useful, |
3172 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3173 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3174 | + * GNU Lesser General Public License for more details. |
3175 | + * |
3176 | + * You should have received a copy of the GNU Lesser General Public License |
3177 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3178 | + * |
3179 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
3180 | + * |
3181 | + */ |
3182 | +#ifndef LOCATION_UTIL_WELL_KNOWN_BUS_H_ |
3183 | +#define LOCATION_UTIL_WELL_KNOWN_BUS_H_ |
3184 | + |
3185 | +#include <core/dbus/well_known_bus.h> |
3186 | + |
3187 | +#include <iosfwd> |
3188 | + |
3189 | +namespace core |
3190 | +{ |
3191 | +namespace dbus |
3192 | +{ |
3193 | +// operator<< inserts bus into out. |
3194 | +std::ostream& operator<<(std::ostream& out, WellKnownBus bus); |
3195 | +// operator>> extracts bus from in. |
3196 | +std::istream& operator>>(std::istream& in, WellKnownBus& bus); |
3197 | +} |
3198 | +} |
3199 | + |
3200 | +#endif // LOCATION_UTIL_WELL_KNOWN_BUS_H_ |
Very nice. LGTM