Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions
io.c File Reference

I/O Managment (Derived from Cheops-NG) More...

#include "asterisk.h"
#include <termios.h>
#include <sys/ioctl.h>
#include "asterisk/io.h"
#include "asterisk/utils.h"
Include dependency graph for io.c:

Go to the source code of this file.

Data Structures

struct  io_context
 Global IO variables are now in a struct in order to be made threadsafe. More...
 
struct  io_rec
 Kept for each file descriptor. More...
 

Macros

#define DEBUG(a)
 
#define GROW_SHRINK_SIZE   512
 

Functions

int ast_get_termcols (int fd)
 
int ast_hide_password (int fd)
 
int * ast_io_add (struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
 Add a new I/O entry for this file descriptor with the given event mask, to call callback with data as an argument. More...
 
int * ast_io_change (struct io_context *ioc, int *id, int fd, ast_io_cb callback, short events, void *data)
 Changes an IO handler. More...
 
void ast_io_dump (struct io_context *ioc)
 Dumps the IO array. Debugging: Dump everything in the I/O array. More...
 
int ast_io_remove (struct io_context *ioc, int *_id)
 Removes an IO context. More...
 
int ast_io_wait (struct io_context *ioc, int howlong)
 Make the poll call, and call the callbacks for anything that needs to be handled. More...
 
int ast_restore_tty (int fd, int oldstate)
 Restores TTY mode. Call with result from previous ast_hide_password. More...
 
int ast_sd_get_fd (int type, const struct ast_sockaddr *addr)
 Find a listening file descriptor provided by socket activation. More...
 
int ast_sd_get_fd_un (int type, const char *path)
 Find a listening AF_LOCAL file descriptor provided by socket activation. More...
 
int ast_sd_notify (const char *state)
 a wrapper for sd_notify(): notify systemd of any state changes. More...
 
struct io_contextio_context_create (void)
 Create an I/O context. More...
 
void io_context_destroy (struct io_context *ioc)
 Destroys a context. More...
 
static int io_grow (struct io_context *ioc)
 Grow the size of our arrays. More...
 
static int io_shrink (struct io_context *ioc)
 

Detailed Description

I/O Managment (Derived from Cheops-NG)

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file io.c.

Macro Definition Documentation

◆ DEBUG

#define DEBUG (   a)

Definition at line 48 of file io.c.

Referenced by ast_io_add(), ast_io_wait(), and io_grow().

◆ GROW_SHRINK_SIZE

#define GROW_SHRINK_SIZE   512

Definition at line 67 of file io.c.

Referenced by io_context_create(), and io_grow().

Function Documentation

◆ ast_get_termcols()

int ast_get_termcols ( int  fd)

Definition at line 373 of file io.c.

References isatty().

Referenced by ast_cli_display_match_list().

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 }
int isatty(int)

◆ ast_hide_password()

int ast_hide_password ( int  fd)

Set fd into non-echoing mode (if fd is a tty)

Definition at line 337 of file io.c.

References ECHO, and isatty().

Referenced by pw_cb().

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 }
int isatty(int)
#define ECHO
Definition: ast_expr2f.c:563

◆ ast_io_add()

int* ast_io_add ( struct io_context ioc,
int  fd,
ast_io_cb  callback,
short  events,
void *  data 
)

Add a new I/O entry for this file descriptor with the given event mask, to call callback with data as an argument.

Adds an IO context.

Returns
Returns NULL on failure.

Definition at line 162 of file io.c.

References ast_debug, ast_malloc, io_rec::callback, io_rec::data, DEBUG, events, io_context::fdcnt, io_context::fds, io_rec::id, io_grow(), io_context::ior, io_context::maxfdcnt, and NULL.

Referenced by ast_netsock_bindaddr(), ast_udptl_new_with_bindaddr(), do_monitor(), mbl_load_adapter(), and network_thread().

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 }
void * data
Definition: io.c:56
struct pollfd * fds
Definition: io.c:72
static const struct adsi_event events[]
Definition: app_adsiprog.c:85
#define NULL
Definition: resample.c:96
#define DEBUG(a)
Definition: io.c:48
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int io_grow(struct io_context *ioc)
Grow the size of our arrays.
Definition: io.c:122
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
ast_io_cb callback
Definition: io.c:55
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
int * id
Definition: io.c:57
unsigned int maxfdcnt
Definition: io.c:75

