e3cfd9082fc07e011901bc47487baff26838966f
[platform/core/security/privacy-guard.git] / server / src / SocketService.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <errno.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <sys/signalfd.h>
22 #include <sys/select.h>
23 #include <sys/stat.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <memory>
28 #include "PrivacyGuardTypes.h"
29 #include "Utils.h"
30 #include "SocketService.h"
31 #include "SocketConnection.h"
32
33 #define BUF_SIZE 256
34
35 const int SocketService::MAX_LISTEN = 5;
36
37 SocketService::SocketService(void)
38         : m_listenFd(-1)
39         , m_signalToClose(-1)
40         , m_mainThread(-1)
41 {
42 }
43
44 SocketService::~SocketService(void)
45 {
46 }
47
48 int
49 SocketService::initialize(void)
50 {
51         //PG_LOGD("SocketService initializing");
52
53         char buf[BUF_SIZE];
54         m_listenFd = socket(AF_UNIX, SOCK_STREAM, 0);
55         TryReturn( m_listenFd != -1, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "socket : %s", strerror_r(errno, buf, sizeof(buf)));
56
57         int flags = -1;
58         int res;
59         if ( (flags = fcntl(m_listenFd, F_GETFL, 0)) == -1)
60                 flags = 0;
61         res = fcntl(m_listenFd, F_SETFL, flags | O_NONBLOCK);
62         TryReturn( res != -1, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "fcntl : %s", strerror_r(errno, buf, sizeof(buf)));
63
64         sockaddr_un server_address;
65         bzero(&server_address, sizeof(server_address));
66         server_address.sun_family = AF_UNIX;
67         strncpy(server_address.sun_path, SERVER_ADDRESS.c_str(), strlen(SERVER_ADDRESS.c_str()));
68         unlink(server_address.sun_path);
69
70         mode_t socket_umask, original_umask;
71         socket_umask = 0;
72         original_umask = umask(socket_umask);
73
74         res = bind(m_listenFd, (struct sockaddr*)&server_address, SUN_LEN(&server_address));
75         TryReturn( res != -1, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "bind : %s", strerror_r(errno, buf, sizeof(buf)));
76
77         umask(original_umask);
78
79         //PG_LOGI("SocketService initialized");
80
81         return PRIV_GUARD_ERROR_SUCCESS;
82 }
83
84 int
85 SocketService::start(void)
86 {
87         sigset_t sigset;
88         sigemptyset(&sigset);
89 //      if ( sigaddset(&sigset, m_signalToClose) == -1 )
90 //      {
91 //              PG_LOGE("Failed to sigaddset : %s", strerror(errno));
92 //              return -1;
93 //      }
94
95         int res = 0;
96         char buf[BUF_SIZE];
97         res = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
98         TryReturn( res >= 0, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "pthread_sigmask : %s", strerror_r(errno, buf, sizeof(buf)));
99
100         pthread_t mainThread;
101         res = pthread_create(&mainThread, NULL, &serverThread, this);
102         TryReturn( res >= 0, PRIV_GUARD_ERROR_SYSTEM_ERROR, errno = res, "pthread_create : %s", strerror_r(res, buf, sizeof(buf)));
103
104         m_mainThread = mainThread;
105
106         return PRIV_GUARD_ERROR_SUCCESS;
107 }
108
109 void*
110 SocketService::serverThread(void* pData)
111 {
112         pthread_detach(pthread_self());
113         SocketService &t = *static_cast< SocketService* > (pData);
114
115         int ret = t.mainloop();
116         if (ret < 0) {
117                 return (void*) 1;
118         }
119
120         return (void*) 0;
121 }
122
123 int
124 SocketService::mainloop(void)
125 {
126         char buf[BUF_SIZE];
127
128         if( listen(m_listenFd, MAX_LISTEN) == -1 ){
129                 PG_LOGE("listen : %s", strerror_r(errno, buf, sizeof(buf)));
130                 return PRIV_GUARD_ERROR_IPC_ERROR;
131         }
132
133         //Settings to catch closing signal in select
134         int signal_fd;
135         sigset_t sigset;
136         int res;
137         res = sigemptyset(&sigset);
138         TryReturn( res != -1, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "sigemptyset : %s", strerror_r(errno, buf, sizeof(buf)));
139
140 //      if( sigaddset(&sigset, m_signalToClose) == -1) {
141 //              PG_LOGE("sigaddset : %s", strerror(errno));
142 //              return -1;
143 //      }
144         signal_fd = signalfd(-1, &sigset, 0);
145         TryReturn( signal_fd >= 0, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "signalfd : %s", strerror_r(errno, buf, sizeof(buf)));
146
147         //Setting descriptors for pselect
148         fd_set allset, rset;
149         int maxfd;
150         FD_ZERO(&allset);
151         FD_SET(m_listenFd, &allset);
152         FD_SET(signal_fd, &allset);
153         maxfd = (m_listenFd > signal_fd) ? (m_listenFd) : (signal_fd);
154         ++maxfd;
155         //this will block SIGPIPE for this thread and every thread created in it
156         //reason : from here on we don't won't to receive SIGPIPE on writing to closed socket
157         //instead of signal we want to receive error from write - hence blocking SIGPIPE
158         sigset_t set;
159         sigemptyset(&set);
160         sigaddset(&set, SIGPIPE);
161         pthread_sigmask(SIG_BLOCK, &set, NULL);
162
163         while(1)
164         {
165                 rset = allset;
166                 if(pselect(maxfd, &rset, NULL, NULL, NULL, NULL) == -1)
167                 {
168                         closeConnections();
169                         PG_LOGE("pselect()");
170                         return PRIV_GUARD_ERROR_SYSTEM_ERROR;
171                 }
172
173                 if(FD_ISSET(signal_fd, &rset))
174                 {
175                         PG_LOGI("Got signal to close");
176                         signalfd_siginfo siginfo;
177                         ssize_t res;
178                         res = read(signal_fd, &siginfo, sizeof(siginfo));
179                         TryReturn( res > 0, PRIV_GUARD_ERROR_IPC_ERROR, closeConnections();, "read : %s", strerror_r(errno, buf, sizeof(buf)));
180                         TryReturn( (size_t)res == sizeof(siginfo), PRIV_GUARD_ERROR_IPC_ERROR, closeConnections();, "couldn't read whole siginfo");
181
182                         if((int)siginfo.ssi_signo == m_signalToClose)
183                         {
184                                 PG_LOGI("Server thread got signal to close");
185                                 closeConnections();
186                                 return PRIV_GUARD_ERROR_SUCCESS;
187                         }
188                         else
189                         {
190                                 PG_LOGI("Got not handled signal");
191                         }
192                 }
193                 if(FD_ISSET(m_listenFd, &rset))
194                 {
195                         int clientFd;
196                         clientFd = accept(m_listenFd, NULL, NULL);
197                         TryReturn( clientFd != -1, PRIV_GUARD_ERROR_IPC_ERROR, closeConnections();, "accept : %s", strerror_r(errno, buf, sizeof(buf)));
198
199                         PG_LOGI("Got incoming connection");
200                         ConnectionInfo * connection = new ConnectionInfo(clientFd, (void *)this);
201                         int res;
202                         pthread_t client_thread;
203                         if((res = pthread_create(&client_thread, NULL, &connectionThread, connection)) < 0)
204                         {
205                                 delete connection;
206                                 errno = res;
207                                 closeConnections();
208                                 PG_LOGE("pthread_create()");
209                                 return PRIV_GUARD_ERROR_SYSTEM_ERROR;
210                         }
211                         addClientSocket(clientFd);
212                 }
213         }
214 }
215
216 void*
217 SocketService::connectionThread(void* pData)
218 {
219         pthread_detach(pthread_self());
220         std::unique_ptr<ConnectionInfo> connectionInfo (static_cast<ConnectionInfo *>(pData));
221         SocketService &t = *static_cast<SocketService *>(connectionInfo->pData);
222
223         int ret = t.connectionService(connectionInfo->connFd);
224         if (ret < 0)
225         {
226                 PG_LOGE("Connection thread error");
227                 t.removeClientSocket(connectionInfo->connFd);
228                 close(connectionInfo->connFd);
229                 return (void*)1;
230         }
231         return (void*)0;
232 }
233
234 int
235 SocketService::connectionService(int fd)
236 {
237         SocketConnection connector = SocketConnection(fd);
238         std::string interfaceName, methodName;
239
240         int res = connector.read(&interfaceName, &methodName);
241         if (res != PRIV_GUARD_ERROR_SUCCESS)
242         {
243                 PG_LOGE("read : %d", res);
244                 return res;
245         }
246
247         PG_LOGD("Got interface : %s", interfaceName.c_str());
248         PG_LOGD("Got method : %s",  methodName.c_str());
249
250         if( m_callbackMap.find(interfaceName) == m_callbackMap.end())
251         {
252                 PG_LOGE("Unknown interface : %s", interfaceName.c_str());
253                 return PRIV_GUARD_ERROR_NO_DATA;
254         }
255
256         if(m_callbackMap[interfaceName].find(methodName) == m_callbackMap[interfaceName].end())
257         {
258                 PG_LOGE("Unknown method : %s", methodName.c_str());
259                 return PRIV_GUARD_ERROR_NO_DATA;
260         }
261
262 //      if(m_callbackMap[interfaceName][methodName]->securityCallback != NULL){
263 //              if(!m_callbackMap[interfaceName][methodName]->securityCallback(fd)){
264 //                      PG_LOGE("Security check returned false");
265 //                      return -1;
266 //              }
267 //      }
268
269         m_callbackMap[interfaceName][methodName]->serviceCallback(&connector);
270
271         removeClientSocket(fd);
272         close(fd);
273
274         return PRIV_GUARD_ERROR_SUCCESS;
275 }
276
277 int
278 SocketService::stop(void)
279 {
280         char buf[BUF_SIZE];
281
282         if(close(m_listenFd) == -1)
283                 if(errno != ENOTCONN)
284                 {
285                         PG_LOGE("close() : %s", strerror_r(errno, buf, sizeof(buf)));
286                         return PRIV_GUARD_ERROR_IPC_ERROR;
287                 }
288
289         int returned_value;
290         if((returned_value = pthread_kill(m_mainThread, m_signalToClose)) < 0)
291         {
292                 errno = returned_value;
293                 PG_LOGE("pthread_kill() : %s", strerror_r(errno, buf, sizeof(buf)));
294                 return PRIV_GUARD_ERROR_IPC_ERROR;
295         }
296         pthread_join(m_mainThread, NULL);
297
298         return PRIV_GUARD_ERROR_SUCCESS;
299 }
300
301 int
302 SocketService::shutdown(void)
303 {
304         return PRIV_GUARD_ERROR_SUCCESS;
305 }
306
307 int
308 SocketService::registerServiceCallback(const std::string &interfaceName,  const std::string &methodName, socketServiceCallback callbackMethod)
309 {
310         if(NULL == callbackMethod)
311         {
312                 PG_LOGE("Null callback");
313                 return PRIV_GUARD_ERROR_INVALID_PARAMETER;
314         }
315         if(interfaceName.empty() || methodName.empty())
316         {
317                 PG_LOGE("Interface and method name cannot be empty");
318                 return PRIV_GUARD_ERROR_INVALID_PARAMETER;
319         }
320
321         auto serviceCallbackPtr = std::make_shared<ServiceCallback>(ServiceCallback(callbackMethod));
322         m_callbackMap[interfaceName][methodName] = serviceCallbackPtr;
323
324         return PRIV_GUARD_ERROR_SUCCESS;
325 }
326
327 void
328 SocketService::addClientSocket(int clientSocket)
329 {
330         std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
331         m_clientSocketList.push_back(clientSocket);
332 }
333
334 void
335 SocketService::removeClientSocket(int clientSocket)
336 {
337         std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
338         m_clientSocketList.remove(clientSocket);
339 }
340
341 bool
342 SocketService::popClientSocket(int * pClientSocket)
343 {
344         std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
345         if(m_clientSocketList.empty())
346                 return false;
347         *pClientSocket = m_clientSocketList.front();
348         m_clientSocketList.pop_front();
349         return true;
350 }
351
352
353 void
354 SocketService::closeConnections(void)
355 {
356         int clientSocket;
357         char buf[BUF_SIZE];
358         PG_LOGI("Closing client sockets");
359         while(popClientSocket(&clientSocket))
360         {
361                 if(close(clientSocket) == -1)
362                 {
363                         PG_LOGE("close() : %s", strerror_r(errno, buf, sizeof(buf)));
364                 }
365         }
366 }