1bb367a9ac70a68f965e3b36fabd9448ac83e3f8
[src/agl-compositor.git] / grpc-proxy / grpc-async-cb.cpp
1 /*
2  * Copyright © 2022 Collabora, Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include <cstdio>
27 #include <ctime>
28 #include <algorithm>
29 #include <queue>
30
31 #define GRPC_CALLBACK_API_NONEXPERIMENTAL
32
33 #include <grpc/grpc.h>
34 #include <grpcpp/grpcpp.h>
35 #include <grpcpp/server.h>
36 #include <grpcpp/server_builder.h>
37 #include <grpcpp/server_context.h>
38
39 #include <grpcpp/ext/proto_server_reflection_plugin.h>
40 #include <grpcpp/health_check_service_interface.h>
41
42 #include "log.h"
43 #include "agl_shell.grpc.pb.h"
44 #include "grpc-async-cb.h"
45
46 Lister::Lister(Shell *shell) : m_shell(shell)
47 {
48         // don't call NextWrite() just yet we do it explicitly when getting
49         // the events from the compositor
50         m_writting = false;
51 }
52
53 void
54 Lister::OnDone()
55 {
56         delete this;
57 }
58
59 void Lister::OnWriteDone(bool ok)
60 {
61         LOG("got ok %d\n", ok);
62         if (ok) {
63                 LOG("done writting %d\n", m_writting);
64                 m_writting = false;
65         }
66 }
67
68 void
69 Lister::NextWrite(void)
70 {
71         if (m_writting) {
72                 LOG(">>>>> still in writting\n");
73                 return;
74         }
75         m_writting = true;
76         StartWrite(&m_shell->m_shell_data->current_app_state);
77 }
78
79 bool
80 Lister::Writting(void)
81 {
82         return m_writting;
83 }
84
85 grpc::ServerUnaryReactor *
86 GrpcServiceImpl::ActivateApp(grpc::CallbackServerContext *context,
87                             const ::agl_shell_ipc::ActivateRequest* request,
88                             ::agl_shell_ipc::ActivateResponse* /*response*/)
89 {
90         LOG("activating app %s on output %s\n", request->app_id().c_str(),
91                                                 request->output_name().c_str());
92
93         m_aglShell->ActivateApp(request->app_id(), request->output_name());
94
95         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
96         reactor->Finish(grpc::Status::OK);
97         return reactor;
98 }
99
100 grpc::ServerUnaryReactor *
101 GrpcServiceImpl::DeactivateApp(grpc::CallbackServerContext *context,
102                               const ::agl_shell_ipc::DeactivateRequest* request,
103                               ::agl_shell_ipc::DeactivateResponse* /*response*/)
104 {
105         m_aglShell->DeactivateApp(request->app_id());
106
107         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
108         reactor->Finish(grpc::Status::OK);
109         return reactor;
110 }
111
112 grpc::ServerUnaryReactor *
113 GrpcServiceImpl::SetAppFloat(grpc::CallbackServerContext *context,
114                             const ::agl_shell_ipc::FloatRequest* request,
115                             ::agl_shell_ipc::FloatResponse* /* response */)
116 {
117         m_aglShell->SetAppFloat(request->app_id(),
118                                 request->x_pos(), request->y_pos());
119
120         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
121         reactor->Finish(grpc::Status::OK);
122         return reactor;
123 }
124
125 grpc::ServerUnaryReactor *
126 GrpcServiceImpl::SetAppNormal(grpc::CallbackServerContext *context,
127                             const ::agl_shell_ipc::NormalRequest* request,
128                             ::agl_shell_ipc::NormalResponse* /* response */)
129 {
130         m_aglShell->SetAppNormal(request->app_id());
131
132         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
133         reactor->Finish(grpc::Status::OK);
134         return reactor;
135 }
136
137 grpc::ServerUnaryReactor *
138 GrpcServiceImpl::SetAppFullscreen(grpc::CallbackServerContext *context,
139                             const ::agl_shell_ipc::FullscreenRequest* request,
140                             ::agl_shell_ipc::FullscreenResponse* /* response */)
141 {
142         m_aglShell->SetAppFullscreen(request->app_id());
143
144         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
145         reactor->Finish(grpc::Status::OK);
146         return reactor;
147 }
148
149 grpc::ServerUnaryReactor *
150 GrpcServiceImpl::SetAppOnOutput(grpc::CallbackServerContext *context,
151                             const ::agl_shell_ipc::AppOnOutputRequest* request,
152                             ::agl_shell_ipc::AppOnOutputResponse* /* response */)
153 {
154         m_aglShell->SetAppOnOutput(request->app_id(), request->output());
155
156         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
157         reactor->Finish(grpc::Status::OK);
158         return reactor;
159 }
160
161 grpc::ServerUnaryReactor *
162 GrpcServiceImpl::SetAppSplit(grpc::CallbackServerContext *context,
163            const ::agl_shell_ipc::SplitRequest* request,
164            ::agl_shell_ipc::SplitResponse* /*response*/)
165 {
166         m_aglShell->SetAppSplit(request->app_id(), request->tile_orientation());
167
168         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
169         reactor->Finish(grpc::Status::OK);
170         return reactor;
171 }
172
173 grpc::ServerUnaryReactor *
174 GrpcServiceImpl::GetOutputs(grpc::CallbackServerContext *context,
175            const ::agl_shell_ipc::OutputRequest* /* request */,
176            ::agl_shell_ipc::ListOutputResponse* response)
177 {
178         struct window_output *output;
179
180         struct wl_list *list = &m_aglShell->m_shell_data->output_list;
181         wl_list_for_each(output, list, link) {
182                 auto m_output = response->add_outputs();
183                 m_output->set_name(output->name);
184         }
185
186         grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
187         reactor->Finish(grpc::Status::OK);
188         return reactor;
189 }
190
191 grpc::ServerWriteReactor<::agl_shell_ipc::AppStateResponse>*
192 GrpcServiceImpl::AppStatusState(grpc::CallbackServerContext* context,
193                                  const ::agl_shell_ipc::AppStateRequest* /*request */)
194 {
195
196         Lister *n = new Lister(m_aglShell);
197
198         m_aglShell->m_shell_data->server_context_list.push_back(std::pair(context, n));
199         LOG("added lister %p\n", static_cast<void *>(n));
200
201         // just return a Lister to keep the channel open
202         return n;
203 }