◆ ast_io_change()

int* ast_io_change ( struct io_context ioc,
int *  id,
int  fd,
ast_io_cb  callback,
short  events,
void *  data 
)

Changes an IO handler.

Parameters
iocwhich context to use
id
fdthe fd you wish it to contain now
callbacknew callback function
eventsevent mask to wait for
datadata to pass to the callback function Change an I/O handler, updating fd if > -1, callback if non-null, and revents if >-1, and data if non-null.
Return values
apointer to the ID of the IO event
NULLon failure

Definition at line 200 of file io.c.

References io_rec::callback, io_rec::data, events, io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and NULL.

Referenced by do_monitor().

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 }
void * data
Definition: io.c:56
struct pollfd * fds
Definition: io.c:72
static const struct adsi_event events[]
Definition: app_adsiprog.c:85
#define NULL
Definition: resample.c:96
ast_io_cb callback
Definition: io.c:55
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
enum queue_result id
Definition: app_queue.c:1507

◆ ast_io_dump()

void ast_io_dump ( struct io_context ioc)

Dumps the IO array. Debugging: Dump everything in the I/O array.

Definition at line 312 of file io.c.

References ast_debug, io_rec::callback, io_rec::data, io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and io_context::maxfdcnt.

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 }
void * data
Definition: io.c:56
struct pollfd * fds
Definition: io.c:72
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
ast_io_cb callback
Definition: io.c:55
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
int * id
Definition: io.c:57
unsigned int maxfdcnt
Definition: io.c:75

◆ ast_io_remove()

int ast_io_remove ( struct io_context ioc,
int *  id 
)

Removes an IO context.

Parameters
iocwhich io_context to remove it from
idwhich ID to remove Remove an I/O id from consideration
Return values
0on success
-1on failure

Definition at line 245 of file io.c.

References ast_free, ast_log, io_context::current_ioc, io_context::fdcnt, io_context::fds, io_rec::id, io_shrink(), io_context::ior, LOG_NOTICE, LOG_WARNING, io_context::needshrink, and NULL.

Referenced by ast_io_wait(), ast_netsock_destroy(), ast_udptl_destroy(), do_monitor(), mbl_load_adapter(), network_thread(), reload_config(), and unload_module().

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 }
static int io_shrink(struct io_context *ioc)
Definition: io.c:218
struct pollfd * fds
Definition: io.c:72
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
int current_ioc
Definition: io.c:76
#define LOG_NOTICE
Definition: logger.h:263
#define ast_free(a)
Definition: astmm.h:182
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
int * id
Definition: io.c:57
int needshrink
Definition: io.c:77

◆ ast_io_wait()

int ast_io_wait ( struct io_context ioc,
int  howlong 
)

Make the poll call, and call the callbacks for anything that needs to be handled.

Waits for IO.

Definition at line 278 of file io.c.

References ast_debug, ast_io_remove(), ast_poll, io_rec::callback, io_context::current_ioc, io_rec::data, DEBUG, io_context::fdcnt, io_context::fds, io_rec::id, io_shrink(), io_context::ior, and io_context::needshrink.

Referenced by do_monitor(), do_sco_listen(), network_thread(), and reload_config().

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 }
static int io_shrink(struct io_context *ioc)
Definition: io.c:218
void * data
Definition: io.c:56
struct pollfd * fds
Definition: io.c:72
#define DEBUG(a)
Definition: io.c:48
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int current_ioc
Definition: io.c:76
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
ast_io_cb callback
Definition: io.c:55
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
int * id
Definition: io.c:57
int needshrink
Definition: io.c:77
int ast_io_remove(struct io_context *ioc, int *_id)
Removes an IO context.
Definition: io.c:245

◆ ast_restore_tty()

int ast_restore_tty ( int  fd,
int  oldstate 
)

Restores TTY mode. Call with result from previous ast_hide_password.

Definition at line 356 of file io.c.

References ECHO.

Referenced by pw_cb().

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 }
#define ECHO
Definition: ast_expr2f.c:563

◆ ast_sd_get_fd()

