Sat Aug 6 00:39:57 2011

Asterisk developer's documentation


io.c File Reference

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

#include "asterisk.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <termios.h>
#include <string.h>
#include <sys/ioctl.h>
#include "asterisk/io.h"
#include "asterisk/logger.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Data Structures

struct  io_context
struct  io_rec

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)
int * ast_io_change (struct io_context *ioc, int *id, int fd, ast_io_cb callback, short events, void *data)
void ast_io_dump (struct io_context *ioc)
int ast_io_remove (struct io_context *ioc, int *_id)
int ast_io_wait (struct io_context *ioc, int howlong)
int ast_restore_tty (int fd, int oldstate)
io_contextio_context_create (void)
void io_context_destroy (struct io_context *ioc)
static int io_grow (struct io_context *ioc)
static int io_shrink (struct io_context *ioc)


Detailed Description

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

Author:
Mark Spencer <markster@digium.com>

Definition in file io.c.


Define Documentation

#define DEBUG (  ) 

Definition at line 44 of file io.c.

Referenced by ast_io_add(), ast_io_wait(), ast_sched_add_variable(), ast_sched_del(), ast_sched_runq(), ast_sched_wait(), ast_sched_when(), and io_grow().

#define GROW_SHRINK_SIZE   512

Definition at line 63 of file io.c.

Referenced by io_context_create(), and io_grow().


Function Documentation

int ast_get_termcols ( int  fd  ) 

Definition at line 353 of file io.c.

Referenced by ast_cli_display_match_list().

00354 {
00355    struct winsize win;
00356    int cols = 0;
00357 
00358    if (!isatty(fd))
00359       return -1;
00360 
00361    if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
00362       if ( !cols && win.ws_col > 0 )
00363          cols = (int) win.ws_col;
00364    } else {
00365       /* assume 80 characters if the ioctl fails for some reason */
00366       cols = 80;
00367    }
00368 
00369    return cols;
00370 }

int ast_hide_password ( int  fd  ) 

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

Definition at line 317 of file io.c.

References ECHO.

Referenced by pw_cb().

00318 {
00319    struct termios tios;
00320    int res;
00321    int old;
00322    if (!isatty(fd))
00323       return -1;
00324    res = tcgetattr(fd, &tios);
00325    if (res < 0)
00326       return -1;
00327    old = tios.c_lflag & (ECHO | ECHONL);
00328    tios.c_lflag &= ~ECHO;
00329    tios.c_lflag |= ECHONL;
00330    res = tcsetattr(fd, TCSAFLUSH, &tios);
00331    if (res < 0)
00332       return -1;
00333    return old;
00334 }

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

Parameters:
ioc which context to use
fd which fd to monitor
callback callback function to run
events event mask of events to wait for
data data to pass to the callback Watch for any of revents activites on fd, calling callback with data as callback data. Returns a pointer to ID of the IO event, or NULL on failure.

Definition at line 149 of file io.c.

References ast_log(), ast_malloc, io_rec::callback, io_rec::data, DEBUG, io_context::fdcnt, io_context::fds, io_rec::id, io_grow(), io_context::ior, LOG_DEBUG, and io_context::maxfdcnt.

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

00150 {
00151    /*
00152     * Add a new I/O entry for this file descriptor
00153     * with the given event mask, to call callback with
00154     * data as an argument.  Returns NULL on failure.
00155     */
00156    int *ret;
00157    DEBUG(ast_log(LOG_DEBUG, "ast_io_add()\n"));
00158    if (ioc->fdcnt >= ioc->maxfdcnt) {
00159       /* 
00160        * We don't have enough space for this entry.  We need to
00161        * reallocate maxfdcnt poll fd's and io_rec's, or back out now.
00162        */
00163       if (io_grow(ioc))
00164          return NULL;
00165    }
00166 
00167    /*
00168     * At this point, we've got sufficiently large arrays going
00169     * and we can make an entry for it in the pollfd and io_r
00170     * structures.
00171     */
00172    ioc->fds[ioc->fdcnt].fd = fd;
00173    ioc->fds[ioc->fdcnt].events = events;
00174    ioc->fds[ioc->fdcnt].revents = 0;
00175    ioc->ior[ioc->fdcnt].callback = callback;
00176    ioc->ior[ioc->fdcnt].data = data;
00177    if (!(ioc->ior[ioc->fdcnt].id = ast_malloc(sizeof(*ioc->ior[ioc->fdcnt].id)))) {
00178       /* Bonk if we couldn't allocate an int */
00179       return NULL;
00180    }
00181    *(ioc->ior[ioc->fdcnt].id) = ioc->fdcnt;
00182    ret = ioc->ior[ioc->fdcnt].id;
00183    ioc->fdcnt++;
00184    return ret;
00185 }

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

