Remove garbage channelIds
[platform/framework/native/channel-service.git] / src / FIo_MessagePortService.cpp
1 // // Open Service Platform
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file        FIo_MessagePortService.cpp
19  * @brief       This is the implementation file for the _MessagePortService class.
20  *
21  */
22
23 #include <unique_ptr.h>
24
25 #include <bundle.h>
26 #include <message-port.h>
27 #include <package_manager.h>
28
29 #include <FBaseStringComparer.h>
30 #include <FBaseSysLog.h>
31 #include <FBase_StringConverter.h>
32
33 #include "FIo_MessagePortStub.h"
34 #include "FIo_MessagePortService.h"
35
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Collection;
38 using namespace Tizen::Io;
39 using namespace Tizen::App;
40
41 using namespace std;
42
43 static const char LOCAL_APPID[] = "LOCAL_APPID";
44 static const char LOCAL_PORT[] = "LOCAL_PORT";
45 static const char TRUSTED_LOCAL[] = "TRUSTED_LOCAL";
46
47 static const char REMOTE_APPID[] = "REMOTE_APPID";
48 static const char REMOTE_PORT[] = "REMOTE_PORT";
49 static const char TRUSTED_REMOTE[] = "TRUSTED_REMOTE";
50 static const char TRUSTED_MESSAGE[] = "TRUSTED_MESSAGE";
51
52 _MessagePortService::_MessagePortService(void)
53         : __pStub(null)
54 {
55
56 }
57
58 _MessagePortService::~_MessagePortService(void)
59 {
60
61 }
62
63 result
64 _MessagePortService::Construct(_MessagePortStub& stub)
65 {
66         static _StringHashProvider hashProvider;
67         static _StringComparer stringComparer;
68
69         __pPorts = new HashMapT <String, int>();
70         __pPorts->Construct(0, 0, hashProvider, stringComparer);
71
72         __pTrustedPorts = new HashMapT <String, int>();
73         __pTrustedPorts->Construct(0, 0, hashProvider, stringComparer);
74
75         __pStub = &stub;
76
77         return E_SUCCESS;
78 }
79
80 int
81 _MessagePortService::RegisterMessagePort(int clientId, const BundleBuffer& buffer)
82 {
83         bundle* b = buffer.b;
84
85         String key = GetKey(buffer);
86         String trusted(bundle_get_val(b, TRUSTED_LOCAL));
87
88         SysLog(NID_IO, "Register a message port: [%ls], client id = %d", key.GetPointer(), clientId);
89
90         result r = E_SUCCESS;
91         int value = -1;
92         if (trusted.Equals(L"TRUE", false))
93         {
94                 r = __pTrustedPorts->GetValue(key, value);
95                 if (r == E_SUCCESS)
96                 {
97                         SysTryReturn(NID_IO, value != clientId, MESSAGEPORT_ERROR_IO_ERROR, E_SYSTEM,
98                                         "[E_SYSTEM] The local message port (%ls) has already registered", key.GetPointer());
99
100                         SysLog(NID_IO, "Remove garbage values : %ls", key.GetPointer());
101                         __pTrustedPorts->Remove(key);
102                 }
103
104                 __pTrustedPorts->Add(key, clientId);
105         }
106         else
107         {
108                 r = __pPorts->GetValue(key, value);
109                 if (r == E_SUCCESS)
110                 {
111                         SysTryReturn(NID_IO, value != clientId, MESSAGEPORT_ERROR_IO_ERROR, E_SYSTEM,
112                                         "[E_SYSTEM] The local message port (%ls) has already registered", key.GetPointer());
113
114                         SysLog(NID_IO, "Remove garbage values : %ls", key.GetPointer());
115                         __pPorts->Remove(key);
116                 }
117
118                 __pPorts->Add(key, clientId);
119         }
120
121         return 0;
122 }
123
124 int
125 _MessagePortService::CheckRemotePort(const BundleBuffer& buffer)
126 {
127         bundle* b = buffer.b;
128
129         String key = GetKey(buffer, false);
130         String trusted(bundle_get_val(b, TRUSTED_REMOTE));
131
132         SysLog(NID_IO, "Check a remote message port: [%ls]", key.GetPointer());
133
134         bool out = false;
135
136         if (trusted.Equals(L"TRUE", false))
137         {
138                 __pTrustedPorts->ContainsKey(key, out);
139         }
140         else
141         {
142                 __pPorts->ContainsKey(key, out);
143         }
144
145         SysTryReturn(NID_IO, out == true, MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND, E_OBJ_NOT_FOUND,
146                         "[E_OBJ_NOT_FOUND] The remote message port (%ls) is not found.", key.GetPointer());
147
148         if (trusted.Equals(L"TRUE", false))
149         {
150                 String localAppId = bundle_get_val(b, LOCAL_APPID);
151                 String remoteAppId = bundle_get_val(b, REMOTE_APPID);
152
153                 // Check the preloaded
154                 if (!IsPreloaded(localAppId, remoteAppId))
155                 {
156                         // Check the certificate
157                         return CheckCertificate(localAppId, remoteAppId);
158                 }
159         }
160
161         return 0;
162 }
163
164 result
165 _MessagePortService::UnregisterMessagePort(int clientId)
166 {
167         result r = E_OBJ_NOT_FOUND;
168
169         int value = 0;
170         int count = __pPorts->GetCount();
171
172         String key;
173         IListT<String>* pKeys = __pPorts->GetKeysN();
174         SysTryReturnResult(NID_IO, pKeys != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
175
176         for (int i = 0; i < count; i++)
177         {
178                 pKeys->GetAt(i, key);
179                 __pPorts->GetValue(key, value);
180                 if (value == clientId)
181                 {
182                         SysLog(NID_IO, "Unregister - key = %ls", key.GetPointer());
183
184                         __pPorts->Remove(key);
185
186                         r = E_SUCCESS;
187                 }
188         }
189
190         delete pKeys;
191
192         count = __pTrustedPorts->GetCount();
193         pKeys = __pTrustedPorts->GetKeysN();
194         SysTryReturnResult(NID_IO, pKeys != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
195
196         for (int i = 0; i < count; i++)
197         {
198                 pKeys->GetAt(i, key);
199                 __pTrustedPorts->GetValue(key, value);
200                 if (value == clientId)
201                 {
202                         SysLog(NID_IO, "Unregister - key = %ls", key.GetPointer());
203
204                         __pTrustedPorts->Remove(key);
205
206                         r = E_SUCCESS;
207                 }
208         }
209
210         delete pKeys;
211
212         return r;
213 }
214
215 int
216 _MessagePortService::SendMessage(const BundleBuffer& metadata, const BundleBuffer& buffer)
217 {
218         result r = E_SUCCESS;
219         int clientId = 0;
220
221         bundle* b = metadata.b;
222
223         String key = GetKey(metadata, false);
224         SysLog(NID_IO, "Sends a message to a remote message port [%ls]", key.GetPointer());
225
226         String trustedMessage(bundle_get_val(b, TRUSTED_MESSAGE));
227         if (trustedMessage.Equals(L"TRUE", false))
228         {
229                 r = __pTrustedPorts->GetValue(key, clientId);
230         }
231         else
232         {
233                 r = __pPorts->GetValue(key, clientId);
234         }
235
236         SysTryReturn(NID_IO, r == E_SUCCESS, MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND, E_OBJ_NOT_FOUND,
237                                 "[E_OBJ_NOT_FOUND] The destination message port (%ls) is not found.", key.GetPointer());
238
239         if (trustedMessage.Equals(L"TRUE", false))
240         {
241                 String localAppId = bundle_get_val(b, LOCAL_APPID);
242                 String remoteAppId = bundle_get_val(b, REMOTE_APPID);
243
244                 // Check the preloaded
245                 if (!IsPreloaded(localAppId, remoteAppId))
246                 {
247                         // Check the certificate
248                         int ret = CheckCertificate(localAppId, remoteAppId);
249                         if (ret < 0)
250                         {
251                                 return ret;
252                         }
253                 }
254         }
255
256         r = __pStub->SendMessage(clientId, metadata, buffer);
257         SysTryReturn(NID_IO, r == E_SUCCESS, MESSAGEPORT_ERROR_IO_ERROR, E_SYSTEM,
258                                 "[E_SYSTEM] Failed to send a message.");
259
260         return E_SUCCESS;
261 }
262
263 String 
264 _MessagePortService::GetKey(const BundleBuffer& buffer, bool local) const
265 {
266         const char* pAppId = null; 
267         const char* pPortName = null; 
268
269         bundle* b = buffer.b;
270
271         if (local)
272         {
273                 pAppId = bundle_get_val(b, LOCAL_APPID);
274                 pPortName = bundle_get_val(b, LOCAL_PORT);
275         }
276         else
277         {
278                 pAppId = bundle_get_val(b, REMOTE_APPID);
279                 pPortName = bundle_get_val(b, REMOTE_PORT);
280         }
281
282         String key(pAppId);
283         key.Append(L':');
284         key.Append(pPortName);
285
286         return key;
287 }
288
289 bool
290 _MessagePortService::IsPreloaded(const String& localAppId, const String& remoteAppId) const
291 {
292         bool preload_local = false;
293         bool preload_remote = false;
294
295         unique_ptr<char[]> pLocalAppId(_StringConverter::CopyToCharArrayN(localAppId));
296         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
297
298         int ret = package_manager_is_preload_package_by_app_id(pLocalAppId.get(), &preload_local);
299         if (ret == 0)
300         {
301                 ret = package_manager_is_preload_package_by_app_id(pRemoteAppId.get(), &preload_remote);
302                 if (ret == 0)
303                 {
304                         if (preload_local && preload_remote)
305                         {
306                                 return true;
307                         }
308                 }
309                 else
310                 {
311                         SysLog(NID_IO, "Failed to check the preloaded application. %d", ret);
312                 }
313         }
314         else
315         {
316                 SysLog(NID_IO, "Failed to check the preloaded application. %d", ret);
317         }
318
319         return false;
320 }
321
322 int
323 _MessagePortService::CheckCertificate(const String& localAppId, const String& remoteAppId) const
324 {
325         package_manager_compare_result_type_e res;
326
327         unique_ptr<char[]> pLocalAppId(_StringConverter::CopyToCharArrayN(localAppId));
328         unique_ptr<char[]> pRemoteAppId(_StringConverter::CopyToCharArrayN(remoteAppId));
329
330         int ret = package_manager_compare_app_cert_info(pLocalAppId.get(), pRemoteAppId.get(), &res);
331         SysTryReturn(NID_IO, ret == 0, MESSAGEPORT_ERROR_IO_ERROR, E_SYSTEM,
332                                 "[E_SYSTEM] Failed to check the certificate: %d", ret);
333
334         SysTryReturn(NID_IO, res == PACAKGE_MANAGER_COMPARE_MATCH, MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH, E_CERTIFICATE_VERIFICATION_FAILED,
335                                 "[E_CERTIFICATE_VERIFICATION_FAILED] Both applications are not signed with the same certificate: %d", res);
336
337         return 0;
338 }
339