Mir

Merge lp:~albaguirre/mir/fix-1465883 into lp:mir

Proposed by Alberto Aguirre
Status: Merged
Approved by: Alberto Aguirre
Approved revision: no longer in the source branch.
Merged at revision: 2674
Proposed branch: lp:~albaguirre/mir/fix-1465883
Merge into: lp:mir
Diff against target: 1413 lines (+308/-238)
12 files modified
src/client/buffer_stream.cpp (+38/-37)
src/client/buffer_stream.h (+3/-3)
src/client/make_protobuf_object.h (+42/-0)
src/client/mir_connection.cpp (+56/-49)
src/client/mir_connection.h (+8/-6)
src/client/mir_prompt_session.cpp (+21/-15)
src/client/mir_prompt_session.h (+5/-5)
src/client/mir_screencast.cpp (+24/-21)
src/client/mir_screencast.h (+4/-2)
src/client/mir_surface.cpp (+83/-76)
src/client/mir_surface.h (+6/-7)
src/client/rpc/mir_protobuf_rpc_channel.cpp (+18/-17)
To merge this branch: bzr merge lp:~albaguirre/mir/fix-1465883
Reviewer Review Type Date Requested Status
Alan Griffiths Approve
Chris Halse Rogers Approve
Daniel van Vugt Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+262160@code.launchpad.net

Commit message

Avoid allocating mir::protobuf objects on the stack

When an addition is made to a protobuf message, a stack allocation of such object may differ from what the destructor of that message is expecting as the destructor is defined by libmirprotobuf and the allocation may have been made from an older definition of the message (by an older mirclient library for example) which can lead to stack corruption.

Ideally, the mirprotobuf library would have versioned symbols and have the ability to be loaded in parallel to a previous version but that's not currently possible.

As an alternative, avoid allocating mir defined protobuf objects on the stack and instead use the xxx::default_instance().New() factory methods which are defined in the mirprotobuf library.

Description of the change

Avoid allocating mir::protobuf objects on the stack

When an addition is made to a protobuf message, a stack allocation of such object may differ from what the destructor of that message is expecting as the destructor is defined by libmirprotobuf and the allocation may have been made from an older definition of the message (by an older mirclient library for example) which can lead to stack corruption.

Ideally, the mirprotobuf library would have versioned symbols and have the ability to be loaded in parallel to a previous version but that's not currently possible.

As an alternative, avoid allocating mir defined protobuf objects on the stack and instead use the xxx::default_instance().New() factory methods which are defined in the mirprotobuf library.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Slightly scary no one figured this out earlier.