Parameters:
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. Returns a pointero to the ID of the IO event, or NULL on failure.

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

00188 {
00189    if (*id < ioc->fdcnt) {
00190       if (fd > -1)
00191          ioc->fds[*id].fd = fd;
00192       if (callback)
00193          ioc->ior[*id].callback = callback;
00194       if (events)
00195          ioc->fds[*id].events = events;
00196       if (data)
00197          ioc->ior[*id].data = data;
00198       return id;
00199    }
00200    return NULL;
00201 }

void ast_io_dump ( struct io_context ioc  ) 

Dumps the IO array

Definition at line 293 of file io.c.

References ast_log(), io_rec::callback, io_rec::data, io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, LOG_DEBUG, and io_context::maxfdcnt.

00294 {
00295    /*
00296     * Print some debugging information via
00297     * the logger interface
00298     */
00299    int x;
00300    ast_log(LOG_DEBUG, "Asterisk IO Dump: %d entries, %d max entries\n", ioc->fdcnt, ioc->maxfdcnt);
00301    ast_log(LOG_DEBUG, "================================================\n");
00302    ast_log(LOG_DEBUG, "| ID    FD     Callback    Data        Events  |\n");
00303    ast_log(LOG_DEBUG, "+------+------+-----------+-----------+--------+\n");
00304    for (x = 0; x < ioc->fdcnt; x++) {
00305       ast_log(LOG_DEBUG, "| %.4d | %.4d | %p | %p | %.6x |\n", 
00306             *ioc->ior[x].id,
00307             ioc->fds[x].fd,
00308             ioc->ior[x].callback,
00309             ioc->ior[x].data,
00310             ioc->fds[x].events);
00311    }
00312    ast_log(LOG_DEBUG, "================================================\n");
00313 }

int ast_io_remove ( struct io_context ioc,
int *  id 
)

Parameters:
ioc which io_context to remove it from
id which ID to remove Remove an I/O id from consideration Returns 0 on success or -1 on failure.

Definition at line 230 of file io.c.

References ast_log(), io_context::current_ioc, io_context::fdcnt, io_context::fds, free, io_rec::id, io_shrink(), io_context::ior, 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().

00231 {
00232    int x;
00233    if (!_id) {
00234       ast_log(LOG_WARNING, "Asked to remove NULL?\n");
00235       return -1;
00236    }
00237    for (x = 0; x < ioc->fdcnt; x++) {
00238       if (ioc->ior[x].id == _id) {
00239          /* Free the int immediately and set to NULL so we know it's unused now */
00240          free(ioc->ior[x].id);
00241          ioc->ior[x].id = NULL;
00242          ioc->fds[x].events = 0;
00243          ioc->fds[x].revents = 0;
00244          ioc->needshrink = 1;
00245          if (ioc->current_ioc == -1)
00246             io_shrink(ioc);
00247          return 0;
00248       }
00249    }
00250    
00251    ast_log(LOG_NOTICE, "Unable to remove unknown id %p\n", _id);
00252    return -1;
00253 }

int ast_io_wait ( struct io_context ioc,
int  howlong 
)

Parameters:
ioc which context to act upon
howlong how many milliseconds to wait Wait for I/O to happen, returning after howlong milliseconds, and after processing any necessary I/O. Returns the number of I/O events which took place.

Definition at line 255 of file io.c.

References ast_io_remove(), ast_log(), ast_poll, io_rec::callback, io_context::current_ioc, io_rec::data, DEBUG, io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and LOG_DEBUG.

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

00256 {
00257    /*
00258     * Make the poll call, and call
00259     * the callbacks for anything that needs
00260     * to be handled
00261     */
00262    int res;
00263    int x;
00264    int origcnt;
00265    DEBUG(ast_log(LOG_DEBUG, "ast_io_wait()\n"));
00266    res = ast_poll(ioc->fds, ioc->fdcnt, howlong);
00267    if (res > 0) {
00268       /*
00269        * At least one event
00270        */
00271       origcnt = ioc->fdcnt;
00272       for(x = 0; x < origcnt; x++) {
00273          /* Yes, it is possible for an entry to be deleted and still have an
00274             event waiting if it occurs after the original calling id */
00275          if (ioc->fds[x].revents && ioc->ior[x].id) {
00276             /* There's an event waiting */
00277             ioc->current_ioc = *ioc->ior[x].id;
00278             if (ioc->ior[x].callback) {
00279                if (!ioc->ior[x].callback(ioc->ior[x].id, ioc->fds[x].fd, ioc->fds[x].revents, ioc->ior[x].data)) {
00280                   /* Time to delete them since they returned a 0 */
00281                   ast_io_remove(ioc, ioc->ior[x].id);
00282                }
00283             }
00284             ioc->current_ioc = -1;
00285          }
00286       }
00287       if (ioc->needshrink)
00288          io_shrink(ioc);
00289    }
00290    return res;
00291 }

