2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "access_control/Privilege.h"
21 #include "ProviderHandler.h"
23 #define DELETE_DELAY 10
27 std::map<std::string, ProviderHandler*> ProviderHandler::__instanceMap;
29 ProviderHandler::ProviderHandler(const std::string &subject) :
31 __deleteScheduled(false)
33 _D("Subject: %s", __subject.c_str());
36 ProviderHandler::~ProviderHandler()
38 _D("Subject: %s", __subject.c_str());
40 for (RequestInfo*& info : __subscribeRequests) {
43 __subscribeRequests.clear();
45 for (RequestInfo*& info : __readRequests) {
48 __readRequests.clear();
53 /* TODO: Return proper error code */
54 ProviderHandler* ProviderHandler::getInstance(std::string subject, bool force)
56 InstanceMap::iterator it = __instanceMap.find(subject);
58 if (it != __instanceMap.end())
64 ProviderHandler *handle = new(std::nothrow) ProviderHandler(subject);
65 IF_FAIL_RETURN_TAG(handle, NULL, _E, "Memory allocation failed");
67 if (!handle->__loadProvider()) {
72 __instanceMap[subject] = handle;
77 void ProviderHandler::purge()
79 for (InstanceMap::iterator it = __instanceMap.begin(); it != __instanceMap.end(); ++it) {
83 __instanceMap.clear();
86 bool ProviderHandler::isSupported()
88 return __provider->isSupported();
91 bool ProviderHandler::isAllowed(const Credentials *creds)
93 IF_FAIL_RETURN(creds, true); /* In case of internal requests */
95 std::vector<const char*> priv;
96 __provider->getPrivilege(priv);
98 for (unsigned int i = 0; i < priv.size(); ++i) {
99 if (!privilege_manager::isAllowed(creds, priv[i]))
106 void ProviderHandler::subscribe(RequestInfo *request)
108 _I(CYAN("'%s' subscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
111 int error = __provider->subscribe(request->getDescription().str(), &requestResult);
113 if (!request->reply(error, requestResult) || error != ERR_NONE) {
118 __subscribeRequests.push_back(request);
121 void ProviderHandler::unsubscribe(RequestInfo *request)
123 _I(CYAN("'%s' unsubscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
125 /* Search the subscribe request to be removed */
126 auto target = __findRequest(__subscribeRequests, request->getClient(), request->getId());
127 if (target == __subscribeRequests.end()) {
128 _W("Unknown request");
133 /* Keep the pointer to the request found */
134 RequestInfo *reqFound = *target;
136 /* Remove the request from the list */
137 __subscribeRequests.erase(target);
139 /* Check if there exist the same requests */
140 if (__findRequest(__subscribeRequests, reqFound->getDescription()) != __subscribeRequests.end()) {
141 /* Do not stop detecting the subject */
142 _D("A same request from '%s' exists", reqFound->getClient());
143 request->reply(ERR_NONE);
149 /* Stop detecting the subject */
150 int error = __provider->unsubscribe(reqFound->getDescription());
151 request->reply(error);
155 /* If idle, self destruct */
156 __scheduleToDelete();
159 void ProviderHandler::read(RequestInfo *request)
161 _I(CYAN("'%s' reads '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
164 int error = __provider->read(request->getDescription().str(), &requestResult);
166 if (!request->reply(error, requestResult) || error != ERR_NONE) {
171 __readRequests.push_back(request);
174 void ProviderHandler::write(RequestInfo *request)
176 _I(CYAN("'%s' writes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
179 int error = __provider->write(request->getDescription(), &requestResult);
181 request->reply(error, requestResult);
184 /* If idle, self destruct */
185 __scheduleToDelete();
188 bool ProviderHandler::publish(Json &option, int error, Json &dataUpdated)
190 auto end = __subscribeRequests.end();
191 auto target = __findRequest(__subscribeRequests.begin(), end, option);
193 while (target != end) {
194 if (!(*target)->publish(error, dataUpdated)) {
197 target = __findRequest(++target, end, option);
203 bool ProviderHandler::replyToRead(Json &option, int error, Json &dataRead)
205 auto end = __readRequests.end();
206 auto target = __findRequest(__readRequests.begin(), end, option);
211 while (target != end) {
212 (*target)->reply(error, dummy, dataRead);
214 target = __findRequest(++target, end, option);
217 __readRequests.erase(prev);
220 /* If idle, self destruct */
221 __scheduleToDelete();
226 bool ProviderHandler::__loadProvider()
228 __provider = __loader.load(__subject.c_str());
229 return (__provider != NULL);
232 bool ProviderHandler::__idle()
234 return __subscribeRequests.empty() && __readRequests.empty();
237 void ProviderHandler::__scheduleToDelete()
239 if (!__deleteScheduled && __idle()) {
240 __deleteScheduled = true;
241 g_timeout_add_seconds(DELETE_DELAY, __deletor, this);
242 _D("Delete scheduled for '%s' (%#x)", __subject.c_str(), this);
246 gboolean ProviderHandler::__deletor(gpointer data)
248 ProviderHandler *handle = static_cast<ProviderHandler*>(data);
250 if (handle->__idle()) {
251 __instanceMap.erase(handle->__subject);
256 handle->__deleteScheduled = false;
260 ProviderHandler::RequestList::iterator
261 ProviderHandler::__findRequest(RequestList &reqList, Json &option)
263 return __findRequest(reqList.begin(), reqList.end(), option);
266 ProviderHandler::RequestList::iterator
267 ProviderHandler::__findRequest(RequestList &reqList, std::string client, int reqId)
269 for (auto it = reqList.begin(); it != reqList.end(); ++it) {
270 if (client == (*it)->getClient() && reqId == (*it)->getId()) {
274 return reqList.end();
277 ProviderHandler::RequestList::iterator
278 ProviderHandler::__findRequest(RequestList::iterator begin, RequestList::iterator end, Json &option)
280 for (auto it = begin; it != end; ++it) {
281 if (option == (*it)->getDescription()) {