ast_json_pack(): Use safer json ref mechanism.
[asterisk/asterisk.git] / main / io.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief I/O Managment (Derived from Cheops-NG)
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 #include <termios.h>
33 #include <sys/ioctl.h>
34
35 #include "asterisk/io.h"
36 #include "asterisk/utils.h"
37 #ifdef HAVE_SYSTEMD
38 #include <systemd/sd-daemon.h>
39
40 #ifndef SD_LISTEN_FDS_START
41 #define SD_LISTEN_FDS_START 3
42 #endif
43 #endif
44
45 #ifdef DEBUG_IO
46 #define DEBUG DEBUG_M
47 #else
48 #define DEBUG(a)
49 #endif
50
51 /*! \brief
52  * Kept for each file descriptor
53  */
54 struct io_rec {
55         ast_io_cb callback;             /*!< What is to be called */
56         void *data;                     /*!< Data to be passed */
57         int *id;                        /*!< ID number */
58 };
59
60 /* These two arrays are keyed with
61    the same index.  it's too bad that
62    pollfd doesn't have a callback field
63    or something like that.  They grow as
64    needed, by GROW_SHRINK_SIZE structures
65    at once */
66
67 #define GROW_SHRINK_SIZE 512
68
69 /*! \brief Global IO variables are now in a struct in order to be
70    made threadsafe */
71 struct io_context {
72         struct pollfd *fds;           /*!< Poll structure */
73         struct io_rec *ior;           /*!< Associated I/O records */
74         unsigned int fdcnt;           /*!< First available fd */
75         unsigned int maxfdcnt;        /*!< Maximum available fd */
76         int current_ioc;              /*!< Currently used io callback */
77         int needshrink;               /*!< Whether something has been deleted */
78 };
79
80 /*! \brief Create an I/O context */
81 struct io_context *io_context_create(void)
82 {
83         struct io_context *tmp = NULL;
84
85         if (!(tmp = ast_malloc(sizeof(*tmp))))
86                 return NULL;
87
88         tmp->needshrink = 0;
89         tmp->fdcnt = 0;
90         tmp->maxfdcnt = GROW_SHRINK_SIZE/2;
91         tmp->current_ioc = -1;
92
93         if (!(tmp->fds = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->fds)))) {
94                 ast_free(tmp);
95                 tmp = NULL;
96         } else {
97                 if (!(tmp->ior = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->ior)))) {
98                         ast_free(tmp->fds);
99                         ast_free(tmp);
100                         tmp = NULL;
101                 }
102         }
103
104         return tmp;
105 }
106
107 void io_context_destroy(struct io_context *ioc)
108 {
109         /* Free associated memory with an I/O context */
110         if (ioc->fds)
111                 ast_free(ioc->fds);
112         if (ioc->ior)
113                 ast_free(ioc->ior);
114
115         ast_free(ioc);
116 }
117
118 /*! \brief
119  * Grow the size of our arrays.
120  * \return 0 on success or -1 on failure
121  */
122 static int io_grow(struct io_context *ioc)
123 {
124         void *tmp;
125
126         DEBUG(ast_debug(1, "io_grow()\n"));
127
128         ioc->maxfdcnt += GROW_SHRINK_SIZE;
129
130         if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) {
131                 ioc->ior = tmp;
132                 if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) {
133                         ioc->fds = tmp;
134                 } else {
135                         /*
136                          * Failed to allocate enough memory for the pollfd.  Not
137                          * really any need to shrink back the iorec's as we'll
138                          * probably want to grow them again soon when more memory
139                          * is available, and then they'll already be the right size
140                          */
141                         ioc->maxfdcnt -= GROW_SHRINK_SIZE;
142                         return -1;
143                 }
144         } else {
145                 /*
146                  * Memory allocation failure.  We return to the old size, and
147                  * return a failure
148                  */
149                 ioc->maxfdcnt -= GROW_SHRINK_SIZE;
150                 return -1;
151         }
152
153         return 0;
154 }
155
156 /*! \brief
157  * Add a new I/O entry for this file descriptor
158  * with the given event mask, to call callback with
159  * data as an argument.
160  * \return Returns NULL on failure.
161  */
162 int *ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
163 {
164         int *ret;
165
166         DEBUG(ast_debug(1, "ast_io_add()\n"));
167
168         if (ioc->fdcnt >= ioc->maxfdcnt) {
169                 /*
170                  * We don't have enough space for this entry.  We need to
171                  * reallocate maxfdcnt poll fd's and io_rec's, or back out now.
172                  */
173                 if (io_grow(ioc))
174                         return NULL;
175         }
176
177         /*
178          * At this point, we've got sufficiently large arrays going
179          * and we can make an entry for it in the pollfd and io_r
180          * structures.
181          */
182         ioc->fds[ioc->fdcnt].fd = fd;
183         ioc->fds[ioc->fdcnt].events = events;
184         ioc->fds[ioc->fdcnt].revents = 0;
185         ioc->ior[ioc->fdcnt].callback = callback;
186         ioc->ior[ioc->fdcnt].data = data;
187
188         if (!(ioc->ior[ioc->fdcnt].id = ast_malloc(sizeof(*ioc->ior[ioc->fdcnt].id)))) {
189                 /* Bonk if we couldn't allocate an int */
190                 return NULL;
191         }
192
193         *(ioc->ior[ioc->fdcnt].id) = ioc->fdcnt;
194         ret = ioc->ior[ioc->fdcnt].id;
195         ioc->fdcnt++;
196
197         return ret;
198 }
199
200 int *ast_io_change(struct io_context *ioc, int *id, int fd, ast_io_cb callback, short events, void *data)
201 {
202         /* If this id exceeds our file descriptor count it doesn't exist here */
203         if (*id > ioc->fdcnt)
204                 return NULL;
205
206         if (fd > -1)
207                 ioc->fds[*id].fd = fd;
208         if (callback)
209                 ioc->ior[*id].callback = callback;
210         if (events)
211                 ioc->fds[*id].events = events;
212         if (data)
213                 ioc->ior[*id].data = data;
214
215         return id;
216 }
217
218 static int io_shrink(struct io_context *ioc)
219 {
220         int getfrom, putto = 0;
221
222         /*
223          * Bring the fields from the very last entry to cover over
224          * the entry we are removing, then decrease the size of the
225          * arrays by one.
226          */
227         for (getfrom = 0; getfrom < ioc->fdcnt; getfrom++) {
228                 if (ioc->ior[getfrom].id) {
229                         /* In use, save it */
230                         if (getfrom != putto) {
231                                 ioc->fds[putto] = ioc->fds[getfrom];
232                                 ioc->ior[putto] = ioc->ior[getfrom];
233                                 *(ioc->ior[putto].id) = putto;
234                         }
235                         putto++;
236                 }
237         }
238         ioc->fdcnt = putto;
239         ioc->needshrink = 0;
240         /* FIXME: We should free some memory if we have lots of unused
241            io structs */
242         return 0;
243 }
244
245 int ast_io_remove(struct io_context *ioc, int *_id)
246 {
247         int x;
248
249         if (!_id) {
250                 ast_log(LOG_WARNING, "Asked to remove NULL?\n");
251                 return -1;
252         }
253
254         for (x = 0; x < ioc->fdcnt; x++) {
255                 if (ioc->ior[x].id == _id) {
256                         /* Free the int immediately and set to NULL so we know it's unused now */
257                         ast_free(ioc->ior[x].id);
258                         ioc->ior[x].id = NULL;
259                         ioc->fds[x].events = 0;
260                         ioc->fds[x].revents = 0;
261                         ioc->needshrink = 1;
262                         if (ioc->current_ioc == -1)
263                                 io_shrink(ioc);
264                         return 0;
265                 }
266         }
267
268         ast_log(LOG_NOTICE, "Unable to remove unknown id %p\n", _id);
269
270         return -1;
271 }
272
273 /*! \brief
274  * Make the poll call, and call
275  * the callbacks for anything that needs
276  * to be handled
277  */
278 int ast_io_wait(struct io_context *ioc, int howlong)
279 {
280         int res, x, origcnt;
281
282         DEBUG(ast_debug(1, "ast_io_wait()\n"));
283
284         if ((res = ast_poll(ioc->fds, ioc->fdcnt, howlong)) <= 0) {
285                 return res;
286         }
287
288         /* At least one event tripped */
289         origcnt = ioc->fdcnt;
290         for (x = 0; x < origcnt; x++) {
291                 /* Yes, it is possible for an entry to be deleted and still have an
292                    event waiting if it occurs after the original calling id */
293                 if (ioc->fds[x].revents && ioc->ior[x].id) {
294                         /* There's an event waiting */
295                         ioc->current_ioc = *ioc->ior[x].id;
296                         if (ioc->ior[x].callback) {
297                                 if (!ioc->ior[x].callback(ioc->ior[x].id, ioc->fds[x].fd, ioc->fds[x].revents, ioc->ior[x].data)) {
298                                         /* Time to delete them since they returned a 0 */
299                                         ast_io_remove(ioc, ioc->ior[x].id);
300                                 }
301                         }
302                         ioc->current_ioc = -1;
303                 }
304         }
305
306         if (ioc->needshrink)
307                 io_shrink(ioc);
308
309         return res;
310 }
311
312 void ast_io_dump(struct io_context *ioc)
313 {
314         /*
315          * Print some debugging information via
316          * the logger interface
317          */
318         int x;
319
320         ast_debug(1, "Asterisk IO Dump: %u entries, %u max entries\n", ioc->fdcnt, ioc->maxfdcnt);
321         ast_debug(1, "================================================\n");
322         ast_debug(1, "| ID    FD     Callback    Data        Events  |\n");
323         ast_debug(1, "+------+------+-----------+-----------+--------+\n");
324         for (x = 0; x < ioc->fdcnt; x++) {
325                 ast_debug(1, "| %.4d | %.4d | %p | %p | %.6x |\n",
326                                 *ioc->ior[x].id,
327                                 ioc->fds[x].fd,
328                                 ioc->ior[x].callback,
329                                 ioc->ior[x].data,
330                                 (unsigned)ioc->fds[x].events);
331         }
332         ast_debug(1, "================================================\n");
333 }
334
335 /* Unrelated I/O functions */
336
337 int ast_hide_password(int fd)
338 {
339         struct termios tios;
340         int res;
341         int old;
342         if (!isatty(fd))
343                 return -1;
344         res = tcgetattr(fd, &tios);
345         if (res < 0)
346                 return -1;
347         old = tios.c_lflag & (ECHO | ECHONL);
348         tios.c_lflag &= ~ECHO;
349         tios.c_lflag |= ECHONL;
350         res = tcsetattr(fd, TCSAFLUSH, &tios);
351         if (res < 0)
352                 return -1;
353         return old;
354 }
355
356 int ast_restore_tty(int fd, int oldstate)
357 {
358         int res;
359         struct termios tios;
360         if (oldstate < 0)
361                 return 0;
362         res = tcgetattr(fd, &tios);
363         if (res < 0)
364                 return -1;
365         tios.c_lflag &= ~(ECHO | ECHONL);
366         tios.c_lflag |= oldstate;
367         res = tcsetattr(fd, TCSAFLUSH, &tios);
368         if (res < 0)
369                 return -1;
370         return 0;
371 }
372
373 int ast_get_termcols(int fd)
374 {
375         struct winsize win;
376         int cols = 0;
377
378         if (!isatty(fd))
379                 return -1;
380
381         if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
382                 if ( !cols && win.ws_col > 0 )
383                         cols = (int) win.ws_col;
384         } else {
385                 /* assume 80 characters if the ioctl fails for some reason */
386                 cols = 80;
387         }
388
389         return cols;
390 }
391
392 int ast_sd_notify(const char *state) {
393 #ifdef HAVE_SYSTEMD
394         return sd_notify(0, state);
395 #else
396         return 0;
397 #endif
398 }
399
400 /*!
401  * \internal \brief Check the type and sockaddr of a file descriptor.
402  * \param fd File Descriptor to check.
403  * \param type SOCK_STREAM or SOCK_DGRAM
404  * \param addr The socket address to match.
405  * \retval 0 if matching
406  * \retval -1 if not matching
407  */
408 #ifdef HAVE_SYSTEMD
409 static int ast_sd_is_socket_sockaddr(int fd, int type, const struct ast_sockaddr* addr)
410 {
411         int canretry = 1;
412         struct ast_sockaddr fd_addr;
413         struct sockaddr ss;
414         socklen_t ss_len;
415
416         if (sd_is_socket(fd, AF_UNSPEC, type, 1) <= 0) {
417                 return -1;
418         }
419
420 doretry:
421         if (getsockname(fd, &ss, &ss_len) != 0) {
422                 return -1;
423         }
424
425         if (ss.sa_family == AF_UNSPEC && canretry) {
426                 /* An unknown bug can cause silent failure from
427                  * the first call to getsockname. */
428                 canretry = 0;
429                 goto doretry;
430         }
431
432         ast_sockaddr_copy_sockaddr(&fd_addr, &ss, ss_len);
433
434         return ast_sockaddr_cmp(addr, &fd_addr);
435 }
436 #endif
437
438 int ast_sd_get_fd(int type, const struct ast_sockaddr *addr)
439 {
440 #ifdef HAVE_SYSTEMD
441         int count = sd_listen_fds(0);
442         int idx;
443
444         for (idx = 0; idx < count; idx++) {
445                 if (!ast_sd_is_socket_sockaddr(idx + SD_LISTEN_FDS_START, type, addr)) {
446                         return idx + SD_LISTEN_FDS_START;
447                 }
448         }
449 #endif
450
451         return -1;
452 }
453
454 int ast_sd_get_fd_un(int type, const char *path)
455 {
456 #ifdef HAVE_SYSTEMD
457         int count = sd_listen_fds(0);
458         int idx;
459
460         for (idx = 0; idx < count; idx++) {
461                 if (sd_is_socket_unix(idx + SD_LISTEN_FDS_START, type, 1, path, 0) > 0) {
462                         return idx + SD_LISTEN_FDS_START;
463                 }
464         }
465 #endif
466
467         return -1;
468 }