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... | |
Defines | |
#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. | |
int * | ast_io_change (struct io_context *ioc, int *id, int fd, ast_io_cb callback, short events, void *data) |
Changes an IO handler. | |
void | ast_io_dump (struct io_context *ioc) |
Dumps the IO array. Debugging: Dump everything in the I/O array. | |
int | ast_io_remove (struct io_context *ioc, int *_id) |
Removes an IO context. | |
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. | |
int | ast_restore_tty (int fd, int oldstate) |
Restores TTY mode. Call with result from previous ast_hide_password. | |
struct io_context * | io_context_create (void) |
Create an I/O context. | |
void | io_context_destroy (struct io_context *ioc) |
Destroys a context. | |
static int | io_grow (struct io_context *ioc) |
Grow the size of our arrays. | |
static int | io_shrink (struct io_context *ioc) |
I/O Managment (Derived from Cheops-NG)
Definition in file io.c.
#define DEBUG | ( | a | ) |
Definition at line 39 of file io.c.
Referenced by ast_io_add(), ast_io_wait(), and io_grow().
#define GROW_SHRINK_SIZE 512 |
Definition at line 58 of file io.c.
Referenced by io_context_create(), and io_grow().
int ast_get_termcols | ( | int | fd | ) |
Definition at line 364 of file io.c.
Referenced by ast_cli_display_match_list().
{ struct winsize win; int cols = 0; if (!isatty(fd)) return -1; if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) { if ( !cols && win.ws_col > 0 ) cols = (int) win.ws_col; } else { /* assume 80 characters if the ioctl fails for some reason */ cols = 80; } return cols; }
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.
Adds an IO context.
Definition at line 153 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_rtp_new_with_bindaddr(), ast_udptl_new_with_bindaddr(), do_monitor(), network_thread(), and p2p_callback_disable().
{ int *ret; DEBUG(ast_debug(1, "ast_io_add()\n")); if (ioc->fdcnt >= ioc->maxfdcnt) { /* * We don't have enough space for this entry. We need to * reallocate maxfdcnt poll fd's and io_rec's, or back out now. */ if (io_grow(ioc)) return NULL; } /* * At this point, we've got sufficiently large arrays going * and we can make an entry for it in the pollfd and io_r * structures. */ ioc->fds[ioc->fdcnt].fd = fd; ioc->fds[ioc->fdcnt].events = events; ioc->fds[ioc->fdcnt].revents = 0; ioc->ior[ioc->fdcnt].callback = callback; ioc->ior[ioc->fdcnt].data = data; if (!(ioc->ior[ioc->fdcnt].id = ast_malloc(sizeof(*ioc->ior[ioc->fdcnt].id)))) { /* Bonk if we couldn't allocate an int */ return NULL; } *(ioc->ior[ioc->fdcnt].id) = ioc->fdcnt; ret = ioc->ior[ioc->fdcnt].id; ioc->fdcnt++; return ret; }
int* ast_io_change | ( | struct io_context * | ioc, |
int * | id, | ||
int | fd, | ||
ast_io_cb | callback, | ||
short | events, | ||
void * | data | ||
) |
Changes an IO handler.
ioc | which context to use |
id | |
fd | the fd you wish it to contain now |
callback | new callback function |
events | event mask to wait for |
data | data 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. |
a | pointer to the ID of the IO event |
NULL | on failure |
Definition at line 191 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().
void ast_io_dump | ( | struct io_context * | ioc | ) |
Dumps the IO array. Debugging: Dump everything in the I/O array.
Definition at line 303 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.
{ /* * Print some debugging information via * the logger interface */ int x; ast_debug(1, "Asterisk IO Dump: %d entries, %d max entries\n", ioc->fdcnt, ioc->maxfdcnt); ast_debug(1, "================================================\n"); ast_debug(1, "| ID FD Callback Data Events |\n"); ast_debug(1, "+------+------+-----------+-----------+--------+\n"); for (x = 0; x < ioc->fdcnt; x++) { ast_debug(1, "| %.4d | %.4d | %p | %p | %.6x |\n", *ioc->ior[x].id, ioc->fds[x].fd, ioc->ior[x].callback, ioc->ior[x].data, ioc->fds[x].events); } ast_debug(1, "================================================\n"); }
int ast_io_remove | ( | struct io_context * | ioc, |
int * | id | ||
) |
Removes an IO context.
ioc | which io_context to remove it from |
id | which ID to remove Remove an I/O id from consideration |
0 | on success |
-1 | on failure |
Definition at line 236 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_rtp_destroy(), ast_udptl_destroy(), do_monitor(), p2p_callback_disable(), and reload_config().
{ int x; if (!_id) { ast_log(LOG_WARNING, "Asked to remove NULL?\n"); return -1; } for (x = 0; x < ioc->fdcnt; x++) { if (ioc->ior[x].id == _id) { /* Free the int immediately and set to NULL so we know it's unused now */ ast_free(ioc->ior[x].id); ioc->ior[x].id = NULL; ioc->fds[x].events = 0; ioc->fds[x].revents = 0; ioc->needshrink = 1; if (ioc->current_ioc == -1) io_shrink(ioc); return 0; } } ast_log(LOG_NOTICE, "Unable to remove unknown id %p\n", _id); return -1; }
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 269 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().
{ int res, x, origcnt; DEBUG(ast_debug(1, "ast_io_wait()\n")); if ((res = ast_poll(ioc->fds, ioc->fdcnt, howlong)) <= 0) { return res; } /* At least one event tripped */ origcnt = ioc->fdcnt; for (x = 0; x < origcnt; x++) { /* Yes, it is possible for an entry to be deleted and still have an event waiting if it occurs after the original calling id */ if (ioc->fds[x].revents && ioc->ior[x].id) { /* There's an event waiting */ ioc->current_ioc = *ioc->ior[x].id; if (ioc->ior[x].callback) { if (!ioc->ior[x].callback(ioc->ior[x].id, ioc->fds[x].fd, ioc->fds[x].revents, ioc->ior[x].data)) { /* Time to delete them since they returned a 0 */ ast_io_remove(ioc, ioc->ior[x].id); } } ioc->current_ioc = -1; } } if (ioc->needshrink) io_shrink(ioc); return res; }
int ast_restore_tty | ( | int | fd, |
int | oldstate | ||
) |
Restores TTY mode. Call with result from previous ast_hide_password.
Definition at line 347 of file io.c.
References ECHO.
Referenced by pw_cb().
{ int res; struct termios tios; if (oldstate < 0) return 0; res = tcgetattr(fd, &tios); if (res < 0) return -1; tios.c_lflag &= ~(ECHO | ECHONL); tios.c_lflag |= oldstate; res = tcsetattr(fd, TCSAFLUSH, &tios); if (res < 0) return -1; return 0; }
struct io_context* io_context_create | ( | void | ) | [read] |
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 72 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().
{ struct io_context *tmp = NULL; if (!(tmp = ast_malloc(sizeof(*tmp)))) return NULL; tmp->needshrink = 0; tmp->fdcnt = 0; tmp->maxfdcnt = GROW_SHRINK_SIZE/2; tmp->current_ioc = -1; if (!(tmp->fds = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->fds)))) { ast_free(tmp); tmp = NULL; } else { if (!(tmp->ior = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->ior)))) { ast_free(tmp->fds); ast_free(tmp); tmp = NULL; } } return tmp; }
void io_context_destroy | ( | struct io_context * | ioc | ) |
Destroys a context.
ioc | structure 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 98 of file io.c.
References ast_free, io_context::fds, and io_context::ior.
Referenced by load_module(), and unload_module().
static int io_grow | ( | struct io_context * | ioc | ) | [static] |
Grow the size of our arrays.
Definition at line 113 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().
{ void *tmp; DEBUG(ast_debug(1, "io_grow()\n")); ioc->maxfdcnt += GROW_SHRINK_SIZE; if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) { ioc->ior = tmp; if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) { ioc->fds = tmp; } else { /* * Failed to allocate enough memory for the pollfd. Not * really any need to shrink back the iorec's as we'll * probably want to grow them again soon when more memory * is available, and then they'll already be the right size */ ioc->maxfdcnt -= GROW_SHRINK_SIZE; return -1; } } else { /* * Memory allocation failure. We return to the old size, and * return a failure */ ioc->maxfdcnt -= GROW_SHRINK_SIZE; return -1; } return 0; }
static int io_shrink | ( | struct io_context * | ioc | ) | [static] |
Definition at line 209 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().
{ int getfrom, putto = 0; /* * Bring the fields from the very last entry to cover over * the entry we are removing, then decrease the size of the * arrays by one. */ for (getfrom = 0; getfrom < ioc->fdcnt; getfrom++) { if (ioc->ior[getfrom].id) { /* In use, save it */ if (getfrom != putto) { ioc->fds[putto] = ioc->fds[getfrom]; ioc->ior[putto] = ioc->ior[getfrom]; *(ioc->ior[putto].id) = putto; } putto++; } } ioc->fdcnt = putto; ioc->needshrink = 0; /* FIXME: We should free some memory if we have lots of unused io structs */ return 0; }