int ast_restore_tty ( int  fd,
int  oldstatus 
)

Restores TTY mode

Definition at line 336 of file io.c.

References ECHO.

Referenced by pw_cb().

00337 {
00338    int res;
00339    struct termios tios;
00340    if (oldstate < 0)
00341       return 0;
00342    res = tcgetattr(fd, &tios);
00343    if (res < 0)
00344       return -1;
00345    tios.c_lflag &= ~(ECHO | ECHONL);
00346    tios.c_lflag |= oldstate;
00347    res = tcsetattr(fd, TCSAFLUSH, &tios);
00348    if (res < 0)
00349       return -1;
00350    return 0;
00351 }

struct io_context* io_context_create ( void   ) 

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

Definition at line 82 of file io.c.

References ast_calloc, ast_malloc, free, GROW_SHRINK_SIZE, and io_context::needshrink.

Referenced by load_module().

00083 {
00084    /* Create an I/O context */
00085    struct io_context *tmp;
00086    if ((tmp = ast_malloc(sizeof(*tmp)))) {
00087       tmp->needshrink = 0;
00088       tmp->fdcnt = 0;
00089       tmp->maxfdcnt = GROW_SHRINK_SIZE/2;
00090       tmp->current_ioc = -1;
00091       if (!(tmp->fds = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->fds)))) {
00092          free(tmp);
00093          tmp = NULL;
00094       } else {
00095          if (!(tmp->ior = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->ior)))) {
00096             free(tmp->fds);
00097             free(tmp);
00098             tmp = NULL;
00099          }
00100       }
00101    }
00102    return tmp;
00103 }

void io_context_destroy ( struct io_context ioc  ) 

Destroys a context

Definition at line 105 of file io.c.

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

Referenced by load_module(), and unload_module().

00106 {
00107    /* Free associated memory with an I/O context */
00108    if (ioc->fds)
00109       free(ioc->fds);
00110    if (ioc->ior)
00111       free(ioc->ior);
00112    free(ioc);
00113 }

static int io_grow ( struct io_context ioc  )  [static]

Definition at line 115 of file io.c.

References ast_log(), ast_realloc, DEBUG, io_context::fds, GROW_SHRINK_SIZE, io_context::ior, LOG_DEBUG, and io_context::maxfdcnt.

Referenced by ast_io_add().

00116 {
00117    /* 
00118     * Grow the size of our arrays.  Return 0 on success or
00119     * -1 on failure
00120     */
00121    void *tmp;
00122    DEBUG(ast_log(LOG_DEBUG, "io_grow()\n"));
00123    ioc->maxfdcnt += GROW_SHRINK_SIZE;
00124    if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) {
00125       ioc->ior = tmp;
00126       if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) {
00127          ioc->fds = tmp;
00128       } else {
00129          /*
00130           * Failed to allocate enough memory for the pollfd.  Not
00131           * really any need to shrink back the iorec's as we'll
00132           * probably want to grow them again soon when more memory
00133           * is available, and then they'll already be the right size
00134           */
00135          ioc->maxfdcnt -= GROW_SHRINK_SIZE;
00136          return -1;
00137       }
00138    } else {
00139       /*
00140        * Memory allocation failure.  We return to the old size, and 
00141        * return a failure
00142        */
00143       ioc->maxfdcnt -= GROW_SHRINK_SIZE;
00144       return -1;
00145    }
00146    return 0;
00147 }

static int io_shrink ( struct io_context ioc  )  [static]

Definition at line 203 of file io.c.

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

Referenced by ast_io_remove().

00204 {
00205    int getfrom;
00206    int putto = 0;
00207    /* 
00208     * Bring the fields from the very last entry to cover over
00209     * the entry we are removing, then decrease the size of the 
00210     * arrays by one.
00211     */
00212    for (getfrom = 0; getfrom < ioc->fdcnt; getfrom++) {
00213       if (ioc->ior[getfrom].id) {
00214          /* In use, save it */
00215          if (getfrom != putto) {
00216             ioc->fds[putto] = ioc->fds[getfrom];
00217             ioc->ior[putto] = ioc->ior[getfrom];
00218             *(ioc->ior[putto].id) = putto;
00219          }
00220          putto++;
00221       }
00222    }
00223    ioc->fdcnt = putto;
00224    ioc->needshrink = 0;
00225    /* FIXME: We should free some memory if we have lots of unused
00226       io structs */
00227    return 0;
00228 }


Generated on Sat Aug 6 00:39:57 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7