2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
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.
18 #include <sys/types.h>
19 #include <sys/socket.h>
21 #include <sys/signalfd.h>
22 #include <sys/select.h>
28 #include "PrivacyGuardTypes.h"
30 #include "SocketService.h"
31 #include "SocketConnection.h"
35 const int SocketService::MAX_LISTEN = 5;
37 SocketService::SocketService(void)
44 SocketService::~SocketService(void)
49 SocketService::initialize(void)
51 //PG_LOGD("SocketService initializing");
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)));
59 if ( (flags = fcntl(m_listenFd, F_GETFL, 0)) == -1)
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)));
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);
70 mode_t socket_umask, original_umask;
72 original_umask = umask(socket_umask);
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)));
77 umask(original_umask);
79 //PG_LOGI("SocketService initialized");
81 return PRIV_GUARD_ERROR_SUCCESS;
85 SocketService::start(void)
89 // if ( sigaddset(&sigset, m_signalToClose) == -1 )
91 // PG_LOGE("Failed to sigaddset : %s", strerror(errno));
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)));
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)));
104 m_mainThread = mainThread;
106 return PRIV_GUARD_ERROR_SUCCESS;
110 SocketService::serverThread(void* pData)
112 pthread_detach(pthread_self());
113 SocketService &t = *static_cast< SocketService* > (pData);
115 int ret = t.mainloop();
124 SocketService::mainloop(void)
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;
133 //Settings to catch closing signal in select
137 res = sigemptyset(&sigset);
138 TryReturn( res != -1, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "sigemptyset : %s", strerror_r(errno, buf, sizeof(buf)));
140 // if( sigaddset(&sigset, m_signalToClose) == -1) {
141 // PG_LOGE("sigaddset : %s", strerror(errno));
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)));
147 //Setting descriptors for pselect
151 FD_SET(m_listenFd, &allset);
152 FD_SET(signal_fd, &allset);
153 maxfd = (m_listenFd > signal_fd) ? (m_listenFd) : (signal_fd);
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
160 sigaddset(&set, SIGPIPE);
161 pthread_sigmask(SIG_BLOCK, &set, NULL);
166 if(pselect(maxfd, &rset, NULL, NULL, NULL, NULL) == -1)
169 PG_LOGE("pselect()");
170 return PRIV_GUARD_ERROR_SYSTEM_ERROR;
173 if(FD_ISSET(signal_fd, &rset))
175 PG_LOGI("Got signal to close");
176 signalfd_siginfo siginfo;
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");
182 if((int)siginfo.ssi_signo == m_signalToClose)
184 PG_LOGI("Server thread got signal to close");
186 return PRIV_GUARD_ERROR_SUCCESS;
190 PG_LOGI("Got not handled signal");
193 if(FD_ISSET(m_listenFd, &rset))
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)));
199 PG_LOGI("Got incoming connection");
200 ConnectionInfo * connection = new ConnectionInfo(clientFd, (void *)this);
202 pthread_t client_thread;
203 if((res = pthread_create(&client_thread, NULL, &connectionThread, connection)) < 0)
208 PG_LOGE("pthread_create()");
209 return PRIV_GUARD_ERROR_SYSTEM_ERROR;
211 addClientSocket(clientFd);
217 SocketService::connectionThread(void* pData)
219 pthread_detach(pthread_self());
220 std::unique_ptr<ConnectionInfo> connectionInfo (static_cast<ConnectionInfo *>(pData));
221 SocketService &t = *static_cast<SocketService *>(connectionInfo->pData);
223 int ret = t.connectionService(connectionInfo->connFd);
226 PG_LOGE("Connection thread error");
227 t.removeClientSocket(connectionInfo->connFd);
228 close(connectionInfo->connFd);
235 SocketService::connectionService(int fd)
237 SocketConnection connector = SocketConnection(fd);
238 std::string interfaceName, methodName;
240 int res = connector.read(&interfaceName, &methodName);
241 if (res != PRIV_GUARD_ERROR_SUCCESS)
243 PG_LOGE("read : %d", res);
247 PG_LOGD("Got interface : %s", interfaceName.c_str());
248 PG_LOGD("Got method : %s", methodName.c_str());
250 if( m_callbackMap.find(interfaceName) == m_callbackMap.end())
252 PG_LOGE("Unknown interface : %s", interfaceName.c_str());
253 return PRIV_GUARD_ERROR_NO_DATA;
256 if(m_callbackMap[interfaceName].find(methodName) == m_callbackMap[interfaceName].end())
258 PG_LOGE("Unknown method : %s", methodName.c_str());
259 return PRIV_GUARD_ERROR_NO_DATA;
262 // if(m_callbackMap[interfaceName][methodName]->securityCallback != NULL){
263 // if(!m_callbackMap[interfaceName][methodName]->securityCallback(fd)){
264 // PG_LOGE("Security check returned false");
269 m_callbackMap[interfaceName][methodName]->serviceCallback(&connector);
271 removeClientSocket(fd);
274 return PRIV_GUARD_ERROR_SUCCESS;
278 SocketService::stop(void)
282 if(close(m_listenFd) == -1)
283 if(errno != ENOTCONN)
285 PG_LOGE("close() : %s", strerror_r(errno, buf, sizeof(buf)));
286 return PRIV_GUARD_ERROR_IPC_ERROR;
290 if((returned_value = pthread_kill(m_mainThread, m_signalToClose)) < 0)
292 errno = returned_value;
293 PG_LOGE("pthread_kill() : %s", strerror_r(errno, buf, sizeof(buf)));
294 return PRIV_GUARD_ERROR_IPC_ERROR;
296 pthread_join(m_mainThread, NULL);
298 return PRIV_GUARD_ERROR_SUCCESS;
302 SocketService::shutdown(void)
304 return PRIV_GUARD_ERROR_SUCCESS;
308 SocketService::registerServiceCallback(const std::string &interfaceName, const std::string &methodName, socketServiceCallback callbackMethod)
310 if(NULL == callbackMethod)
312 PG_LOGE("Null callback");
313 return PRIV_GUARD_ERROR_INVALID_PARAMETER;
315 if(interfaceName.empty() || methodName.empty())
317 PG_LOGE("Interface and method name cannot be empty");
318 return PRIV_GUARD_ERROR_INVALID_PARAMETER;
321 auto serviceCallbackPtr = std::make_shared<ServiceCallback>(ServiceCallback(callbackMethod));
322 m_callbackMap[interfaceName][methodName] = serviceCallbackPtr;
324 return PRIV_GUARD_ERROR_SUCCESS;
328 SocketService::addClientSocket(int clientSocket)
330 std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
331 m_clientSocketList.push_back(clientSocket);
335 SocketService::removeClientSocket(int clientSocket)
337 std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
338 m_clientSocketList.remove(clientSocket);
342 SocketService::popClientSocket(int * pClientSocket)
344 std::lock_guard<std::mutex> guard(m_clientSocketListMutex);
345 if(m_clientSocketList.empty())
347 *pClientSocket = m_clientSocketList.front();
348 m_clientSocketList.pop_front();
354 SocketService::closeConnections(void)
358 PG_LOGI("Closing client sockets");
359 while(popClientSocket(&clientSocket))
361 if(close(clientSocket) == -1)
363 PG_LOGE("close() : %s", strerror_r(errno, buf, sizeof(buf)));