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