• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
245     if (serviceCount_ > 0) {
246         tmp1 = "enum {\n";
247         for (int i = 0; i < serviceCount_; i++) {
248             for (int j = 0; j < serviceList_[i].methodCount_; j++) {
249                 tmp1 += "\tIpcProtocol" + baseName_ + serviceList_[i].requestList_[j];
250                 tmp1 += "=" + std::to_string(j * 2) + ",\n";
251                 tmp1 += "\tIpcProtocol" + baseName_ + serviceList_[i].responseList_[j];
252                 tmp1 += "=" + std::to_string(j * 2 + 1) + ",\n";
253             }
254         }
255         tmp1 += "};";
256     } else {
257         tmp1 = "";
258     }
259     header_str = ReplaceStr(header_str, "#PROTOCOL_ENUM#", tmp1);
260 
261     GenerateHeader(header_str);
262     header_str = ReplaceStr(header_str, "\t", "    ");
263     return header_str;
264 }
265 
266 namespace {
267 const std::string SEND_RESPONSE_IMPL_STRING = R"(
268 bool #SERVER_CLASS_NAME#::SendResponse#RESPONSE_NAME#(SocketContext &context,
269                                                       #PACKAGE_NAME##RESPONSE_NAME# &response) {
270     context.SendProtobuf(#ENUM_STR#, response);
271     return false;
272 }
273 )";
274 }
GenSendResponseImpl(int servicep,const std::string & server_class_name)275 std::string IpcGeneratorImpl::GenSendResponseImpl(int servicep, const std::string& server_class_name)
276 {
277     std::string ret = "";
278     for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
279         std::string enum_str = "IpcProtocol" + baseName_ + serviceList_[servicep].responseList_[j];
280         std::string tmp = ReplaceStr(SEND_RESPONSE_IMPL_STRING, "#SERVER_CLASS_NAME#", server_class_name);
281         tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
282         tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
283         tmp = ReplaceStr(tmp, "#ENUM_STR#", enum_str);
284         ret += tmp;
285     }
286     return ret;
287 }
288 namespace {
289 const std::string ON_RESPONSE_IMPL_STRING = R"(
290 bool #CLIENT_CLASS_NAME#::On#RESPONSE_NAME#(SocketContext &context, #PACKAGE_NAME##RESPONSE_NAME# &response) {
291     return false;
292 }
293 )";
294 }
GenOnResponseImpl(int servicep,const std::string & client_class_name)295 std::string IpcGeneratorImpl::GenOnResponseImpl(int servicep, const std::string& client_class_name)
296 {
297     std::string ret = "";
298     for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
299         std::string tmp = ReplaceStr(ON_RESPONSE_IMPL_STRING, "#CLIENT_CLASS_NAME#", client_class_name);
300         tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
301         tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
302         ret += tmp;
303     }
304     return ret;
305 }
306 namespace {
307 const std::string SERVICE_CALL_IMPL_STRING = R"(
308 bool #SERVER_CLASS_NAME#::#METHOD_NAME#(SocketContext &context,
309                                         #PACKAGE_NAME##REQUEST_NAME# &request,
310                                         #PACKAGE_NAME##RESPONSE_NAME# &response){
311     return false;
312 }
313 )";
314 }
GenServiceCallImpl(int servicep,const std::string & server_class_name)315 std::string IpcGeneratorImpl::GenServiceCallImpl(int servicep, const std::string& server_class_name)
316 {
317     std::string ret = "";
318     for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
319         std::string tmp = ReplaceStr(SERVICE_CALL_IMPL_STRING, "#SERVER_CLASS_NAME#", server_class_name);
320         tmp = ReplaceStr(tmp, "#SERVER_CLASS_NAME#", server_class_name);
321         tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
322         tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
323         tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
324         tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
325         ret += tmp;
326     }
327     return ret;
328 }
329 namespace {
330 const std::string CLIENT_PROC_IMPL_STRING = R"(
331     case IpcProtocol#BASE_NAME##REQUEST_NAME#:{
332         #PACKAGE_NAME##REQUEST_NAME# request;
333         #PACKAGE_NAME##RESPONSE_NAME# response;
334         request.ParseFromArray(buf, size);
335         if (#METHOD_NAME#(context, request, response)) {
336             context.SendProtobuf(IpcProtocol#BASE_NAME##RESPONSE_NAME#, response);
337         }
338     }
339         break;
340 )";
341 const std::string CLIENT_PROC_NOTIFYRESULT_STRING = R"(
342     case IpcProtocol#BASE_NAME##REQUEST_NAME#:{
343         #PACKAGE_NAME##REQUEST_NAME# request;
344         #PACKAGE_NAME##RESPONSE_NAME# response;
345         request.ParseFromArray(buf, size);
346         #METHOD_NAME#(context, request, response);
347     }
348         break;
349 )";
350 }
GenClientProcImpl(int servicep)351 std::string IpcGeneratorImpl::GenClientProcImpl(int servicep)
352 {
353     std::string ret = "";
354     for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
355         std::string tmp = ReplaceStr(CLIENT_PROC_IMPL_STRING, "#BASE_NAME#", baseName_);
356         if (serviceList_[servicep].methodList_[j] == "NotifyResult") {
357             tmp = ReplaceStr(CLIENT_PROC_NOTIFYRESULT_STRING, "#BASE_NAME#", baseName_);
358         }
359         tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
360         tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
361         tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
362         tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
363         tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
364         ret += tmp;
365     }
366     return ret;
367 }
368 namespace {
369 const std::string CLIENT_REQUEST_IMPL_STRING = R"(
370 bool #CLIENT_CLASS_NAME#::#METHOD_NAME#(#PACKAGE_NAME##REQUEST_NAME# &request,
371                                         #PACKAGE_NAME##RESPONSE_NAME# &response,
372                                         uint32_t timeout_ms)
373 {
374     mWait_.lock();
375     if (timeout_ms<=0) {
376         timeout_ms=WAIT_FOR_EVER;
377     }
378     waitingFor=IpcProtocol#BASE_NAME##RESPONSE_NAME#;
379     presponse=&response;
380     if (unixSocketClient_!=nullptr) {
381         unixSocketClient_->SendProtobuf(IpcProtocol#BASE_NAME##REQUEST_NAME#, request);
382     }
383     if (mWait_.try_lock_for(std::chrono::milliseconds(timeout_ms))) {
384         mWait_.unlock();
385         return true;
386     }
387     waitingFor=-1;
388     mWait_.unlock();
389     return false;
390 }
391 bool #CLIENT_CLASS_NAME#::#METHOD_NAME#(#PACKAGE_NAME##REQUEST_NAME# &request)
392 {
393     unixSocketClient_->SendProtobuf(IpcProtocol#BASE_NAME##REQUEST_NAME#, request);
394     return true;
395 }
396 )";
397 }
GenClientRequestImpl(int servicep,const std::string & client_class_name)398 std::string IpcGeneratorImpl::GenClientRequestImpl(int servicep, const std::string& client_class_name)
399 {
400     std::string ret = "";
401     for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
402         std::string tmp = ReplaceStr(CLIENT_REQUEST_IMPL_STRING, "#CLIENT_CLASS_NAME#", client_class_name);
403         tmp = ReplaceStr(tmp, "#METHOD_NAME#", serviceList_[servicep].methodList_[j]);
404         tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
405         tmp = ReplaceStr(tmp, "#REQUEST_NAME#", serviceList_[servicep].requestList_[j]);
406         tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
407         tmp = ReplaceStr(tmp, "#BASE_NAME#", baseName_);
408         ret += tmp;
409     }
410     return ret;
411 }
412 namespace {
413 const std::string SERVICE_PROC_IMPL_STRING = R"(
414     case IpcProtocol#BASE_NAME##RESPONSE_NAME#:
415         {
416             if (waitingFor==pnum) {
417                 presponse->ParseFromArray(buf, size);
418             }
419             else {
420                 #PACKAGE_NAME##RESPONSE_NAME# response#NUM#;
421                 response#NUM#.ParseFromArray(buf, size);
422                 On#RESPONSE_NAME#(context, response#NUM#);
423             }
424         }
425         break;
426 )";
427 }
GenServiceProcImpl(int servicep)428 std::string IpcGeneratorImpl::GenServiceProcImpl(int servicep)
429 {
430     std::string ret = "";
431     for (int j = 0; j < serviceList_[servicep].methodCount_; j++) {
432         std::string tmp = ReplaceStr(SERVICE_PROC_IMPL_STRING, "#BASE_NAME#", baseName_);
433         tmp = ReplaceStr(tmp, "#RESPONSE_NAME#", serviceList_[servicep].responseList_[j]);
434         tmp = ReplaceStr(tmp, "#PACKAGE_NAME#", packageName_);
435         tmp = ReplaceStr(tmp, "#NUM#", std::to_string(j + 1));
436 
437         ret += tmp;
438     }
439     return ret;
440 }
441 
GenSource()442 std::string IpcGeneratorImpl::GenSource()
443 {
444     std::string source_str = BASE_SOURCE_STRING;
445 
446     source_str = ReplaceStr(source_str, "#HEAD_FILE_NAME#", headFileName_);
447 
448     for (int i = 0; i < serviceCount_; i++) {
449         std::string server_class_name = serviceList_[i].serviceName_ + "Server";
450         source_str = ReplaceStr(source_str, "#SERVICE_CLASS_NAME#", server_class_name);
451         source_str = ReplaceStr(source_str, "#SERVICE_NAME#", serviceList_[i].serviceName_);
452         std::string client_class_name = serviceList_[i].serviceName_ + "Client";
453         source_str = ReplaceStr(source_str, "#CLIENT_CLASS_NAME#", client_class_name);
454 
455         source_str = ReplaceStr(source_str, "#RESPONSE_IMPLEMENT#", GenSendResponseImpl(i, server_class_name));
456         source_str = ReplaceStr(source_str, "#CLIENT_SEND_REQUEST_PROC_FUNC#", GenOnResponseImpl(i, client_class_name));
457 
458         source_str = ReplaceStr(source_str, "#SERVICE_PROTOCOL_PROC_FUNC#", GenServiceCallImpl(i, server_class_name));
459         source_str = ReplaceStr(source_str, "#SERVICE_PROTOCOL_PROC#", GenClientProcImpl(i));
460         source_str = ReplaceStr(source_str, "#SERVICE_NAME#", serviceList_[i].serviceName_);
461 
462         source_str = ReplaceStr(source_str, "#CLIENT_PROTOCOL_PROC#", GenServiceProcImpl(i));
463         source_str =
464             ReplaceStr(source_str, "#CLIENT_SEND_PROTOCOL_PROC_FUNC#", GenClientRequestImpl(i, client_class_name));
465     }
466 
467     source_str = ReplaceStr(source_str, "\t", "    ");
468     return source_str;
469 }
470