2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Rafal Krypa <r.krypa@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
19 * @file socket-manager.cpp
20 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
22 * @brief Implementation of SocketManager.
28 #include <sys/select.h>
29 #include <sys/signalfd.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/smack.h>
41 #include <systemd/sd-daemon.h>
43 #include <dpl/log/log.h>
44 #include <dpl/assert.h>
46 #include <smack-check.h>
47 #include <socket-manager.h>
51 const time_t SOCKET_TIMEOUT = 20;
53 } // namespace anonymous
55 namespace SecurityManager {
57 struct DummyService : public GenericSocketService {
58 ServiceDescriptionVector GetServiceDescription() {
59 return ServiceDescriptionVector();
61 void Event(const AcceptEvent &event) { (void)event; }
62 void Event(const WriteEvent &event) { (void)event; }
63 void Event(const ReadEvent &event) { (void)event; }
64 void Event(const CloseEvent &event) { (void)event; }
67 struct SignalService : public GenericSocketService {
72 sigaddset(&mask, SIGTERM);
73 if (-1 == pthread_sigmask(SIG_BLOCK, &mask, NULL))
75 return signalfd(-1, &mask, 0);
78 ServiceDescriptionVector GetServiceDescription() {
79 return ServiceDescriptionVector();
82 void Event(const AcceptEvent &event) { (void)event; } // not supported
83 void Event(const WriteEvent &event) { (void)event; } // not supported
84 void Event(const CloseEvent &event) { (void)event; } // not supported
86 void Event(const ReadEvent &event) {
87 LogDebug("Get signal information");
89 if(sizeof(struct signalfd_siginfo) != event.rawBuffer.size()) {
90 LogError("Wrong size of signalfd_siginfo struct. Expected: "
91 << sizeof(signalfd_siginfo) << " Get: "
92 << event.rawBuffer.size());
96 signalfd_siginfo *siginfo = (signalfd_siginfo*)(&(event.rawBuffer[0]));
98 if (siginfo->ssi_signo == SIGTERM) {
99 LogInfo("Got signal: SIGTERM");
100 static_cast<SocketManager*>(m_serviceManager)->MainLoopStop();
104 LogInfo("This should not happend. Got signal: " << siginfo->ssi_signo);
108 SocketManager::SocketDescription&
109 SocketManager::CreateDefaultReadSocketDescription(int sock, bool timeout)
111 if ((int)m_socketDescriptionVector.size() <= sock)
112 m_socketDescriptionVector.resize(sock+20);
114 auto &desc = m_socketDescriptionVector[sock];
115 desc.isListen = false;
117 desc.interfaceID = 0;
119 desc.counter = ++m_counter;
122 desc.timeout = time(NULL) + SOCKET_TIMEOUT;
123 if (false == desc.isTimeout) {
125 tm.time = desc.timeout;
127 m_timeoutQueue.push(tm);
131 desc.isTimeout = timeout;
133 FD_SET(sock, &m_readSet);
134 m_maxDesc = sock > m_maxDesc ? sock : m_maxDesc;
138 SocketManager::SocketManager()
143 FD_ZERO(&m_writeSet);
144 if (-1 == pipe(m_notifyMe)) {
146 ThrowMsg(Exception::InitFailed, "Error in pipe: " << strerror(err));
148 LogInfo("Pipe: Read desc: " << m_notifyMe[0] << " Write desc: " << m_notifyMe[1]);
150 auto &desc = CreateDefaultReadSocketDescription(m_notifyMe[0], false);
151 desc.service = new DummyService;
153 // std::thread bases on pthread so this should work fine
156 sigaddset(&set, SIGPIPE);
157 pthread_sigmask(SIG_BLOCK, &set, NULL);
159 // add support for TERM signal (passed from systemd)
160 auto *signalService = new SignalService;
161 signalService->SetSocketManager(this);
162 int filefd = signalService->GetDescriptor();
164 LogError("Error in SignalService.GetDescriptor()");
165 delete signalService;
167 auto &desc2 = CreateDefaultReadSocketDescription(filefd, false);
168 desc2.service = signalService;
169 LogInfo("SignalService mounted on " << filefd << " descriptor");
173 SocketManager::~SocketManager() {
174 std::set<GenericSocketService*> serviceMap;
176 // Find all services. Set is used to remove duplicates.
177 // In this implementation, services are not able to react in any way.
178 for (size_t i=0; i < m_socketDescriptionVector.size(); ++i)
179 if (m_socketDescriptionVector[i].isOpen)
180 serviceMap.insert(m_socketDescriptionVector[i].service);
182 // Time to destroy all services.
183 for(auto it = serviceMap.begin(); it != serviceMap.end(); ++it) {
184 LogDebug("delete " << (void*)(*it));
188 for (size_t i = 0; i < m_socketDescriptionVector.size(); ++i)
189 if (m_socketDescriptionVector[i].isOpen)
192 // All socket except one were closed. Now pipe input must be closed.
193 close(m_notifyMe[1]);
196 void SocketManager::ReadyForAccept(int sock) {
197 struct sockaddr_un clientAddr;
198 unsigned int clientLen = sizeof(clientAddr);
199 int client = accept4(sock, (struct sockaddr*) &clientAddr, &clientLen, SOCK_NONBLOCK);
200 // LogInfo("Accept on sock: " << sock << " Socket opended: " << client);
203 LogError("Error in accept: " << strerror(err));
207 auto &desc = CreateDefaultReadSocketDescription(client, true);
208 desc.interfaceID = m_socketDescriptionVector[sock].interfaceID;
209 desc.service = m_socketDescriptionVector[sock].service;
210 desc.useSendMsg = m_socketDescriptionVector[sock].useSendMsg;
212 GenericSocketService::AcceptEvent event;
213 event.connectionID.sock = client;
214 event.connectionID.counter = desc.counter;
215 event.interfaceID = desc.interfaceID;
216 desc.service->Event(event);
219 void SocketManager::ReadyForRead(int sock) {
220 if (m_socketDescriptionVector[sock].isListen) {
221 ReadyForAccept(sock);
225 GenericSocketService::ReadEvent event;
226 event.connectionID.sock = sock;
227 event.connectionID.counter = m_socketDescriptionVector[sock].counter;
228 event.rawBuffer.resize(4096);
230 auto &desc = m_socketDescriptionVector[sock];
231 desc.timeout = time(NULL) + SOCKET_TIMEOUT;
233 ssize_t size = read(sock, &event.rawBuffer[0], 4096);
237 } else if (size >= 0) {
238 event.rawBuffer.resize(size);
239 desc.service->Event(event);
240 } else if (size == -1) {
247 LogError("Reading sock error: " << strerror(err));
253 void SocketManager::ReadyForSendMsg(int sock) {
254 auto &desc = m_socketDescriptionVector[sock];
256 if (desc.sendMsgDataQueue.empty()) {
257 FD_CLR(sock, &m_writeSet);
261 auto data = desc.sendMsgDataQueue.front();
262 ssize_t result = sendmsg(sock, data.getMsghdr(), data.flags());
272 LogError("Error during send: " << strerror(err));
278 desc.sendMsgDataQueue.pop();
281 if (desc.sendMsgDataQueue.empty()) {
282 FD_CLR(sock, &m_writeSet);
285 desc.timeout = time(NULL) + SOCKET_TIMEOUT;
287 GenericSocketService::WriteEvent event;
288 event.connectionID.sock = sock;
289 event.connectionID.counter = desc.counter;
291 event.left = desc.sendMsgDataQueue.size();
293 desc.service->Event(event);
296 void SocketManager::ReadyForWriteBuffer(int sock) {
297 auto &desc = m_socketDescriptionVector[sock];
298 size_t size = desc.rawBuffer.size();
299 ssize_t result = write(sock, &desc.rawBuffer[0], size);
305 // select will trigger write once again, nothing to do
309 LogError("Error during write: " << strerror(err));
313 return; // We do not want to propagate error to next layer
316 desc.rawBuffer.erase(desc.rawBuffer.begin(), desc.rawBuffer.begin()+result);
318 desc.timeout = time(NULL) + SOCKET_TIMEOUT;
320 if (desc.rawBuffer.empty())
321 FD_CLR(sock, &m_writeSet);
323 GenericSocketService::WriteEvent event;
324 event.connectionID.sock = sock;
325 event.connectionID.counter = desc.counter;
327 event.left = desc.rawBuffer.size();
329 desc.service->Event(event);
332 void SocketManager::ReadyForWrite(int sock) {
333 m_socketDescriptionVector[sock].useSendMsg ?
334 ReadyForSendMsg(sock) : ReadyForWriteBuffer(sock);
337 void SocketManager::MainLoop() {
338 // remove evironment values passed by systemd
341 // Daemon is ready to work.
342 sd_notify(0, "READY=1");
346 fd_set readSet = m_readSet;
347 fd_set writeSet = m_writeSet;
349 timeval localTempTimeout;
350 timeval *ptrTimeout = &localTempTimeout;
352 // I need to extract timeout from priority_queue.
353 // Timeout in priority_queue may be deprecated.
354 // I need to find some actual one.
355 while(!m_timeoutQueue.empty()) {
356 auto &top = m_timeoutQueue.top();
357 auto &desc = m_socketDescriptionVector[top.sock];
359 if (top.time == desc.timeout) {
360 // This timeout matches timeout from socket.
364 // This socket was used after timeout in priority queue was set up.
365 // We need to update timeout and find some useable one.
366 Timeout tm = { desc.timeout , top.sock};
367 m_timeoutQueue.pop();
368 m_timeoutQueue.push(tm);
372 if (m_timeoutQueue.empty()) {
373 LogDebug("No usaable timeout found.");
374 ptrTimeout = NULL; // select will wait without timeout
376 time_t currentTime = time(NULL);
377 auto &pqTimeout = m_timeoutQueue.top();
379 // 0 means that select won't block and socket will be closed ;-)
381 currentTime < pqTimeout.time ? pqTimeout.time - currentTime : 0;
382 ptrTimeout->tv_usec = 0;
383 // LogDebug("Set up timeout: " << (int)ptrTimeout->tv_sec
384 // << " seconds. Socket: " << pqTimeout.sock);
387 int ret = select(m_maxDesc+1, &readSet, &writeSet, NULL, ptrTimeout);
389 if (0 == ret) { // timeout
390 Assert(!m_timeoutQueue.empty());
392 Timeout pqTimeout = m_timeoutQueue.top();
393 m_timeoutQueue.pop();
395 auto &desc = m_socketDescriptionVector[pqTimeout.sock];
397 if (!desc.isTimeout || !desc.isOpen) {
398 // Connection was closed. Timeout is useless...
399 desc.isTimeout = false;
403 if (pqTimeout.time < desc.timeout) {
405 // This socket was used after timeout. We need to update timeout.
406 pqTimeout.time = desc.timeout;
407 m_timeoutQueue.push(pqTimeout);
411 // timeout from m_timeoutQueue matches with socket.timeout
412 // and connection is open. Time to close it!
413 // Putting new timeout in queue here is pointless.
414 desc.isTimeout = false;
415 CloseSocket(pqTimeout.sock);
417 // All done. Now we should process next select ;-)
424 LogDebug("EINTR in select");
428 LogError("Error in select: " << strerror(err));
433 for(int i = 0; i<m_maxDesc+1 && ret; ++i) {
434 if (FD_ISSET(i, &readSet)) {
438 if (FD_ISSET(i, &writeSet)) {
447 void SocketManager::MainLoopStop()
453 int SocketManager::GetSocketFromSystemD(
454 const GenericSocketService::ServiceDescription &desc)
458 // TODO optimalization - do it once in object constructor
459 // and remember all information path->sockfd
460 int n = sd_listen_fds(0);
462 LogInfo("sd_listen_fds returns: " << n);
465 LogError("Error in sd_listend_fds");
466 ThrowMsg(Exception::InitFailed, "Error in sd_listend_fds");
469 for(fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START+n; ++fd) {
470 if (0 < sd_is_socket_unix(fd, SOCK_STREAM, 1,
471 desc.serviceHandlerPath.c_str(), 0))
473 LogInfo("Useable socket " << desc.serviceHandlerPath <<
474 " was passed by SystemD under descriptor " << fd);
478 LogInfo("No useable sockets were passed by systemd.");
482 int SocketManager::CreateDomainSocketHelp(
483 const GenericSocketService::ServiceDescription &desc)
487 if (-1 == (sockfd = socket(AF_UNIX, SOCK_STREAM, 0))) {
489 LogError("Error in socket: " << strerror(err));
490 ThrowMsg(Exception::InitFailed, "Error in socket: " << strerror(err));
494 LogInfo("Set up smack label: " << desc.smackLabel);
496 if (0 != smack_fsetlabel(sockfd, desc.smackLabel.c_str(), SMACK_LABEL_IPIN)) {
497 LogError("Error in smack_fsetlabel");
498 ThrowMsg(Exception::InitFailed, "Error in smack_fsetlabel");
501 LogInfo("No smack on platform. Socket won't be securied with smack label!");
505 if (-1 == (flags = fcntl(sockfd, F_GETFL, 0)))
508 if (-1 == fcntl(sockfd, F_SETFL, flags | O_NONBLOCK)) {
511 LogError("Error in fcntl: " << strerror(err));
512 ThrowMsg(Exception::InitFailed, "Error in fcntl: " << strerror(err));
515 sockaddr_un serverAddress;
516 memset(&serverAddress, 0, sizeof(serverAddress));
517 serverAddress.sun_family = AF_UNIX;
518 strcpy(serverAddress.sun_path, desc.serviceHandlerPath.c_str());
519 unlink(serverAddress.sun_path);
521 mode_t originalUmask;
522 originalUmask = umask(0);
524 if (-1 == bind(sockfd, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) {
527 LogError("Error in bind: " << strerror(err));
528 ThrowMsg(Exception::InitFailed, "Error in bind: " << strerror(err));
531 umask(originalUmask);
533 if (-1 == listen(sockfd, 5)) {
536 LogError("Error in listen: " << strerror(err));
537 ThrowMsg(Exception::InitFailed, "Error in listen: " << strerror(err));
543 void SocketManager::CreateDomainSocket(
544 GenericSocketService *service,
545 const GenericSocketService::ServiceDescription &desc)
547 int sockfd = GetSocketFromSystemD(desc);
549 sockfd = CreateDomainSocketHelp(desc);
551 auto &description = CreateDefaultReadSocketDescription(sockfd, false);
553 description.isListen = true;
554 description.interfaceID = desc.interfaceID;
555 description.useSendMsg = desc.useSendMsg;
556 description.service = service;
558 LogDebug("Listen on socket: " << sockfd <<
559 " Handler: " << desc.serviceHandlerPath.c_str());
562 void SocketManager::RegisterSocketService(GenericSocketService *service) {
563 service->SetSocketManager(this);
564 auto serviceVector = service->GetServiceDescription();
566 for (auto iter = serviceVector.begin(); iter != serviceVector.end(); ++iter)
567 CreateDomainSocket(service, *iter);
568 } Catch (Exception::Base) {
569 for (int i =0; i < (int)m_socketDescriptionVector.size(); ++i)
571 auto &desc = m_socketDescriptionVector[i];
572 if (desc.service == service && desc.isOpen) {
577 ReThrow(Exception::Base);
581 void SocketManager::Close(ConnectionID connectionID) {
583 std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
584 m_closeQueue.push(connectionID);
589 void SocketManager::Write(ConnectionID connectionID, const RawBuffer &rawBuffer) {
591 buffer.connectionID = connectionID;
592 buffer.rawBuffer = rawBuffer;
594 std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
595 m_writeBufferQueue.push(buffer);
600 void SocketManager::Write(ConnectionID connectionID, const SendMsgData &sendMsgData) {
602 data.connectionID = connectionID;
603 data.sendMsgData = sendMsgData;
605 std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
606 m_writeDataQueue.push(data);
611 void SocketManager::NotifyMe() {
612 TEMP_FAILURE_RETRY(write(m_notifyMe[1], "You have message ;-)", 1));
615 void SocketManager::ProcessQueue() {
619 std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
620 while (!m_writeBufferQueue.empty()) {
621 buffer = m_writeBufferQueue.front();
622 m_writeBufferQueue.pop();
624 auto &desc = m_socketDescriptionVector[buffer.connectionID.sock];
627 LogDebug("Received packet for write but connection is closed. Packet ignored!");
631 if (desc.counter != buffer.connectionID.counter)
633 LogDebug("Received packet for write but counter is broken. Packet ignored!");
637 if (desc.useSendMsg) {
638 LogError("Some service tried to push rawdata to socket that usees sendmsg!");
643 buffer.rawBuffer.begin(),
644 buffer.rawBuffer.end(),
645 std::back_inserter(desc.rawBuffer));
647 FD_SET(buffer.connectionID.sock, &m_writeSet);
650 while(!m_writeDataQueue.empty()) {
651 data = m_writeDataQueue.front();
652 m_writeDataQueue.pop();
654 auto &desc = m_socketDescriptionVector[data.connectionID.sock];
657 LogDebug("Received packet for sendmsg but connection is closed. Packet ignored!");
661 if (desc.counter != data.connectionID.counter)
663 LogDebug("Received packet for write but counter is broken. Packet ignored!");
667 if (!desc.useSendMsg) {
668 LogError("Some service tries to push SendMsgData to socket that uses write!");
672 desc.sendMsgDataQueue.push(data.sendMsgData);
674 FD_SET(data.connectionID.sock, &m_writeSet);
679 ConnectionID connection;
681 std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
682 if (m_closeQueue.empty())
684 connection = m_closeQueue.front();
688 if (!m_socketDescriptionVector[connection.sock].isOpen)
691 if (connection.counter != m_socketDescriptionVector[connection.sock].counter)
694 CloseSocket(connection.sock);
698 void SocketManager::CloseSocket(int sock) {
699 // LogInfo("Closing socket: " << sock);
700 auto &desc = m_socketDescriptionVector[sock];
702 if (!(desc.isOpen)) {
703 // This may happend when some information was waiting for write to the
704 // socket and in the same time socket was closed by the client.
705 LogError("Socket " << sock << " is not open. Nothing to do!");
709 GenericSocketService::CloseEvent event;
710 event.connectionID.sock = sock;
711 event.connectionID.counter = desc.counter;
712 auto service = desc.service;
716 desc.interfaceID = -1;
717 desc.rawBuffer.clear();
718 while(!desc.sendMsgDataQueue.empty())
719 desc.sendMsgDataQueue.pop();
722 service->Event(event);
724 LogError("Critical! Service is NULL! This should never happend!");
726 TEMP_FAILURE_RETRY(close(sock));
727 FD_CLR(sock, &m_readSet);
728 FD_CLR(sock, &m_writeSet);
731 } // namespace SecurityManager