A worse way to think of the bug is: If a new field is added to a message then any existing code will try to construct that message on the stack using its old (smaller) size while Protobuf itself fills out the new fields (which we didn't allow for in the stack allocation). Hence stack corruption.

The solution presented here however fails to work in all cases of ABI breaks such as when a member is removed from the middle of the object. Not likely, but there is a better option...

The issue is really that we're breaking MIRPROTOBUF_ABI but have never thought to bump it. If it was bumped any any change to message sizes/structure then everyone would always be linked to a version that is safe for them. And bumping MIRPROTOBUF_ABI would mean we could keep our nice fast stack variables.

review: Needs Information
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

So I think Disapprove/Needs fixing. A simple bump of MIRPROTOBUF_ABI will solve it more reliably and give us more efficient code. Unless anyone can prove there's a protobuf issue preventing us from doing that.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

It's also worth noting you don't need versioned symbols at all if your major ABI number is changing instead.

Revision history for this message
Chris Halse Rogers (raof) wrote :

There *is* a protobuf issue preventing us from doing that; see for example the failures on input-methods-can-... when I bumped protobuf ABI (eg: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-mako/5597/console )

The issue is that protobuf will abort() if it's loaded twice, and bumping mirprotobuf ABI ensures that it's loaded twice. Otherwise we wouldn't be building libmirprotobuf.so at all, and would be statically linking it as nature intended.

Revision history for this message
Chris Halse Rogers (raof) wrote :

So, urgh. Yeah, this is better than what we've got.

Is there any obvious way to test that we don't stack-create protobuf objects? It'd be nice to have a test, but I can't think of one.

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> So I think Disapprove/Needs fixing. A simple bump of MIRPROTOBUF_ABI will
> solve it more reliably and give us more efficient code. Unless anyone can
> prove there's a protobuf issue preventing us from doing that.

It really isn't that simple: protobuf has a number of issues in this area. Essentially, we can only have one protobuf instantiation in process.

We've "got away" with it while the client ABI has remained at 8 (as only the latest limbirprotobuf gets loaded). Now we're proposing 9 we need to keep the same limbirprotobuf version.

Alexandros has tried to upstream some fixes to protobuf, and Kevin and Chris have recently run into problems.

AFAICS the approach proposed here is the least bad of the feasible options.

review: Approve
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

@Daniel,

As others have said, yes there are protobuf issues preventing loading two versions in the same process (for more comments see Chris branch https://code.launchpad.net/~raof/mir/input-methods-can-specify-foreign-parents/+merge/258001)

Loading two versions of protobuf in the same process is more common than is apparent at first glance, because the mesa client platform module links against libmirclient.

Indeed, just by probing the modules, a client that links against libmirclient8, will end up loading libmirprotobuf.so.1 since the module will load libmirclient9 (which is linked to libmirprotobuf.so.1)

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

"The solution presented here however fails to work in all cases of ABI breaks such as when a member is removed from the middle of the object. Not likely, but there is a better option..."

This is true, we still need to tread carefully when modifying protobuf message definitions.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/client/buffer_stream.cpp'
2--- src/client/buffer_stream.cpp 2015-06-03 19:17:55 +0000
3+++ src/client/buffer_stream.cpp 2015-06-16 23:39:42 +0000
4@@ -19,6 +19,7 @@
5 #define MIR_LOG_COMPONENT "MirBufferStream"
6
7 #include "buffer_stream.h"
8+#include "make_protobuf_object.h"
9
10 #include "mir_connection.h"
11 #include "mir/frontend/client_constants.h"
12@@ -97,11 +98,11 @@
13 display_server(server),
14 mode(mode),
15 client_platform(client_platform),
16- protobuf_bs(protobuf_bs),
17+ protobuf_bs{mcl::make_protobuf_object<mir::protobuf::BufferStream>(protobuf_bs)},
18 buffer_depository{client_platform->create_buffer_factory(), mir::frontend::client_buffer_cache_size},
19 swap_interval_(1),
20- perf_report(perf_report)
21-
22+ perf_report(perf_report),
23+ protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()}
24 {
25 created(nullptr, nullptr);
26 perf_report->name_surface(surface_name.c_str());
27@@ -119,21 +120,23 @@
28 display_server(server),
29 mode(BufferStreamMode::Producer),
30 client_platform(client_platform),
31+ protobuf_bs{mcl::make_protobuf_object<mir::protobuf::BufferStream>()},
32 buffer_depository{client_platform->create_buffer_factory(), mir::frontend::client_buffer_cache_size},
33 swap_interval_(1),
34- perf_report(perf_report)
35+ perf_report(perf_report),
36+ protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()}
37 {
38 perf_report->name_surface(std::to_string(reinterpret_cast<long int>(this)).c_str());
39
40 create_wait_handle.expect_result();
41 try
42 {
43- server.create_buffer_stream(0, &parameters, &protobuf_bs, gp::NewCallback(this, &mcl::BufferStream::created, callback,
44+ server.create_buffer_stream(0, &parameters, protobuf_bs.get(), gp::NewCallback(this, &mcl::BufferStream::created, callback,
45 context));
46 }
47 catch (std::exception const& ex)
48 {
49- protobuf_bs.set_error(std::string{"Error invoking create buffer stream: "} +
50+ protobuf_bs->set_error(std::string{"Error invoking create buffer stream: "} +
51 boost::diagnostic_information(ex));
52 }
53
54@@ -141,16 +144,16 @@
55
56 void mcl::BufferStream::created(mir_buffer_stream_callback callback, void *context)
57 {
58- if (!protobuf_bs.has_id() || protobuf_bs.has_error())
59- BOOST_THROW_EXCEPTION(std::runtime_error("Can not create buffer stream: " + std::string(protobuf_bs.error())));
60- if (!protobuf_bs.has_buffer())
61+ if (!protobuf_bs->has_id() || protobuf_bs->has_error())
62+ BOOST_THROW_EXCEPTION(std::runtime_error("Can not create buffer stream: " + std::string(protobuf_bs->error())));
63+ if (!protobuf_bs->has_buffer())
64 BOOST_THROW_EXCEPTION(std::runtime_error("Buffer stream did not come with a buffer"));
65
66- process_buffer(protobuf_bs.buffer());
67+ process_buffer(protobuf_bs->buffer());
68 egl_native_window_ = client_platform->create_egl_native_window(this);
69
70 if (connection)
71- connection->on_stream_created(protobuf_bs.id().value(), this);
72+ connection->on_stream_created(protobuf_bs->id().value(), this);
73
74 if (callback)
75 callback(reinterpret_cast<MirBufferStream*>(this), context);
76@@ -180,7 +183,7 @@
77
78 try
79 {
80- auto pixel_format = static_cast<MirPixelFormat>(protobuf_bs.pixel_format());
81+ auto pixel_format = static_cast<MirPixelFormat>(protobuf_bs->pixel_format());
82 buffer_depository.deposit_package(buffer_package,
83 buffer.buffer_id(),
84 cached_buffer_size, pixel_format);
85@@ -199,40 +202,37 @@
86
87 secured_region.reset();
88
89- mir::protobuf::BufferStreamId buffer_stream_id;
90- buffer_stream_id.set_value(protobuf_bs.id().value());
91-
92-// TODO: We can fix the strange "ID casting" used below in the second phase
93-// of buffer stream which generalizes and clarifies the server side logic.
94+ // TODO: We can fix the strange "ID casting" used below in the second phase
95+ // of buffer stream which generalizes and clarifies the server side logic.
96 if (mode == mcl::BufferStreamMode::Producer)
97 {
98- mp::BufferRequest request;
99- request.mutable_id()->set_value(protobuf_bs.id().value());
100- request.mutable_buffer()->set_buffer_id(protobuf_bs.buffer().buffer_id());
101+ auto request = mcl::make_protobuf_object<mp::BufferRequest>();
102+ request->mutable_id()->set_value(protobuf_bs->id().value());
103+ request->mutable_buffer()->set_buffer_id(protobuf_bs->buffer().buffer_id());
104
105 lock.unlock();
106 next_buffer_wait_handle.expect_result();
107
108 display_server.exchange_buffer(
109 nullptr,
110- &request,
111- protobuf_bs.mutable_buffer(),
112+ request.get(),
113+ protobuf_bs->mutable_buffer(),
114 google::protobuf::NewCallback(
115 this, &mcl::BufferStream::next_buffer_received,
116 done));
117 }
118 else
119 {
120- mp::ScreencastId screencast_id;
121- screencast_id.set_value(protobuf_bs.id().value());
122+ auto screencast_id = mcl::make_protobuf_object<mp::ScreencastId>();
123+ screencast_id->set_value(protobuf_bs->id().value());
124
125 lock.unlock();
126 next_buffer_wait_handle.expect_result();
127
128 display_server.screencast_buffer(
129 nullptr,
130- &screencast_id,
131- protobuf_bs.mutable_buffer(),
132+ screencast_id.get(),
133+ protobuf_bs->mutable_buffer(),
134 google::protobuf::NewCallback(
135 this, &mcl::BufferStream::next_buffer_received,
136 done));
137@@ -270,7 +270,7 @@
138 void mcl::BufferStream::next_buffer_received(
139 std::function<void()> done)
140 {
141- process_buffer(protobuf_bs.buffer());
142+ process_buffer(protobuf_bs->buffer());
143
144 done();
145
146@@ -285,8 +285,8 @@
147 "",
148 cached_buffer_size.width.as_int(),
149 cached_buffer_size.height.as_int(),
150- static_cast<MirPixelFormat>(protobuf_bs.pixel_format()),
151- static_cast<MirBufferUsage>(protobuf_bs.buffer_usage()),
152+ static_cast<MirPixelFormat>(protobuf_bs->pixel_format()),
153+ static_cast<MirBufferUsage>(protobuf_bs->buffer_usage()),
154 mir_display_output_id_invalid};
155 }
156
157@@ -318,20 +318,21 @@
158 BOOST_THROW_EXCEPTION(std::logic_error("Attempt to set swap interval on screencast is invalid"));
159 }
160
161- mp::SurfaceSetting setting, result;
162- setting.mutable_surfaceid()->set_value(protobuf_bs.id().value());
163- setting.set_attrib(attrib);
164- setting.set_ivalue(value);
165+ auto setting = mcl::make_protobuf_object<mp::SurfaceSetting>();
166+ auto result = mcl::make_protobuf_object<mp::SurfaceSetting>();
167+ setting->mutable_surfaceid()->set_value(protobuf_bs->id().value());
168+ setting->set_attrib(attrib);
169+ setting->set_ivalue(value);
170 lock.unlock();
171
172 configure_wait_handle.expect_result();
173- display_server.configure_surface(0, &setting, &result,
174+ display_server.configure_surface(0, setting.get(), result.get(),
175 google::protobuf::NewCallback(this, &mcl::BufferStream::on_configured));
176
177 configure_wait_handle.wait_for_all();
178
179 lock.lock();
180- swap_interval_ = result.ivalue();
181+ swap_interval_ = result->ivalue();
182 }
183
184 uint32_t mcl::BufferStream::get_current_buffer_id()
185@@ -381,13 +382,13 @@
186 {
187 std::unique_lock<decltype(mutex)> lock(mutex);
188
189- return mf::BufferStreamId(protobuf_bs.id().value());
190+ return mf::BufferStreamId(protobuf_bs->id().value());
191 }
192
193 bool mcl::BufferStream::valid() const
194 {
195 std::unique_lock<decltype(mutex)> lock(mutex);
196- return protobuf_bs.has_id() && !protobuf_bs.has_error();
197+ return protobuf_bs->has_id() && !protobuf_bs->has_error();
198 }
199
200 void mcl::BufferStream::set_buffer_cache_size(unsigned int cache_size)
201
202=== modified file 'src/client/buffer_stream.h'
203--- src/client/buffer_stream.h 2015-06-03 19:17:55 +0000
204+++ src/client/buffer_stream.h 2015-06-16 23:39:42 +0000
205@@ -62,7 +62,7 @@
206 mir::protobuf::DisplayServer& server,
207 BufferStreamMode mode,
208 std::shared_ptr<ClientPlatform> const& native_window_factory,
209- protobuf::BufferStream const& protobuf_bs,
210+ mir::protobuf::BufferStream const& protobuf_bs,
211 std::shared_ptr<PerfReport> const& perf_report,
212 std::string const& surface_name);
213 // For surfaceless buffer streams
214@@ -124,7 +124,7 @@
215 BufferStreamMode const mode;
216 std::shared_ptr<ClientPlatform> const client_platform;
217
218- mir::protobuf::BufferStream protobuf_bs;
219+ std::unique_ptr<mir::protobuf::BufferStream> protobuf_bs;
220 mir::client::ClientBufferDepository buffer_depository;
221
222 int swap_interval_;
223@@ -137,7 +137,7 @@
224 MirWaitHandle release_wait_handle;
225 MirWaitHandle next_buffer_wait_handle;
226 MirWaitHandle configure_wait_handle;
227- mir::protobuf::Void protobuf_void;
228+ std::unique_ptr<mir::protobuf::Void> protobuf_void;
229
230 std::shared_ptr<MemoryRegion> secured_region;
231
232
233=== added file 'src/client/make_protobuf_object.h'
234--- src/client/make_protobuf_object.h 1970-01-01 00:00:00 +0000
235+++ src/client/make_protobuf_object.h 2015-06-16 23:39:42 +0000
236@@ -0,0 +1,42 @@
237+/*
238+ * Copyright © 2015 Canonical Ltd.
239+ *
240+ * This program is free software: you can redistribute it and/or modify it
241+ * under the terms of the GNU Lesser General Public License version 3,
242+ * as published by the Free Software Foundation.
243+ *
244+ * This program is distributed in the hope that it will be useful,
245+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
246+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
247+ * GNU Lesser General Public License for more details.
248+ *
249+ * You should have received a copy of the GNU Lesser General Public License
250+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
251+ *
252+ * Authored by: Alberto Aguirre <alberto.aguirre@canonical.com>
253+ */
254+
255+#ifndef MIR_CLIENT_MAKE_PROTOBUF_OBJECT_
256+#define MIR_CLIENT_MAKE_PROTOBUF_OBJECT_
257+
258+namespace mir
259+{
260+namespace client
261+{
262+template <typename ProtobufType>
263+auto make_protobuf_object()
264+{
265+ return std::unique_ptr<ProtobufType>{ProtobufType::default_instance().New()};
266+}
267+
268+template <typename ProtobufType>
269+auto make_protobuf_object(ProtobufType const& from)
270+{
271+ auto object = make_protobuf_object<ProtobufType>();
272+ object->CopyFrom(from);
273+ return object;
274+}
275+}
276+}
277+
278+#endif
279
280=== modified file 'src/client/mir_connection.cpp'
281--- src/client/mir_connection.cpp 2015-06-03 17:01:43 +0000
282+++ src/client/mir_connection.cpp 2015-06-16 23:39:42 +0000
283@@ -20,6 +20,7 @@
284 #include "mir_surface.h"
285 #include "mir_prompt_session.h"
286 #include "default_client_buffer_stream_factory.h"
287+#include "make_protobuf_object.h"
288 #include "mir_toolkit/mir_platform_message.h"
289 #include "mir/client_platform.h"
290 #include "mir/client_platform_factory.h"
291@@ -107,7 +108,13 @@
292 server(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
293 debug(channel.get(), ::google::protobuf::Service::STUB_DOESNT_OWN_CHANNEL),
294 logger(conf.the_logger()),
295+ void_response{mcl::make_protobuf_object<mir::protobuf::Void>()},
296+ connect_result{mcl::make_protobuf_object<mir::protobuf::Connection>()},
297 connect_done{false},
298+ ignored{mcl::make_protobuf_object<mir::protobuf::Void>()},
299+ connect_parameters{mcl::make_protobuf_object<mir::protobuf::ConnectParameters>()},
300+ platform_operation_reply{mcl::make_protobuf_object<mir::protobuf::PlatformOperationMessage>()},
301+ display_configuration_response{mcl::make_protobuf_object<mir::protobuf::DisplayConfiguration>()},
302 client_platform_factory(conf.the_client_platform_factory()),
303 input_platform(conf.the_input_platform()),
304 display_configuration(conf.the_display_configuration()),
305@@ -116,7 +123,7 @@
306 event_handler_register(conf.the_event_handler_register()),
307 eventloop{new md::ThreadedDispatcher{"RPC Thread", std::dynamic_pointer_cast<md::Dispatchable>(channel)}}
308 {
309- connect_result.set_error("connect not called");
310+ connect_result->set_error("connect not called");
311 {
312 std::lock_guard<std::mutex> lock(connection_guard);
313 next_valid = valid_connections;
314@@ -131,9 +138,9 @@
315 connect_wait_handle.wait_for_pending(std::chrono::milliseconds(500));
316
317 std::lock_guard<decltype(mutex)> lock(mutex);
318- if (connect_result.has_platform())
319+ if (connect_result && connect_result->has_platform())
320 {
321- auto const& platform = connect_result.platform();
322+ auto const& platform = connect_result->platform();
323 for (int i = 0, end = platform.fd_size(); i != end; ++i)
324 close(platform.fd(i));
325 }
326@@ -154,9 +161,9 @@
327 {
328 std::lock_guard<decltype(mutex)> lock(mutex);
329
330- if (connect_result.has_error())
331+ if (connect_result && connect_result->has_error())
332 {
333- return connect_result.error().c_str();
334+ return connect_result->error().c_str();
335 }
336
337 return error_message.c_str();
338@@ -220,8 +227,8 @@
339
340 SurfaceRelease surf_release{surface, new_wait_handle, callback, context};
341
342- mir::protobuf::SurfaceId message;
343- message.set_value(surface->id());
344+ auto message = mcl::make_protobuf_object<mir::protobuf::SurfaceId>();
345+ message->set_value(surface->id());
346
347 {
348 std::lock_guard<decltype(release_wait_handle_guard)> rel_lock(release_wait_handle_guard);
349@@ -229,7 +236,7 @@
350 }
351
352 new_wait_handle->expect_result();
353- server.release_surface(0, &message, &void_response,
354+ server.release_surface(0, message.get(), void_response.get(),
355 gp::NewCallback(this, &MirConnection::released, surf_release));
356
357
358@@ -248,9 +255,9 @@
359 {
360 std::lock_guard<decltype(mutex)> lock(mutex);
361
362- if (!connect_result.has_platform() || !connect_result.has_display_configuration())
363+ if (!connect_result->has_platform() || !connect_result->has_display_configuration())
364 {
365- if (!connect_result.has_error())
366+ if (!connect_result->has_error())
367 {
368 // We're handling an error scenario that means we're not sync'd
369 // with the client code - a callback isn't safe (or needed)
370@@ -283,12 +290,12 @@
371 buffer_stream_factory = std::make_shared<mcl::DefaultClientBufferStreamFactory>(
372 platform, the_logger());
373 native_display = platform->create_egl_native_display();
374- display_configuration->set_configuration(connect_result.display_configuration());
375+ display_configuration->set_configuration(connect_result->display_configuration());
376 lifecycle_control->set_lifecycle_event_handler(default_lifecycle_event_handler);
377 }
378 catch (std::exception const& e)
379 {
380- connect_result.set_error(std::string{"Failed to process connect response: "} +
381+ connect_result->set_error(std::string{"Failed to process connect response: "} +
382 boost::diagnostic_information(e));
383 }
384
385@@ -304,14 +311,14 @@
386 {
387 std::lock_guard<decltype(mutex)> lock(mutex);
388
389- connect_parameters.set_application_name(app_name);
390+ connect_parameters->set_application_name(app_name);
391 connect_wait_handle.expect_result();
392 }
393
394 server.connect(
395 0,
396- &connect_parameters,
397- &connect_result,
398+ connect_parameters.get(),
399+ connect_result.get(),
400 google::protobuf::NewCallback(
401 this, &MirConnection::connected, callback, context));
402 return &connect_wait_handle;
403@@ -339,7 +346,7 @@
404 disconnecting = true;
405 }
406 disconnect_wait_handle.expect_result();
407- server.disconnect(0, &ignored, &ignored,
408+ server.disconnect(0, ignored.get(), ignored.get(),
409 google::protobuf::NewCallback(this, &MirConnection::done_disconnect));
410
411 return &disconnect_wait_handle;
412@@ -348,19 +355,19 @@
413 void MirConnection::done_platform_operation(
414 mir_platform_operation_callback callback, void* context)
415 {
416- auto reply = mir_platform_message_create(platform_operation_reply.opcode());
417+ auto reply = mir_platform_message_create(platform_operation_reply->opcode());
418
419- set_error_message(platform_operation_reply.error());
420+ set_error_message(platform_operation_reply->error());
421
422 mir_platform_message_set_data(
423 reply,
424- platform_operation_reply.data().data(),
425- platform_operation_reply.data().size());
426+ platform_operation_reply->data().data(),
427+ platform_operation_reply->data().size());
428
429 mir_platform_message_set_fds(
430 reply,
431- platform_operation_reply.fd().data(),
432- platform_operation_reply.fd().size());
433+ platform_operation_reply->fd().data(),
434+ platform_operation_reply->fd().size());
435
436 callback(this, reply, context);
437
438@@ -379,21 +386,21 @@
439 return nullptr;
440 }
441
442- mir::protobuf::PlatformOperationMessage protobuf_request;
443+ auto protobuf_request = mcl::make_protobuf_object<mir::protobuf::PlatformOperationMessage>();
444
445- protobuf_request.set_opcode(mir_platform_message_get_opcode(request));
446+ protobuf_request->set_opcode(mir_platform_message_get_opcode(request));
447 auto const request_data = mir_platform_message_get_data(request);
448 auto const request_fds = mir_platform_message_get_fds(request);
449
450- protobuf_request.set_data(request_data.data, request_data.size);
451+ protobuf_request->set_data(request_data.data, request_data.size);
452 for (size_t i = 0; i != request_fds.num_fds; ++i)
453- protobuf_request.add_fd(request_fds.fds[i]);
454+ protobuf_request->add_fd(request_fds.fds[i]);
455
456 platform_operation_wait_handle.expect_result();
457 server.platform_operation(
458 0,
459- &protobuf_request,
460- &platform_operation_reply,
461+ protobuf_request.get(),
462+ platform_operation_reply.get(),
463 google::protobuf::NewCallback(this, &MirConnection::done_platform_operation,
464 callback, context));
465
466@@ -411,7 +418,7 @@
467 {
468 lock.unlock();
469 std::lock_guard<decltype(connection->mutex)> lock(connection->mutex);
470- return !connection->connect_result.has_error();
471+ return !connection->connect_result->has_error();
472 }
473 }
474 }
475@@ -427,9 +434,9 @@
476 {
477 // connect_result is write-once: once it's valid, we don't need to lock
478 // to use it.
479- if (connect_done && !connect_result.has_error() && connect_result.has_platform())
480+ if (connect_done && !connect_result->has_error() && connect_result->has_platform())
481 {
482- auto const& platform = connect_result.platform();
483+ auto const& platform = connect_result->platform();
484
485 platform_package.data_items = platform.data_size();
486 for (int i = 0; i != platform.data_size(); ++i)
487@@ -460,15 +467,15 @@
488 valid_formats = 0;
489
490 std::lock_guard<decltype(mutex)> lock(mutex);
491- if (!connect_result.has_error())
492+ if (!connect_result->has_error())
493 {
494 valid_formats = std::min(
495- static_cast<unsigned int>(connect_result.surface_pixel_format_size()),
496+ static_cast<unsigned int>(connect_result->surface_pixel_format_size()),
497 formats_size);
498
499 for (auto i = 0u; i < valid_formats; i++)
500 {
501- formats[i] = static_cast<MirPixelFormat>(connect_result.surface_pixel_format(i));
502+ formats[i] = static_cast<MirPixelFormat>(connect_result->surface_pixel_format(i));
503 }
504 }
505 }
506@@ -488,13 +495,13 @@
507 mir_buffer_stream_callback callback,
508 void *context)
509 {
510- mir::protobuf::BufferStreamParameters params;
511- params.set_width(width);
512- params.set_height(height);
513- params.set_pixel_format(format);
514- params.set_buffer_usage(buffer_usage);
515+ auto params = mcl::make_protobuf_object<mir::protobuf::BufferStreamParameters>();
516+ params->set_width(width);
517+ params->set_height(height);
518+ params->set_pixel_format(format);
519+ params->set_buffer_usage(buffer_usage);
520
521- return buffer_stream_factory->make_producer_stream(this, server, params, callback, context);
522+ return buffer_stream_factory->make_producer_stream(this, server, *params, callback, context);
523 }
524
525 std::shared_ptr<mir::client::ClientBufferStream> MirConnection::make_consumer_stream(
526@@ -559,10 +566,10 @@
527 {
528 std::lock_guard<decltype(mutex)> lock(mutex);
529
530- set_error_message(display_configuration_response.error());
531+ set_error_message(display_configuration_response->error());
532
533- if (!display_configuration_response.has_error())
534- display_configuration->set_configuration(display_configuration_response);
535+ if (!display_configuration_response->has_error())
536+ display_configuration->set_configuration(*display_configuration_response);
537
538 return configure_display_wait_handle.result_received();
539 }
540@@ -574,14 +581,14 @@
541 return NULL;
542 }
543
544- mir::protobuf::DisplayConfiguration request;
545+ auto request = mcl::make_protobuf_object<mir::protobuf::DisplayConfiguration>();
546 {
547 std::lock_guard<decltype(mutex)> lock(mutex);
548
549 for (auto i=0u; i < config->num_outputs; i++)
550 {
551 auto output = config->outputs[i];
552- auto display_request = request.add_display_output();
553+ auto display_request = request->add_display_output();
554 display_request->set_output_id(output.output_id);
555 display_request->set_used(output.used);
556 display_request->set_current_mode(output.current_mode);
557@@ -594,7 +601,7 @@
558 }
559
560 configure_display_wait_handle.expect_result();
561- server.configure_display(0, &request, &display_configuration_response,
562+ server.configure_display(0, request.get(), display_configuration_response.get(),
563 google::protobuf::NewCallback(this, &MirConnection::done_display_configure));
564
565 return &configure_display_wait_handle;
566@@ -619,8 +626,8 @@
567
568 StreamRelease stream_release{stream, new_wait_handle, callback, context};
569
570- mir::protobuf::BufferStreamId buffer_stream_id;
571- buffer_stream_id.set_value(stream->rpc_id().as_value());
572+ auto buffer_stream_id = mcl::make_protobuf_object<mir::protobuf::BufferStreamId>();
573+ buffer_stream_id->set_value(stream->rpc_id().as_value());
574
575 {
576 std::lock_guard<decltype(release_wait_handle_guard)> rel_lock(release_wait_handle_guard);
577@@ -629,7 +636,7 @@
578
579 new_wait_handle->expect_result();
580 server.release_buffer_stream(
581- nullptr, &buffer_stream_id, &void_response,
582+ nullptr, buffer_stream_id.get(), void_response.get(),
583 google::protobuf::NewCallback(this, &MirConnection::released, stream_release));
584 return new_wait_handle;
585 }
586
587=== modified file 'src/client/mir_connection.h'
588--- src/client/mir_connection.h 2015-06-03 17:01:43 +0000
589+++ src/client/mir_connection.h 2015-06-16 23:39:42 +0000
590@@ -35,6 +35,8 @@
591
592 #include "mir_wait_handle.h"
593
594+#include <memory>
595+
596 namespace mir
597 {
598 class SharedLibrary;
599@@ -172,13 +174,13 @@
600 mir::protobuf::DisplayServer::Stub server;
601 mir::protobuf::Debug::Stub debug;
602 std::shared_ptr<mir::logging::Logger> const logger;
603- mir::protobuf::Void void_response;
604- mir::protobuf::Connection connect_result;
605+ std::unique_ptr<mir::protobuf::Void> void_response;
606+ std::unique_ptr<mir::protobuf::Connection> connect_result;
607 std::atomic<bool> connect_done;
608- mir::protobuf::Void ignored;
609- mir::protobuf::ConnectParameters connect_parameters;
610- mir::protobuf::PlatformOperationMessage platform_operation_reply;
611- mir::protobuf::DisplayConfiguration display_configuration_response;
612+ std::unique_ptr<mir::protobuf::Void> ignored;
613+ std::unique_ptr<mir::protobuf::ConnectParameters> connect_parameters;
614+ std::unique_ptr<mir::protobuf::PlatformOperationMessage> platform_operation_reply;
615+ std::unique_ptr<mir::protobuf::DisplayConfiguration> display_configuration_response;
616 std::atomic<bool> disconnecting{false};
617
618 std::shared_ptr<mir::client::ClientPlatformFactory> const client_platform_factory;
619
620=== modified file 'src/client/mir_prompt_session.cpp'
621--- src/client/mir_prompt_session.cpp 2015-03-31 02:35:42 +0000
622+++ src/client/mir_prompt_session.cpp 2015-06-16 23:39:42 +0000
623@@ -18,6 +18,7 @@
624
625 #include "mir_prompt_session.h"
626 #include "event_handler_register.h"
627+#include "make_protobuf_object.h"
628
629 namespace mp = mir::protobuf;
630 namespace mcl = mir::client;
631@@ -26,6 +27,10 @@
632 mp::DisplayServer& server,
633 std::shared_ptr<mcl::EventHandlerRegister> const& event_handler_register) :
634 server(server),
635+ parameters(mcl::make_protobuf_object<mir::protobuf::PromptSessionParameters>()),
636+ add_result(mcl::make_protobuf_object<mir::protobuf::Void>()),
637+ protobuf_void(mcl::make_protobuf_object<mir::protobuf::Void>()),
638+ socket_fd_response(mcl::make_protobuf_object<mir::protobuf::SocketFD>()),
639 event_handler_register(event_handler_register),
640 event_handler_register_id{event_handler_register->register_event_handler(
641 [this](MirEvent const& event)
642@@ -34,6 +39,7 @@
643 set_state(mir_prompt_session_event_get_state(mir_event_get_prompt_session_event(&event)));
644 })},
645 state(mir_prompt_session_state_stopped),
646+ session(mcl::make_protobuf_object<mir::protobuf::Void>()),
647 handle_prompt_session_state_change{[](MirPromptSessionState){}}
648 {
649 }
650@@ -64,14 +70,14 @@
651 {
652 {
653 std::lock_guard<decltype(mutex)> lock(mutex);
654- parameters.set_application_pid(application_pid);
655+ parameters->set_application_pid(application_pid);
656 }
657
658 start_wait_handle.expect_result();
659 server.start_prompt_session(
660 0,
661- &parameters,
662- &session,
663+ parameters.get(),
664+ session.get(),
665 google::protobuf::NewCallback(this, &MirPromptSession::done_start,
666 callback, context));
667
668@@ -84,8 +90,8 @@
669
670 server.stop_prompt_session(
671 0,
672- &protobuf_void,
673- &protobuf_void,
674+ protobuf_void.get(),
675+ protobuf_void.get(),
676 google::protobuf::NewCallback(this, &MirPromptSession::done_stop,
677 callback, context));
678
679@@ -110,7 +116,7 @@
680 {
681 std::lock_guard<decltype(session_mutex)> lock(session_mutex);
682
683- state = session.has_error() ? mir_prompt_session_state_stopped : mir_prompt_session_state_started;
684+ state = session->has_error() ? mir_prompt_session_state_stopped : mir_prompt_session_state_started;
685 }
686
687 callback(this, context);
688@@ -129,10 +135,10 @@
689 {
690 std::lock_guard<decltype(session_mutex)> lock(session_mutex);
691
692- if (!session.has_error())
693- session.set_error(std::string{});
694+ if (!session->has_error())
695+ session->set_error(std::string{});
696
697- return session.error().c_str();
698+ return session->error().c_str();
699 }
700
701 MirWaitHandle* MirPromptSession::new_fds_for_prompt_providers(
702@@ -140,15 +146,15 @@
703 mir_client_fd_callback callback,
704 void * context)
705 {
706- mir::protobuf::SocketFDRequest request;
707- request.set_number(no_of_fds);
708+ auto request = mcl::make_protobuf_object<mir::protobuf::SocketFDRequest>();
709+ request->set_number(no_of_fds);
710
711 fds_for_prompt_providers_wait_handle.expect_result();
712
713 server.new_fds_for_prompt_providers(
714 nullptr,
715- &request,
716- &socket_fd_response,
717+ request.get(),
718+ socket_fd_response.get(),
719 google::protobuf::NewCallback(this, &MirPromptSession::done_fds_for_prompt_providers,
720 callback, context));
721
722@@ -159,13 +165,13 @@
723 mir_client_fd_callback callback,
724 void* context)
725 {
726- auto const size = socket_fd_response.fd_size();
727+ auto const size = socket_fd_response->fd_size();
728
729 std::vector<int> fds;
730 fds.reserve(size);
731
732 for (auto i = 0; i != size; ++i)
733- fds.push_back(socket_fd_response.fd(i));
734+ fds.push_back(socket_fd_response->fd(i));
735
736 callback(this, size, fds.data(), context);
737 fds_for_prompt_providers_wait_handle.result_received();
738
739=== modified file 'src/client/mir_prompt_session.h'
740--- src/client/mir_prompt_session.h 2015-01-21 07:34:50 +0000
741+++ src/client/mir_prompt_session.h 2015-06-16 23:39:42 +0000
742@@ -60,10 +60,10 @@
743 private:
744 std::mutex mutable mutex; // Protects parameters, wait_handles & results
745 mir::protobuf::DisplayServer& server;
746- mir::protobuf::PromptSessionParameters parameters;
747- mir::protobuf::Void add_result;
748- mir::protobuf::Void protobuf_void;
749- mir::protobuf::SocketFD socket_fd_response;
750+ std::unique_ptr<mir::protobuf::PromptSessionParameters> parameters;
751+ std::unique_ptr<mir::protobuf::Void> add_result;
752+ std::unique_ptr<mir::protobuf::Void> protobuf_void;
753+ std::unique_ptr<mir::protobuf::SocketFD> socket_fd_response;
754 std::shared_ptr<mir::client::EventHandlerRegister> const event_handler_register;
755 int const event_handler_register_id;
756
757@@ -73,7 +73,7 @@
758 std::atomic<MirPromptSessionState> state;
759
760 std::mutex mutable session_mutex; // Protects session
761- mir::protobuf::Void session;
762+ std::unique_ptr<mir::protobuf::Void> session;
763
764 std::mutex mutable event_handler_mutex; // Need another mutex for callback access to members
765 std::function<void(MirPromptSessionState)> handle_prompt_session_state_change;
766
767=== modified file 'src/client/mir_screencast.cpp'
768--- src/client/mir_screencast.cpp 2015-06-03 17:35:29 +0000
769+++ src/client/mir_screencast.cpp 2015-06-16 23:39:42 +0000
770@@ -18,6 +18,7 @@
771
772 #include "mir_screencast.h"
773 #include "mir_connection.h"
774+#include "make_protobuf_object.h"
775 #include "client_buffer_stream.h"
776 #include "mir/frontend/client_constants.h"
777 #include "mir_toolkit/mir_native_buffer.h"
778@@ -38,7 +39,9 @@
779 mir_screencast_callback callback, void* context)
780 : server(server),
781 connection{connection},
782- output_size{size}
783+ output_size{size},
784+ protobuf_screencast{mcl::make_protobuf_object<mir::protobuf::Screencast>()},
785+ protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()}
786 {
787 if (output_size.width.as_int() == 0 ||
788 output_size.height.as_int() == 0 ||
789@@ -48,23 +51,23 @@
790 {
791 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid parameters"));
792 }
793- protobuf_screencast.set_error("Not initialized");
794-
795- mir::protobuf::ScreencastParameters parameters;
796-
797- parameters.mutable_region()->set_left(region.top_left.x.as_int());
798- parameters.mutable_region()->set_top(region.top_left.y.as_int());
799- parameters.mutable_region()->set_width(region.size.width.as_uint32_t());
800- parameters.mutable_region()->set_height(region.size.height.as_uint32_t());
801- parameters.set_width(output_size.width.as_uint32_t());
802- parameters.set_height(output_size.height.as_uint32_t());
803- parameters.set_pixel_format(pixel_format);
804+ protobuf_screencast->set_error("Not initialized");
805+
806+ auto parameters = mcl::make_protobuf_object<mir::protobuf::ScreencastParameters>();
807+
808+ parameters->mutable_region()->set_left(region.top_left.x.as_int());
809+ parameters->mutable_region()->set_top(region.top_left.y.as_int());
810+ parameters->mutable_region()->set_width(region.size.width.as_uint32_t());
811+ parameters->mutable_region()->set_height(region.size.height.as_uint32_t());
812+ parameters->set_width(output_size.width.as_uint32_t());
813+ parameters->set_height(output_size.height.as_uint32_t());
814+ parameters->set_pixel_format(pixel_format);
815
816 create_screencast_wait_handle.expect_result();
817 server.create_screencast(
818 nullptr,
819- &parameters,
820- &protobuf_screencast,
821+ parameters.get(),
822+ protobuf_screencast.get(),
823 google::protobuf::NewCallback(
824 this, &MirScreencast::screencast_created,
825 callback, context));
826@@ -77,20 +80,20 @@
827
828 bool MirScreencast::valid()
829 {
830- return !protobuf_screencast.has_error();
831+ return !protobuf_screencast->has_error();
832 }
833
834 MirWaitHandle* MirScreencast::release(
835 mir_screencast_callback callback, void* context)
836 {
837- mir::protobuf::ScreencastId screencast_id;
838- screencast_id.set_value(protobuf_screencast.screencast_id().value());
839+ auto screencast_id = mcl::make_protobuf_object<mir::protobuf::ScreencastId>();
840+ screencast_id->set_value(protobuf_screencast->screencast_id().value());
841
842 release_wait_handle.expect_result();
843 server.release_screencast(
844 nullptr,
845- &screencast_id,
846- &protobuf_void,
847+ screencast_id.get(),
848+ protobuf_void.get(),
849 google::protobuf::NewCallback(
850 this, &MirScreencast::released, callback, context));
851
852@@ -104,10 +107,10 @@
853 void MirScreencast::screencast_created(
854 mir_screencast_callback callback, void* context)
855 {
856- if (!protobuf_screencast.has_error() && connection)
857+ if (!protobuf_screencast->has_error() && connection)
858 {
859 buffer_stream = connection->make_consumer_stream(
860- protobuf_screencast.buffer_stream(), "MirScreencast");
861+ protobuf_screencast->buffer_stream(), "MirScreencast");
862 }
863
864 callback(this, context);
865
866=== modified file 'src/client/mir_screencast.h'
867--- src/client/mir_screencast.h 2015-06-03 17:35:29 +0000
868+++ src/client/mir_screencast.h 2015-06-16 23:39:42 +0000
869@@ -27,6 +27,8 @@
870
871 #include <EGL/eglplatform.h>
872
873+#include <memory>
874+
875 namespace mir
876 {
877 namespace protobuf { class DisplayServer; }
878@@ -71,8 +73,8 @@
879 mir::geometry::Size const output_size;
880 std::shared_ptr<mir::client::ClientBufferStream> buffer_stream;
881
882- mir::protobuf::Screencast protobuf_screencast;
883- mir::protobuf::Void protobuf_void;
884+ std::unique_ptr<mir::protobuf::Screencast> protobuf_screencast;
885+ std::unique_ptr<mir::protobuf::Void> protobuf_void;
886
887 MirWaitHandle create_screencast_wait_handle;
888 MirWaitHandle release_wait_handle;
889
890=== modified file 'src/client/mir_surface.cpp'
891--- src/client/mir_surface.cpp 2015-06-16 12:18:54 +0000
892+++ src/client/mir_surface.cpp 2015-06-16 23:39:42 +0000
893@@ -16,12 +16,13 @@
894 * Authored by: Thomas Guest <thomas.guest@canonical.com>
895 */
896
897+#include "mir_surface.h"
898+#include "cursor_configuration.h"
899+#include "client_buffer_stream_factory.h"
900+#include "make_protobuf_object.h"
901 #include "mir_toolkit/mir_client_library.h"
902 #include "mir/frontend/client_constants.h"
903 #include "mir/client_buffer.h"
904-#include "mir_surface.h"
905-#include "cursor_configuration.h"
906-#include "client_buffer_stream_factory.h"
907 #include "mir_connection.h"
908 #include "client_buffer_stream.h"
909 #include "mir/dispatch/threaded_dispatcher.h"
910@@ -42,7 +43,7 @@
911
912 #define SERIALIZE_OPTION_IF_SET(option, message) \
913 if (option.is_set()) \
914- message.set_##option(option.value());
915+ message->set_##option(option.value());
916
917 namespace
918 {
919@@ -79,9 +80,10 @@
920 {
921 }
922
923-mir::protobuf::SurfaceParameters MirSurfaceSpec::serialize() const
924+std::unique_ptr<mir::protobuf::SurfaceParameters> MirSurfaceSpec::serialize() const
925 {
926- mir::protobuf::SurfaceParameters message;
927+ //std::unique_ptr<mp::SurfaceParameters> message{mp::SurfaceParameters::default_instance().New()};
928+ auto message = mcl::make_protobuf_object<mp::SurfaceParameters>();
929
930 SERIALIZE_OPTION_IF_SET(width, message);
931 SERIALIZE_OPTION_IF_SET(height, message);
932@@ -103,26 +105,26 @@
933 // max_aspect is a special case (below)
934
935 if (parent.is_set() && parent.value() != nullptr)
936- message.set_parent_id(parent.value()->id());
937+ message->set_parent_id(parent.value()->id());
938
939 if (aux_rect.is_set())
940 {
941- message.mutable_aux_rect()->set_left(aux_rect.value().left);
942- message.mutable_aux_rect()->set_top(aux_rect.value().top);
943- message.mutable_aux_rect()->set_width(aux_rect.value().width);
944- message.mutable_aux_rect()->set_height(aux_rect.value().height);
945+ message->mutable_aux_rect()->set_left(aux_rect.value().left);
946+ message->mutable_aux_rect()->set_top(aux_rect.value().top);
947+ message->mutable_aux_rect()->set_width(aux_rect.value().width);
948+ message->mutable_aux_rect()->set_height(aux_rect.value().height);
949 }
950
951 if (min_aspect.is_set())
952 {
953- message.mutable_min_aspect()->set_width(min_aspect.value().width);
954- message.mutable_min_aspect()->set_height(min_aspect.value().height);
955+ message->mutable_min_aspect()->set_width(min_aspect.value().width);
956+ message->mutable_min_aspect()->set_height(min_aspect.value().height);
957 }
958
959 if (max_aspect.is_set())
960 {
961- message.mutable_max_aspect()->set_width(max_aspect.value().width);
962- message.mutable_max_aspect()->set_height(max_aspect.value().height);
963+ message->mutable_max_aspect()->set_width(max_aspect.value().width);
964+ message->mutable_max_aspect()->set_height(max_aspect.value().height);
965 }
966
967 return message;
968@@ -139,8 +141,9 @@
969 }
970
971 MirSurface::MirSurface(std::string const& error)
972+ : surface{mcl::make_protobuf_object<mir::protobuf::Surface>()}
973 {
974- surface.set_error(error);
975+ surface->set_error(error);
976
977 std::lock_guard<decltype(handle_mutex)> lock(handle_mutex);
978 valid_surfaces.insert(this);
979@@ -156,11 +159,16 @@
980 mir_surface_callback callback, void * context)
981 : server{&the_server},
982 debug{debug},
983+ surface{mcl::make_protobuf_object<mir::protobuf::Surface>()},
984+ persistent_id{mcl::make_protobuf_object<mir::protobuf::PersistentSurfaceId>()},
985 name{spec.surface_name.is_set() ? spec.surface_name.value() : ""},
986+ void_response{mcl::make_protobuf_object<mir::protobuf::Void>()},
987+ modify_result{mcl::make_protobuf_object<mir::protobuf::Void>()},
988 connection(allocating_connection),
989 buffer_stream_factory(buffer_stream_factory),
990 input_platform(input_platform),
991- keymapper(std::make_shared<mircv::XKBMapper>())
992+ keymapper(std::make_shared<mircv::XKBMapper>()),
993+ configure_result{mcl::make_protobuf_object<mir::protobuf::SurfaceSetting>()}
994 {
995 for (int i = 0; i < mir_surface_attribs; i++)
996 attrib_cache[i] = -1;
997@@ -169,11 +177,11 @@
998 create_wait_handle.expect_result();
999 try
1000 {
1001- server->create_surface(0, &message, &surface, gp::NewCallback(this, &MirSurface::created, callback, context));
1002+ server->create_surface(0, message.get(), surface.get(), gp::NewCallback(this, &MirSurface::created, callback, context));
1003 }
1004 catch (std::exception const& ex)
1005 {
1006- surface.set_error(std::string{"Error invoking create surface: "} +
1007+ surface->set_error(std::string{"Error invoking create surface: "} +
1008 boost::diagnostic_information(ex));
1009 }
1010
1011@@ -192,8 +200,8 @@
1012
1013 input_thread.reset();
1014
1015- for (auto i = 0, end = surface.fd_size(); i != end; ++i)
1016- close(surface.fd(i));
1017+ for (auto i = 0, end = surface->fd_size(); i != end; ++i)
1018+ close(surface->fd(i));
1019 }
1020
1021 MirSurfaceParameters MirSurface::get_parameters() const
1022@@ -207,9 +215,9 @@
1023 {
1024 std::lock_guard<decltype(mutex)> lock(mutex);
1025
1026- if (surface.has_error())
1027+ if (surface->has_error())
1028 {
1029- return surface.error().c_str();
1030+ return surface->error().c_str();
1031 }
1032 return error_message.c_str();
1033 }
1034@@ -218,7 +226,7 @@
1035 {
1036 std::lock_guard<decltype(mutex)> lock(mutex);
1037
1038- return surface.id().value();
1039+ return surface->id().value();
1040 }
1041
1042 bool MirSurface::is_valid(MirSurface* query)
1043@@ -226,16 +234,16 @@
1044 std::lock_guard<decltype(handle_mutex)> lock(handle_mutex);
1045
1046 if (valid_surfaces.count(query))
1047- return !query->surface.has_error();
1048+ return !query->surface->has_error();
1049
1050 return false;
1051 }
1052
1053 void MirSurface::acquired_persistent_id(mir_surface_id_callback callback, void* context)
1054 {
1055- if (!persistent_id.has_error())
1056+ if (!persistent_id->has_error())
1057 {
1058- callback(this, new MirPersistentId{persistent_id.value()}, context);
1059+ callback(this, new MirPersistentId{persistent_id->value()}, context);
1060 }
1061 else
1062 {
1063@@ -248,20 +256,20 @@
1064 {
1065 std::lock_guard<decltype(mutex)> lock{mutex};
1066
1067- if (persistent_id.has_value())
1068+ if (persistent_id->has_value())
1069 {
1070- callback(this, new MirPersistentId{persistent_id.value()}, context);
1071+ callback(this, new MirPersistentId{persistent_id->value()}, context);
1072 return nullptr;
1073 }
1074
1075 persistent_id_wait_handle.expect_result();
1076 try
1077 {
1078- server->request_persistent_surface_id(0, &surface.id(), &persistent_id, gp::NewCallback(this, &MirSurface::acquired_persistent_id, callback, context));
1079+ server->request_persistent_surface_id(0, &surface->id(), persistent_id.get(), gp::NewCallback(this, &MirSurface::acquired_persistent_id, callback, context));
1080 }
1081 catch (std::exception const& ex)
1082 {
1083- surface.set_error(std::string{"Failed to acquire a persistent ID from the server: "} +
1084+ surface->set_error(std::string{"Failed to acquire a persistent ID from the server: "} +
1085 boost::diagnostic_information(ex));
1086 }
1087 return &persistent_id_wait_handle;
1088@@ -283,10 +291,10 @@
1089 {
1090 {
1091 std::lock_guard<decltype(mutex)> lock(mutex);
1092- if (!surface.has_id())
1093+ if (!surface->has_id())
1094 {
1095- if (!surface.has_error())
1096- surface.set_error("Error processing surface create response, no ID (disconnected?)");
1097+ if (!surface->has_error())
1098+ surface->set_error("Error processing surface create response, no ID (disconnected?)");
1099
1100 callback(this, context);
1101 create_wait_handle.result_received();
1102@@ -299,11 +307,11 @@
1103 std::lock_guard<decltype(mutex)> lock(mutex);
1104
1105 buffer_stream = buffer_stream_factory->
1106- make_producer_stream(connection, *server, surface.buffer_stream(), name);
1107+ make_producer_stream(connection, *server, surface->buffer_stream(), name);
1108
1109- for(int i = 0; i < surface.attributes_size(); i++)
1110+ for(int i = 0; i < surface->attributes_size(); i++)
1111 {
1112- auto const& attrib = surface.attributes(i);
1113+ auto const& attrib = surface->attributes(i);
1114 attrib_cache[attrib.attrib()] = attrib.ivalue();
1115 }
1116 }
1117@@ -312,7 +320,7 @@
1118 }
1119 catch (std::exception const& error)
1120 {
1121- surface.set_error(std::string{"Error processing Surface creating response:"} +
1122+ surface->set_error(std::string{"Error processing Surface creating response:"} +
1123 boost::diagnostic_information(error));
1124 }
1125
1126@@ -331,7 +339,7 @@
1127 was_valid = true;
1128 valid_surfaces.erase(this);
1129 }
1130- if (this->surface.has_error())
1131+ if (this->surface->has_error())
1132 was_valid = false;
1133
1134 MirWaitHandle* wait_handle{nullptr};
1135@@ -350,29 +358,28 @@
1136
1137 MirWaitHandle* MirSurface::configure_cursor(MirCursorConfiguration const* cursor)
1138 {
1139- mp::CursorSetting setting;
1140+ auto setting = mcl::make_protobuf_object<mp::CursorSetting>();
1141
1142 {
1143 std::unique_lock<decltype(mutex)> lock(mutex);
1144- setting.mutable_surfaceid()->CopyFrom(surface.id());
1145+ setting->mutable_surfaceid()->CopyFrom(surface->id());
1146 if (cursor)
1147 {
1148 if (cursor->stream != nullptr)
1149 {
1150- setting.mutable_buffer_stream()->set_value(cursor->stream->rpc_id().as_value());
1151- setting.set_hotspot_x(cursor->hotspot_x);
1152- setting.set_hotspot_y(cursor->hotspot_y);
1153+ setting->mutable_buffer_stream()->set_value(cursor->stream->rpc_id().as_value());
1154+ setting->set_hotspot_x(cursor->hotspot_x);
1155+ setting->set_hotspot_y(cursor->hotspot_y);
1156 }
1157 else if (cursor->name != mir_disabled_cursor_name)
1158 {
1159- setting.set_name(cursor->name.c_str());
1160+ setting->set_name(cursor->name.c_str());
1161 }
1162-
1163 }
1164 }
1165
1166 configure_cursor_wait_handle.expect_result();
1167- server->configure_cursor(0, &setting, &void_response,
1168+ server->configure_cursor(0, setting.get(), void_response.get(),
1169 google::protobuf::NewCallback(this, &MirSurface::on_cursor_configured));
1170
1171 return &configure_cursor_wait_handle;
1172@@ -392,14 +399,14 @@
1173
1174 std::unique_lock<decltype(mutex)> lock(mutex);
1175
1176- mp::SurfaceSetting setting;
1177- setting.mutable_surfaceid()->CopyFrom(surface.id());
1178- setting.set_attrib(at);
1179- setting.set_ivalue(value);
1180+ auto setting = mcl::make_protobuf_object<mp::SurfaceSetting>();
1181+ setting->mutable_surfaceid()->CopyFrom(surface->id());
1182+ setting->set_attrib(at);
1183+ setting->set_ivalue(value);
1184 lock.unlock();
1185
1186 configure_wait_handle.expect_result();
1187- server->configure_surface(0, &setting, &configure_result,
1188+ server->configure_surface(0, setting.get(), configure_result.get(),
1189 google::protobuf::NewCallback(this, &MirSurface::on_configured));
1190
1191 return &configure_wait_handle;
1192@@ -421,12 +428,12 @@
1193 return false;
1194 }
1195
1196- mp::CoordinateTranslationRequest request;
1197+ auto request = mcl::make_protobuf_object<mp::CoordinateTranslationRequest>();
1198
1199- request.set_x(x);
1200- request.set_y(y);
1201- *request.mutable_surfaceid() = surface.id();
1202- mp::CoordinateTranslationResponse response;
1203+ request->set_x(x);
1204+ request->set_y(y);
1205+ *request->mutable_surfaceid() = surface->id();
1206+ auto response = mcl::make_protobuf_object<mp::CoordinateTranslationResponse>();
1207
1208 MirWaitHandle signal;
1209 signal.expect_result();
1210@@ -436,27 +443,27 @@
1211
1212 debug->translate_surface_to_screen(
1213 nullptr,
1214- &request,
1215- &response,
1216+ request.get(),
1217+ response.get(),
1218 google::protobuf::NewCallback(&signal_response_received, &signal));
1219 }
1220
1221 signal.wait_for_one();
1222
1223- *screen_x = response.x();
1224- *screen_y = response.y();
1225- return !response.has_error();
1226+ *screen_x = response->x();
1227+ *screen_y = response->y();
1228+ return !response->has_error();
1229 }
1230
1231 void MirSurface::on_configured()
1232 {
1233 std::lock_guard<decltype(mutex)> lock(mutex);
1234
1235- if (configure_result.has_surfaceid() &&
1236- configure_result.surfaceid().value() == surface.id().value() &&
1237- configure_result.has_attrib())
1238+ if (configure_result->has_surfaceid() &&
1239+ configure_result->surfaceid().value() == surface->id().value() &&
1240+ configure_result->has_attrib())
1241 {
1242- int a = configure_result.attrib();
1243+ int a = configure_result->attrib();
1244
1245 switch (a)
1246 {
1247@@ -465,10 +472,10 @@
1248 case mir_surface_attrib_focus:
1249 case mir_surface_attrib_dpi:
1250 case mir_surface_attrib_preferred_orientation:
1251- if (configure_result.has_ivalue())
1252- attrib_cache[a] = configure_result.ivalue();
1253+ if (configure_result->has_ivalue())
1254+ attrib_cache[a] = configure_result->ivalue();
1255 else
1256- assert(configure_result.has_error());
1257+ assert(configure_result->has_error());
1258 break;
1259 default:
1260 assert(false);
1261@@ -513,9 +520,9 @@
1262 std::placeholders::_1,
1263 context);
1264
1265- if (surface.fd_size() > 0 && handle_event_callback)
1266+ if (surface->fd_size() > 0 && handle_event_callback)
1267 {
1268- auto input_dispatcher = input_platform->create_input_receiver(surface.fd(0),
1269+ auto input_dispatcher = input_platform->create_input_receiver(surface->fd(0),
1270 keymapper,
1271 handle_event_callback);
1272 input_thread = std::make_shared<md::ThreadedDispatcher>("Input dispatch", input_dispatcher);
1273@@ -587,7 +594,7 @@
1274 {
1275 {
1276 std::lock_guard<decltype(mutex)> lock(mutex);
1277- if (modify_result.has_error())
1278+ if (modify_result->has_error())
1279 {
1280 // TODO return errors like lp:~vanvugt/mir/wait-result
1281 }
1282@@ -597,14 +604,14 @@
1283
1284 MirWaitHandle* MirSurface::modify(MirSurfaceSpec const& spec)
1285 {
1286- mp::SurfaceModifications mods;
1287+ auto mods = mcl::make_protobuf_object<mp::SurfaceModifications>();
1288
1289 {
1290 std::unique_lock<decltype(mutex)> lock(mutex);
1291- mods.mutable_surface_id()->set_value(surface.id().value());
1292+ mods->mutable_surface_id()->set_value(surface->id().value());
1293 }
1294
1295- auto const surface_specification = mods.mutable_surface_specification();
1296+ auto const surface_specification = mods->mutable_surface_specification();
1297
1298 #define COPY_IF_SET(field)\
1299 if (spec.field.is_set())\
1300@@ -678,7 +685,7 @@
1301 }
1302
1303 modify_wait_handle.expect_result();
1304- server->modify_surface(0, &mods, &modify_result,
1305+ server->modify_surface(0, mods.get(), modify_result.get(),
1306 google::protobuf::NewCallback(this, &MirSurface::on_modified));
1307
1308 return &modify_wait_handle;
1309
1310=== modified file 'src/client/mir_surface.h'
1311--- src/client/mir_surface.h 2015-06-10 12:01:33 +0000
1312+++ src/client/mir_surface.h 2015-06-16 23:39:42 +0000
1313@@ -65,7 +65,7 @@
1314 MirSurfaceSpec(MirConnection* connection, int width, int height, MirPixelFormat format);
1315 MirSurfaceSpec(MirConnection* connection, MirSurfaceParameters const& params);
1316
1317- mir::protobuf::SurfaceParameters serialize() const;
1318+ std::unique_ptr<mir::protobuf::SurfaceParameters> serialize() const;
1319
1320 struct AspectRatio { unsigned width; unsigned height; };
1321
1322@@ -178,16 +178,15 @@
1323
1324 mir::protobuf::DisplayServer::Stub* server{nullptr};
1325 mir::protobuf::Debug::Stub* debug{nullptr};
1326- mir::protobuf::Surface surface;
1327- mir::protobuf::BufferRequest buffer_request;
1328- mir::protobuf::PersistentSurfaceId persistent_id;
1329+ std::unique_ptr<mir::protobuf::Surface> surface;
1330+ std::unique_ptr<mir::protobuf::PersistentSurfaceId> persistent_id;
1331 std::string error_message;
1332 std::string name;
1333- mir::protobuf::Void void_response;
1334+ std::unique_ptr<mir::protobuf::Void> void_response;
1335
1336 void on_modified();
1337 MirWaitHandle modify_wait_handle;
1338- mir::protobuf::Void modify_result;
1339+ std::unique_ptr<mir::protobuf::Void> modify_result;
1340
1341 MirConnection* const connection{nullptr};
1342
1343@@ -201,7 +200,7 @@
1344 std::shared_ptr<mir::input::receiver::InputPlatform> const input_platform;
1345 std::shared_ptr<mir::input::receiver::XKBMapper> const keymapper;
1346
1347- mir::protobuf::SurfaceSetting configure_result;
1348+ std::unique_ptr<mir::protobuf::SurfaceSetting> configure_result;
1349
1350 // Cache of latest SurfaceSettings returned from the server
1351 int attrib_cache[mir_surface_attribs];
1352
1353=== modified file 'src/client/rpc/mir_protobuf_rpc_channel.cpp'
1354--- src/client/rpc/mir_protobuf_rpc_channel.cpp 2015-06-03 17:16:04 +0000
1355+++ src/client/rpc/mir_protobuf_rpc_channel.cpp 2015-06-16 23:39:42 +0000
1356@@ -25,6 +25,7 @@
1357 #include "../display_configuration.h"
1358 #include "../lifecycle_control.h"
1359 #include "../event_sink.h"
1360+#include "../make_protobuf_object.h"
1361 #include "mir/variable_length_array.h"
1362 #include "mir/events/event_private.h"
1363
1364@@ -236,24 +237,24 @@
1365
1366 void mclr::MirProtobufRpcChannel::process_event_sequence(std::string const& event)
1367 {
1368- mir::protobuf::EventSequence seq;
1369-
1370- seq.ParseFromString(event);
1371-
1372- if (seq.has_display_configuration())
1373- {
1374- display_configuration->update_configuration(seq.display_configuration());
1375- }
1376-
1377- if (seq.has_lifecycle_event())
1378- {
1379- lifecycle_control->call_lifecycle_event_handler(seq.lifecycle_event().new_state());
1380- }
1381-
1382- int const nevents = seq.event_size();
1383+ auto seq = mcl::make_protobuf_object<mir::protobuf::EventSequence>();
1384+
1385+ seq->ParseFromString(event);
1386+
1387+ if (seq->has_display_configuration())
1388+ {
1389+ display_configuration->update_configuration(seq->display_configuration());
1390+ }
1391+
1392+ if (seq->has_lifecycle_event())
1393+ {
1394+ lifecycle_control->call_lifecycle_event_handler(seq->lifecycle_event().new_state());
1395+ }
1396+
1397+ int const nevents = seq->event_size();
1398 for (int i = 0; i != nevents; ++i)
1399 {
1400- mir::protobuf::Event const& event = seq.event(i);
1401+ mir::protobuf::Event const& event = seq->event(i);
1402 if (event.has_raw())
1403 {
1404 std::string const& raw_event = event.raw();
1405@@ -320,7 +321,7 @@
1406 */
1407 std::lock_guard<decltype(read_mutex)> lock(read_mutex);
1408
1409- auto result = std::make_unique<mir::protobuf::wire::Result>();
1410+ auto result = mcl::make_protobuf_object<mir::protobuf::wire::Result>();
1411 try
1412 {
1413 uint16_t message_size;

Subscribers

People subscribed via source and target branches