Merge lp:~thomas-voss/location-service/introduce-locationd into lp:location-service

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
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.
Revision history for this message
Simon Fels (morphis) wrote :

Very nice. LGTM

review: Approve

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_

Subscribers

People subscribed via source and target branches

to all changes: