Thu Apr 28 2011 17:13:56

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"
Include dependency graph for io.c:

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_contextio_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)

Detailed Description

I/O Managment (Derived from Cheops-NG)

Author:
Mark Spencer <markster@digium.com>

Definition in file io.c.


Define Documentation

#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().


Function Documentation

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)

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

Definition at line 328 of file io.c.

References ECHO.

Referenced by pw_cb().

{
   struct termios tios;
   int res;
   int old;
   if (!isatty(fd))
      return -1;
   res = tcgetattr(fd, &tios);
   if (res < 0)
      return -1;
   old = tios.c_lflag & (ECHO | ECHONL);
   tios.c_lflag &= ~ECHO;
   tios.c_lflag |= ECHONL;
   res = tcsetattr(fd, TCSAFLUSH, &tios);
   if (res < 0)
      return -1;
   return old;
}
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 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.

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

{
   /* If this id exceeds our file descriptor count it doesn't exist here */
   if (*id > ioc->fdcnt)
      return NULL;

   if (fd > -1)
      ioc->fds[*id].fd = fd;
   if (callback)
      ioc->ior[*id].callback = callback;
   if (events)
      ioc->fds[*id].events = events;
   if (data)
      ioc->ior[*id].data = data;

   return id;
}
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.

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

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 98 of file io.c.

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

Referenced by load_module(), and unload_module().

{
   /* Free associated memory with an I/O context */
   if (ioc->fds)
      ast_free(ioc->fds);
   if (ioc->ior)
      ast_free(ioc->ior);

   ast_free(ioc);
}
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 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;
}