Wed Jan 8 2020 09:50:13

Asterisk developer's documentation


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"

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

#define DEBUG (   a)

Definition at line 43 of file io.c.

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

#define GROW_SHRINK_SIZE   512

Definition at line 62 of file io.c.

Referenced by io_context_create(), and io_grow().

Function Documentation

int ast_get_termcols ( int  fd)

Definition at line 368 of file io.c.

References isatty().

Referenced by ast_cli_display_match_list().

369 {
370  struct winsize win;
371  int cols = 0;
372 
373  if (!isatty(fd))
374  return -1;
375 
376  if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
377  if ( !cols && win.ws_col > 0 )
378  cols = (int) win.ws_col;
379  } else {
380  /* assume 80 characters if the ioctl fails for some reason */
381  cols = 80;
382  }
383 
384  return cols;
385 }
int isatty(int)
int ast_hide_password ( int  fd)

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

Definition at line 332 of file io.c.

References ECHO, and isatty().

Referenced by pw_cb().

333 {
334  struct termios tios;
335  int res;
336  int old;
337  if (!isatty(fd))
338  return -1;
339  res = tcgetattr(fd, &tios);
340  if (res < 0)
341  return -1;
342  old = tios.c_lflag & (ECHO | ECHONL);
343  tios.c_lflag &= ~ECHO;
344  tios.c_lflag |= ECHONL;
345  res = tcsetattr(fd, TCSAFLUSH, &tios);
346  if (res < 0)
347  return -1;
348  return old;
349 }
int isatty(int)
#define ECHO
Definition: ast_expr2f.c:555
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 157 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, and io_context::maxfdcnt.

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

158 {
159  int *ret;
160 
161  DEBUG(ast_debug(1, "ast_io_add()\n"));
162 
163  if (ioc->fdcnt >= ioc->maxfdcnt) {
164  /*
165  * We don't have enough space for this entry. We need to
166  * reallocate maxfdcnt poll fd's and io_rec's, or back out now.
167  */
168  if (io_grow(ioc))
169  return NULL;
170  }
171 
172  /*
173  * At this point, we've got sufficiently large arrays going
174  * and we can make an entry for it in the pollfd and io_r
175  * structures.
176  */
177  ioc->fds[ioc->fdcnt].fd = fd;
178  ioc->fds[ioc->fdcnt].events = events;
179  ioc->fds[ioc->fdcnt].revents = 0;
180  ioc->ior[ioc->fdcnt].callback = callback;
181  ioc->ior[ioc->fdcnt].data = data;
182 
183  if (!(ioc->ior[ioc->fdcnt].id = ast_malloc(sizeof(*ioc->ior[ioc->fdcnt].id)))) {
184  /* Bonk if we couldn't allocate an int */
185  return NULL;
186  }
187 
188  *(ioc->ior[ioc->fdcnt].id) = ioc->fdcnt;
189  ret = ioc->ior[ioc->fdcnt].id;
190  ioc->fdcnt++;
191 
192  return ret;
193 }
void * data
Definition: io.c:51
struct pollfd * fds
Definition: io.c:67
#define DEBUG(a)
Definition: io.c:43
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int io_grow(struct io_context *ioc)
Grow the size of our arrays.
Definition: io.c:117
ast_io_cb callback
Definition: io.c:50
unsigned int fdcnt
Definition: io.c:69
struct io_rec * ior
Definition: io.c:68
int * id
Definition: io.c:52
static struct adsi_event events[]
Definition: app_adsiprog.c:78
#define ast_malloc(a)
Definition: astmm.h:91
unsigned int maxfdcnt
Definition: io.c:70
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 195 of file io.c.

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

Referenced by do_monitor().

196 {
197  /* If this id exceeds our file descriptor count it doesn't exist here */
198  if (*id > ioc->fdcnt)
199  return NULL;
200 
201  if (fd > -1)
202  ioc->fds[*id].fd = fd;
203  if (callback)
204  ioc->ior[*id].callback = callback;
205  if (events)
206  ioc->fds[*id].events = events;
207  if (data)
208  ioc->ior[*id].data = data;
209 
210  return id;
211 }
void * data
Definition: io.c:51
struct pollfd * fds
Definition: io.c:67
ast_io_cb callback
Definition: io.c:50
unsigned int fdcnt
Definition: io.c:69
struct io_rec * ior
Definition: io.c:68
enum queue_result id
Definition: app_queue.c:1090
static struct adsi_event events[]
Definition: app_adsiprog.c:78
void ast_io_dump ( struct io_context ioc)

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

Definition at line 307 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.

