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

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

#include "asterisk.h"
#include <termios.h>
#include <sys/ioctl.h>
#include "asterisk/io.h"
#include "asterisk/utils.h"
#include <systemd/sd-daemon.h>

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
 
#define SD_LISTEN_FDS_START   3
 

Functions

int ast_get_termcols (int fd)
 Columns of Terminal. More...
 
int ast_hide_password (int fd)
 Hide password. More...
 
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. 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. 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...
 
static int ast_sd_is_socket_sockaddr (int fd, int type, const struct ast_sockaddr *addr)
 
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 Management (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.

Function Documentation

int ast_get_termcols ( int  fd)

Columns of Terminal.

Parameters
fdFalls back to 80 if the underlying ioctl fails.

Definition at line 373 of file io.c.

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 ast_hide_password ( int  fd)

Hide password.

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

Definition at line 337 of file io.c.

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* 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.

Definition at line 162 of file io.c.

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

Referenced by mbl_load_adapter().

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 int io_grow(struct io_context *ioc)
Grow the size of our arrays.
Definition: io.c:123
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_debug(level,...)
Log a DEBUG message.
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
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.
Returns
a pointer to the ID of the IO event
Return values
NULLon failure

Definition at line 200 of file io.c.

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

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 struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
ast_io_cb callback
Definition: io.c:55
unsigned int fdcnt
Definition: io.c:74
struct io_rec * ior
Definition: io.c:73
void ast_io_dump ( struct io_context ioc)

Dumps the IO array.

Parameters
iocDebugging: 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.
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
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 io_context::current_ioc, io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and io_context::needshrink.

Referenced by ast_io_wait(), and mbl_load_adapter().

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 }
struct pollfd * fds
Definition: io.c:72
int current_ioc
Definition: io.c:76
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_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(), io_rec::callback, io_context::current_ioc, io_rec::data, io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and io_context::needshrink.

Referenced by do_sco_listen().

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 }
void * data
Definition: io.c:56
struct pollfd * fds
Definition: io.c:72
int current_ioc
Definition: io.c:76
#define ast_debug(level,...)
Log a DEBUG message.
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
int ast_restore_tty ( int  fd,
int  oldstatus 
)

Restores TTY mode.

Parameters
fd,oldstatusCall with result from previous ast_hide_password

Definition at line 356 of file io.c.

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 }
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
negativeNo match.
positiveFile 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 }
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
negativeNo match.
positiveFile 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 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 }
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.
Return values
0on success.
positieon success.
negativeon error.

Definition at line 392 of file io.c.

Referenced by ast_module_reload(), and really_quit().

392  {
393 #ifdef HAVE_SYSTEMD
394  return sd_notify(0, state);
395 #else
396  return 0;
397 #endif
398 }
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_malloc, io_context::current_ioc, io_context::fdcnt, io_context::fds, io_context::ior, io_context::maxfdcnt, and io_context::needshrink.

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
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:191
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
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
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 io_context::fds, and io_context::ior.

Referenced by load_module(), and mbl_load_adapter().

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
struct io_rec * ior
Definition: io.c:73
static int io_grow ( struct io_context ioc)
static

Grow the size of our arrays.

Return values
0on success
-1on failure

Definition at line 123 of file io.c.

References ast_debug, ast_realloc, io_context::fds, io_context::ior, and io_context::maxfdcnt.

Referenced by ast_io_add().

124 {
125  void *tmp;
126 
127  DEBUG(ast_debug(1, "io_grow()\n"));
128 
129  ioc->maxfdcnt += GROW_SHRINK_SIZE;
130 
131  if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) {
132  ioc->ior = tmp;
133  if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) {
134  ioc->fds = tmp;
135  } else {
136  /*
137  * Failed to allocate enough memory for the pollfd. Not
138  * really any need to shrink back the iorec's as we'll
139  * probably want to grow them again soon when more memory
140  * is available, and then they'll already be the right size
141  */
142  ioc->maxfdcnt -= GROW_SHRINK_SIZE;
143  return -1;
144  }
145  } else {
146  /*
147  * Memory allocation failure. We return to the old size, and
148  * return a failure
149  */
150  ioc->maxfdcnt -= GROW_SHRINK_SIZE;
151  return -1;
152  }
153 
154  return 0;
155 }
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
struct pollfd * fds
Definition: io.c:72
#define ast_debug(level,...)
Log a DEBUG message.
struct io_rec * ior
Definition: io.c:73
unsigned int maxfdcnt
Definition: io.c:75