Merge lp:~alan-griffiths/mir/spike-passing-out-client-fds into lp:mir
- spike-passing-out-client-fds
- Merge into development-branch
Proposed by
Alan Griffiths
Status: | Superseded |
---|---|
Proposed branch: | lp:~alan-griffiths/mir/spike-passing-out-client-fds |
Merge into: | lp:mir |
Prerequisite: | lp:~alan-griffiths/mir/cleanup-receive_file_descriptors |
Diff against target: |
1171 lines (+524/-40) 34 files modified
examples/render_surfaces.cpp (+1/-0) include/client/mir_toolkit/mir_connection.h (+19/-0) include/server/mir/frontend/connection_context.h (+55/-0) include/server/mir/frontend/connection_creator.h (+5/-1) include/server/mir/frontend/connector.h (+8/-1) include/server/mir/frontend/protobuf_connection_creator.h (+3/-1) include/server/mir/frontend/session.h (+1/-3) include/shared/mir_toolkit/client_types.h (+11/-0) include/test/mir_test_doubles/mock_scene_session.h (+2/-0) include/test/mir_test_doubles/stub_ipc_factory.h (+3/-2) src/client/mir_connection.cpp (+34/-0) src/client/mir_connection.h (+8/-0) src/client/mir_connection_api.cpp (+18/-0) src/client/rpc/mir_socket_rpc_channel.cpp (+7/-0) src/server/frontend/CMakeLists.txt (+1/-0) src/server/frontend/connection_context.cpp (+36/-0) src/server/frontend/default_configuration.cpp (+5/-3) src/server/frontend/protobuf_connection_creator.cpp (+4/-2) src/server/frontend/protobuf_ipc_factory.h (+3/-1) src/server/frontend/protobuf_message_processor.cpp (+11/-0) src/server/frontend/protobuf_message_processor.h (+1/-0) src/server/frontend/published_socket_connector.cpp (+12/-4) src/server/frontend/published_socket_connector.h (+5/-2) src/server/frontend/session_mediator.cpp (+40/-4) src/server/frontend/session_mediator.h (+15/-7) src/server/scene/application_session.h (+2/-0) src/shared/protobuf/mir_protobuf.proto (+13/-1) tests/acceptance-tests/CMakeLists.txt (+1/-0) tests/acceptance-tests/test_trust_session_helper.cpp (+91/-0) tests/integration-tests/test_display_server_main_loop_events.cpp (+1/-0) tests/integration-tests/test_session.cpp (+1/-0) tests/unit-tests/frontend/test_session_mediator.cpp (+103/-6) tests/unit-tests/frontend/test_session_mediator_android.cpp (+2/-1) tests/unit-tests/frontend/test_session_mediator_mesa.cpp (+2/-1) |
To merge this branch: | bzr merge lp:~alan-griffiths/mir/spike-passing-out-client-fds |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir development team | Pending | ||
Review via email: mp+218074@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-05-07.
Commit message
frontend, client: sort out the "wiring" to allow clients to get a connected FD.
Description of the change
frontend, client: sort out the "wiring" to allow clients to get a connected FD.
This is largely a "proof of concept" of an approach required by trust sessions - allowing a client to request a socket FD for use by a process that it then launches.
To post a comment you must log in.
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'examples/render_surfaces.cpp' |
2 | --- examples/render_surfaces.cpp 2014-05-05 03:36:45 +0000 |
3 | +++ examples/render_surfaces.cpp 2014-05-07 14:18:03 +0000 |
4 | @@ -241,6 +241,7 @@ |
5 | void start() {} |
6 | void stop() {} |
7 | int client_socket_fd() const override { return 0; } |
8 | + int client_socket_fd(std::function<void(std::shared_ptr<mf::Session> const&)> const&) const override { return 0; } |
9 | void remove_endpoint() const override { } |
10 | }; |
11 | |
12 | |
13 | === modified file 'include/client/mir_toolkit/mir_connection.h' |
14 | --- include/client/mir_toolkit/mir_connection.h 2014-03-31 14:36:08 +0000 |
15 | +++ include/client/mir_toolkit/mir_connection.h 2014-05-07 14:18:03 +0000 |
16 | @@ -169,6 +169,25 @@ |
17 | MirConnection* connection, MirPixelFormat* formats, |
18 | unsigned const int format_size, unsigned int *num_valid_formats); |
19 | |
20 | +/** |
21 | + * Allocate some FDs for trusted clients to connect on |
22 | + * |
23 | + * Trust session helpers need to allocate connection FDs it will pass to |
24 | + * trusted clients to use when connecting to the server. The server can |
25 | + * then associate them with the trust session. |
26 | + * |
27 | + * \warning This API is tentative until the implementation of trust sessions is complete |
28 | + * \param [in] connection The connection |
29 | + * \param [in] no_of_fds The number of fds to allocate |
30 | + * \param [in] callback Callback invoked when request completes |
31 | + * \param [in,out] context User data passed to the callback function |
32 | + * \return A handle that can be passed to mir_wait_for |
33 | + */ |
34 | +MirWaitHandle* mir_connection_new_fds_for_trusted_clients( |
35 | + MirConnection* connection, |
36 | + unsigned int no_of_fds, |
37 | + mir_client_fd_callback callback, |
38 | + void * context); |
39 | |
40 | #ifdef __cplusplus |
41 | } |
42 | |
43 | === added file 'include/server/mir/frontend/connection_context.h' |
44 | --- include/server/mir/frontend/connection_context.h 1970-01-01 00:00:00 +0000 |
45 | +++ include/server/mir/frontend/connection_context.h 2014-05-07 14:18:03 +0000 |
46 | @@ -0,0 +1,55 @@ |
47 | +/* |
48 | + * Copyright © 014 Canonical Ltd. |
49 | + * |
50 | + * This program is free software: you can redistribute it and/or modify it |
51 | + * under the terms of the GNU General Public License version 3, |
52 | + * as published by the Free Software Foundation. |
53 | + * |
54 | + * This program is distributed in the hope that it will be useful, |
55 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
56 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
57 | + * GNU General Public License for more details. |
58 | + * |
59 | + * You should have received a copy of the GNU General Public License |
60 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
61 | + * |
62 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
63 | + */ |
64 | + |
65 | +#ifndef MIR_FRONTEND_CONNECTION_CONTEXT_H_ |
66 | +#define MIR_FRONTEND_CONNECTION_CONTEXT_H_ |
67 | + |
68 | +#include <functional> |
69 | +#include <memory> |
70 | + |
71 | +namespace mir |
72 | +{ |
73 | +namespace frontend |
74 | +{ |
75 | +class Connector; |
76 | +class Session; |
77 | + |
78 | +class ConnectionContext |
79 | +{ |
80 | +public: |
81 | + ConnectionContext() = delete; |
82 | + ConnectionContext(const ConnectionContext&) = default; |
83 | + ConnectionContext& operator=(const ConnectionContext&) = default; |
84 | + ConnectionContext(Connector const* connector) : |
85 | + ConnectionContext([](std::shared_ptr<Session> const&){}, connector) {} |
86 | + ConnectionContext( |
87 | + std::function<void(std::shared_ptr<Session> const& session)> const connect_handler, |
88 | + Connector const* connector); |
89 | + |
90 | + int fd_for_new_client(std::function<void(std::shared_ptr<Session> const& session)> const& connect_handler) const; |
91 | + |
92 | + void handle_client_connect(std::shared_ptr<Session> const& session) const { connect_handler(session); } |
93 | + |
94 | +private: |
95 | + std::function<void(std::shared_ptr<Session> const& session)> const connect_handler; |
96 | + Connector const* const connector; |
97 | +}; |
98 | +} |
99 | +} |
100 | + |
101 | +#endif /* MIR_FRONTEND_CONNECTION_CONTEXT_H_ */ |
102 | |
103 | === modified file 'include/server/mir/frontend/connection_creator.h' |
104 | --- include/server/mir/frontend/connection_creator.h 2014-05-05 03:36:45 +0000 |
105 | +++ include/server/mir/frontend/connection_creator.h 2014-05-07 14:18:03 +0000 |
106 | @@ -27,10 +27,14 @@ |
107 | { |
108 | namespace frontend |
109 | { |
110 | +class ConnectionContext; |
111 | + |
112 | class ConnectionCreator |
113 | { |
114 | public: |
115 | - virtual void create_connection_for(std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) = 0; |
116 | + virtual void create_connection_for( |
117 | + std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket, |
118 | + ConnectionContext const& connection_context) = 0; |
119 | |
120 | protected: |
121 | ConnectionCreator() = default; |
122 | |
123 | === modified file 'include/server/mir/frontend/connector.h' |
124 | --- include/server/mir/frontend/connector.h 2013-10-15 08:53:10 +0000 |
125 | +++ include/server/mir/frontend/connector.h 2014-05-07 14:18:03 +0000 |
126 | @@ -1,5 +1,5 @@ |
127 | /* |
128 | - * Copyright © 2012 Canonical Ltd. |
129 | + * Copyright © 2012-2014 Canonical Ltd. |
130 | * |
131 | * This program is free software: you can redistribute it and/or modify it |
132 | * under the terms of the GNU General Public License version 3, |
133 | @@ -19,10 +19,15 @@ |
134 | #ifndef MIR_FRONTEND_CONNECTOR_H_ |
135 | #define MIR_FRONTEND_CONNECTOR_H_ |
136 | |
137 | +#include <functional> |
138 | +#include <memory> |
139 | + |
140 | namespace mir |
141 | { |
142 | namespace frontend |
143 | { |
144 | +class Session; |
145 | + |
146 | /// Handle client process connections |
147 | class Connector |
148 | { |
149 | @@ -33,6 +38,8 @@ |
150 | virtual int client_socket_fd() const = 0; |
151 | virtual void remove_endpoint() const = 0; |
152 | |
153 | + virtual int client_socket_fd(std::function<void(std::shared_ptr<Session> const& session)> const& connect_handler) const = 0; |
154 | + |
155 | protected: |
156 | Connector() = default; |
157 | virtual ~Connector() = default; |
158 | |
159 | === modified file 'include/server/mir/frontend/protobuf_connection_creator.h' |
160 | --- include/server/mir/frontend/protobuf_connection_creator.h 2014-05-05 03:36:45 +0000 |
161 | +++ include/server/mir/frontend/protobuf_connection_creator.h 2014-05-07 14:18:03 +0000 |
162 | @@ -49,7 +49,9 @@ |
163 | std::shared_ptr<MessageProcessorReport> const& report); |
164 | ~ProtobufConnectionCreator() noexcept; |
165 | |
166 | - void create_connection_for(std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket); |
167 | + void create_connection_for( |
168 | + std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket, |
169 | + ConnectionContext const& connection_context) override; |
170 | |
171 | virtual std::shared_ptr<detail::MessageProcessor> create_processor( |
172 | std::shared_ptr<detail::ProtobufMessageSender> const& sender, |
173 | |
174 | === modified file 'include/server/mir/frontend/session.h' |
175 | --- include/server/mir/frontend/session.h 2014-04-15 05:31:19 +0000 |
176 | +++ include/server/mir/frontend/session.h 2014-05-07 14:18:03 +0000 |
177 | @@ -22,8 +22,6 @@ |
178 | #include "mir_toolkit/common.h" |
179 | #include "mir/frontend/surface_id.h" |
180 | |
181 | -#include <mutex> |
182 | -#include <atomic> |
183 | #include <memory> |
184 | #include <string> |
185 | |
186 | @@ -46,7 +44,7 @@ |
187 | class Session |
188 | { |
189 | public: |
190 | - virtual ~Session() {} |
191 | + virtual ~Session() = default; |
192 | |
193 | virtual SurfaceId create_surface(scene::SurfaceCreationParameters const& params) = 0; |
194 | virtual void destroy_surface(SurfaceId surface) = 0; |
195 | |
196 | === modified file 'include/shared/mir_toolkit/client_types.h' |
197 | --- include/shared/mir_toolkit/client_types.h 2014-03-11 16:19:27 +0000 |
198 | +++ include/shared/mir_toolkit/client_types.h 2014-05-07 14:18:03 +0000 |
199 | @@ -104,6 +104,17 @@ |
200 | MirConnection* connection, void* context); |
201 | |
202 | /** |
203 | + * Callback called when a request for client file descriptors completes |
204 | + * \param [in] connection The connection associated with the display change |
205 | + * \param [in] count The number of FDs allocated |
206 | + * \param [in] fds Array of FDs |
207 | + * \param [in,out] context The context provided by client |
208 | + */ |
209 | + |
210 | +typedef void (*mir_client_fd_callback)( |
211 | + MirConnection* connection, size_t count, int const* fds, void* context); |
212 | + |
213 | +/** |
214 | * MirBufferUsage specifies how a surface can and will be used. A "hardware" |
215 | * surface can be used for OpenGL accelerated rendering. A "software" surface |
216 | * is one that can be addressed in main memory and blitted to directly. |
217 | |
218 | === modified file 'include/test/mir_test_doubles/mock_scene_session.h' |
219 | --- include/test/mir_test_doubles/mock_scene_session.h 2014-04-15 05:31:19 +0000 |
220 | +++ include/test/mir_test_doubles/mock_scene_session.h 2014-05-07 14:18:03 +0000 |
221 | @@ -52,6 +52,8 @@ |
222 | MOCK_METHOD3(configure_surface, int(frontend::SurfaceId, MirSurfaceAttrib, int)); |
223 | |
224 | MOCK_METHOD1(set_lifecycle_state, void(MirLifecycleState state)); |
225 | + |
226 | + MOCK_METHOD0(child_connect_handler, std::function<void(std::shared_ptr<frontend::Session> const& session)>()); |
227 | }; |
228 | |
229 | } |
230 | |
231 | === modified file 'include/test/mir_test_doubles/stub_ipc_factory.h' |
232 | --- include/test/mir_test_doubles/stub_ipc_factory.h 2014-05-06 03:33:05 +0000 |
233 | +++ include/test/mir_test_doubles/stub_ipc_factory.h 2014-05-07 14:18:03 +0000 |
234 | @@ -45,8 +45,9 @@ |
235 | } |
236 | |
237 | std::shared_ptr<protobuf::DisplayServer> make_ipc_server( |
238 | - mir::frontend::SessionCredentials const&, |
239 | - std::shared_ptr<frontend::EventSink> const&) override |
240 | + mir::frontend::SessionCredentials const& /*creds*/, |
241 | + std::shared_ptr<mir::frontend::EventSink> const& /*sink*/, |
242 | + mir::frontend::ConnectionContext const& /*connection_context*/) override |
243 | { |
244 | return server; |
245 | } |
246 | |
247 | === modified file 'src/client/mir_connection.cpp' |
248 | --- src/client/mir_connection.cpp 2014-03-06 06:05:17 +0000 |
249 | +++ src/client/mir_connection.cpp 2014-05-07 14:18:03 +0000 |
250 | @@ -304,6 +304,40 @@ |
251 | return &drm_auth_magic_wait_handle; |
252 | } |
253 | |
254 | +MirWaitHandle* MirConnection::new_fds_for_trusted_clients( |
255 | + unsigned int no_of_fds, |
256 | + mir_client_fd_callback callback, |
257 | + void * context) |
258 | +{ |
259 | + mir::protobuf::SocketFDRequest request; |
260 | + request.set_number(no_of_fds); |
261 | + |
262 | + server.new_fds_for_trusted_clients( |
263 | + nullptr, |
264 | + &request, |
265 | + &socket_fd_response, |
266 | + google::protobuf::NewCallback(this, &MirConnection::done_fds_for_trusted_clients, |
267 | + callback, context)); |
268 | + |
269 | + return &fds_for_trusted_clients_wait_handle; |
270 | +} |
271 | + |
272 | +void MirConnection::done_fds_for_trusted_clients( |
273 | + mir_client_fd_callback callback, |
274 | + void* context) |
275 | +{ |
276 | + auto const size = socket_fd_response.fd_size(); |
277 | + |
278 | + std::vector<int> fds; |
279 | + fds.reserve(size); |
280 | + |
281 | + for (auto i = 0; i != size; ++i) |
282 | + fds.push_back(socket_fd_response.fd(i)); |
283 | + |
284 | + callback(this, size, fds.data(), context); |
285 | + fds_for_trusted_clients_wait_handle.result_received(); |
286 | +} |
287 | + |
288 | bool MirConnection::is_valid(MirConnection *connection) |
289 | { |
290 | { |
291 | |
292 | === modified file 'src/client/mir_connection.h' |
293 | --- src/client/mir_connection.h 2014-03-06 06:05:17 +0000 |
294 | +++ src/client/mir_connection.h 2014-05-07 14:18:03 +0000 |
295 | @@ -123,6 +123,11 @@ |
296 | |
297 | bool set_extra_platform_data(std::vector<int> const& extra_platform_data); |
298 | |
299 | + MirWaitHandle* new_fds_for_trusted_clients( |
300 | + unsigned int no_of_fds, |
301 | + mir_client_fd_callback callback, |
302 | + void * context); |
303 | + |
304 | std::shared_ptr<google::protobuf::RpcChannel> rpc_channel() const |
305 | { |
306 | return channel; |
307 | @@ -142,6 +147,7 @@ |
308 | mir::protobuf::ConnectParameters connect_parameters; |
309 | mir::protobuf::DRMAuthMagicStatus drm_auth_magic_status; |
310 | mir::protobuf::DisplayConfiguration display_configuration_response; |
311 | + mir::protobuf::SocketFD socket_fd_response; |
312 | |
313 | std::shared_ptr<mir::client::ClientPlatformFactory> const client_platform_factory; |
314 | std::shared_ptr<mir::client::ClientPlatform> platform; |
315 | @@ -155,6 +161,7 @@ |
316 | MirWaitHandle disconnect_wait_handle; |
317 | MirWaitHandle drm_auth_magic_wait_handle; |
318 | MirWaitHandle configure_display_wait_handle; |
319 | + MirWaitHandle fds_for_trusted_clients_wait_handle; |
320 | |
321 | std::mutex release_wait_handle_guard; |
322 | std::vector<MirWaitHandle*> release_wait_handles; |
323 | @@ -174,6 +181,7 @@ |
324 | void connected(mir_connected_callback callback, void * context); |
325 | void released(SurfaceRelease ); |
326 | void done_drm_auth_magic(mir_drm_auth_magic_callback callback, void* context); |
327 | + void done_fds_for_trusted_clients(mir_client_fd_callback callback, void* context); |
328 | bool validate_user_display_config(MirDisplayConfiguration* config); |
329 | }; |
330 | |
331 | |
332 | === modified file 'src/client/mir_connection_api.cpp' |
333 | --- src/client/mir_connection_api.cpp 2014-03-31 14:36:08 +0000 |
334 | +++ src/client/mir_connection_api.cpp 2014-05-07 14:18:03 +0000 |
335 | @@ -272,6 +272,24 @@ |
336 | } |
337 | } |
338 | |
339 | +MirWaitHandle* mir_connection_new_fds_for_trusted_clients( |
340 | + MirConnection* connection, |
341 | + unsigned int no_of_fds, |
342 | + mir_client_fd_callback callback, |
343 | + void * context) |
344 | +{ |
345 | + try |
346 | + { |
347 | + return connection ? |
348 | + connection->new_fds_for_trusted_clients(no_of_fds, callback, context) : |
349 | + nullptr; |
350 | + } |
351 | + catch (std::exception const&) |
352 | + { |
353 | + return nullptr; |
354 | + } |
355 | +} |
356 | + |
357 | MirEGLNativeDisplayType mir_connection_get_egl_native_display( |
358 | MirConnection* connection) |
359 | { |
360 | |
361 | === modified file 'src/client/rpc/mir_socket_rpc_channel.cpp' |
362 | --- src/client/rpc/mir_socket_rpc_channel.cpp 2014-05-05 03:36:45 +0000 |
363 | +++ src/client/rpc/mir_socket_rpc_channel.cpp 2014-05-07 14:18:03 +0000 |
364 | @@ -166,6 +166,7 @@ |
365 | mir::protobuf::Surface* surface = nullptr; |
366 | mir::protobuf::Buffer* buffer = nullptr; |
367 | mir::protobuf::Platform* platform = nullptr; |
368 | + mir::protobuf::SocketFD* socket_fd = nullptr; |
369 | |
370 | if (message_type == "mir.protobuf.Buffer") |
371 | { |
372 | @@ -193,9 +194,15 @@ |
373 | if (connection && connection->has_platform()) |
374 | platform = connection->mutable_platform(); |
375 | } |
376 | + else if (message_type == "mir.protobuf.SocketFD") |
377 | + { |
378 | + socket_fd = static_cast<mir::protobuf::SocketFD*>(response); |
379 | + } |
380 | + |
381 | receive_any_file_descriptors_for(surface); |
382 | receive_any_file_descriptors_for(buffer); |
383 | receive_any_file_descriptors_for(platform); |
384 | + receive_any_file_descriptors_for(socket_fd); |
385 | } |
386 | |
387 | complete->Run(); |
388 | |
389 | === modified file 'src/server/frontend/CMakeLists.txt' |
390 | --- src/server/frontend/CMakeLists.txt 2014-05-05 03:36:45 +0000 |
391 | +++ src/server/frontend/CMakeLists.txt 2014-05-07 14:18:03 +0000 |
392 | @@ -2,6 +2,7 @@ |
393 | FRONTEND_SOURCES |
394 | |
395 | client_buffer_tracker.cpp |
396 | + connection_context.cpp |
397 | session_mediator.cpp |
398 | protobuf_message_processor.cpp |
399 | protobuf_responder.cpp |
400 | |
401 | === added file 'src/server/frontend/connection_context.cpp' |
402 | --- src/server/frontend/connection_context.cpp 1970-01-01 00:00:00 +0000 |
403 | +++ src/server/frontend/connection_context.cpp 2014-05-07 14:18:03 +0000 |
404 | @@ -0,0 +1,36 @@ |
405 | +/* |
406 | + * Copyright © 2014 Canonical Ltd. |
407 | + * |
408 | + * This program is free software: you can redistribute it and/or modify it |
409 | + * under the terms of the GNU General Public License version 3, |
410 | + * as published by the Free Software Foundation. |
411 | + * |
412 | + * This program is distributed in the hope that it will be useful, |
413 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
414 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
415 | + * GNU General Public License for more details. |
416 | + * |
417 | + * You should have received a copy of the GNU General Public License |
418 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
419 | + * |
420 | + * Authored By: Alan Griffiths <alan@octopull.co.uk> |
421 | + */ |
422 | + |
423 | +#include "mir/frontend/connection_context.h" |
424 | + |
425 | +#include "mir/frontend/connector.h" |
426 | + |
427 | +namespace mf = mir::frontend; |
428 | + |
429 | +mf::ConnectionContext::ConnectionContext( |
430 | + std::function<void(std::shared_ptr<Session> const& session)> const connect_handler, |
431 | + Connector const* connector) : |
432 | + connect_handler(connect_handler), |
433 | + connector(connector) |
434 | +{ |
435 | +} |
436 | + |
437 | +int mf::ConnectionContext::fd_for_new_client(std::function<void(std::shared_ptr<Session> const& session)> const& connect_handler) const |
438 | +{ |
439 | + return connector->client_socket_fd(connect_handler); |
440 | +} |
441 | |
442 | === modified file 'src/server/frontend/default_configuration.cpp' |
443 | --- src/server/frontend/default_configuration.cpp 2014-05-06 03:33:05 +0000 |
444 | +++ src/server/frontend/default_configuration.cpp 2014-05-07 14:18:03 +0000 |
445 | @@ -70,9 +70,10 @@ |
446 | std::shared_ptr<mf::Screencast> const screencast; |
447 | std::shared_ptr<mf::SessionAuthorizer> const session_authorizer; |
448 | |
449 | - virtual std::shared_ptr<mir::protobuf::DisplayServer> make_ipc_server( |
450 | + std::shared_ptr<mir::protobuf::DisplayServer> make_ipc_server( |
451 | mf::SessionCredentials const& creds, |
452 | - std::shared_ptr<mf::EventSink> const& sink) override |
453 | + std::shared_ptr<mf::EventSink> const& sink, |
454 | + mf::ConnectionContext const& connection_context) override |
455 | { |
456 | std::shared_ptr<mf::DisplayChanger> changer; |
457 | std::shared_ptr<mf::Screencast> effective_screencast; |
458 | @@ -104,7 +105,8 @@ |
459 | sm_report, |
460 | sink, |
461 | resource_cache(), |
462 | - effective_screencast); |
463 | + effective_screencast, |
464 | + connection_context); |
465 | } |
466 | |
467 | virtual std::shared_ptr<mf::ResourceCache> resource_cache() |
468 | |
469 | === modified file 'src/server/frontend/protobuf_connection_creator.cpp' |
470 | --- src/server/frontend/protobuf_connection_creator.cpp 2014-05-05 03:36:45 +0000 |
471 | +++ src/server/frontend/protobuf_connection_creator.cpp 2014-05-07 14:18:03 +0000 |
472 | @@ -54,7 +54,9 @@ |
473 | return next_session_id.fetch_add(1); |
474 | } |
475 | |
476 | -void mf::ProtobufConnectionCreator::create_connection_for(std::shared_ptr<ba::local::stream_protocol::socket> const& socket) |
477 | +void mf::ProtobufConnectionCreator::create_connection_for( |
478 | + std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket, |
479 | + ConnectionContext const& connection_context) |
480 | { |
481 | auto const messenger = std::make_shared<detail::SocketMessenger>(socket); |
482 | auto const creds = messenger->client_creds(); |
483 | @@ -68,7 +70,7 @@ |
484 | auto const event_sink = std::make_shared<detail::EventSender>(messenger); |
485 | auto const msg_processor = create_processor( |
486 | message_sender, |
487 | - ipc_factory->make_ipc_server(creds, event_sink), |
488 | + ipc_factory->make_ipc_server(creds, event_sink, connection_context), |
489 | report); |
490 | |
491 | const auto& connection = std::make_shared<mfd::SocketConnection>(messenger, next_id(), connections, msg_processor); |
492 | |
493 | === modified file 'src/server/frontend/protobuf_ipc_factory.h' |
494 | --- src/server/frontend/protobuf_ipc_factory.h 2014-05-05 03:36:45 +0000 |
495 | +++ src/server/frontend/protobuf_ipc_factory.h 2014-05-07 14:18:03 +0000 |
496 | @@ -31,6 +31,7 @@ |
497 | } |
498 | namespace frontend |
499 | { |
500 | +class ConnectionContext; |
501 | class EventSink; |
502 | class ResourceCache; |
503 | class MessageProcessorReport; |
504 | @@ -41,7 +42,8 @@ |
505 | public: |
506 | virtual std::shared_ptr<protobuf::DisplayServer> make_ipc_server( |
507 | SessionCredentials const& creds, |
508 | - std::shared_ptr<EventSink> const& sink) = 0; |
509 | + std::shared_ptr<EventSink> const& sink, |
510 | + ConnectionContext const& connection_context) = 0; |
511 | |
512 | virtual std::shared_ptr<ResourceCache> resource_cache() = 0; |
513 | |
514 | |
515 | === modified file 'src/server/frontend/protobuf_message_processor.cpp' |
516 | --- src/server/frontend/protobuf_message_processor.cpp 2014-03-06 06:05:17 +0000 |
517 | +++ src/server/frontend/protobuf_message_processor.cpp 2014-05-07 14:18:03 +0000 |
518 | @@ -57,6 +57,7 @@ |
519 | template<> struct result_ptr_t<::mir::protobuf::Connection> { typedef ::mir::protobuf::Connection* type; }; |
520 | template<> struct result_ptr_t<::mir::protobuf::Surface> { typedef ::mir::protobuf::Surface* type; }; |
521 | template<> struct result_ptr_t<::mir::protobuf::Screencast> { typedef ::mir::protobuf::Screencast* type; }; |
522 | +template<> struct result_ptr_t<mir::protobuf::SocketFD> { typedef ::mir::protobuf::SocketFD* type; }; |
523 | |
524 | template<> |
525 | void invoke( |
526 | @@ -173,6 +174,10 @@ |
527 | { |
528 | invoke(this, display_server.get(), &protobuf::DisplayServer::release_screencast, invocation); |
529 | } |
530 | + else if ("new_fds_for_trusted_clients" == invocation.method_name()) |
531 | + { |
532 | + invoke(this, display_server.get(), &protobuf::DisplayServer::new_fds_for_trusted_clients, invocation); |
533 | + } |
534 | else if ("disconnect" == invocation.method_name()) |
535 | { |
536 | invoke(this, display_server.get(), &protobuf::DisplayServer::disconnect, invocation); |
537 | @@ -239,3 +244,9 @@ |
538 | |
539 | sender->send_response(id, response, {buffer_fd}); |
540 | } |
541 | + |
542 | +void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, mir::protobuf::SocketFD* response) |
543 | +{ |
544 | + const auto& fd = extract_fds_from(response); |
545 | + sender->send_response(id, response, {fd}); |
546 | +} |
547 | |
548 | === modified file 'src/server/frontend/protobuf_message_processor.h' |
549 | --- src/server/frontend/protobuf_message_processor.h 2014-03-06 06:05:17 +0000 |
550 | +++ src/server/frontend/protobuf_message_processor.h 2014-05-07 14:18:03 +0000 |
551 | @@ -54,6 +54,7 @@ |
552 | void send_response(::google::protobuf::uint32 id, protobuf::Surface* response); |
553 | void send_response(::google::protobuf::uint32 id, std::shared_ptr<protobuf::Buffer> response); |
554 | void send_response(::google::protobuf::uint32 id, mir::protobuf::Screencast* response); |
555 | + void send_response(::google::protobuf::uint32 id, mir::protobuf::SocketFD* response); |
556 | |
557 | private: |
558 | bool dispatch(Invocation const& invocation); |
559 | |
560 | === modified file 'src/server/frontend/published_socket_connector.cpp' |
561 | --- src/server/frontend/published_socket_connector.cpp 2014-05-05 03:36:45 +0000 |
562 | +++ src/server/frontend/published_socket_connector.cpp 2014-05-07 14:18:03 +0000 |
563 | @@ -19,6 +19,7 @@ |
564 | #include "published_socket_connector.h" |
565 | #include "mir/frontend/protobuf_connection_creator.h" |
566 | |
567 | +#include "mir/frontend/connection_context.h" |
568 | #include "mir/frontend/connector_report.h" |
569 | |
570 | #include <boost/signals2.hpp> |
571 | @@ -138,7 +139,7 @@ |
572 | { |
573 | if (!ec) |
574 | { |
575 | - create_session_for(socket); |
576 | + create_session_for(socket, [](std::shared_ptr<mf::Session> const&) {}); |
577 | } |
578 | start_accept(); |
579 | } |
580 | @@ -199,14 +200,21 @@ |
581 | io_service.reset(); |
582 | } |
583 | |
584 | -void mf::BasicConnector::create_session_for(std::shared_ptr<boost::asio::local::stream_protocol::socket> const& server_socket) const |
585 | +void mf::BasicConnector::create_session_for( |
586 | + std::shared_ptr<boost::asio::local::stream_protocol::socket> const& server_socket, |
587 | + std::function<void(std::shared_ptr<Session> const& session)> const& connect_handler) const |
588 | { |
589 | report->creating_session_for(server_socket->native_handle()); |
590 | - connection_creator->create_connection_for(server_socket); |
591 | + connection_creator->create_connection_for(server_socket, {connect_handler, this}); |
592 | } |
593 | |
594 | int mf::BasicConnector::client_socket_fd() const |
595 | { |
596 | + return client_socket_fd([](std::shared_ptr<mf::Session> const&) {}); |
597 | +} |
598 | + |
599 | +int mf::BasicConnector::client_socket_fd(std::function<void(std::shared_ptr<Session> const& session)> const& connect_handler) const |
600 | +{ |
601 | enum { server, client, size }; |
602 | int socket_fd[size]; |
603 | |
604 | @@ -222,7 +230,7 @@ |
605 | |
606 | report->creating_socket_pair(socket_fd[server], socket_fd[client]); |
607 | |
608 | - create_session_for(server_socket); |
609 | + create_session_for(server_socket, connect_handler); |
610 | |
611 | return socket_fd[client]; |
612 | } |
613 | |
614 | === modified file 'src/server/frontend/published_socket_connector.h' |
615 | --- src/server/frontend/published_socket_connector.h 2014-05-05 03:36:45 +0000 |
616 | +++ src/server/frontend/published_socket_connector.h 2014-05-07 14:18:03 +0000 |
617 | @@ -56,10 +56,13 @@ |
618 | void stop() override; |
619 | int client_socket_fd() const override; |
620 | void remove_endpoint() const override; |
621 | - |
622 | + int client_socket_fd(std::function<void(std::shared_ptr<Session> const& session)> const& connect_handler) const override; |
623 | |
624 | protected: |
625 | - void create_session_for(std::shared_ptr<boost::asio::local::stream_protocol::socket> const& server_socket) const; |
626 | + void create_session_for( |
627 | + std::shared_ptr<boost::asio::local::stream_protocol::socket> const& server_socket, |
628 | + std::function<void(std::shared_ptr<Session> const& session)> const& connect_handler) const; |
629 | + |
630 | boost::asio::io_service mutable io_service; |
631 | boost::asio::io_service::work work; |
632 | std::shared_ptr<ConnectorReport> const report; |
633 | |
634 | === modified file 'src/server/frontend/session_mediator.cpp' |
635 | --- src/server/frontend/session_mediator.cpp 2014-04-15 05:31:19 +0000 |
636 | +++ src/server/frontend/session_mediator.cpp 2014-05-07 14:18:03 +0000 |
637 | @@ -67,7 +67,8 @@ |
638 | std::shared_ptr<SessionMediatorReport> const& report, |
639 | std::shared_ptr<EventSink> const& sender, |
640 | std::shared_ptr<ResourceCache> const& resource_cache, |
641 | - std::shared_ptr<Screencast> const& screencast) : |
642 | + std::shared_ptr<Screencast> const& screencast, |
643 | + ConnectionContext const& connection_context) : |
644 | client_pid(client_pid), |
645 | shell(shell), |
646 | graphics_platform(graphics_platform), |
647 | @@ -76,7 +77,8 @@ |
648 | report(report), |
649 | event_sink(sender), |
650 | resource_cache(resource_cache), |
651 | - screencast(screencast) |
652 | + screencast(screencast), |
653 | + connection_context(connection_context) |
654 | { |
655 | } |
656 | |
657 | @@ -97,10 +99,12 @@ |
658 | { |
659 | report->session_connect_called(request->application_name()); |
660 | |
661 | + auto const session = shell->open_session(client_pid, request->application_name(), event_sink); |
662 | { |
663 | - std::unique_lock<std::mutex> lock(session_mutex); |
664 | - weak_session = shell->open_session(client_pid, request->application_name(), event_sink); |
665 | + std::lock_guard<std::mutex> lock(session_mutex); |
666 | + weak_session = session; |
667 | } |
668 | + connection_context.handle_client_connect(session); |
669 | |
670 | auto ipc_package = graphics_platform->get_ipc_package(); |
671 | auto platform = response->mutable_platform(); |
672 | @@ -411,6 +415,38 @@ |
673 | done->Run(); |
674 | } |
675 | |
676 | +void mf::SessionMediator::new_fds_for_trusted_clients( |
677 | + ::google::protobuf::RpcController* , |
678 | + ::mir::protobuf::SocketFDRequest const* parameters, |
679 | + ::mir::protobuf::SocketFD* response, |
680 | + ::google::protobuf::Closure* done) |
681 | +{ |
682 | + { |
683 | + std::unique_lock<std::mutex> lock(session_mutex); |
684 | + auto session = weak_session.lock(); |
685 | + |
686 | + if (session.get() == nullptr) |
687 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
688 | + |
689 | + // TODO write a handler that connects the new session to our trust session |
690 | + auto const connect_handler = [](std::shared_ptr<frontend::Session> const&) {}; |
691 | + |
692 | + auto const fds_requested = parameters->number(); |
693 | + |
694 | + // < 1 is illogical, > 42 is unreasonable |
695 | + if (fds_requested < 1 || fds_requested > 42) |
696 | + BOOST_THROW_EXCEPTION(std::runtime_error("number of fds requested out of range")); |
697 | + |
698 | + for (auto i = 0; i != fds_requested; ++i) |
699 | + { |
700 | + auto const fd = connection_context.fd_for_new_client(connect_handler); |
701 | + response->add_fd(fd); |
702 | + } |
703 | + } |
704 | + |
705 | + done->Run(); |
706 | +} |
707 | + |
708 | void mf::SessionMediator::drm_auth_magic( |
709 | google::protobuf::RpcController* /*controller*/, |
710 | const mir::protobuf::DRMMagic* request, |
711 | |
712 | === modified file 'src/server/frontend/session_mediator.h' |
713 | --- src/server/frontend/session_mediator.h 2014-03-06 06:05:17 +0000 |
714 | +++ src/server/frontend/session_mediator.h 2014-05-07 14:18:03 +0000 |
715 | @@ -16,11 +16,11 @@ |
716 | * Authored by: Alan Griffiths <alan@octopull.co.uk> |
717 | */ |
718 | |
719 | - |
720 | #ifndef MIR_FRONTEND_SESSION_MEDIATOR_H_ |
721 | #define MIR_FRONTEND_SESSION_MEDIATOR_H_ |
722 | |
723 | #include "mir_protobuf.pb.h" |
724 | +#include "mir/frontend/connection_context.h" |
725 | #include "mir/frontend/surface_id.h" |
726 | #include "mir_toolkit/common.h" |
727 | |
728 | @@ -40,7 +40,6 @@ |
729 | class GraphicBufferAllocator; |
730 | } |
731 | |
732 | - |
733 | /// Frontend interface. Mediates the interaction between client |
734 | /// processes and the core of the mir system. |
735 | namespace frontend |
736 | @@ -59,6 +58,7 @@ |
737 | class SessionMediator : public mir::protobuf::DisplayServer |
738 | { |
739 | public: |
740 | + |
741 | SessionMediator( |
742 | pid_t client_pid, |
743 | std::shared_ptr<Shell> const& shell, |
744 | @@ -68,7 +68,8 @@ |
745 | std::shared_ptr<SessionMediatorReport> const& report, |
746 | std::shared_ptr<EventSink> const& event_sink, |
747 | std::shared_ptr<ResourceCache> const& resource_cache, |
748 | - std::shared_ptr<Screencast> const& screencast); |
749 | + std::shared_ptr<Screencast> const& screencast, |
750 | + ConnectionContext const& connection_context); |
751 | |
752 | ~SessionMediator() noexcept; |
753 | |
754 | @@ -112,17 +113,17 @@ |
755 | void create_screencast(google::protobuf::RpcController*, |
756 | const mir::protobuf::ScreencastParameters*, |
757 | mir::protobuf::Screencast*, |
758 | - google::protobuf::Closure* done); |
759 | + google::protobuf::Closure* done) override; |
760 | |
761 | void release_screencast(google::protobuf::RpcController*, |
762 | const mir::protobuf::ScreencastId*, |
763 | mir::protobuf::Void*, |
764 | - google::protobuf::Closure* done); |
765 | + google::protobuf::Closure* done) override; |
766 | |
767 | void screencast_buffer(google::protobuf::RpcController*, |
768 | const mir::protobuf::ScreencastId*, |
769 | mir::protobuf::Buffer*, |
770 | - google::protobuf::Closure* done); |
771 | + google::protobuf::Closure* done) override; |
772 | |
773 | /* Platform specific requests */ |
774 | void drm_auth_magic(google::protobuf::RpcController* controller, |
775 | @@ -130,6 +131,12 @@ |
776 | mir::protobuf::DRMAuthMagicStatus* response, |
777 | google::protobuf::Closure* done) override; |
778 | |
779 | + void new_fds_for_trusted_clients( |
780 | + ::google::protobuf::RpcController* controller, |
781 | + ::mir::protobuf::SocketFDRequest const* parameters, |
782 | + ::mir::protobuf::SocketFD* response, |
783 | + ::google::protobuf::Closure* done) override; |
784 | + |
785 | private: |
786 | void pack_protobuf_buffer(protobuf::Buffer& protobuf_buffer, |
787 | graphics::Buffer* graphics_buffer, |
788 | @@ -153,10 +160,11 @@ |
789 | |
790 | std::mutex session_mutex; |
791 | std::weak_ptr<Session> weak_session; |
792 | + |
793 | + ConnectionContext const connection_context; |
794 | }; |
795 | |
796 | } |
797 | } |
798 | |
799 | - |
800 | #endif /* MIR_FRONTEND_SESSION_MEDIATOR_H_ */ |
801 | |
802 | === modified file 'src/server/scene/application_session.h' |
803 | --- src/server/scene/application_session.h 2014-04-15 05:31:19 +0000 |
804 | +++ src/server/scene/application_session.h 2014-05-07 14:18:03 +0000 |
805 | @@ -21,7 +21,9 @@ |
806 | |
807 | #include "mir/scene/session.h" |
808 | |
809 | +#include <atomic> |
810 | #include <map> |
811 | +#include <mutex> |
812 | |
813 | namespace mir |
814 | { |
815 | |
816 | === modified file 'src/shared/protobuf/mir_protobuf.proto' |
817 | --- src/shared/protobuf/mir_protobuf.proto 2014-03-11 16:19:27 +0000 |
818 | +++ src/shared/protobuf/mir_protobuf.proto 2014-05-07 14:18:03 +0000 |
819 | @@ -175,6 +175,18 @@ |
820 | optional string error = 127; |
821 | } |
822 | |
823 | +message SocketFDRequest { |
824 | + required int32 number = 1; |
825 | +} |
826 | + |
827 | + |
828 | +message SocketFD { |
829 | + repeated sint32 fd = 1; |
830 | + optional int32 fds_on_side_channel = 2; |
831 | + |
832 | + optional string error = 127; |
833 | +} |
834 | + |
835 | service DisplayServer { |
836 | // Platform independent requests |
837 | rpc connect(ConnectParameters) returns (Connection); |
838 | @@ -194,5 +206,5 @@ |
839 | rpc create_screencast(ScreencastParameters) returns (Screencast); |
840 | rpc screencast_buffer(ScreencastId) returns (Buffer); |
841 | rpc release_screencast(ScreencastId) returns (Void); |
842 | + rpc new_fds_for_trusted_clients(SocketFDRequest) returns (SocketFD); |
843 | } |
844 | - |
845 | |
846 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
847 | --- tests/acceptance-tests/CMakeLists.txt 2014-05-05 03:36:45 +0000 |
848 | +++ tests/acceptance-tests/CMakeLists.txt 2014-05-07 14:18:03 +0000 |
849 | @@ -31,6 +31,7 @@ |
850 | test_protobuf.cpp |
851 | test_client_screencast.cpp |
852 | test_client_surface_swap_buffers.cpp |
853 | + test_trust_session_helper.cpp |
854 | ${GENERATED_PROTOBUF_SRCS} |
855 | ${GENERATED_PROTOBUF_HDRS} |
856 | ) |
857 | |
858 | === added file 'tests/acceptance-tests/test_trust_session_helper.cpp' |
859 | --- tests/acceptance-tests/test_trust_session_helper.cpp 1970-01-01 00:00:00 +0000 |
860 | +++ tests/acceptance-tests/test_trust_session_helper.cpp 2014-05-07 14:18:03 +0000 |
861 | @@ -0,0 +1,91 @@ |
862 | +/* |
863 | + * Copyright © 2014 Canonical Ltd. |
864 | + * |
865 | + * This program is free software: you can redistribute it and/or modify it |
866 | + * under the terms of the GNU General Public License version 3, |
867 | + * as published by the Free Software Foundation. |
868 | + * |
869 | + * This program is distributed in the hope that it will be useful, |
870 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
871 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
872 | + * GNU General Public License for more details. |
873 | + * |
874 | + * You should have received a copy of the GNU General Public License |
875 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
876 | + * |
877 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
878 | + */ |
879 | + |
880 | +#include "mir_toolkit/mir_client_library.h" |
881 | + |
882 | +#include "mir_test_framework/stubbed_server_configuration.h" |
883 | +#include "mir_test_framework/in_process_server.h" |
884 | + |
885 | +#include <gtest/gtest.h> |
886 | +#include <gmock/gmock.h> |
887 | + |
888 | +#include <algorithm> |
889 | +#include <condition_variable> |
890 | +#include <mutex> |
891 | + |
892 | +namespace |
893 | +{ |
894 | +using DemoServerConfiguration = mir_test_framework::StubbedServerConfiguration; |
895 | + |
896 | +struct TrustSessionHelper : mir_test_framework::InProcessServer |
897 | +{ |
898 | + DemoServerConfiguration my_server_config; |
899 | + |
900 | + mir::DefaultServerConfiguration& server_config() override { return my_server_config; } |
901 | + |
902 | + void SetUp() |
903 | + { |
904 | + mir_test_framework::InProcessServer::SetUp(); |
905 | + connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__); |
906 | + } |
907 | + |
908 | + void TearDown() |
909 | + { |
910 | + mir_connection_release(connection); |
911 | + mir_test_framework::InProcessServer::TearDown(); |
912 | + } |
913 | + |
914 | + MirConnection* connection = nullptr; |
915 | + |
916 | + static std::size_t const arbritary_fd_request_count = 3; |
917 | + |
918 | + std::mutex mutex; |
919 | + std::size_t actual_fd_count = 0; |
920 | + int actual_fds[arbritary_fd_request_count] = {}; |
921 | + std::condition_variable cv; |
922 | + bool called_back = false; |
923 | + |
924 | + bool wait_for_callback(std::chrono::milliseconds timeout) |
925 | + { |
926 | + std::unique_lock<decltype(mutex)> lock(mutex); |
927 | + return cv.wait_for(lock, timeout, [this]{ return called_back; }); |
928 | + } |
929 | +}; |
930 | + |
931 | +void client_fd_callback(MirConnection*, size_t count, int const* fds, void* context) |
932 | +{ |
933 | + auto const self = static_cast<TrustSessionHelper*>(context); |
934 | + |
935 | + std::unique_lock<decltype(self->mutex)> lock(self->mutex); |
936 | + self->actual_fd_count = count; |
937 | + |
938 | + std::copy(fds, fds+count, self->actual_fds); |
939 | + self->called_back = true; |
940 | + self->cv.notify_one(); |
941 | +} |
942 | +} |
943 | + |
944 | +using namespace testing; |
945 | + |
946 | +TEST_F(TrustSessionHelper, gets_fds_for_trusted_clients) |
947 | +{ |
948 | + mir_connection_new_fds_for_trusted_clients(connection, arbritary_fd_request_count, &client_fd_callback, this); |
949 | + EXPECT_TRUE(wait_for_callback(std::chrono::milliseconds(500))); |
950 | + |
951 | + EXPECT_THAT(actual_fd_count, Eq(arbritary_fd_request_count)); |
952 | +} |
953 | |
954 | === modified file 'tests/integration-tests/test_display_server_main_loop_events.cpp' |
955 | --- tests/integration-tests/test_display_server_main_loop_events.cpp 2014-03-06 06:05:17 +0000 |
956 | +++ tests/integration-tests/test_display_server_main_loop_events.cpp 2014-05-07 14:18:03 +0000 |
957 | @@ -63,6 +63,7 @@ |
958 | * to silence gmock warnings. |
959 | */ |
960 | int client_socket_fd() const { return 0; } |
961 | + int client_socket_fd(std::function<void(std::shared_ptr<mf::Session> const&)> const&) const override { return 0; } |
962 | void remove_endpoint() const {} |
963 | }; |
964 | |
965 | |
966 | === modified file 'tests/integration-tests/test_session.cpp' |
967 | --- tests/integration-tests/test_session.cpp 2014-04-15 05:31:19 +0000 |
968 | +++ tests/integration-tests/test_session.cpp 2014-05-07 14:18:03 +0000 |
969 | @@ -69,6 +69,7 @@ |
970 | void start() {} |
971 | void stop() {} |
972 | int client_socket_fd() const override { return 0; } |
973 | + int client_socket_fd(std::function<void(std::shared_ptr<mf::Session> const&)> const&) const override { return 0; } |
974 | void remove_endpoint() const override { } |
975 | }; |
976 | |
977 | |
978 | === modified file 'tests/unit-tests/frontend/test_session_mediator.cpp' |
979 | --- tests/unit-tests/frontend/test_session_mediator.cpp 2014-05-01 07:13:02 +0000 |
980 | +++ tests/unit-tests/frontend/test_session_mediator.cpp 2014-05-07 14:18:03 +0000 |
981 | @@ -41,6 +41,7 @@ |
982 | #include "mir_test_doubles/null_screencast.h" |
983 | #include "mir_test/display_config_matchers.h" |
984 | #include "mir_test/fake_shared.h" |
985 | +#include "mir/frontend/connector.h" |
986 | #include "mir/frontend/event_sink.h" |
987 | |
988 | #include "gmock_set_arg.h" |
989 | @@ -86,10 +87,18 @@ |
990 | MOCK_METHOD1(for_each_output, void(std::function<void(mg::UserDisplayConfigurationOutput&)>)); |
991 | }; |
992 | |
993 | -} |
994 | - |
995 | -namespace |
996 | +struct MockConnector : public mf::Connector |
997 | { |
998 | +public: |
999 | + void start() override {} |
1000 | + void stop() override {} |
1001 | + |
1002 | + int client_socket_fd() const override { return 0; } |
1003 | + void remove_endpoint() const override {} |
1004 | + |
1005 | + MOCK_CONST_METHOD1(client_socket_fd, int (std::function<void(std::shared_ptr<mf::Session> const&)> const&)); |
1006 | +}; |
1007 | + |
1008 | class StubbedSession : public mtd::StubSession |
1009 | { |
1010 | public: |
1011 | @@ -209,7 +218,7 @@ |
1012 | mediator{__LINE__, shell, graphics_platform, graphics_changer, |
1013 | surface_pixel_formats, report, |
1014 | std::make_shared<mtd::NullEventSink>(), |
1015 | - resource_cache, stub_screencast}, |
1016 | + resource_cache, stub_screencast, &connector}, |
1017 | stubbed_session{std::make_shared<StubbedSession>()}, |
1018 | null_callback{google::protobuf::NewPermanentCallback(google::protobuf::DoNothing)} |
1019 | { |
1020 | @@ -220,6 +229,7 @@ |
1021 | .WillByDefault(WithArg<1>(Invoke(stubbed_session.get(), &StubbedSession::create_surface))); |
1022 | } |
1023 | |
1024 | + MockConnector connector; |
1025 | std::shared_ptr<testing::NiceMock<mtd::MockShell>> const shell; |
1026 | std::shared_ptr<MockPlatform> const graphics_platform; |
1027 | std::shared_ptr<mf::DisplayChanger> const graphics_changer; |
1028 | @@ -247,6 +257,42 @@ |
1029 | mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get()); |
1030 | } |
1031 | |
1032 | +TEST_F(SessionMediatorTest, connect_calls_connect_handler) |
1033 | +{ |
1034 | + int connects_handled_count = 0; |
1035 | + |
1036 | + mf::ConnectionContext const context = |
1037 | + { |
1038 | + [&](std::shared_ptr<mf::Session> const&) { ++connects_handled_count; }, |
1039 | + nullptr |
1040 | + }; |
1041 | + |
1042 | + mf::SessionMediator mediator{ |
1043 | + __LINE__, |
1044 | + shell, |
1045 | + graphics_platform, |
1046 | + graphics_changer, |
1047 | + surface_pixel_formats, |
1048 | + report, |
1049 | + std::make_shared<mtd::NullEventSink>(), |
1050 | + resource_cache, |
1051 | + stub_screencast, |
1052 | + context}; |
1053 | + |
1054 | + mp::ConnectParameters connect_parameters; |
1055 | + mp::Connection connection; |
1056 | + |
1057 | + using namespace ::testing; |
1058 | + |
1059 | + EXPECT_THAT(connects_handled_count, Eq(0)); |
1060 | + |
1061 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
1062 | + EXPECT_THAT(connects_handled_count, Eq(1)); |
1063 | + |
1064 | + mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get()); |
1065 | + EXPECT_THAT(connects_handled_count, Eq(1)); |
1066 | +} |
1067 | + |
1068 | TEST_F(SessionMediatorTest, calling_methods_before_connect_throws) |
1069 | { |
1070 | EXPECT_THROW({ |
1071 | @@ -373,7 +419,8 @@ |
1072 | __LINE__, shell, graphics_platform, mock_display, |
1073 | surface_pixel_formats, report, |
1074 | std::make_shared<mtd::NullEventSink>(), |
1075 | - resource_cache, std::make_shared<mtd::NullScreencast>()); |
1076 | + resource_cache, std::make_shared<mtd::NullScreencast>(), |
1077 | + nullptr); |
1078 | |
1079 | mp::ConnectParameters connect_parameters; |
1080 | mp::Connection connection; |
1081 | @@ -597,7 +644,8 @@ |
1082 | __LINE__, shell, graphics_platform, mock_display_selector, |
1083 | surface_pixel_formats, report, |
1084 | std::make_shared<mtd::NullEventSink>(), resource_cache, |
1085 | - std::make_shared<mtd::NullScreencast>()}; |
1086 | + std::make_shared<mtd::NullScreencast>(), |
1087 | + nullptr}; |
1088 | |
1089 | session_mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
1090 | |
1091 | @@ -665,3 +713,52 @@ |
1092 | EXPECT_EQ(stub_buffer.id().as_uint32_t(), |
1093 | protobuf_buffer.buffer_id()); |
1094 | } |
1095 | + |
1096 | +TEST_F(SessionMediatorTest, client_socket_fd_calls_connector_client_socket_fd) |
1097 | +{ |
1098 | + const int fd_count = 1; |
1099 | + const int dummy_fd = __LINE__; |
1100 | + |
1101 | + mp::ConnectParameters connect_parameters; |
1102 | + mp::Connection connection; |
1103 | + |
1104 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
1105 | + |
1106 | + ::mir::protobuf::SocketFDRequest request; |
1107 | + ::mir::protobuf::SocketFD response; |
1108 | + request.set_number(1); |
1109 | + |
1110 | + using namespace ::testing; |
1111 | + |
1112 | + EXPECT_CALL(connector, client_socket_fd(_)).Times(1).WillOnce(Return(dummy_fd)); |
1113 | + mediator.new_fds_for_trusted_clients(nullptr, &request, &response, null_callback.get()); |
1114 | + |
1115 | + EXPECT_THAT(response.fd_size(), Eq(fd_count)); |
1116 | + EXPECT_THAT(response.fd(0), Eq(dummy_fd)); |
1117 | + |
1118 | + mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get()); |
1119 | +} |
1120 | + |
1121 | +TEST_F(SessionMediatorTest, client_socket_fd_allocates_requested_number_of_fds) |
1122 | +{ |
1123 | + const int fd_count = 11; |
1124 | + const int dummy_fd = __LINE__; |
1125 | + |
1126 | + mp::ConnectParameters connect_parameters; |
1127 | + mp::Connection connection; |
1128 | + |
1129 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
1130 | + |
1131 | + ::mir::protobuf::SocketFDRequest request; |
1132 | + ::mir::protobuf::SocketFD response; |
1133 | + request.set_number(fd_count); |
1134 | + |
1135 | + using namespace ::testing; |
1136 | + |
1137 | + EXPECT_CALL(connector, client_socket_fd(_)).Times(fd_count).WillRepeatedly(Return(dummy_fd)); |
1138 | + mediator.new_fds_for_trusted_clients(nullptr, &request, &response, null_callback.get()); |
1139 | + |
1140 | + EXPECT_THAT(response.fd_size(), Eq(fd_count)); |
1141 | + |
1142 | + mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get()); |
1143 | +} |
1144 | |
1145 | === modified file 'tests/unit-tests/frontend/test_session_mediator_android.cpp' |
1146 | --- tests/unit-tests/frontend/test_session_mediator_android.cpp 2014-04-15 05:31:19 +0000 |
1147 | +++ tests/unit-tests/frontend/test_session_mediator_android.cpp 2014-05-07 14:18:03 +0000 |
1148 | @@ -61,7 +61,8 @@ |
1149 | mediator{__LINE__, shell, graphics_platform, display_changer, |
1150 | surface_pixel_formats, report, |
1151 | std::make_shared<mtd::NullEventSink>(), |
1152 | - resource_cache, std::make_shared<mtd::NullScreencast>()}, |
1153 | + resource_cache, std::make_shared<mtd::NullScreencast>(), |
1154 | + nullptr}, |
1155 | null_callback{google::protobuf::NewPermanentCallback(google::protobuf::DoNothing)} |
1156 | { |
1157 | } |
1158 | |
1159 | === modified file 'tests/unit-tests/frontend/test_session_mediator_mesa.cpp' |
1160 | --- tests/unit-tests/frontend/test_session_mediator_mesa.cpp 2014-04-15 05:31:19 +0000 |
1161 | +++ tests/unit-tests/frontend/test_session_mediator_mesa.cpp 2014-05-07 14:18:03 +0000 |
1162 | @@ -75,7 +75,8 @@ |
1163 | mediator{__LINE__, shell, mock_platform, display_changer, |
1164 | surface_pixel_formats, report, |
1165 | std::make_shared<mtd::NullEventSink>(), |
1166 | - resource_cache, std::make_shared<mtd::NullScreencast>()}, |
1167 | + resource_cache, std::make_shared<mtd::NullScreencast>(), |
1168 | + nullptr}, |
1169 | null_callback{google::protobuf::NewPermanentCallback(google::protobuf::DoNothing)} |
1170 | { |
1171 | } |
Looks ok overall. It takes some effort to follow the logic through the many layers, but this is a pre-existing problem with this part of the code.
60 + int fd_for_ client_ handled_ by(std: :function< void(std: :shared_ ptr<Session> const& session)> const& connect_handler) const; client_ connect( std::shared_ ptr<Session> const& session) const { connect_ handler( session) ; }
61 +
62 + void handle_
This part confused me a bit because I was trying to figure out the relationship between the two operations for the same session. It took me some time to realize that one is (primarily) used by the parent session and the other in the child sessions. Is there is a use case in which a session is both a parent of some sessions and a child of another session?