0da326de46a8ae20089e174b2a487751c9acc210
[platform/core/security/cynara.git] / src / service / sockets / SocketManager.cpp
1 /*
2  * Copyright (c) 2014-2015 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  * @file        src/service/sockets/SocketManager.cpp
18  * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
19  * @author      Adam Malinowski <a.malinowsk2@partner.samsung.com>
20  * @version     1.0
21  * @brief       This file implements socket layer manager for cynara
22  */
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <memory>
27 #include <signal.h>
28 #include <sys/select.h>
29 #include <sys/signalfd.h>
30 #include <sys/socket.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/un.h>
34 #include <unistd.h>
35
36 #ifdef BUILD_WITH_SYSTEMD
37 #include <systemd/sd-daemon.h>
38 #endif
39
40 #include <log/log.h>
41 #include <common.h>
42 #include <config/PathConfig.h>
43 #include <exceptions/DescriptorNotExistsException.h>
44 #include <exceptions/InitException.h>
45 #include <exceptions/UnexpectedErrorException.h>
46
47 #include <logic/Logic.h>
48 #include <main/Cynara.h>
49 #include <protocol/ProtocolAdmin.h>
50 #include <protocol/ProtocolAgent.h>
51 #include <protocol/ProtocolClient.h>
52 #include <protocol/ProtocolSignal.h>
53 #include <request/pointers.h>
54 #include <request/RequestContext.h>
55 #include <stdexcept>
56
57 #include "SocketManager.h"
58
59 namespace Cynara {
60
61 SocketManager::SocketManager() : m_working(false), m_maxDesc(-1) {
62     FD_ZERO(&m_readSet);
63     FD_ZERO(&m_writeSet);
64 }
65
66 SocketManager::~SocketManager() {
67 }
68
69 void SocketManager::run(void) {
70     init();
71     mainLoop();
72 }
73
74 void SocketManager::init(void) {
75     LOGI("SocketManger init start");
76     const mode_t clientSocketUMask(0);
77     const mode_t adminSocketUMask(0077);
78     const mode_t agentSocketUMask(0);
79
80     createDomainSocket(std::make_shared<ProtocolClient>(), PathConfig::SocketPath::client,
81                        clientSocketUMask, true);
82     createDomainSocket(std::make_shared<ProtocolAdmin>(), PathConfig::SocketPath::admin,
83                        adminSocketUMask, false);
84     createDomainSocket(std::make_shared<ProtocolAgent>(), PathConfig::SocketPath::agent,
85                        agentSocketUMask, false);
86     createSignalSocket(std::make_shared<ProtocolSignal>());
87     LOGI("SocketManger init done");
88 }
89
90 void SocketManager::mainLoop(void) {
91     LOGI("SocketManger mainLoop start");
92     m_working  = true;
93     while (m_working) {
94         fd_set readSet = m_readSet;
95         fd_set writeSet = m_writeSet;
96
97         int ret = select(m_maxDesc + 1, &readSet, &writeSet, nullptr, nullptr);
98
99         if (ret < 0) {
100             switch (errno) {
101             case EINTR:
102                 continue;
103             default:
104                 int err = errno;
105                 throw UnexpectedErrorException(err, strerror(err));
106             }
107         } else if (ret > 0) {
108             for (int i = 0; i < m_maxDesc + 1 && ret; ++i) {
109                 if (FD_ISSET(i, &readSet)) {
110                     readyForRead(i);
111                     --ret;
112                 }
113                 if (FD_ISSET(i, &writeSet)) {
114                     readyForWrite(i);
115                     --ret;
116                 }
117             }
118
119             for (int i = 0; i < m_maxDesc + 1; ++i) {
120                 if (m_fds[i].isUsed() && m_fds[i].hasDataToWrite())
121                     addWriteSocket(i);
122             }
123         }
124     }
125     LOGI("SocketManger mainLoop done");
126 }
127
128 void SocketManager::mainLoopStop(void) {
129     m_working = false;
130 }
131
132 void SocketManager::readyForRead(int fd) {
133     LOGD("SocketManger readyForRead on fd [%d] start", fd);
134     auto &desc = m_fds[fd];
135     if (desc.isListen()) {
136         readyForAccept(fd);
137         return;
138     }
139
140     RawBuffer readBuffer(DEFAULT_BUFFER_SIZE);
141     ssize_t size = read(fd, readBuffer.data(), DEFAULT_BUFFER_SIZE);
142
143     if (size > 0) {
144         LOGD("read [%zd] bytes", size);
145         readBuffer.resize(size);
146         if (handleRead(fd, readBuffer)) {
147             LOGD("SocketManger readyForRead on fd [%d] successfully done", fd);
148             return;
149         }
150         LOGI("interpreting buffer read from [%d] failed", fd);
151     } else if (size < 0) {
152         int err = errno;
153         switch (err) {
154             case EAGAIN:
155 #if EWOULDBLOCK != EAGAIN
156             case EWOULDBLOCK:
157 #endif
158             case EINTR:
159                 return;
160             default:
161                 LOGW("While reading from [%d] socket, error [%d]:<%s>",
162                      fd, err, strerror(err));
163         }
164     } else {
165         LOGN("Socket [%d] closed on other end", fd);
166     }
167     closeSocket(fd);
168     LOGD("SocketManger readyForRead on fd [%d] done", fd);
169 }
170
171 void SocketManager::readyForWrite(int fd) {
172     LOGD("SocketManger readyForWrite on fd [%d] start", fd);
173     auto &desc = m_fds[fd];
174     auto &buffer = desc.prepareWriteBuffer();
175     size_t size = buffer.size();
176     ssize_t result = write(fd, buffer.data(), size);
177     if (result == -1) {
178         int err = errno;
179         switch (err) {
180         case EAGAIN:
181         case EINTR:
182             // select will trigger write once again, nothing to do
183             break;
184         case EPIPE:
185         default:
186             LOGD("Error during write to fd [%d]:<%s> ", fd, strerror(err));
187             closeSocket(fd);
188             break;
189         }
190         return; // We do not want to propagate error to next layer
191     }
192
193     LOGD("written [%zd] bytes", result);
194     buffer.erase(buffer.begin(), buffer.begin() + result);
195
196     if (buffer.empty())
197         removeWriteSocket(fd);
198     LOGD("SocketManger readyForWrite on fd [%d] done", fd);
199 }
200
201 void SocketManager::readyForAccept(int fd) {
202     LOGD("SocketManger readyForAccept on fd [%d] start", fd);
203     struct sockaddr_un clientAddr;
204     unsigned int clientLen = sizeof(clientAddr);
205     int clientFd = accept4(fd, (struct sockaddr*) &clientAddr, &clientLen, SOCK_NONBLOCK);
206     if (clientFd == -1) {
207         int err = errno;
208         LOGW("Error in accept on socket [%d]: <%s>", fd, strerror(err));
209         return;
210     }
211     LOGD("Accept on sock [%d]. New client socket opened [%d]", fd, clientFd);
212
213     auto &desc = createDescriptor(clientFd, m_fds[fd].isClient());
214     desc.setListen(false);
215     desc.setProtocol(m_fds[fd].protocol()->clone());
216     addReadSocket(clientFd);
217     LOGD("SocketManger readyForAccept on fd [%d] done", fd);
218 }
219
220 void SocketManager::closeSocket(int fd) {
221     LOGD("SocketManger closeSocket fd [%d] start", fd);
222     Descriptor &desc = m_fds[fd];
223     requestTaker()->contextClosed(RequestContext(nullptr, desc.writeQueue()));
224     removeReadSocket(fd);
225     removeWriteSocket(fd);
226     desc.clear();
227     close(fd);
228     LOGD("SocketManger closeSocket fd [%d] done", fd);
229 }
230
231 bool SocketManager::handleRead(int fd, const RawBuffer &readbuffer) {
232     LOGD("SocketManger handleRead on fd [%d] start", fd);
233     auto &desc = m_fds[fd];
234     desc.pushReadBuffer(readbuffer);
235
236     try {
237         while(true) {
238             //try extract request from binary data received on socket
239             auto req = desc.extractRequest();
240             if (!req)   // not enough data to build request yet
241                 break;
242             LOGD("request extracted");
243
244             //build context
245             RequestContext context(desc.responseTaker(), desc.writeQueue());
246             //pass request to request taker
247             req->execute(*requestTaker(), context);
248         }
249     } catch (const Exception &ex) {
250         LOGE("Error handling request <%s>. Closing socket", ex.what());
251         return false;
252     }
253     LOGD("SocketManger handleRead on fd [%d] done", fd);
254     return true;
255 }
256
257 void SocketManager::createDomainSocket(ProtocolPtr protocol, const std::string &path, mode_t mask,
258                                        bool client) {
259     int fd;
260 #ifdef BUILD_WITH_SYSTEMD
261     fd = getSocketFromSystemD(path);
262     if (fd == -1)
263 #endif
264         fd = createDomainSocketHelp(path, mask);
265
266     auto &desc = createDescriptor(fd, client);
267     desc.setListen(true);
268     desc.setProtocol(protocol);
269     addReadSocket(fd);
270
271     LOGD("Domain socket: [%d] added.", fd);
272 }
273
274 int SocketManager::createDomainSocketHelp(const std::string &path, mode_t mask) {
275     int fd;
276
277     if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
278         int err = errno;
279         LOGE("Error during UNIX socket creation: <%s>",  strerror(err));
280         throw InitException();
281     }
282
283     int flags;
284     if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
285         flags = 0;
286     if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
287         int err = errno;
288         close(fd);
289         LOGE("Error setting \"O_NONBLOCK\" on descriptor [%d] with fcntl: <%s>",
290              fd, strerror(err));
291         throw InitException();
292     }
293
294     sockaddr_un serverAddress;
295     memset(&serverAddress, 0, sizeof(serverAddress));
296     serverAddress.sun_family = AF_UNIX;
297     if (path.length() > sizeof(serverAddress.sun_path)) {
298         LOGE("Path for unix domain socket <%s> is [%zu] bytes long, while it should be maximum "
299              "[%zu] bytes long", path.c_str(), path.length(), sizeof(serverAddress));
300         throw InitException();
301     }
302     strcpy(serverAddress.sun_path, path.c_str());
303     unlink(serverAddress.sun_path);
304
305     mode_t originalUmask;
306     originalUmask = umask(mask);
307
308     if (bind(fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
309         int err = errno;
310         close(fd);
311         LOGE("Error in bind socket descriptor [%d] to path <%s>: <%s>",
312              fd, path.c_str(), strerror(err));
313         throw InitException();
314     }
315
316     umask(originalUmask);
317
318     if (listen(fd, 5) == -1) {
319         int err = errno;
320         close(fd);
321         LOGE("Error setting listen on file descriptor [%d], path <%s>: <%s>",
322              fd, path.c_str(), strerror(err));
323         throw InitException();
324     }
325
326     return fd;
327 }
328
329 #ifdef BUILD_WITH_SYSTEMD
330 int SocketManager::getSocketFromSystemD(const std::string &path) {
331     int n = sd_listen_fds(0);
332     LOGI("sd_listen_fds returns: [%d]", n);
333     if (n < 0) {
334         LOGE("Error in sd_listend_fds");
335         throw InitException();
336     }
337
338     for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
339         if (sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0) {
340             LOGI("Useable socket <%s> was passed by SystemD under descriptor [%d]",
341                     path.c_str(), fd);
342             return fd;
343         }
344     }
345     LOGI("No useable sockets were passed by systemd.");
346     return -1;
347 }
348 #endif // BUILD_WITH_SYSTEMD
349
350 void SocketManager::createSignalSocket(ProtocolPtr protocol) {
351     sigset_t mask;
352
353     // Maybe someone will find useful some kind of registering signals with callbacks
354     // but for now I'm making it as simple as possible.
355     sigemptyset(&mask);
356     sigaddset(&mask, SIGTERM); // systemd terminates service sending this signal
357
358     if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
359         LOGE("sigprocmask failed: <%s>", strerror(errno));
360         return;
361     }
362
363     int fd = signalfd(-1, &mask, SFD_NONBLOCK);
364     if (fd < 0) {
365         LOGE("Creating signal file descriptor failed: <%s>", strerror(errno));
366         return;
367     }
368
369     auto &desc = createDescriptor(fd, false);
370     desc.setListen(false);
371     desc.setProtocol(protocol);
372     addReadSocket(fd);
373
374     LOGD("Signal socket: [%d] added.", fd);
375 }
376
377 Descriptor &SocketManager::createDescriptor(int fd, bool client) {
378     if (fd > m_maxDesc) {
379         m_maxDesc = fd;
380         if (fd >= static_cast<int>(m_fds.size()))
381             m_fds.resize(fd + 20);
382     }
383     auto &desc = m_fds[fd];
384     desc.setUsed(true);
385     desc.setClient(client);
386     return desc;
387 }
388
389 void SocketManager::addReadSocket(int fd) {
390     FD_SET(fd, &m_readSet);
391 }
392
393 void SocketManager::removeReadSocket(int fd) {
394     FD_CLR(fd, &m_readSet);
395 }
396
397 void SocketManager::addWriteSocket(int fd) {
398     FD_SET(fd, &m_writeSet);
399 }
400
401 void SocketManager::removeWriteSocket(int fd) {
402     FD_CLR(fd, &m_writeSet);
403 }
404
405 RequestTakerPtr SocketManager::requestTaker(void) {
406     return std::static_pointer_cast<RequestTaker>(m_logic);
407 }
408
409 void SocketManager::disconnectAllClients(void) {
410     for(int i = 0; i <= m_maxDesc; ++i) {
411         auto &desc = m_fds[i];
412         if(desc.isUsed() && desc.isClient() && !desc.isListen())
413             closeSocket(i);
414     }
415 }
416
417 } // namespace Cynara