308 {
309  /*
310  * Print some debugging information via
311  * the logger interface
312  */
313  int x;
314 
315  ast_debug(1, "Asterisk IO Dump: %u entries, %u max entries\n", ioc->fdcnt, ioc->maxfdcnt);
316  ast_debug(1, "================================================\n");
317  ast_debug(1, "| ID FD Callback Data Events |\n");
318  ast_debug(1, "+------+------+-----------+-----------+--------+\n");
319  for (x = 0; x < ioc->fdcnt; x++) {
320  ast_debug(1, "| %.4d | %.4d | %p | %p | %.6x |\n",
321  *ioc->ior[x].id,
322  ioc->fds[x].fd,
323  ioc->ior[x].callback,
324  ioc->ior[x].data,
325  (unsigned)ioc->fds[x].events);
326  }
327  ast_debug(1, "================================================\n");
328 }
void * data
Definition: io.c:51
struct pollfd * fds
Definition: io.c:67
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
ast_io_cb callback
Definition: io.c:50
unsigned int fdcnt
Definition: io.c:69
struct io_rec * ior
Definition: io.c:68
int * id
Definition: io.c:52
unsigned int maxfdcnt
Definition: io.c:70
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 240 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, and io_context::needshrink.

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

241 {
242  int x;
243 
244  if (!_id) {
245  ast_log(LOG_WARNING, "Asked to remove NULL?\n");
246  return -1;
247  }
248 
249  for (x = 0; x < ioc->fdcnt; x++) {
250  if (ioc->ior[x].id == _id) {
251  /* Free the int immediately and set to NULL so we know it's unused now */
252  ast_free(ioc->ior[x].id);
253  ioc->ior[x].id = NULL;
254  ioc->fds[x].events = 0;
255  ioc->fds[x].revents = 0;
256  ioc->needshrink = 1;
257  if (ioc->current_ioc == -1)
258  io_shrink(ioc);
259  return 0;
260  }
261  }
262 
263  ast_log(LOG_NOTICE, "Unable to remove unknown id %p\n", _id);
264 
265  return -1;
266 }
static int io_shrink(struct io_context *ioc)
Definition: io.c:213
struct pollfd * fds
Definition: io.c:67
#define LOG_WARNING
Definition: logger.h:144
int current_ioc
Definition: io.c:71
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define ast_free(a)
Definition: astmm.h:97
unsigned int fdcnt
Definition: io.c:69
struct io_rec * ior
Definition: io.c:68
int * id
Definition: io.c:52
int needshrink
Definition: io.c:72
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 273 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(), network_thread(), and reload_config().

274 {
275  int res, x, origcnt;
276 
277  DEBUG(ast_debug(1, "ast_io_wait()\n"));
278 
279  if ((res = ast_poll(ioc->fds, ioc->fdcnt, howlong)) <= 0) {
280  return res;
281  }
282 
283  /* At least one event tripped */
284  origcnt = ioc->fdcnt;
285  for (x = 0; x < origcnt; x++) {
286  /* Yes, it is possible for an entry to be deleted and still have an
287  event waiting if it occurs after the original calling id */
288  if (ioc->fds[x].revents && ioc->ior[x].id) {
289  /* There's an event waiting */
290  ioc->current_ioc = *ioc->ior[x].id;
291  if (ioc->ior[x].callback) {
292  if (!ioc->ior[x].callback(ioc->ior[x].id, ioc->fds[x].fd, ioc->fds[x].revents, ioc->ior[x].data)) {
293  /* Time to delete them since they returned a 0 */
294  ast_io_remove(ioc, ioc->ior[x].id);
295  }
296  }
297  ioc->current_ioc = -1;
298  }
299  }
300 
301  if (ioc->needshrink)
302  io_shrink(ioc);
303 
304  return res;
305 }
static int io_shrink(struct io_context *ioc)
Definition: io.c:213
void * data
Definition: io.c:51
struct pollfd * fds
Definition: io.c:67
#define DEBUG(a)
Definition: io.c:43
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int current_ioc
Definition: io.c:71
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
ast_io_cb callback
Definition: io.c:50
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:240
unsigned int fdcnt
Definition: io.c:69
struct io_rec * ior
Definition: io.c:68
int * id
Definition: io.c:52
int needshrink
Definition: io.c:72
int ast_restore_tty ( int  fd,
int  oldstate 
)

Restores TTY mode. Call with result from previous ast_hide_password.

Definition at line 351 of file io.c.

References ECHO.

Referenced by pw_cb().

