IPC: Support older glib
[platform/core/security/vasum.git] / common / ipc / service.cpp
1 /*
2 *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 *  Contact: Jan Olszak <j.olszak@samsung.com>
5 *
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
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
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
17 */
18
19 /**
20  * @file
21  * @author  Jan Olszak (j.olszak@samsung.com)
22  * @brief   Implementation of the IPC handling class
23  */
24
25 #include "config.hpp"
26
27 #include "ipc/service.hpp"
28 #include "ipc/exception.hpp"
29 #include "logger/logger.hpp"
30
31 using namespace std::placeholders;
32
33 namespace vasum {
34 namespace ipc {
35
36 Service::Service(const std::string& socketPath,
37                  const PeerCallback& addPeerCallback,
38                  const PeerCallback& removePeerCallback)
39     : mProcessor("[SERVICE] "),
40       mAcceptor(socketPath, std::bind(&Processor::addPeer, &mProcessor, _1))
41
42 {
43     LOGS("Service Constructor");
44     setNewPeerCallback(addPeerCallback);
45     setRemovedPeerCallback(removePeerCallback);
46 }
47
48 Service::~Service()
49 {
50     LOGS("Service Destructor");
51     try {
52         stop();
53     } catch (IPCException& e) {
54         LOGE("Error in Service's destructor: " << e.what());
55     }
56 }
57
58 void Service::start(const bool usesExternalPolling)
59 {
60     LOGS("Service start");
61     if (usesExternalPolling) {
62         startPoll();
63     }
64     mProcessor.start(usesExternalPolling);
65
66     // There can be an incoming connection from mAcceptor before mProcessor is listening,
67     // but it's OK. It will handle the connection when ready. So no need to wait for mProcessor.
68     if (!usesExternalPolling) {
69         mAcceptor.start();
70     }
71 }
72
73 bool Service::isStarted()
74 {
75     return mProcessor.isStarted();
76 }
77
78 void Service::stop()
79 {
80     LOGS("Service stop");
81     mAcceptor.stop();
82     mProcessor.stop();
83
84     if (mIPCGSourcePtr) {
85         stopPoll();
86     }
87 }
88
89 void Service::startPoll()
90 {
91     LOGS("Service startPoll");
92
93     mIPCGSourcePtr = IPCGSource::create(std::bind(&Service::handle, this, _1, _2));
94     mIPCGSourcePtr->addFD(mAcceptor.getEventFD());
95     mIPCGSourcePtr->addFD(mAcceptor.getConnectionFD());
96     mIPCGSourcePtr->addFD(mProcessor.getEventFD());
97     mIPCGSourcePtr->attach();
98 }
99
100 void Service::stopPoll()
101 {
102     LOGS("Service stopPoll");
103
104     mIPCGSourcePtr->removeFD(mAcceptor.getEventFD());
105     mIPCGSourcePtr->removeFD(mAcceptor.getConnectionFD());
106     mIPCGSourcePtr->removeFD(mProcessor.getEventFD());
107     mIPCGSourcePtr->detach();
108     mIPCGSourcePtr.reset();
109 }
110
111 void Service::handle(const FileDescriptor fd, const short pollEvent)
112 {
113     LOGS("Service handle");
114
115     if (!isStarted()) {
116         LOGW("Service stopped");
117         return;
118     }
119
120     if (fd == mProcessor.getEventFD() && (pollEvent & POLLIN)) {
121         mProcessor.handleEvent();
122         return;
123
124     } else if (fd == mAcceptor.getConnectionFD() && (pollEvent & POLLIN)) {
125         mAcceptor.handleConnection();
126         return;
127
128     } else if (fd == mAcceptor.getEventFD() && (pollEvent & POLLIN)) {
129         mAcceptor.handleEvent();
130         return;
131
132     } else if (pollEvent & POLLIN) {
133         mProcessor.handleInput(fd);
134         return;
135
136     } else if (pollEvent & POLLHUP) {
137         mProcessor.handleLostConnection(fd);
138         return;
139     }
140 }
141
142 void Service::setNewPeerCallback(const PeerCallback& newPeerCallback)
143 {
144     LOGS("Service setNewPeerCallback");
145     auto callback = [newPeerCallback, this](FileDescriptor fd) {
146         if (mIPCGSourcePtr) {
147             mIPCGSourcePtr->addFD(fd);
148         }
149         if (newPeerCallback) {
150             newPeerCallback(fd);
151         }
152     };
153     mProcessor.setNewPeerCallback(callback);
154 }
155
156 void Service::setRemovedPeerCallback(const PeerCallback& removedPeerCallback)
157 {
158     LOGS("Service setRemovedPeerCallback");
159     auto callback = [removedPeerCallback, this](FileDescriptor fd) {
160         if (mIPCGSourcePtr) {
161             mIPCGSourcePtr->removeFD(fd);
162         }
163         if (removedPeerCallback) {
164             removedPeerCallback(fd);
165         }
166     };
167     mProcessor.setRemovedPeerCallback(callback);
168 }
169
170 void Service::removeMethod(const MethodID methodID)
171 {
172     LOGS("Service removeMethod methodID: " << methodID);
173     mProcessor.removeMethod(methodID);
174 }
175
176
177 } // namespace ipc
178 } // namespace vasum