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