352 {
353  int res;
354  struct termios tios;
355  if (oldstate < 0)
356  return 0;
357  res = tcgetattr(fd, &tios);
358  if (res < 0)
359  return -1;
360  tios.c_lflag &= ~(ECHO | ECHONL);
361  tios.c_lflag |= oldstate;
362  res = tcsetattr(fd, TCSAFLUSH, &tios);
363  if (res < 0)
364  return -1;
365  return 0;
366 }
#define ECHO
Definition: ast_expr2f.c:555
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 76 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, and io_context::needshrink.

Referenced by load_module().

77 {
78  struct io_context *tmp = NULL;
79 
80  if (!(tmp = ast_malloc(sizeof(*tmp))))
81  return NULL;
82 
83  tmp->needshrink = 0;
84  tmp->fdcnt = 0;
85  tmp->maxfdcnt = GROW_SHRINK_SIZE/2;
86  tmp->current_ioc = -1;
87 
88  if (!(tmp->fds = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->fds)))) {
89  ast_free(tmp);
90  tmp = NULL;
91  } else {
92  if (!(tmp->ior = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->ior)))) {
93  ast_free(tmp->fds);
94  ast_free(tmp);
95  tmp = NULL;
96  }
97  }
98 
99  return tmp;
100 }
struct pollfd * fds
Definition: io.c:67
#define GROW_SHRINK_SIZE
Definition: io.c:62
int current_ioc
Definition: io.c:71
Global IO variables are now in a struct in order to be made threadsafe.
Definition: io.c:66
#define ast_free(a)
Definition: astmm.h:97
unsigned int fdcnt
Definition: io.c:69
struct io_rec * ior
Definition: io.c:68
#define ast_calloc(a, b)
Definition: astmm.h:82
int needshrink
Definition: io.c:72
#define ast_malloc(a)
Definition: astmm.h:91
unsigned int maxfdcnt
Definition: io.c:70
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 102 of file io.c.

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

Referenced by load_module(), and unload_module().

103 {
104  /* Free associated memory with an I/O context */
105  if (ioc->fds)
106  ast_free(ioc->fds);
107  if (ioc->ior)
108  ast_free(ioc->ior);
109 
110  ast_free(ioc);
111 }
struct pollfd * fds
Definition: io.c:67
#define ast_free(a)
Definition: astmm.h:97
struct io_rec * ior
Definition: io.c:68
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 117 of file io.c.

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

Referenced by ast_io_add().

118 {
119  void *tmp;
120 
121  DEBUG(ast_debug(1, "io_grow()\n"));
122 
123  ioc->maxfdcnt += GROW_SHRINK_SIZE;
124 
125  if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) {
126  ioc->ior = tmp;
127  if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) {
128  ioc->fds = tmp;
129  } else {
130  /*
131  * Failed to allocate enough memory for the pollfd. Not
132  * really any need to shrink back the iorec's as we'll
133  * probably want to grow them again soon when more memory
134  * is available, and then they'll already be the right size
135  */
136  ioc->maxfdcnt -= GROW_SHRINK_SIZE;
137  return -1;
138  }
139  } else {
140  /*
141  * Memory allocation failure. We return to the old size, and
142  * return a failure
143  */
144  ioc->maxfdcnt -= GROW_SHRINK_SIZE;
145  return -1;
146  }
147 
148  return 0;
149 }
struct pollfd * fds
Definition: io.c:67
#define GROW_SHRINK_SIZE
Definition: io.c:62
#define DEBUG(a)
Definition: io.c:43
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct io_rec * ior
Definition: io.c:68
#define ast_realloc(a, b)
Definition: astmm.h:103
unsigned int maxfdcnt
Definition: io.c:70
static int io_shrink ( struct io_context ioc)
static

Definition at line 213 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().

214 {
215  int getfrom, putto = 0;
216 
217  /*
218  * Bring the fields from the very last entry to cover over
219  * the entry we are removing, then decrease the size of the
220  * arrays by one.
221  */
222  for (getfrom = 0; getfrom < ioc->fdcnt; getfrom++) {
223  if (ioc->ior[getfrom].id) {
224  /* In use, save it */
225  if (getfrom != putto) {
226  ioc->fds[putto] = ioc->fds[getfrom];
227  ioc->ior[putto] = ioc->ior[getfrom];
228  *(ioc->ior[putto].id) = putto;
229  }
230  putto++;
231  }
232  }
233  ioc->fdcnt = putto;
234  ioc->needshrink = 0;
235  /* FIXME: We should free some memory if we have lots of unused
236  io structs */
237  return 0;
238 }
struct pollfd * fds
Definition: io.c:67
unsigned int fdcnt
Definition: io.c:69
struct io_rec * ior
Definition: io.c:68
int * id
Definition: io.c:52
int needshrink
Definition: io.c:72