1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ipc_generator_impl.h"
17
IpcGeneratorImpl()18 IpcGeneratorImpl::IpcGeneratorImpl() {}
19
~IpcGeneratorImpl()20 IpcGeneratorImpl::~IpcGeneratorImpl() {}
21
22 namespace {
23 const std::string BASE_HEADER_STRING = R"(
24 #pragma once
25
26 #include "#HEAD_FILE_NAME#.pb.h"
27 #include "service_base.h"
28 #include <cstdint>
29 #include <mutex>
30
31 class SocketContext;
32 class UnixSocketClient;
33
34 #PROTOCOL_ENUM#
35
36 class #SERVICE_CLASS_NAME#:public ServiceBase
37 {
38 public:
39 #SERVICE_CLASS_NAME#();
40 bool ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size) override;
41 #RESPONSE_DEFINE#
42 };
43
44 class #CLIENT_CLASS_NAME#:public ServiceBase
45 {
46 public:
47 #CLIENT_CLASS_NAME#();
48
49 std::shared_ptr<UnixSocketClient> unixSocketClient_;
50 bool Connect(const std::string addrname);
51 bool ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size) override;
52 google::protobuf::Message *presponse;
53 uint32_t waitingFor;
54 #VIRTUAL_RESPONSE_FUNC#
55 };
56 )";
57
58 const std::string BASE_SOURCE_STRING = R"(
59 #include "#HEAD_FILE_NAME#.ipc.h"
60 #include "#HEAD_FILE_NAME#.pb.h"
61 #include "socket_context.h"
62 #include "unix_socket_client.h"
63 #include "unix_socket_server.h"
64 #include <unistd.h>
65
66 namespace{
67 const uint32_t WAIT_FOR_EVER=24*60*60*1000;
68 }
69
70 #SERVICE_CLASS_NAME#::#SERVICE_CLASS_NAME#()
71 {
72 serviceName_="#SERVICE_NAME#";
73 }
74
75 #RESPONSE_IMPLEMENT#
76
77 #SERVICE_PROTOCOL_PROC_FUNC#
78 bool #SERVICE_CLASS_NAME#::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size)
79 {
80 switch (pnum) {
81 #SERVICE_PROTOCOL_PROC#
82 }
83 return false;
84 }
85
86 #CLIENT_CLASS_NAME#::#CLIENT_CLASS_NAME#()
87 {
88 unixSocketClient_=nullptr;
89 serviceName_="#SERVICE_NAME#";
90 }
91 bool #CLIENT_CLASS_NAME#::Connect(const std::string addrname)
92 {
93 if (unixSocketClient_!=nullptr) {
94 return false;
95 }
96 unixSocketClient_ = std::make_shared<UnixSocketClient>();
97 if (!unixSocketClient_->Connect(addrname, *this)) {
98 printf("Socket Connect failed\n");
99 unixSocketClient_=nullptr;
100 return false;
101 }
102 return true;
103 }
104
105 #CLIENT_SEND_REQUEST_PROC_FUNC#
106
107 #CLIENT_SEND_PROTOCOL_PROC_FUNC#
108 bool #CLIENT_CLASS_NAME#::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size)
109 {
110 switch (pnum) {
111 #CLIENT_PROTOCOL_PROC#
112 }
113 if (waitingFor==pnum) {
114 waitingFor=-1;
115 mWait_.unlock();
116 }
117 return false;
118 }
119 )";
120
SwapName(std::string s)121 std::string SwapName(std::string s)
122 {
123 std::string ret = "";
124 bool b = true;
125 for (size_t i = 0; i < s.length(); i++) {
126 char c = s[i];
127 if (c == '_') {
128 b = true;
129 } else if (b && c >= 'a' && c <= 'z') {
130 ret += (c + 'A' - 'a');
131 b = false;
132 } else {
133 ret += c;
134 }
135 }
136 return ret;
137 }
ReplaceStr(const std::string & base,const std::string & _from,const std::string & _to)138 std::string ReplaceStr(const std::string& base, const std::string& _from, const std::string& _to)
139 {
140 std::string ret = base;
141 while (true) {
142 size_t pos = ret.find(_from, 0);
143 if (pos == std::string::npos) {
144 break;
145 }
146 ret.replace(pos, _from.length(), _to);
147 }
148 return ret;
149 }
150 } // namespace
151
SetNames(std::string fileName,std::string packageName)152 std::string IpcGeneratorImpl::SetNames(std::string fileName, std::string packageName)
153 {
154 fileName_ = fileName;
155 packageName_ = packageName + "::";
156 headFileName_ = "";
157
158 for (size_t i = 0; i < fileName.length(); i++) {
159 if (fileName.c_str()[i] == '.') {
160 break;
161 }
162 headFileName_ += fileName.c_str()[i];
163 }
164 baseName_ = SwapName(headFileName_);
165
166 serviceCount_ = 0;
167
168 serviceList_.clear();
169 enumMessageDict_.clear();
170
171 return headFileName_;
172 }
173
AddService(std::string serviceName)174 bool IpcGeneratorImpl::AddService(std::string serviceName)
175 {
176 for (int i = 0; i < serviceCount_; i++) {
177 if (serviceList_[i].serviceName_ == serviceName) {
178 return false;
179 }
180 }
181 serviceList_[serviceCount_].serviceName_ = serviceName;
182 serviceCount_++;
183 return true;
184 }
185
AddServiceMethod(std::string serviceName,std::string methodName,std::string requestName,std::string responseName)186 bool IpcGeneratorImpl::AddServiceMethod(std::string serviceName,
187 std::string methodName,
188 std::string requestName,
189 std::string responseName)
190 {
191 for (int i = 0; i < serviceCount_; i++) {
192 if (serviceList_[i].serviceName_ == serviceName) {
193 return serviceList_[i].AddMethod(methodName, requestName, responseName);
194 }
195 }
196 return false;
197 }
198
GenerateHeader(std::string & header_str)199 void IpcGeneratorImpl::GenerateHeader(std::string& header_str)
200 {
201 for (int i = 0; i < serviceCount_; i++) {
202 std::string server_class_name = serviceList_[i].serviceName_ + "Server";
203 header_str = ReplaceStr(header_str, "#SERVICE_CLASS_NAME#", server_class_name);
204
205 std::string tmp1 = "";
206 std::string tmp2 = "";
207 for (int j = 0; j < serviceList_[i].methodCount_; j++) {
208 tmp1 += "\tvirtual bool " + serviceList_[i].methodList_[j] + "(SocketContext &context," + packageName_ +
209 serviceList_[i].requestList_[j] + " &request," + packageName_ + serviceList_[i].responseList_[j] +
210 " &response);\n";
211
212 tmp2 += "\tbool SendResponse" + serviceList_[i].responseList_[j] + "(SocketContext &context," +
213 packageName_ + serviceList_[i].responseList_[j] + " &response);\n";
214 }
215 tmp1 += "\n" + tmp2;
216 header_str = ReplaceStr(header_str, "#RESPONSE_DEFINE#", tmp1);
217
218 std::string client_class_name = serviceList_[i].serviceName_ + "Client";
219 header_str = ReplaceStr(header_str, "#CLIENT_CLASS_NAME#", client_class_name);
220
221 tmp1 = "";
222 for (int j = 0; j < serviceList_[i].methodCount_; j++) {
223 tmp1 += "\tbool " + serviceList_[i].methodList_[j] + "(" + packageName_ + serviceList_[i].requestList_[j];
224 tmp1 += " &request," + packageName_ + serviceList_[i].responseList_[j];
225 tmp1 += " &response,uint32_t timeout_ms=5000);\n";
226 tmp1 += "\tbool " + serviceList_[i].methodList_[j] + "(" + packageName_ + serviceList_[i].requestList_[j];
227 tmp1 += " &request);\n";
228 }
229 tmp1 += "\n";
230 for (int j = 0; j < serviceList_[i].methodCount_; j++) {
231 tmp1 += "\tvirtual bool On" + serviceList_[i].responseList_[j] + "(SocketContext &context," + packageName_;
232 tmp1 += serviceList_[i].responseList_[j] + " &response);\n";
233 }
234
235 header_str = ReplaceStr(header_str, "#VIRTUAL_RESPONSE_FUNC#", tmp1);
236 }
237 }
238
GenHeader()239 std::string IpcGeneratorImpl::GenHeader()
240 {
241 std::string header_str = BASE_HEADER_STRING;
242 std::string tmp1;
243 header_str = ReplaceStr(header_str, "#HEAD_FILE_NAME#", headFileName_);
244 const int numTwo = 2;
245
246 if (serviceCount_ > 0) {
247 tmp1 = "enum {\n";
248 for (int i = 0; i < serviceCount_; i++) {
249 for (int j = 0; j < serviceList_[i].methodCount_; j++) {
250 tmp1 += "\tIpcProtocol" + baseName_ + serviceList_[i].requestList_[j];
251 tmp1 += "=" + std::to_string(j * numTwo) + ",\n";
252 tmp1 += "\tIpcProtocol" + baseName_ + serviceList_[i].responseList_[j];
253 tmp1 += "=" + std::to_string(j * numTwo + 1) + ",\n";
254 }
255 }
256 tmp1 += "};";
257 } else {
258 tmp1 = "";
259 }
260 header_str = ReplaceStr(header_str, "#PROTOCOL_ENUM#", tmp1);
261
262 GenerateHeader(header_str);
263 header_str = ReplaceStr(header_str, "\t", " ");
264 return header_str;
265 }
266
267 namespace {
268 const std::string SEND_RESPONSE_IMPL_STRING = R"(
269 bool #SERVER_CLASS_NAME#::SendResponse#RESPONSE_NAME#(SocketContext &context,
270 #PACKAGE_NAME##RESPONSE_NAME# &response) {
271 context.SendProtobuf(#ENUM_STR#, response);
272 return false;
273 }
274 )";
275 }
GenSendResponseImpl(int servicep,const std::string & server_class_name)276 std::string IpcGeneratorImpl::GenSendResponseImpl(int servicep, const std::string& server_class_name)
277 {
278 std::string ret = "";
279 for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
280 std::string enum_str = "IpcProtocol" + baseName_ + serviceList_[servicep].responseList_[j];
281 std::string tmp = ReplaceStr(SEND_RESPONSE_IMPL_STRING, "#SERVER_CLASS_NAME#", server_class_name);
282 tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
283 tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
284 tmp = ReplaceStr(tmp, "#ENUM_STR#", enum_str);
285 ret += tmp;
286 }
287 return ret;
288 }
289 namespace {
290 const std::string ON_RESPONSE_IMPL_STRING = R"(
291 bool #CLIENT_CLASS_NAME#::On#RESPONSE_NAME#(SocketContext &context, #PACKAGE_NAME##RESPONSE_NAME# &response) {
292 return false;
293 }
294 )";
295 }
GenOnResponseImpl(int servicep,const std::string & client_class_name)296 std::string IpcGeneratorImpl::GenOnResponseImpl(int servicep, const std::string& client_class_name)
297 {
298 std::string ret = "";
299 for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
300 std::string tmp = ReplaceStr(ON_RESPONSE_IMPL_STRING, "#CLIENT_CLASS_NAME#", client_class_name);
301 tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
302 tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
303 ret += tmp;
304 }
305 return ret;
306 }
307 namespace {
308 const std::string SERVICE_CALL_IMPL_STRING = R"(
309 bool #SERVER_CLASS_NAME#::#METHOD_NAME#(SocketContext &context,
310 #PACKAGE_NAME##REQUEST_NAME# &request,
311 #PACKAGE_NAME##RESPONSE_NAME# &response){
312 return false;
313 }
314 )";
315 }
GenServiceCallImpl(int servicep,const std::string & server_class_name)316 std::string IpcGeneratorImpl::GenServiceCallImpl(int servicep, const std::string& server_class_name)
317 {
318 std::string ret = "";
319 for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
320 std::string tmp = ReplaceStr(SERVICE_CALL_IMPL_STRING, "#SERVER_CLASS_NAME#", server_class_name);
321 tmp = ReplaceStr(tmp, "#SERVER_CLASS_NAME#", server_class_name);
322 tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
323 tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
324 tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
325 tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
326 ret += tmp;
327 }
328 return ret;
329 }
330 namespace {
331 const std::string CLIENT_PROC_IMPL_STRING = R"(
332 case IpcProtocol#BASE_NAME##REQUEST_NAME#:{
333 #PACKAGE_NAME##REQUEST_NAME# request;
334 #PACKAGE_NAME##RESPONSE_NAME# response;
335 request.ParseFromArray(buf, size);
336 if (#METHOD_NAME#(context, request, response)) {
337 context.SendProtobuf(IpcProtocol#BASE_NAME##RESPONSE_NAME#, response);
338 }
339 }
340 break;
341 )";
342 const std::string CLIENT_PROC_NOTIFYRESULT_STRING = R"(
343 case IpcProtocol#BASE_NAME##REQUEST_NAME#:{
344 #PACKAGE_NAME##REQUEST_NAME# request;
345 #PACKAGE_NAME##RESPONSE_NAME# response;
346 request.ParseFromArray(buf, size);
347 #METHOD_NAME#(context, request, response);
348 }
349 break;
350 )";
351 }
GenClientProcImpl(int servicep)352 std::string IpcGeneratorImpl::GenClientProcImpl(int servicep)
353 {
354 std::string ret = "";
355 for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
356 std::string tmp = ReplaceStr(CLIENT_PROC_IMPL_STRING, "#BASE_NAME#", baseName_);
357 if (serviceList_[servicep].methodList_[j] == "NotifyResult") {
358 tmp = ReplaceStr(CLIENT_PROC_NOTIFYRESULT_STRING, "#BASE_NAME#", baseName_);
359 }
360 tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
361 tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
362 tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
363 tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
364 tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
365 ret += tmp;
366 }
367 return ret;
368 }
369 namespace {
370 const std::string CLIENT_REQUEST_IMPL_STRING = R"(
371 bool #CLIENT_CLASS_NAME#::#METHOD_NAME#(#PACKAGE_NAME##REQUEST_NAME# &request,
372 #PACKAGE_NAME##RESPONSE_NAME# &response,
373 uint32_t timeout_ms)
374 {
375 mWait_.lock();
376 if (timeout_ms<=0) {
377 timeout_ms=WAIT_FOR_EVER;
378 }
379 waitingFor=IpcProtocol#BASE_NAME##RESPONSE_NAME#;
380 presponse=&response;
381 if (unixSocketClient_!=nullptr) {
382 unixSocketClient_->SendProtobuf(IpcProtocol#BASE_NAME##REQUEST_NAME#, request);
383 }
384 if (mWait_.try_lock_for(std::chrono::milliseconds(timeout_ms))) {
385 mWait_.unlock();
386 return true;
387 }
388 waitingFor=-1;
389 mWait_.unlock();
390 return false;
391 }
392 bool #CLIENT_CLASS_NAME#::#METHOD_NAME#(#PACKAGE_NAME##REQUEST_NAME# &request)
393 {
394 unixSocketClient_->SendProtobuf(IpcProtocol#BASE_NAME##REQUEST_NAME#, request);
395 return true;
396 }
397 )";
398 }
GenClientRequestImpl(int servicep,const std::string & client_class_name)399 std::string IpcGeneratorImpl::GenClientRequestImpl(int servicep, const std::string& client_class_name)
400 {
401 std::string ret = "";
402 for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
403 std::string tmp = ReplaceStr(CLIENT_REQUEST_IMPL_STRING, "#CLIENT_CLASS_NAME#", client_class_name);
404 tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
405 tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
406 tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
407 tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
408 tmp = ReplaceStr(tmp, "#BASE_NAME#", baseName_);
409 ret += tmp;
410 }
411 return ret;
412 }
413 namespace {
414 const std::string SERVICE_PROC_IMPL_STRING = R"(
415 case IpcProtocol#BASE_NAME##RESPONSE_NAME#:
416 {
417 if (waitingFor==pnum) {
418 presponse->ParseFromArray(buf, size);
419 }
420 else {
421 #PACKAGE_NAME##RESPONSE_NAME# response#NUM#;
422 response#NUM#.ParseFromArray(buf, size);
423 On#RESPONSE_NAME#(context, response#NUM#);
424 }
425 }
426 break;
427 )";
428 }
GenServiceProcImpl(int servicep)429 std::string IpcGeneratorImpl::GenServiceProcImpl(int servicep)
430 {
431 std::string ret = "";
432 for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
433 std::string tmp = ReplaceStr(SERVICE_PROC_IMPL_STRING, "#BASE_NAME#", baseName_);
434 tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
435 tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
436 tmp = ReplaceStr(tmp, "#NUM#", std::to_string(j + 1));
437
438 ret += tmp;
439 }
440 return ret;
441 }
442
GenSource()443 std::string IpcGeneratorImpl::GenSource()
444 {
445 std::string source_str = BASE_SOURCE_STRING;
446
447 source_str = ReplaceStr(source_str, "#HEAD_FILE_NAME#", headFileName_);
448
449 for (int i = 0; i < serviceCount_; i++) {
450 std::string server_class_name = serviceList_[i].serviceName_ + "Server";
451 source_str = ReplaceStr(source_str, "#SERVICE_CLASS_NAME#", server_class_name);
452 source_str = ReplaceStr(source_str, "#SERVICE_NAME#", serviceList_[i].serviceName_);
453 std::string client_class_name = serviceList_[i].serviceName_ + "Client";
454 source_str = ReplaceStr(source_str, "#CLIENT_CLASS_NAME#", client_class_name);
455
456 source_str = ReplaceStr(source_str, "#RESPONSE_IMPLEMENT#", GenSendResponseImpl(i, server_class_name));
457 source_str = ReplaceStr(source_str, "#CLIENT_SEND_REQUEST_PROC_FUNC#", GenOnResponseImpl(i, client_class_name));
458
459 source_str = ReplaceStr(source_str, "#SERVICE_PROTOCOL_PROC_FUNC#", GenServiceCallImpl(i, server_class_name));
460 source_str = ReplaceStr(source_str, "#SERVICE_PROTOCOL_PROC#", GenClientProcImpl(i));
461 source_str = ReplaceStr(source_str, "#SERVICE_NAME#", serviceList_[i].serviceName_);
462
463 source_str = ReplaceStr(source_str, "#CLIENT_PROTOCOL_PROC#", GenServiceProcImpl(i));
464 source_str =
465 ReplaceStr(source_str, "#CLIENT_SEND_PROTOCOL_PROC_FUNC#", GenClientRequestImpl(i, client_class_name));
466 }
467
468 source_str = ReplaceStr(source_str, "\t", " ");
469 return source_str;
470 }
471