int ast_sd_get_fd ( int  type,
const struct ast_sockaddr addr 
)

Find a listening file descriptor provided by socket activation.

Parameters
typeSOCK_STREAM or SOCK_DGRAM
addrThe socket address of the bound listener.
Return values
<0No match.
>0File Descriptor matching sockaddr.
Note
This function returns -1 if systemd's development headers were not detected on the system.

Definition at line 438 of file io.c.

Referenced by ast_tcptls_server_start().

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 }
static const char type[]
Definition: chan_ooh323.c:109

◆ ast_sd_get_fd_un()

int ast_sd_get_fd_un ( int  type,
const char *  path 
)

Find a listening AF_LOCAL file descriptor provided by socket activation.

Parameters
typeSOCK_STREAM or SOCK_DGRAM
pathThe path of the listener.
Return values
<0No match.
>0File Descriptor matching path.
Note
This function returns -1 if systemd's development headers were not detected on the system.

Definition at line 454 of file io.c.

Referenced by ast_makesocket(), and main().

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 }
static const char type[]
Definition: chan_ooh323.c:109

◆ ast_sd_notify()

int ast_sd_notify ( const char *  state)

a wrapper for sd_notify(): notify systemd of any state changes.

Parameters
statea string that states the changes. See sd_notify(3). The wrapper does nothing if systemd ('s development headers) was not detected on the system.
Returns
>=0 on success, negative value on error.

Definition at line 392 of file io.c.

References ast_sockaddr_cmp(), ast_sockaddr_copy_sockaddr(), and type.

Referenced by ast_module_reload(), asterisk_daemon(), and really_quit().

392  {
393 #ifdef HAVE_SYSTEMD
394  return sd_notify(0, state);
395 #else
396  return 0;
397 #endif
398 }

◆ io_context_create()

struct io_context* io_context_create ( void  )

Create an I/O context.

Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up some default values.

Definition at line 81 of file io.c.

References ast_calloc, ast_free, ast_malloc, io_context::current_ioc, io_context::fdcnt, io_context::fds, GROW_SHRINK_SIZE, io_context::ior, io_context::maxfdcnt, io_context::needshrink, NULL, and tmp().

Referenced by load_module(), and mbl_load_adapter().

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 }
struct pollfd * fds
Definition: io.c:72
#define GROW_SHRINK_SIZE
Definition: io.c:67
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
int current_ioc
Definition: io.c:76
Global IO variables are now in a struct in order to be made threadsafe.
Definition: io.c:71
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
int needshrink
Definition: io.c:77
unsigned int maxfdcnt
Definition: io.c:75

◆ io_context_destroy()

void io_context_destroy ( struct io_context ioc)

Destroys a context.

Parameters
iocstructure to destroy Destroy a context for I/O operations Frees all memory associated with the given io_context structure along with the structure itself

Definition at line 107 of file io.c.

References ast_free, io_context::fds, and io_context::ior.

Referenced by load_module(), mbl_load_adapter(), and unload_module().

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 }
struct pollfd * fds
Definition: io.c:72
#define ast_free(a)
Definition: astmm.h:182
struct io_rec * ior
Definition: io.c:73

◆ io_grow()

static int io_grow ( struct io_context ioc)
static

Grow the size of our arrays.

Returns
0 on success or -1 on failure

Definition at line 122 of file io.c.

References ast_debug, ast_realloc, DEBUG, io_context::fds, GROW_SHRINK_SIZE, io_context::ior, io_context::maxfdcnt, and tmp().

Referenced by ast_io_add().

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 }
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:228
struct pollfd * fds
Definition: io.c:72
#define GROW_SHRINK_SIZE
Definition: io.c:67
static int tmp()
Definition: bt_open.c:389
#define DEBUG(a)
Definition: io.c:48
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct io_rec * ior
Definition: io.c:73
unsigned int maxfdcnt
Definition: io.c:75

◆ io_shrink()

static int io_shrink ( struct io_context ioc)
static

Definition at line 218 of file io.c.

References io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and io_context::needshrink.

Referenced by ast_io_remove(), and ast_io_wait().

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 }
struct pollfd * fds
Definition: io.c:72
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
int * id
Definition: io.c:57
int needshrink
Definition: io.c:77