Rectifyng this poniter deletion from member function
[platform/core/system/sensord.git] / src / shared / channel.cpp
1 /*
2  * sensord
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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 #include "channel.h"
21
22 #include <stdint.h>
23 #include <unistd.h>
24 #include <memory>
25
26 #include "sensor_log.h"
27 #include "channel_event_handler.h"
28
29 #define SYSTEMD_SOCK_BUF_SIZE 40000
30
31 using namespace ipc;
32
33 class send_event_handler : public event_handler
34 {
35 public:
36         send_event_handler(channel *ch, message *msg)
37         : m_ch(ch)
38         , m_msg(msg)
39         { }
40
41         bool handle(int fd, event_condition condition)
42         {
43                 if (!m_ch || !m_ch->is_connected())
44                         return false;
45
46                 if (condition & (EVENT_IN | EVENT_HUP))
47                         return false;
48
49                 if (!m_ch->send_sync(m_msg))
50                         return false;
51
52                 if (m_msg) {
53                         m_msg->unref();
54                         if(m_msg->ref_count() <= 0) {
55                                 delete m_msg;
56                                 m_msg = NULL;
57                         }
58                 }
59
60                 return false;
61         }
62
63 private:
64         channel *m_ch;
65         message *m_msg;
66 };
67
68 class read_event_handler : public event_handler
69 {
70 public:
71         read_event_handler(channel *ch)
72         : m_ch(ch)
73         { }
74
75         bool handle(int fd, event_condition condition)
76         {
77                 message msg;
78
79                 if (!m_ch || !m_ch->is_connected())
80                         return false;
81
82                 if (condition & (EVENT_OUT | EVENT_HUP))
83                         return false;
84
85                 if (!m_ch->read_sync(msg, false))
86                         return false;
87
88                 return false;
89         }
90
91 private:
92         channel *m_ch;
93 };
94
95 channel::channel(socket *sock)
96 : m_fd(sock->get_fd())
97 , m_event_id(0)
98 , m_socket(sock)
99 , m_handler(NULL)
100 , m_loop(NULL)
101 , m_connected(false)
102 {
103 }
104
105 channel::~channel()
106 {
107         /* disconnect() should not be called here */
108 }
109
110 void channel::bind(channel_handler *handler, event_loop *loop)
111 {
112         m_handler = handler;
113         m_loop = loop;
114         m_connected.store(true);
115
116         if (m_handler)
117                 m_handler->connected(this);
118 }
119
120 void channel::bind(void)
121 {
122         ret_if(!m_loop);
123         m_event_id = m_loop->add_event(m_socket->get_fd(),
124                         (EVENT_IN | EVENT_HUP | EVENT_NVAL),
125                         dynamic_cast<channel_event_handler *>(m_handler));
126 }
127
128 bool channel::connect(channel_handler *handler, event_loop *loop)
129 {
130         if (!m_socket->connect())
131                 return false;
132
133         bind(handler, loop);
134         return true;
135 }
136
137 void channel::disconnect(void)
138 {
139         ret_if(!is_connected());
140         m_connected.store(false);
141
142         if (m_handler) {
143                 m_handler->disconnected(this);
144                 m_handler = NULL;
145         }
146
147         if (m_loop) {
148                 m_loop->remove_event(m_event_id, true);
149                 m_loop = NULL;
150                 m_event_id = 0;
151         }
152
153         if (m_socket) {
154                 delete m_socket;
155                 m_socket = NULL;
156         }
157 }
158
159 bool channel::send(message *msg)
160 {
161         retv_if(!m_loop, false);
162
163         int cur_buffer_size = m_socket->get_current_buffer_size();
164         retv_if(cur_buffer_size > SYSTEMD_SOCK_BUF_SIZE, false);
165
166         send_event_handler *handler = new(std::nothrow) send_event_handler(this, msg);
167         retvm_if(!handler, false, "Failed to allocate memory");
168
169         msg->ref();
170
171         m_loop->add_event(m_socket->get_fd(),
172                         (EVENT_OUT | EVENT_HUP | EVENT_NVAL) , handler);
173
174         return true;
175 }
176
177 bool channel::send_sync(message *msg)
178 {
179         retv_if(!msg, false);
180
181         ssize_t size = 0;
182         char *buf = msg->body();
183
184         /* header */
185         size = m_socket->send(reinterpret_cast<void *>(msg->header()),
186                                    sizeof(message_header), true);
187         retv_if(size <= 0, false);
188         retv_if(msg->size() <= 0, true);
189
190         /* body */
191         size = m_socket->send(buf, msg->size(), true);
192         retv_if(size <= 0, false);
193
194         return true;
195 }
196
197 bool channel::read(void)
198 {
199         retv_if(!m_loop, false);
200
201         read_event_handler *handler = new(std::nothrow) read_event_handler(this);
202         retvm_if(!handler, false, "Failed to allocate memory");
203
204         m_loop->add_event(m_socket->get_fd(), (EVENT_IN | EVENT_HUP | EVENT_NVAL), handler);
205
206         return true;
207 }
208
209 bool channel::read_sync(message &msg, bool select)
210 {
211         message_header header;
212         ssize_t size = 0;
213         char buf[MAX_MSG_CAPACITY];
214
215         /* header */
216         size = m_socket->recv(&header, sizeof(message_header), select);
217         retv_if(size <= 0, false);
218
219         /* check error from header */
220         if (m_handler && header.err != 0) {
221                 m_handler->error_caught(this, header.err);
222                 msg.header()->err = header.err;
223                 return true;
224         }
225
226         /* body */
227         if (header.length > 0) {
228                 size = m_socket->recv(&buf, header.length, select);
229                 retv_if(size <= 0, false);
230         }
231
232         buf[header.length] = '\0';
233         msg.enclose(reinterpret_cast<const void *>(buf), header.length);
234         msg.set_type(header.type);
235         msg.header()->err = header.err;
236
237         if (m_handler)
238                 m_handler->read(this, msg);
239
240         return true;
241 }
242
243 bool channel::is_connected(void)
244 {
245         return m_connected.load();
246 }
247
248 bool channel::set_option(int type, int value)
249 {
250         switch (type) {
251         case SO_SNDBUF:
252                 m_socket->set_buffer_size(type, value);
253                 break;
254         case SO_RCVBUF:
255                 m_socket->set_buffer_size(type, value);
256                 break;
257         default:
258                 break;
259         }
260
261         return true;
262 }
263
264 bool channel::get_option(int type, int &value) const
265 {
266         switch (type) {
267         case 0:
268                 value = m_socket->get_current_buffer_size();
269                 break;
270         case SO_SNDBUF:
271                 value = m_socket->get_buffer_size(type);
272                 break;
273         case SO_RCVBUF:
274                 value = m_socket->get_buffer_size(type);
275                 break;
276         default:
277                 break;
278         }
279
280         return true;
281 }
282
283 int channel::get_fd(void) const
284 {
285         return m_fd;
286 }
287
288 void channel::set_event_id(uint64_t id)
289 {
290         m_event_id = id;
291 }