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 GROW_SHRINK_SIZE 512 |
Definition at line 62 of file io.c.
Referenced by io_context_create(), and io_grow().
int ast_get_termcols | ( | int | fd | ) |
Definition at line 368 of file io.c.
Referenced by ast_cli_display_match_list().
00369 { 00370 struct winsize win; 00371 int cols = 0; 00372 00373 if (!isatty(fd)) 00374 return -1; 00375 00376 if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) { 00377 if ( !cols && win.ws_col > 0 ) 00378 cols = (int) win.ws_col; 00379 } else { 00380 /* assume 80 characters if the ioctl fails for some reason */ 00381 cols = 80; 00382 } 00383 00384 return cols; 00385 }
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.
Referenced by pw_cb().
00333 { 00334 struct termios tios; 00335 int res; 00336 int old; 00337 if (!isatty(fd)) 00338 return -1; 00339 res = tcgetattr(fd, &tios); 00340 if (res < 0) 00341 return -1; 00342 old = tios.c_lflag & (ECHO | ECHONL); 00343 tios.c_lflag &= ~ECHO; 00344 tios.c_lflag |= ECHONL; 00345 res = tcsetattr(fd, TCSAFLUSH, &tios); 00346 if (res < 0) 00347 return -1; 00348 return old; 00349 }
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 157 of file io.c.
References ast_debug, ast_malloc, io_rec::callback, io_rec::data, DEBUG, 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().
00158 { 00159 int *ret; 00160 00161 DEBUG(ast_debug(1, "ast_io_add()\n")); 00162 00163 if (ioc->fdcnt >= ioc->maxfdcnt) { 00164 /* 00165 * We don't have enough space for this entry. We need to 00166 * reallocate maxfdcnt poll fd's and io_rec's, or back out now. 00167 */ 00168 if (io_grow(ioc)) 00169 return NULL; 00170 } 00171 00172 /* 00173 * At this point, we've got sufficiently large arrays going 00174 * and we can make an entry for it in the pollfd and io_r 00175 * structures. 00176 */ 00177 ioc->fds[ioc->fdcnt].fd = fd; 00178 ioc->fds[ioc->fdcnt].events = events; 00179 ioc->fds[ioc->fdcnt].revents = 0; 00180 ioc->ior[ioc->fdcnt].callback = callback; 00181 ioc->ior[ioc->fdcnt].data = data; 00182 00183 if (!(ioc->ior[ioc->fdcnt].id = ast_malloc(sizeof(*ioc->ior[ioc->fdcnt].id)))) { 00184 /* Bonk if we couldn't allocate an int */ 00185 return NULL; 00186 } 00187 00188 *(ioc->ior[ioc->fdcnt].id) = ioc->fdcnt; 00189 ret = ioc->ior[ioc->fdcnt].id; 00190 ioc->fdcnt++; 00191 00192 return ret; 00193 }
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 195 of file io.c.
References io_rec::callback, io_rec::data, io_context::fdcnt, io_context::fds, and io_context::ior.
Referenced by do_monitor().
00196 { 00197 /* If this id exceeds our file descriptor count it doesn't exist here */ 00198 if (*id > ioc->fdcnt) 00199 return NULL; 00200 00201 if (fd > -1) 00202 ioc->fds[*id].fd = fd; 00203 if (callback) 00204 ioc->ior[*id].callback = callback; 00205 if (events) 00206 ioc->fds[*id].events = events; 00207 if (data) 00208 ioc->ior[*id].data = data; 00209 00210 return id; 00211 }
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.
00308 { 00309 /* 00310 * Print some debugging information via 00311 * the logger interface 00312 */ 00313 int x; 00314 00315 ast_debug(1, "Asterisk IO Dump: %u entries, %u max entries\n", ioc->fdcnt, ioc->maxfdcnt); 00316 ast_debug(1, "================================================\n"); 00317 ast_debug(1, "| ID FD Callback Data Events |\n"); 00318 ast_debug(1, "+------+------+-----------+-----------+--------+\n"); 00319 for (x = 0; x < ioc->fdcnt; x++) { 00320 ast_debug(1, "| %.4d | %.4d | %p | %p | %.6x |\n", 00321 *ioc->ior[x].id, 00322 ioc->fds[x].fd, 00323 ioc->ior[x].callback, 00324 ioc->ior[x].data, 00325 (unsigned)ioc->fds[x].events); 00326 } 00327 ast_debug(1, "================================================\n"); 00328 }
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 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().
00241 { 00242 int x; 00243 00244 if (!_id) { 00245 ast_log(LOG_WARNING, "Asked to remove NULL?\n"); 00246 return -1; 00247 } 00248 00249 for (x = 0; x < ioc->fdcnt; x++) { 00250 if (ioc->ior[x].id == _id) { 00251 /* Free the int immediately and set to NULL so we know it's unused now */ 00252 ast_free(ioc->ior[x].id); 00253 ioc->ior[x].id = NULL; 00254 ioc->fds[x].events = 0; 00255 ioc->fds[x].revents = 0; 00256 ioc->needshrink = 1; 00257 if (ioc->current_ioc == -1) 00258 io_shrink(ioc); 00259 return 0; 00260 } 00261 } 00262 00263 ast_log(LOG_NOTICE, "Unable to remove unknown id %p\n", _id); 00264 00265 return -1; 00266 }
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().
00274 { 00275 int res, x, origcnt; 00276 00277 DEBUG(ast_debug(1, "ast_io_wait()\n")); 00278 00279 if ((res = ast_poll(ioc->fds, ioc->fdcnt, howlong)) <= 0) { 00280 return res; 00281 } 00282 00283 /* At least one event tripped */ 00284 origcnt = ioc->fdcnt; 00285 for (x = 0; x < origcnt; x++) { 00286 /* Yes, it is possible for an entry to be deleted and still have an 00287 event waiting if it occurs after the original calling id */ 00288 if (ioc->fds[x].revents && ioc->ior[x].id) { 00289 /* There's an event waiting */ 00290 ioc->current_ioc = *ioc->ior[x].id; 00291 if (ioc->ior[x].callback) { 00292 if (!ioc->ior[x].callback(ioc->ior[x].id, ioc->fds[x].fd, ioc->fds[x].revents, ioc->ior[x].data)) { 00293 /* Time to delete them since they returned a 0 */ 00294 ast_io_remove(ioc, ioc->ior[x].id); 00295 } 00296 } 00297 ioc->current_ioc = -1; 00298 } 00299 } 00300 00301 if (ioc->needshrink) 00302 io_shrink(ioc); 00303 00304 return res; 00305 }
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().
00352 { 00353 int res; 00354 struct termios tios; 00355 if (oldstate < 0) 00356 return 0; 00357 res = tcgetattr(fd, &tios); 00358 if (res < 0) 00359 return -1; 00360 tios.c_lflag &= ~(ECHO | ECHONL); 00361 tios.c_lflag |= oldstate; 00362 res = tcsetattr(fd, TCSAFLUSH, &tios); 00363 if (res < 0) 00364 return -1; 00365 return 0; 00366 }
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 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().
00077 { 00078 struct io_context *tmp = NULL; 00079 00080 if (!(tmp = ast_malloc(sizeof(*tmp)))) 00081 return NULL; 00082 00083 tmp->needshrink = 0; 00084 tmp->fdcnt = 0; 00085 tmp->maxfdcnt = GROW_SHRINK_SIZE/2; 00086 tmp->current_ioc = -1; 00087 00088 if (!(tmp->fds = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->fds)))) { 00089 ast_free(tmp); 00090 tmp = NULL; 00091 } else { 00092 if (!(tmp->ior = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->ior)))) { 00093 ast_free(tmp->fds); 00094 ast_free(tmp); 00095 tmp = NULL; 00096 } 00097 } 00098 00099 return tmp; 00100 }
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 102 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 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().
00118 { 00119 void *tmp; 00120 00121 DEBUG(ast_debug(1, "io_grow()\n")); 00122 00123 ioc->maxfdcnt += GROW_SHRINK_SIZE; 00124 00125 if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) { 00126 ioc->ior = tmp; 00127 if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) { 00128 ioc->fds = tmp; 00129 } else { 00130 /* 00131 * Failed to allocate enough memory for the pollfd. Not 00132 * really any need to shrink back the iorec's as we'll 00133 * probably want to grow them again soon when more memory 00134 * is available, and then they'll already be the right size 00135 */ 00136 ioc->maxfdcnt -= GROW_SHRINK_SIZE; 00137 return -1; 00138 } 00139 } else { 00140 /* 00141 * Memory allocation failure. We return to the old size, and 00142 * return a failure 00143 */ 00144 ioc->maxfdcnt -= GROW_SHRINK_SIZE; 00145 return -1; 00146 } 00147 00148 return 0; 00149 }
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().
00214 { 00215 int getfrom, putto = 0; 00216 00217 /* 00218 * Bring the fields from the very last entry to cover over 00219 * the entry we are removing, then decrease the size of the 00220 * arrays by one. 00221 */ 00222 for (getfrom = 0; getfrom < ioc->fdcnt; getfrom++) { 00223 if (ioc->ior[getfrom].id) { 00224 /* In use, save it */ 00225 if (getfrom != putto) { 00226 ioc->fds[putto] = ioc->fds[getfrom]; 00227 ioc->ior[putto] = ioc->ior[getfrom]; 00228 *(ioc->ior[putto].id) = putto; 00229 } 00230 putto++; 00231 } 00232 } 00233 ioc->fdcnt = putto; 00234 ioc->needshrink = 0; 00235 /* FIXME: We should free some memory if we have lots of unused 00236 io structs */ 00237 return 0; 00238 }