dect
/
asterisk
Archived
13
0
Fork 0

Merged revisions 284597 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.8

................
  r284597 | tilghman | 2010-09-02 00:00:34 -0500 (Thu, 02 Sep 2010) | 29 lines
  
  Merged revisions 284593,284595 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.6.2
  
  ................
    r284593 | tilghman | 2010-09-01 17:59:50 -0500 (Wed, 01 Sep 2010) | 18 lines
    
    Merged revisions 284478 via svnmerge from 
    https://origsvn.digium.com/svn/asterisk/branches/1.4
    
    ........
      r284478 | tilghman | 2010-09-01 13:49:11 -0500 (Wed, 01 Sep 2010) | 11 lines
      
      Ensure that all areas that previously used select(2) now use poll(2), with implementations that need poll(2) implemented with select(2) safe against 1024-bit overflows.
      
      This is a followup to the fix for the pthread timer in 1.6.2 and beyond, fixing
      a potential crash bug in all supported releases.
      
      (closes issue #17678)
       Reported by: russell
      Branch: https://origsvn.digium.com/svn/asterisk/team/tilghman/ast_select 
      
      Review: https://reviewboard.asterisk.org/r/824/
    ........
  ................
    r284595 | tilghman | 2010-09-01 22:57:43 -0500 (Wed, 01 Sep 2010) | 2 lines
    
    Failed to rerun bootstrap.sh after last commit
  ................
................


git-svn-id: http://svn.digium.com/svn/asterisk/trunk@284598 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
tilghman 2010-09-02 05:02:54 +00:00
parent 37f68a5475
commit c32f63c825
20 changed files with 32277 additions and 7995 deletions

View File

@ -23,6 +23,7 @@
#define _OOSOCKET_H_
#include "asterisk/poll-compat.h"
#include "asterisk/compiler.h"
#ifdef _WIN32_WCE
#include <winsock.h>
@ -329,9 +330,9 @@ EXTERN int ooSocketSendTo(OOSOCKET socket, const ASN1OCTET* pdata,
* returns.
* @return Completion status of operation: 0 (ASN_OK) = success,
* negative return value is error.
*/
*/
EXTERN int ooSocketSelect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval * timeout);
fd_set *exceptfds, struct timeval * timeout) __attribute_deprecated__;
EXTERN int ooSocketPoll(struct pollfd *pfds, int nfds, int timeout);

View File

@ -15,6 +15,7 @@
*****************************************************************************/
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/poll-compat.h"
#include "ooports.h"
#include "oochannels.h"
@ -1980,22 +1981,12 @@ int ooStopMonitorCalls()
OOBOOL ooChannelsIsConnectionOK(OOH323CallData *call, OOSOCKET sock)
{
struct timeval to;
fd_set readfds;
int ret = 0, nfds=0;
struct timeval to = { .tv_usec = 500 };
struct pollfd pfds = { .fd = sock, .events = POLLIN };
int ret = 0;
to.tv_sec = 0;
to.tv_usec = 500;
FD_ZERO(&readfds);
ret = ast_poll2(&pfds, 1, &to);
FD_SET(sock, &readfds);
if(nfds < (int)sock)
nfds = (int)sock;
nfds++;
ret = ooSocketSelect(nfds, &readfds, NULL, NULL, &to);
if(ret == -1)
{
OOTRACEERR3("Error in select ...broken pipe check(%s, %s)\n",

View File

@ -7160,15 +7160,14 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
static struct ast_frame *misdn_read(struct ast_channel *ast)
{
struct chan_list *tmp;
fd_set rrfs;
struct timeval tv = { 0, 20000 };
int len, t;
struct pollfd pfd = { .fd = -1, .events = POLLIN };
if (!ast) {
chan_misdn_log(1, 0, "misdn_read called without ast\n");
return NULL;
}
if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
return NULL;
}
@ -7178,21 +7177,18 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
return NULL;
}
FD_ZERO(&rrfs);
FD_SET(tmp->pipe[0], &rrfs);
t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv);
if (!t) {
chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
len = 160;
}
pfd.fd = tmp->pipe[0];
t = ast_poll(&pfd, 1, 20);
if (t < 0) {
chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n", strerror(errno));
chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
return NULL;
}
if (FD_ISSET(tmp->pipe[0], &rrfs)) {
if (!t) {
chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
len = 160;
} else if (pfd.revents & POLLIN) {
len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
if (len <= 0) {
@ -10456,25 +10452,21 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ast_queue_frame(ch->ast, &frame);
}
} else {
fd_set wrfs;
struct timeval tv = { 0, 0 };
struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
int t;
FD_ZERO(&wrfs);
FD_SET(ch->pipe[1], &wrfs);
t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
if (!t) {
chan_misdn_log(9, bc->port, "Select Timed out\n");
break;
}
t = ast_poll(&pfd, 1, 0);
if (t < 0) {
chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
break;
}
if (!t) {
chan_misdn_log(9, bc->port, "poll() timed out\n");
break;
}
if (FD_ISSET(ch->pipe[1], &wrfs)) {
if (pfd.revents & POLLOUT) {
chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));

View File

@ -1017,12 +1017,12 @@ static void phone_check_exception(struct phone_pvt *i)
static void *do_monitor(void *data)
{
fd_set rfds, efds;
int n, res;
struct pollfd *fds = NULL;
int nfds = 0, inuse_fds = 0, res;
struct phone_pvt *i;
int tonepos = 0;
/* The tone we're playing this round */
struct timeval wait = {0,0};
struct timeval tv = { 0, 0 };
int dotone;
/* This thread monitors all the frame relay interfaces which are not yet in use
(and thus do not have a separate thread) indefinitely */
@ -1036,33 +1036,38 @@ static void *do_monitor(void *data)
}
/* Build the stuff we're going to select on, that is the socket of every
phone_pvt that does not have an associated owner channel */
n = -1;
FD_ZERO(&rfds);
FD_ZERO(&efds);
i = iflist;
dotone = 0;
while (i) {
if (FD_ISSET(i->fd, &rfds))
ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
inuse_fds = 0;
for (i = iflist; i; i = i->next) {
if (!i->owner) {
/* This needs to be watched, as it lacks an owner */
FD_SET(i->fd, &rfds);
FD_SET(i->fd, &efds);
if (i->fd > n)
n = i->fd;
if (inuse_fds == nfds) {
void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
if (!tmp) {
/* Avoid leaking */
continue;
}
fds = tmp;
nfds++;
}
fds[inuse_fds].fd = i->fd;
fds[inuse_fds].events = POLLIN | POLLERR;
fds[inuse_fds].revents = 0;
inuse_fds++;
if (i->dialtone && i->mode != MODE_SIGMA) {
/* Remember we're going to have to come back and play
more dialtones */
if (ast_tvzero(wait)) {
if (ast_tvzero(tv)) {
/* If we're due for a dialtone, play one */
if (write(i->fd, DialTone + tonepos, 240) != 240)
if (write(i->fd, DialTone + tonepos, 240) != 240) {
ast_log(LOG_WARNING, "Dial tone write error\n");
}
}
dotone++;
}
}
i = i->next;
}
/* Okay, now that we know what to do, release the interface lock */
ast_mutex_unlock(&iflock);
@ -1071,26 +1076,28 @@ static void *do_monitor(void *data)
if (dotone && i && i->mode != MODE_SIGMA) {
/* If we're ready to recycle the time, set it to 30 ms */
tonepos += 240;
if (tonepos >= sizeof(DialTone))
tonepos = 0;
if (ast_tvzero(wait)) {
wait = ast_tv(30000, 0);
if (tonepos >= sizeof(DialTone)) {
tonepos = 0;
}
res = ast_select(n + 1, &rfds, NULL, &efds, &wait);
if (ast_tvzero(tv)) {
tv = ast_tv(0, 30000);
}
res = ast_poll2(fds, inuse_fds, &tv);
} else {
res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
wait = ast_tv(0,0);
res = ast_poll(fds, inuse_fds, -1);
tv = ast_tv(0, 0);
tonepos = 0;
}
/* Okay, select has finished. Let's see what happened. */
if (res < 0) {
ast_debug(1, "select return %d: %s\n", res, strerror(errno));
ast_debug(1, "poll returned %d: %s\n", res, strerror(errno));
continue;
}
/* If there are no fd's changed, just continue, it's probably time
to play some more dialtones */
if (!res)
if (!res) {
continue;
}
/* Alright, lock the interface list again, and let's look and see what has
happened */
if (ast_mutex_lock(&iflock)) {
@ -1098,15 +1105,27 @@ static void *do_monitor(void *data)
continue;
}
i = iflist;
for(; i; i=i->next) {
if (FD_ISSET(i->fd, &rfds)) {
for (i = iflist; i; i = i->next) {
int j;
/* Find the record */
for (j = 0; j < inuse_fds; j++) {
if (fds[j].fd == i->fd) {
break;
}
}
/* Not found? */
if (j == inuse_fds) {
continue;
}
if (fds[j].revents & POLLIN) {
if (i->owner) {
continue;
}
phone_mini_packet(i);
}
if (FD_ISSET(i->fd, &efds)) {
if (fds[j].revents & POLLERR) {
if (i->owner) {
continue;
}
@ -1116,7 +1135,6 @@ static void *do_monitor(void *data)
ast_mutex_unlock(&iflock);
}
return NULL;
}
static int restart_monitor()

View File

@ -1119,8 +1119,7 @@ static void *hidthread(void *arg)
struct usb_device *usb_dev;
struct usb_dev_handle *usb_handle;
struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
struct timeval to;
fd_set rfds;
struct pollfd pfd = { .events = POLLIN };
usb_dev = hid_device_init(o->devstr);
if (usb_dev == NULL) {
@ -1156,63 +1155,49 @@ static void *hidthread(void *arg)
traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
lastrx = 0;
// popen
while(!o->stophid)
{
to.tv_sec = 0;
to.tv_usec = 50000; // maw sph
while (!o->stophid) {
pfd.fd = o->pttkick;
pfd.revents = 0;
FD_ZERO(&rfds);
FD_SET(o->pttkick[0],&rfds);
/* ast_select emulates linux behaviour in terms of timeout handling */
res = ast_select(o->pttkick[0] + 1, &rfds, NULL, NULL, &to);
res = ast_poll2(&pfd, 1, 50);
if (res < 0) {
ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
usleep(10000);
continue;
}
if (FD_ISSET(o->pttkick[0],&rfds))
{
if (pfd.revents & POLLIN) { {
char c;
if (read(o->pttkick[0],&c,1) < 0) {
if (read(o->pttkick[0], &c, 1) < 0) {
ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
}
}
if(o->wanteeprom)
{
if (o->wanteeprom) {
ast_mutex_lock(&o->eepromlock);
if (o->eepromctl == 1) /* to read */
{
if (o->eepromctl == 1) { /* to read */
/* if CS okay */
if (!get_eeprom(usb_handle,o->eeprom))
{
if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC)
{
ast_log(LOG_NOTICE,"UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n",o->name);
}
else
{
if (!get_eeprom(usb_handle, o->eeprom)) {
if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC) {
ast_log(LOG_NOTICE, "UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n", o->name);
} else {
o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
memcpy(&o->rxvoiceadj,&o->eeprom[EEPROM_RXVOICEADJ],sizeof(float));
memcpy(&o->rxctcssadj,&o->eeprom[EEPROM_RXCTCSSADJ],sizeof(float));
memcpy(&o->rxvoiceadj, &o->eeprom[EEPROM_RXVOICEADJ], sizeof(float));
memcpy(&o->rxctcssadj, &o->eeprom[EEPROM_RXCTCSSADJ], sizeof(float));
o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ];
o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
}
}
else
{
ast_log(LOG_NOTICE,"USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n",o->name);
} else {
ast_log(LOG_NOTICE, "USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n", o->name);
}
hid_set_outputs(usb_handle,bufsave);
}
if (o->eepromctl == 2) /* to write */
{
}
if (o->eepromctl == 2) { /* to write */
put_eeprom(usb_handle,o->eeprom);
hid_set_outputs(usb_handle,bufsave);
ast_log(LOG_NOTICE,"USB Parameters written to EEPROM on %s\n",o->name);
ast_log(LOG_NOTICE, "USB Parameters written to EEPROM on %s\n", o->name);
}
o->eepromctl = 0;
ast_mutex_unlock(&o->eepromlock);
@ -1220,38 +1205,43 @@ static void *hidthread(void *arg)
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
hid_get_inputs(usb_handle,buf);
keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
if (keyed != o->rxhidsq)
{
if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed);
if (keyed != o->rxhidsq) {
if (o->debuglevel) {
printf("chan_usbradio() hidthread: update rxhidsq = %d\n", keyed);
}
o->rxhidsq=keyed;
}
/* if change in tx state as controlled by xpmr */
txtmp=o->pmrChan->txPttOut;
if (o->lasttx != txtmp)
{
o->pmrChan->txPttHid=o->lasttx = txtmp;
if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp);
buf[o->hid_gpio_loc] = 0;
if (!o->invertptt)
{
if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
txtmp = o->pmrChan->txPttOut;
if (o->lasttx != txtmp) {
o->pmrChan->txPttHid = o->lasttx = txtmp;
if (o->debuglevel) {
ast_debug(0, "hidthread: tx set to %d\n", txtmp);
}
else
{
if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
buf[o->hid_gpio_loc] = 0;
if (!o->invertptt) {
if (txtmp) {
buf[o->hid_gpio_loc] = o->hid_io_ptt;
}
} else {
if (!txtmp) {
buf[o->hid_gpio_loc] = o->hid_io_ptt;
}
}
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
memcpy(bufsave,buf,sizeof(buf));
hid_set_outputs(usb_handle,buf);
memcpy(bufsave, buf, sizeof(buf));
hid_set_outputs(usb_handle, buf);
}
time(&o->lasthidtime);
}
buf[o->hid_gpio_loc] = 0;
if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt;
if (o->invertptt) {
buf[o->hid_gpio_loc] = o->hid_io_ptt;
}
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
hid_set_outputs(usb_handle,buf);
hid_set_outputs(usb_handle, buf);
pthread_exit(0);
}
@ -1452,37 +1442,29 @@ static void *sound_thread(void *arg)
*/
read(o->sounddev, ign, sizeof(ign));
for (;;) {
fd_set rfds, wfds;
int maxfd, res;
struct pollfd pfd[2] = { { .fd = o->sndcmd[0], .events = POLLIN }, { .fd = o->sounddev } };
int res;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(o->sndcmd[0], &rfds);
maxfd = o->sndcmd[0]; /* pipe from the main process */
if (o->cursound > -1 && o->sounddev < 0)
if (o->cursound > -1 && o->sounddev < 0) {
setformat(o, O_RDWR); /* need the channel, try to reopen */
else if (o->cursound == -1 && o->owner == NULL)
{
} else if (o->cursound == -1 && o->owner == NULL) {
setformat(o, O_CLOSE); /* can close */
}
if (o->sounddev > -1) {
if (!o->owner) { /* no one owns the audio, so we must drain it */
FD_SET(o->sounddev, &rfds);
maxfd = MAX(o->sounddev, maxfd);
pfd[1].events = POLLIN;
}
if (o->cursound > -1) {
FD_SET(o->sounddev, &wfds);
maxfd = MAX(o->sounddev, maxfd);
pfd[1].events |= POLLOUT;
}
}
/* ast_select emulates linux behaviour in terms of timeout handling */
res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
res = ast_poll(pfd, o->sounddev > -1 ? 2 : 1, -1);
if (res < 1) {
ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
ast_log(LOG_WARNING, "poll failed: %s\n", strerror(errno));
sleep(1);
continue;
}
if (FD_ISSET(o->sndcmd[0], &rfds)) {
if (pfd[0].revents & POLLIN) {
/* read which sound to play from the pipe */
int i, what = -1;
@ -1495,14 +1477,17 @@ static void *sound_thread(void *arg)
break;
}
}
if (sounds[i].ind == -1)
if (sounds[i].ind == -1) {
ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
}
}
if (o->sounddev > -1) {
if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
if (pfd[1].revents & POLLIN) { /* read and ignore errors */
read(o->sounddev, ign, sizeof(ign));
if (FD_ISSET(o->sounddev, &wfds))
}
if (pfd[1].revents & POLLOUT) {
send_sound(o);
}
}
}
return NULL; /* Never reached */

View File

@ -234,34 +234,34 @@ struct video_out_desc {
* and contain all configurtion info.
*/
struct video_desc {
char codec_name[64]; /* the codec we use */
char codec_name[64]; /* the codec we use */
int stayopen; /* set if gui starts manually */
pthread_t vthread; /* video thread */
ast_mutex_t dec_lock; /* sync decoder and video thread */
int shutdown; /* set to shutdown vthread */
struct ast_channel *owner; /* owner channel */
int stayopen; /* set if gui starts manually */
pthread_t vthread; /* video thread */
ast_mutex_t dec_lock; /* sync decoder and video thread */
int shutdown; /* set to shutdown vthread */
struct ast_channel *owner; /* owner channel */
struct fbuf_t enc_in; /* encoder input buffer, allocated in video_out_init() */
struct fbuf_t enc_in; /* encoder input buffer, allocated in video_out_init() */
char keypad_file[256]; /* image for the keypad */
char keypad_font[256]; /* font for the keypad */
char keypad_file[256]; /* image for the keypad */
char keypad_font[256]; /* font for the keypad */
char sdl_videodriver[256];
char sdl_videodriver[256];
struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */
struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */
struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */
struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */
/* geometry of the thumbnails for all video sources. */
struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */
struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */
int frame_freeze; /* flag to freeze the incoming frame */
int frame_freeze; /* flag to freeze the incoming frame */
/* local information for grabbers, codecs, gui */
struct gui_info *gui;
struct video_dec_desc *in; /* remote video descriptor */
struct video_out_desc out; /* local video descriptor */
struct gui_info *gui;
struct video_dec_desc *in; /* remote video descriptor */
struct video_out_desc out; /* local video descriptor */
};
static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
@ -387,8 +387,9 @@ static struct fbuf_t *grabber_read(struct video_device *dev, int fps)
*/
static void grabber_move(struct video_device *dev, int dx, int dy)
{
if (dev->grabber && dev->grabber->move)
dev->grabber->move(dev->grabber_data, dx, dy);
if (dev->grabber && dev->grabber->move) {
dev->grabber->move(dev->grabber_data, dx, dy);
}
}
/*
@ -508,33 +509,32 @@ static int video_out_init(struct video_desc *env)
/* now setup the parameters for the encoder.
* XXX should be codec-specific
*/
{
AVCodecContext *enc_ctx = avcodec_alloc_context();
v->enc_ctx = enc_ctx;
enc_ctx->pix_fmt = enc_in->pix_fmt;
enc_ctx->width = enc_in->w;
enc_ctx->height = enc_in->h;
/* XXX rtp_callback ?
* rtp_mode so ffmpeg inserts as many start codes as possible.
*/
enc_ctx->rtp_mode = 1;
enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2
enc_ctx->bit_rate = v->bitrate;
enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
enc_ctx->qmin = v->qmin; /* should be configured */
enc_ctx->time_base = (AVRational){1, v->fps};
enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
{
AVCodecContext *enc_ctx = avcodec_alloc_context();
v->enc_ctx = enc_ctx;
enc_ctx->pix_fmt = enc_in->pix_fmt;
enc_ctx->width = enc_in->w;
enc_ctx->height = enc_in->h;
/* XXX rtp_callback ?
* rtp_mode so ffmpeg inserts as many start codes as possible.
*/
enc_ctx->rtp_mode = 1;
enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2
enc_ctx->bit_rate = v->bitrate;
enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
enc_ctx->qmin = v->qmin; /* should be configured */
enc_ctx->time_base = (AVRational){1, v->fps};
enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
v->enc->enc_init(v->enc_ctx);
if (avcodec_open(enc_ctx, v->codec) < 0) {
ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n",
codec);
av_free(enc_ctx);
v->enc_ctx = NULL;
return video_out_uninit(env);
v->enc->enc_init(v->enc_ctx);
if (avcodec_open(enc_ctx, v->codec) < 0) {
ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n", codec);
av_free(enc_ctx);
v->enc_ctx = NULL;
return video_out_uninit(env);
}
}
}
/*
* Allocate enough for the encoded bitstream. As we are compressing,
* we hope that the output is never larger than the input size.
@ -637,9 +637,9 @@ static void my_scale(struct fbuf_t *in, AVPicture *p_in,
p_in = fill_pict(in, &my_p_in);
if (p_out == NULL)
p_out = fill_pict(out, &my_p_out);
/*if win_w is different from zero then we must change
the size of the scaled buffer (the position is already
/*if win_w is different from zero then we must change
the size of the scaled buffer (the position is already
encoded into the out parameter)*/
if (out->win_w) { /* picture in picture enabled */
eff_w=out->win_w;
@ -650,26 +650,26 @@ static void my_scale(struct fbuf_t *in, AVPicture *p_in,
img_convert(p_out, out->pix_fmt,
p_in, in->pix_fmt, in->w, in->h);
#else /* XXX replacement */
{
struct SwsContext *convert_ctx;
convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
eff_w, eff_h, out->pix_fmt,
SWS_BICUBIC, NULL, NULL, NULL);
if (convert_ctx == NULL) {
ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
return;
}
if (0)
ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
in->pix_fmt, in->w, in->h, out->pix_fmt, eff_w, eff_h);
sws_scale(convert_ctx,
p_in->data, p_in->linesize,
in->w, in->h, /* src slice */
p_out->data, p_out->linesize);
{
struct SwsContext *convert_ctx;
sws_freeContext(convert_ctx);
}
convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
eff_w, eff_h, out->pix_fmt,
SWS_BICUBIC, NULL, NULL, NULL);
if (convert_ctx == NULL) {
ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
return;
}
if (0)
ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
in->pix_fmt, in->w, in->h, out->pix_fmt, eff_w, eff_h);
sws_scale(convert_ctx,
p_in->data, p_in->linesize,
in->w, in->h, /* src slice */
p_out->data, p_out->linesize);
sws_freeContext(convert_ctx);
}
#endif /* XXX replacement */
}
@ -873,18 +873,20 @@ static void *video_thread(void *arg)
}
}
sdl_setup(env);
if (!ast_strlen_zero(save_display))
if (!ast_strlen_zero(save_display)) {
setenv("DISPLAY", save_display, 1);
}
ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */
if (grabber_open(&env->out)) {
ast_log(LOG_WARNING, "cannot open local video source\n");
}
}
if (env->out.device_num)
if (env->out.device_num) {
env->out.devices[env->out.device_primary].status_index |= IS_PRIMARY | IS_SECONDARY;
}
/* even if no device is connected, we must call video_out_init,
* as some of the data structures it initializes are
* used in get_video_frames()
@ -893,14 +895,14 @@ static void *video_thread(void *arg)
/* Writes intial status of the sources. */
if (env->gui) {
for (i = 0; i < env->out.device_num; i++) {
print_message(env->gui->thumb_bd_array[i].board,
src_msgs[env->out.devices[i].status_index]);
}
for (i = 0; i < env->out.device_num; i++) {
print_message(env->gui->thumb_bd_array[i].board,
src_msgs[env->out.devices[i].status_index]);
}
}
for (;;) {
struct timeval t = { 0, 50000 }; /* XXX 20 times/sec */
struct timespec t = { 0, 50000000 }; /* XXX 20 times/sec */
struct ast_frame *p, *f;
struct ast_channel *chan;
int fd;
@ -908,13 +910,14 @@ static void *video_thread(void *arg)
/* determine if video format changed */
if (count++ % 10 == 0) {
if (env->out.sendvideo && env->out.devices)
sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
if (env->out.sendvideo && env->out.devices) {
snprintf(buf, sizeof(buf), "%s %s %dx%d @@ %dfps %dkbps",
env->out.devices[env->out.device_primary].name, env->codec_name,
env->enc_in.w, env->enc_in.h,
env->out.fps, env->out.bitrate/1000);
else
sprintf(buf, "hold");
env->out.fps, env->out.bitrate / 1000);
} else {
sprintf(buf, "hold");
}
caption = buf;
}
@ -923,36 +926,36 @@ static void *video_thread(void *arg)
* otherwise the drag will not work */
if (env->gui)
eventhandler(env, caption);
/* sleep for a while */
ast_select(0, NULL, NULL, NULL, &t);
nanosleep(&t, NULL);
if (env->in) {
struct video_dec_desc *v = env->in;
/*
* While there is something to display, call the decoder and free
* the buffer, possibly enabling the receiver to store new data.
*/
while (v->dec_in_dpy) {
struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */
struct video_dec_desc *v = env->in;
/* decode the frame, but show it only if not frozen */
if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze)
show_frame(env, WIN_REMOTE);
tmp->used = 0; /* mark buffer as free */
tmp->ebit = 0;
ast_mutex_lock(&env->dec_lock);
if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */
v->dec_in_dpy = &v->dec_in[0];
/*
* While there is something to display, call the decoder and free
* the buffer, possibly enabling the receiver to store new data.
*/
while (v->dec_in_dpy) {
struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */
if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */
v->dec_in_cur = tmp; /* using the slot just freed */
else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
v->dec_in_dpy = NULL; /* nothing more to display */
ast_mutex_unlock(&env->dec_lock);
/* decode the frame, but show it only if not frozen */
if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze)
show_frame(env, WIN_REMOTE);
tmp->used = 0; /* mark buffer as free */
tmp->ebit = 0;
ast_mutex_lock(&env->dec_lock);
if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */
v->dec_in_dpy = &v->dec_in[0];
if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */
v->dec_in_cur = tmp; /* using the slot just freed */
else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
v->dec_in_dpy = NULL; /* nothing more to display */
ast_mutex_unlock(&env->dec_lock);
}
}
}
if (env->shutdown)
break;
@ -988,7 +991,7 @@ static void *video_thread(void *arg)
for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
if (write(fd, &blah, l) != l)
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
chan->name, f->frametype, f->subclass, strerror(errno));
chan->name, f->frametype, f->subclass, strerror(errno));
}
}
ast_channel_unlock(chan);
@ -1194,13 +1197,13 @@ int console_video_cli(struct video_desc *env, const char *var, int fd)
if (env == NULL)
return 1; /* unrecognised */
if (!strcasecmp(var, "videodevice")) {
if (!strcasecmp(var, "videodevice")) {
ast_cli(fd, "videodevice is [%s]\n", env->out.devices[env->out.device_primary].name);
} else if (!strcasecmp(var, "videocodec")) {
} else if (!strcasecmp(var, "videocodec")) {
ast_cli(fd, "videocodec is [%s]\n", env->codec_name);
} else if (!strcasecmp(var, "sendvideo")) {
} else if (!strcasecmp(var, "sendvideo")) {
ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
} else if (!strcasecmp(var, "video_size")) {
} else if (!strcasecmp(var, "video_size")) {
int in_w = 0, in_h = 0;
if (env->in) {
in_w = env->in->dec_out.w;
@ -1212,22 +1215,22 @@ int console_video_cli(struct video_desc *env, const char *var, int fd)
env->loc_dpy.w, env->loc_dpy.h,
env->rem_dpy.w, env->rem_dpy.h,
in_w, in_h);
} else if (!strcasecmp(var, "bitrate")) {
} else if (!strcasecmp(var, "bitrate")) {
ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
} else if (!strcasecmp(var, "qmin")) {
} else if (!strcasecmp(var, "qmin")) {
ast_cli(fd, "qmin is [%d]\n", env->out.qmin);
} else if (!strcasecmp(var, "fps")) {
} else if (!strcasecmp(var, "fps")) {
ast_cli(fd, "fps is [%d]\n", env->out.fps);
} else if (!strcasecmp(var, "startgui")) {
} else if (!strcasecmp(var, "startgui")) {
env->stayopen = 1;
console_video_start(env, NULL);
} else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) {
} else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) {
env->stayopen = 0;
if (env->gui && env->owner)
ast_cli_command(-1, "console hangup");
else /* not in a call */
console_video_uninit(env);
} else {
} else {
return 1; /* unrecognised */
}
return 0; /* recognised */

38808
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -60,6 +60,7 @@ case "${host_os}" in
;;
darwin*)
AC_DEFINE([AST_POLL_COMPAT], 1, [Define to 1 if internal poll should be used.])
AC_DEFINE([_DARWIN_UNLIMITED_SELECT], 1, [Define to 1 if running on Darwin.])
;;
*)
AC_PREFIX_DEFAULT([/usr])
@ -466,7 +467,7 @@ AC_FUNC_STRNLEN
AC_FUNC_STRTOD
AC_FUNC_UTIME_NULL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob htonll ioperm inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap ntohll newlocale putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv utime vasprintf getpeereid sysctl swapctl])
AC_CHECK_FUNCS([asprintf atexit closefrom dup2 eaccess endpwent euidaccess ffsll ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday glob htonll ioperm inet_ntoa isascii memchr memmove memset mkdir munmap ntohll newlocale ppoll putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtod strtol strtold strtoq unsetenv utime vasprintf getpeereid sysctl swapctl])
# NOTE: we use AC_CHECK_LIB to get -lm into the arguments for later checks,
# so that AC_CHECK_FUNCS can detect functions in that library.
@ -741,6 +742,48 @@ AC_RUN_IFELSE(
AC_MSG_RESULT(unknown)
)
AC_MSG_CHECKING(if we can increase the maximum select-able file descriptor)
AC_RUN_IFELSE(
AC_LANG_PROGRAM([
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
], [[
struct rlimit rlim = { FD_SETSIZE * 2, FD_SETSIZE * 2 };
int fd0, fd1;
struct timeval tv = { 0, };
struct ast_fdset { long fds_bits[[1024]]; } fds = { { 0, } };
if (setrlimit(RLIMIT_NOFILE, &rlim)) { exit(1); }
if ((fd0 = open("/dev/null", O_RDONLY)) < 0) { exit(1); }
if (dup2(fd0, (fd1 = FD_SETSIZE + 1)) < 0) { exit(1); }
FD_SET(fd0, (fd_set *) &fds);
FD_SET(fd1, (fd_set *) &fds);
if (select(FD_SETSIZE + 2, (fd_set *) &fds, NULL, NULL, &tv) < 0) { exit(1); }
exit(0)]]),
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_VARIABLE_FDSET], 1, [Define to 1 if your system can support larger than default select bitmasks.]),
AC_MSG_RESULT(no),
AC_MSG_RESULT(cross-compile)
)
if test "${ac_cv_have_variable_fdset}x" = "0x"; then
AC_RUN_IFELSE(
AC_LANG_PROGRAM([
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
], [if (getuid() != 0) { exit(1); }]),
AC_DEFINE([CONFIGURE_RAN_AS_ROOT], 1, [Some configure tests will unexpectedly fail if configure is run by a non-root user. These may be able to be tested at runtime.]))
fi
AST_GCC_ATTRIBUTE(pure)
AST_GCC_ATTRIBUTE(malloc)
AST_GCC_ATTRIBUTE(const)

View File

@ -17,6 +17,10 @@
/* Define to 1 if the `closedir' function returns void instead of `int'. */
#undef CLOSEDIR_VOID
/* Some configure tests will unexpectedly fail if configure is run by a
non-root user. These may be able to be tested at runtime. */
#undef CONFIGURE_RAN_AS_ROOT
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
@ -381,9 +385,6 @@
/* Define to 1 if your system defines the locale_t type in xlocale.h */
#undef HAVE_LOCALE_T_IN_XLOCALE_H
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define to 1 if you have the `log' function. */
#undef HAVE_LOG
@ -538,6 +539,9 @@
/* Define to 1 if you have the `powl' function. */
#undef HAVE_POWL
/* Define to 1 if you have the `ppoll' function. */
#undef HAVE_PPOLL
/* Define to 1 if you have the ISDN PRI library. */
#undef HAVE_PRI
@ -803,7 +807,7 @@
/* Define to 1 if you have the `strtoq' function. */
#undef HAVE_STRTOQ
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
/* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if you have the mISDN Supplemental Services library. */
@ -956,6 +960,10 @@
/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL
/* Define to 1 if your system can support larger than default select bitmasks.
*/
#undef HAVE_VARIABLE_FDSET
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
@ -1074,12 +1082,12 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if the C compiler supports function prototypes. */
#undef PROTOTYPES
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
@ -1099,6 +1107,11 @@
/* Define to the type of arg 5 for `select'. */
#undef SELECT_TYPE_ARG5
/* Define to 1 if the `setvbuf' function takes the buffering type as its
second argument and the buffer pointer as the third, as on System V before
release 3. */
#undef SETVBUF_REVERSED
/* The size of `char *', as computed by sizeof. */
#undef SIZEOF_CHAR_P
@ -1128,30 +1141,23 @@
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
/* Enable extensions on AIX 3, Interix. */
/* Define to 1 if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Define to 1 if running on Darwin. */
#undef _DARWIN_UNLIMITED_SELECT
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
#undef _LARGEFILE_SOURCE
@ -1169,6 +1175,20 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* Enable extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Define like PROTOTYPES; this can be used by system headers. */
#undef __PROTOTYPES
/* Define to empty if `const' does not conform to ANSI C. */
#undef const

View File

@ -2232,44 +2232,6 @@ static inline void timersub(struct timeval *tvend, struct timeval *tvstart, stru
}
#endif
/*!
* \brief Waits for activity on a group of channels
* \param nfds the maximum number of file descriptors in the sets
* \param rfds file descriptors to check for read availability
* \param wfds file descriptors to check for write availability
* \param efds file descriptors to check for exceptions (OOB data)
* \param tvp timeout while waiting for events
* \details
* This is the same as a standard select(), except it guarantees the
* behaviour where the passed struct timeval is updated with how much
* time was not slept while waiting for the specified events
*/
static inline int ast_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tvp)
{
#ifdef __linux__
return select(nfds, rfds, wfds, efds, tvp);
#else
if (tvp) {
struct timeval tv, tvstart, tvend, tvlen;
int res;
tv = *tvp;
gettimeofday(&tvstart, NULL);
res = select(nfds, rfds, wfds, efds, tvp);
gettimeofday(&tvend, NULL);
timersub(&tvend, &tvstart, &tvlen);
timersub(&tv, &tvlen, tvp);
if (tvp->tv_sec < 0 || (tvp->tv_sec == 0 && tvp->tv_usec < 0)) {
tvp->tv_sec = 0;
tvp->tv_usec = 0;
}
return res;
}
else
return select(nfds, rfds, wfds, efds, NULL);
#endif
}
/*! \brief Retrieves the current T38 state of a channel */
static inline enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
{

View File

@ -79,6 +79,8 @@
#ifndef __AST_POLL_COMPAT_H
#define __AST_POLL_COMPAT_H
#include "asterisk/select.h"
#ifndef AST_POLL_COMPAT
#include <sys/poll.h>
@ -114,4 +116,24 @@ int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout);
#endif /* AST_POLL_COMPAT */
/*!
* \brief Same as poll(2), except the time is specified in microseconds and
* the tv argument is modified to indicate the time remaining.
*/
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv);
/*!
* \brief Shortcut for conversion of FD_ISSET to poll(2)-based
*/
static inline int ast_poll_fd_index(struct pollfd *haystack, int nfds, int needle)
{
int i;
for (i = 0; i < nfds; i++) {
if (haystack[i].fd == needle) {
return i;
}
}
return -1;
}
#endif /* __AST_POLL_COMPAT_H */

110
include/asterisk/select.h Normal file
View File

@ -0,0 +1,110 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2010, Digium, Inc.
*
* Tilghman Lesher <tlesher AT digium DOT com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!\file
* \brief Bitfield expansions for ast_select
*/
#ifndef __AST_SELECT_H
#define __AST_SELECT_H
#include <sys/select.h>
#include <errno.h>
#include "asterisk/utils.h"
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned int ast_FD_SETSIZE;
#if !defined(HAVE_VARIABLE_FDSET) && defined(CONFIGURE_RAN_AS_ROOT)
#define ast_fdset fd_set
#else
typedef struct {
long fds_bits[4096 / sizeof(long)]; /* 32768 bits */
} ast_fdset;
#undef FD_ZERO
#define FD_ZERO(a) \
do { \
long *bytes = (long *) a; \
int i; \
for (i = 0; i < sizeof(*(a)) / sizeof(long); i++) { \
bytes[i] = 0; \
} \
} while (0)
#undef FD_SET
#define FD_SET(fd, fds) \
do { \
long *bytes = (long *) fds; \
if (fd / sizeof(*bytes) + ((fd + 1) % sizeof(*bytes) ? 1 : 0) < sizeof(*(fds))) { \
bytes[fd / (sizeof(*bytes))] |= 1L << (fd % sizeof(*bytes)); \
} else { \
ast_log(LOG_ERROR, "FD %d exceeds the maximum size of ast_fdset!\n", fd); \
} \
} while (0)
#endif /* HAVE_VARIABLE_FDSET */
/*! \brief Waits for activity on a group of channels
* \param nfds the maximum number of file descriptors in the sets
* \param rfds file descriptors to check for read availability
* \param wfds file descriptors to check for write availability
* \param efds file descriptors to check for exceptions (OOB data)
* \param tvp timeout while waiting for events
* This is the same as a standard select(), except it guarantees the
* behaviour where the passed struct timeval is updated with how much
* time was not slept while waiting for the specified events
*/
static inline int ast_select(int nfds, ast_fdset *rfds, ast_fdset *wfds, ast_fdset *efds, struct timeval *tvp)
{
#ifdef __linux__
ast_assert((unsigned int) nfds <= ast_FD_SETSIZE);
return select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, tvp);
#else
int save_errno = 0;
ast_assert((unsigned int) nfds <= ast_FD_SETSIZE);
if (tvp) {
struct timeval tv, tvstart, tvend, tvlen;
int res;
tv = *tvp;
gettimeofday(&tvstart, NULL);
res = select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, tvp);
save_errno = errno;
gettimeofday(&tvend, NULL);
timersub(&tvend, &tvstart, &tvlen);
timersub(&tv, &tvlen, tvp);
if (tvp->tv_sec < 0 || (tvp->tv_sec == 0 && tvp->tv_usec < 0)) {
tvp->tv_sec = 0;
tvp->tv_usec = 0;
}
errno = save_errno;
return res;
}
else
return select(nfds, (fd_set *) rfds, (fd_set *) wfds, (fd_set *) efds, NULL);
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* __AST_SELECT_H */

View File

@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2008, Digium, Inc.
* Copyright (C) 1999 - 2010, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@ -272,6 +272,8 @@ static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
extern unsigned int ast_FD_SETSIZE;
static char *_argv[256];
static int shuttingdown;
static int restartnow;
@ -3167,7 +3169,8 @@ int main(int argc, char *argv[])
char *buf;
const char *runuser = NULL, *rungroup = NULL;
char *remotesock = NULL;
int moduleresult; /*!< Result from the module load subsystem */
int moduleresult; /*!< Result from the module load subsystem */
struct rlimit l;
/* Remember original args for restart */
if (argc > ARRAY_LEN(_argv) - 1) {
@ -3352,7 +3355,6 @@ int main(int argc, char *argv[])
}
if (ast_opt_dump_core) {
struct rlimit l;
memset(&l, 0, sizeof(l));
l.rlim_cur = RLIM_INFINITY;
l.rlim_max = RLIM_INFINITY;
@ -3361,6 +3363,44 @@ int main(int argc, char *argv[])
}
}
if (getrlimit(RLIMIT_NOFILE, &l)) {
ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
}
#if !defined(CONFIGURE_RAN_AS_ROOT)
/* Check if select(2) will run with more file descriptors */
do {
int fd, fd2;
ast_fdset readers;
struct timeval tv = { 0, };
if (l.rlim_cur <= FD_SETSIZE) {
/* The limit of select()able FDs is irrelevant, because we'll never
* open one that high. */
break;
}
if (!(fd = open("/dev/null", O_RDONLY))) {
ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
break; /* XXX Should we exit() here? XXX */
}
fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
if (dup2(fd, fd2)) {
ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
break;
}
FD_ZERO(&readers);
FD_SET(fd2, &readers);
if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
}
} while (0);
#elif defined(HAVE_VARIABLE_FDSET)
ast_FD_SETSIZE = l.rlim_cur;
#endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
rungroup = ast_config_AST_RUN_GROUP;
if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))

View File

@ -438,7 +438,7 @@ static const struct ast_datastore_info dial_features_info = {
static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
static void parkinglot_unref(struct ast_parkinglot *parkinglot);
static void parkinglot_destroy(void *obj);
int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
int manage_parkinglot(struct ast_parkinglot *curlot, struct pollfd **pfds, int *nfds, int *fs);
struct ast_parkinglot *find_parkinglot(const char *name);
static struct ast_parkinglot *create_parkinglot(const char *name);
static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot);
@ -3603,9 +3603,10 @@ static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_
}
/*! \brief Run management on parkinglots, called once per parkinglot */
int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *ms, int *max)
int manage_parkinglot(struct ast_parkinglot *curlot, struct pollfd **pfds, int *nfds, int *ms)
{
struct pollfd *new_fds = NULL;
int new_nfds = 0;
struct parkeduser *pu;
int res = 0;
char parkingslot[AST_MAX_EXTENSION];
@ -3628,12 +3629,12 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
/* Get chan, exten from derived kludge */
if (pu->peername[0]) {
char *peername = ast_strdupa(pu->peername);
char *cp = strrchr(peername, '-');
char *dash = strrchr(peername, '-');
char *peername_flat; /* using something like DAHDI/52 for an extension name is NOT a good idea */
int i;
if (cp) {
*cp = 0;
if (dash) {
*dash = '\0';
}
peername_flat = ast_strdupa(peername);
@ -3712,14 +3713,33 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
} else { /* still within parking time, process descriptors */
for (x = 0; x < AST_MAX_FDS; x++) {
struct ast_frame *f;
int y;
if ((chan->fds[x] == -1) || (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds)))
if (chan->fds[x] == -1) {
continue; /* nothing on this descriptor */
}
for (y = 0; y < *nfds; y++) {
if ((*pfds[y]).fd == chan->fds[x]) {
/* Found poll record! */
break;
}
}
if (y == *nfds) {
/* Not found */
continue;
if (FD_ISSET(chan->fds[x], efds))
}
if (!((*pfds[y]).revents & (POLLIN | POLLERR))) {
/* Next x */
continue;
}
if ((*pfds[y]).revents & POLLERR) {
ast_set_flag(chan, AST_FLAG_EXCEPTION);
else
} else {
ast_clear_flag(chan, AST_FLAG_EXCEPTION);
}
chan->fdno = x;
/* See if they need servicing */
@ -3760,22 +3780,32 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
}
} /* End for */
if (x >= AST_MAX_FDS) {
std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
if (chan->fds[x] > -1) {
FD_SET(chan->fds[x], nrfds);
FD_SET(chan->fds[x], nefds);
if (chan->fds[x] > *max)
*max = chan->fds[x];
void *tmp = ast_realloc(new_fds, (new_nfds + 1) * sizeof(*new_fds));
if (!tmp) {
continue;
}
new_fds = tmp;
new_fds[new_nfds].fd = chan->fds[x];
new_fds[new_nfds].events = POLLIN | POLLERR;
new_fds[new_nfds].revents = 0;
new_nfds++;
}
}
/* Keep track of our shortest wait */
if (tms < *ms || *ms < 0)
if (tms < *ms || *ms < 0) {
*ms = tms;
}
}
}
}
AST_LIST_TRAVERSE_SAFE_END;
AST_LIST_UNLOCK(&curlot->parkings);
ast_free(*pfds);
*pfds = new_fds;
*nfds = new_nfds;
return res;
}
@ -3789,35 +3819,26 @@ std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
*/
static void *do_parking_thread(void *ignore)
{
fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
fd_set nrfds, nefds; /* args for the next select */
FD_ZERO(&rfds);
FD_ZERO(&efds);
struct pollfd *pfds = NULL;
int nfds = 0;
for (;;) {
int res = 0;
int ms = -1; /* select timeout, uninitialized */
int max = -1; /* max fd, none there yet */
struct ao2_iterator iter;
struct ast_parkinglot *curlot;
FD_ZERO(&nrfds);
FD_ZERO(&nefds);
int ms = -1; /* poll2 timeout, uninitialized */
iter = ao2_iterator_init(parkinglots, 0);
while ((curlot = ao2_iterator_next(&iter))) {
res = manage_parkinglot(curlot, &rfds, &efds, &nrfds, &nefds, &ms, &max);
manage_parkinglot(curlot, &pfds, &nfds, &ms);
ao2_ref(curlot, -1);
}
ao2_iterator_destroy(&iter);
rfds = nrfds;
efds = nefds;
{
struct timeval wait = ast_samp2tv(ms, 1000);
/* Wait for something to happen */
ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &wait : NULL);
}
/* Wait for something to happen */
ast_poll(pfds, nfds, ms);
pthread_testcancel();
}
/* If this WERE reached, we'd need to free(pfds) */
return NULL; /* Never reached */
}

View File

@ -10,9 +10,9 @@
struct pollfd
{
int fd;
short events;
short revents;
int fd;
short events;
short revents;
}
int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
@ -73,54 +73,44 @@
#include "asterisk.h"
#include <unistd.h> /* standard Unix definitions */
#include <sys/types.h> /* system types */
#include <sys/time.h> /* time definitions */
#include <assert.h> /* assertion macros */
#include <string.h> /* string functions */
#include <unistd.h> /* standard Unix definitions */
#include <sys/types.h> /* system types */
#include <sys/time.h> /* time definitions */
#include <assert.h> /* assertion macros */
#include <string.h> /* string functions */
#include <errno.h>
#include "asterisk/utils.h" /* this package */
#include "asterisk/poll-compat.h" /* this package */
#ifdef AST_POLL_COMPAT
unsigned int ast_FD_SETSIZE = FD_SETSIZE;
#ifndef MAX
#define MAX(a,b) a > b ? a : b
#endif
/*---------------------------------------------------------------------------*\
Private Functions
Private Functions
\*---------------------------------------------------------------------------*/
static int map_poll_spec
#if __STDC__ > 0
(struct pollfd *pArray,
unsigned long n_fds,
fd_set *pReadSet,
fd_set *pWriteSet,
fd_set *pExceptSet)
#else
(pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
struct pollfd *pArray;
unsigned long n_fds;
fd_set *pReadSet;
fd_set *pWriteSet;
fd_set *pExceptSet;
#endif
#if defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL)
static int map_poll_spec(struct pollfd *pArray, unsigned long n_fds,
ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
{
register unsigned long i; /* loop control */
register struct pollfd *pCur; /* current array element */
register int max_fd = -1; /* return value */
register unsigned long i; /* loop control */
register struct pollfd *pCur; /* current array element */
register int max_fd = -1; /* return value */
/*!\note
/*
* Map the poll() structures into the file descriptor sets required
* by select().
*/
for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
/* Skip any bad FDs in the array. */
if (pCur->fd < 0)
if (pCur->fd < 0) {
continue;
}
if (pCur->events & POLLIN) {
/* "Input Ready" notification desired. */
@ -145,34 +135,28 @@ static int map_poll_spec
return max_fd;
}
static struct timeval *map_timeout
#if __STDC__ > 0
(int poll_timeout, struct timeval *pSelTimeout)
#else
(poll_timeout, pSelTimeout)
int poll_timeout;
struct timeval *pSelTimeout;
#endif
#ifdef AST_POLL_COMPAT
static struct timeval *map_timeout(int poll_timeout, struct timeval *pSelTimeout)
{
struct timeval *pResult;
/*!\note
* Map the poll() timeout value into a select() timeout. The possible
* values of the poll() timeout value, and their meanings, are:
*
* VALUE MEANING
*
* -1 wait indefinitely (until signal occurs)
* 0 return immediately, don't block
* >0 wait specified number of milliseconds
*
* select() uses a "struct timeval", which specifies the timeout in
* seconds and microseconds, so the milliseconds value has to be mapped
* accordingly.
*/
/*
Map the poll() timeout value into a select() timeout. The possible
values of the poll() timeout value, and their meanings, are:
assert(pSelTimeout != (struct timeval *) NULL);
VALUE MEANING
-1 wait indefinitely (until signal occurs)
0 return immediately, don't block
>0 wait specified number of milliseconds
select() uses a "struct timeval", which specifies the timeout in
seconds and microseconds, so the milliseconds value has to be mapped
accordingly.
*/
assert(pSelTimeout != NULL);
switch (poll_timeout) {
case -1:
@ -203,25 +187,13 @@ static struct timeval *map_timeout
return pResult;
}
#endif /* AST_POLL_COMPAT */
static void map_select_results
#if __STDC__ > 0
(struct pollfd *pArray,
unsigned long n_fds,
fd_set *pReadSet,
fd_set *pWriteSet,
fd_set *pExceptSet)
#else
(pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
struct pollfd *pArray;
unsigned long n_fds;
fd_set *pReadSet;
fd_set *pWriteSet;
fd_set *pExceptSet;
#endif
static void map_select_results(struct pollfd *pArray, unsigned long n_fds,
ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
{
register unsigned long i; /* loop control */
register struct pollfd *pCur; /* current array element */
register unsigned long i; /* loop control */
register struct pollfd *pCur; /* current array element */
for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
/* Skip any bad FDs in the array. */
@ -231,59 +203,101 @@ static void map_select_results
}
/* Exception events take priority over input events. */
pCur->revents = 0;
if (FD_ISSET (pCur->fd, pExceptSet)) {
if (FD_ISSET(pCur->fd, (fd_set *) pExceptSet)) {
pCur->revents |= POLLPRI;
} else if (FD_ISSET (pCur->fd, pReadSet)) {
} else if (FD_ISSET(pCur->fd, (fd_set *) pReadSet)) {
pCur->revents |= POLLIN;
}
if (FD_ISSET (pCur->fd, pWriteSet)) {
if (FD_ISSET(pCur->fd, (fd_set *) pWriteSet)) {
pCur->revents |= POLLOUT;
}
}
return;
}
#endif /* defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL) */
/*---------------------------------------------------------------------------*\
Public Functions
Public Functions
\*---------------------------------------------------------------------------*/
#ifdef AST_POLL_COMPAT
int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
{
fd_set read_descs; /* input file descs */
fd_set write_descs; /* output file descs */
fd_set except_descs; /* exception descs */
ast_fdset read_descs; /* input file descs */
ast_fdset write_descs; /* output file descs */
ast_fdset except_descs; /* exception descs */
struct timeval stime; /* select() timeout value */
int ready_descriptors; /* function result */
int max_fd = 0; /* maximum fd value */
int ready_descriptors; /* function result */
int max_fd = 0; /* maximum fd value */
struct timeval *pTimeout; /* actually passed */
int save_errno;
FD_ZERO (&read_descs);
FD_ZERO (&write_descs);
FD_ZERO (&except_descs);
FD_ZERO(&read_descs);
FD_ZERO(&write_descs);
FD_ZERO(&except_descs);
/* Map the poll() file descriptor list in the select() data structures. */
if (pArray) {
max_fd = map_poll_spec (pArray, n_fds,
max_fd = map_poll_spec (pArray, n_fds,
&read_descs, &write_descs, &except_descs);
}
/* Map the poll() timeout value in the select() timeout structure. */
pTimeout = map_timeout(timeout, &stime);
pTimeout = map_timeout (timeout, &stime);
/* Make the select() call. */
ready_descriptors = select(max_fd + 1, &read_descs, &write_descs,
ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs,
&except_descs, pTimeout);
save_errno = errno;
if (ready_descriptors >= 0) {
map_select_results (pArray, n_fds,
&read_descs, &write_descs, &except_descs);
}
errno = save_errno;
return ready_descriptors;
}
#endif /* AST_POLL_COMPAT */
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
{
#ifdef HAVE_PPOLL
struct timeval start = ast_tvnow();
struct timespec ts = { tv ? tv->tv_sec : 0, tv ? tv->tv_usec * 1000 : 0 };
int res = ppoll(pArray, n_fds, tv ? &ts : NULL, NULL);
struct timeval after = ast_tvnow();
if (res > 0 && tv && ast_tvdiff_ms(ast_tvadd(*tv, start), after) > 0) {
*tv = ast_tvsub(*tv, ast_tvsub(after, start));
} else if (res > 0 && tv) {
*tv = ast_tv(0, 0);
}
return res;
#else
ast_fdset read_descs, write_descs, except_descs;
int ready_descriptors, max_fd = 0;
FD_ZERO(&read_descs);
FD_ZERO(&write_descs);
FD_ZERO(&except_descs);
if (pArray) {
max_fd = map_poll_spec(pArray, n_fds, &read_descs, &write_descs, &except_descs);
}
ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs, &except_descs, tv);
if (ready_descriptors >= 0) {
map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs);
}
return ready_descriptors;
#endif
}
#endif /* AST_POLL_COMPAT */

View File

@ -397,8 +397,7 @@ int ast_stun_request(int s, struct sockaddr_in *dst,
for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */
/* send request, possibly wait for reply */
unsigned char reply_buf[1024];
fd_set rfds;
struct timeval to = { 3, 0 }; /* timeout, make it configurable */
struct pollfd pfds = { .fd = s, .events = POLLIN };
struct sockaddr_in src;
socklen_t srclen;
@ -410,9 +409,7 @@ int ast_stun_request(int s, struct sockaddr_in *dst,
}
if (answer == NULL)
break;
FD_ZERO(&rfds);
FD_SET(s, &rfds);
res = ast_select(s + 1, &rfds, NULL, NULL, &to);
res = ast_poll(&pfds, 1, 3000);
if (res <= 0) /* timeout or error */
continue;
memset(&src, 0, sizeof(src));

View File

@ -113,9 +113,9 @@ const char *ais_err2str(SaAisErrorT error)
static void *dispatch_thread_handler(void *data)
{
SaSelectionObjectT clm_fd, evt_fd, max_fd;
SaSelectionObjectT clm_fd, evt_fd;
int res;
fd_set read_fds;
struct pollfd pfd[2] = { { .events = POLLIN, }, { .events = POLLIN, } };
SaAisErrorT ais_res;
ais_res = saClmSelectionObjectGet(clm_handle, &clm_fd);
@ -132,24 +132,26 @@ static void *dispatch_thread_handler(void *data)
return NULL;
}
max_fd = clm_fd > evt_fd ? clm_fd : evt_fd;
pfd[0].fd = clm_fd;
pfd[1].fd = evt_fd;
while (!dispatch_thread.stop) {
FD_ZERO(&read_fds);
FD_SET(clm_fd, &read_fds);
FD_SET(evt_fd, &read_fds);
pfd[0].revents = 0;
pfd[1].revents = 0;
res = ast_select(max_fd + 1, &read_fds, NULL, NULL, NULL);
res = ast_poll(pfd, 2, -1);
if (res == -1 && errno != EINTR && errno != EAGAIN) {
ast_log(LOG_ERROR, "Select error (%s) dispatch thread going away now, "
"and the module will no longer operate.\n", strerror(errno));
break;
}
if (FD_ISSET(clm_fd, &read_fds))
if (pfd[0].revents & POLLIN) {
saClmDispatch(clm_handle, SA_DISPATCH_ALL);
if (FD_ISSET(evt_fd, &read_fds))
}
if (pfd[1].revents & POLLIN) {
saEvtDispatch(evt_handle, SA_DISPATCH_ALL);
}
}
return NULL;

View File

@ -1283,38 +1283,27 @@ static int aji_tls_handshake(struct aji_client *client)
*/
static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout)
{
int sock;
fd_set fds;
struct timeval tv, *tvptr = NULL;
struct pollfd pfd = { .events = POLLIN };
int len, res;
#ifdef HAVE_OPENSSL
if (aji_is_secure(client)) {
sock = SSL_get_fd(client->ssl_session);
if (sock < 0) {
pfd.fd = SSL_get_fd(client->ssl_session);
if (pfd.fd < 0) {
return -1;
}
} else
#endif /* HAVE_OPENSSL */
sock = iks_fd(client->p);
pfd.fd = iks_fd(client->p);
memset(&tv, 0, sizeof(struct timeval));
FD_ZERO(&fds);
FD_SET(sock, &fds);
tv.tv_sec = timeout;
/* NULL value for tvptr makes ast_select wait indefinitely */
tvptr = (timeout != -1) ? &tv : NULL;
/* ast_select emulates linux behaviour in terms of timeout handling */
res = ast_select(sock + 1, &fds, NULL, NULL, tvptr);
res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1);
if (res > 0) {
#ifdef HAVE_OPENSSL
if (aji_is_secure(client)) {
len = SSL_read(client->ssl_session, buffer, buf_len);
} else
#endif /* HAVE_OPENSSL */
len = recv(sock, buffer, buf_len, 0);
len = recv(pfd.fd, buffer, buf_len, 0);
if (len > 0) {
return len;

View File

@ -703,9 +703,8 @@ static void *do_pktccops(void *data)
int res, nfds, len;
struct copsmsg *recmsg, *sendmsg;
struct copsmsg recmsgb, sendmsgb;
fd_set rfds;
struct timeval tv;
struct pktcobj *pobject;
struct pollfd *pfds = NULL, *tmp;
struct pktcobj *pobject;
struct cops_cmts *cmts;
struct cops_gate *gate;
char *sobjp;
@ -719,9 +718,8 @@ static void *do_pktccops(void *data)
ast_debug(3, "COPS: thread started\n");
for (;;) {
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&rfds);
ast_free(pfds);
pfds = NULL;
nfds = 0;
AST_LIST_LOCK(&cmts_list);
AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
@ -735,15 +733,27 @@ static void *do_pktccops(void *data)
}
}
if (cmts->sfd > 0) {
FD_SET(cmts->sfd, &rfds);
if (cmts->sfd > nfds) nfds = cmts->sfd;
if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
continue;
}
pfds = tmp;
pfds[nfds].fd = cmts->sfd;
pfds[nfds].events = POLLIN;
pfds[nfds].revents = 0;
nfds++;
} else {
cmts->sfd = cops_connect(cmts->host, cmts->port);
if (cmts->sfd > 0) {
cmts->state = 1;
if (cmts->sfd > 0) {
FD_SET(cmts->sfd, &rfds);
if (cmts->sfd > nfds) nfds = cmts->sfd;
if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
continue;
}
pfds = tmp;
pfds[nfds].fd = cmts->sfd;
pfds[nfds].events = POLLIN;
pfds[nfds].revents = 0;
nfds++;
}
}
}
@ -781,10 +791,11 @@ static void *do_pktccops(void *data)
if (pktcreload == 2) {
pktcreload = 0;
}
if ((res = select(nfds + 1, &rfds, NULL, NULL, &tv))) {
if ((res = ast_poll(pfds, nfds, 1000))) {
AST_LIST_LOCK(&cmts_list);
AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
if (FD_ISSET(cmts->sfd, &rfds)) {
int idx;
if ((idx = ast_poll_fd_index(pfds, nfds, cmts->sfd)) > -1 && (pfds[idx].revents & POLLIN)) {
len = cops_getmsg(cmts->sfd, recmsg);
if (len > 0) {
ast_debug(3, "COPS: got from %s:\n Header: versflag=0x%.2x opcode=%i clienttype=0x%.4x msglength=%i\n",

253
tests/test_poll.c Normal file
View File

@ -0,0 +1,253 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2010, Digium, Inc.
*
* Tilghman Lesher <tlesher AT digium DOT com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief Poll Tests
*
* \author\verbatim Tilghman Lesher <tlesher AT digium DOT com> \endverbatim
*
* Verify that the various poll implementations work as desired (ast_poll, ast_poll2)
* \ingroup tests
*/
/*** MODULEINFO
<depend>TEST_FRAMEWORK</depend>
***/
#include "asterisk.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/test.h"
#include "asterisk/poll-compat.h"
#ifndef HAVE_SBIN_LAUNCHD
static void *failsafe_cancel(void *vparent)
{
pthread_t parent = (pthread_t) (long) vparent;
sleep(1);
pthread_testcancel();
pthread_kill(parent, SIGURG);
sleep(1);
pthread_testcancel();
pthread_kill(parent, SIGURG);
sleep(1);
pthread_testcancel();
pthread_kill(parent, SIGURG);
pthread_exit(NULL);
}
#define RESET for (i = 0; i < 4; i++) { pfd[i].revents = 0; }
AST_TEST_DEFINE(poll_test)
{
#define FDNO 3
int fd[2], res = AST_TEST_PASS, i, res2;
int rdblocker[2];
#if FDNO > 3
int wrblocker[2], consec_interrupt = 0;
#endif
struct pollfd pfd[4] = { { .events = POLLOUT, }, { .events = POLLIN, }, { .events = POLLIN }, { .events = POLLOUT } };
pthread_t failsafe_tid;
struct timeval tv = { 0, 0 };
#if FDNO > 3
char garbage[256] =
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/";
#endif
switch (cmd) {
case TEST_INIT:
info->name = "poll_test";
info->category = "main/poll/";
info->summary = "unit test for the ast_poll() API";
info->description =
"Verifies behavior for the ast_poll() API call\n";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
ast_test_status_update(test, "Creating handle that should NEVER block on write\n");
if ((fd[0] = open("/dev/null", O_WRONLY)) < 0) {
ast_test_status_update(test, "Unable to open a writable handle to /dev/null: %s\n", strerror(errno));
return AST_TEST_FAIL;
}
ast_test_status_update(test, "Creating handle that should NEVER block on read\n");
if ((fd[1] = open("/dev/zero", O_RDONLY)) < 0) {
ast_test_status_update(test, "Unable to open a readable handle to /dev/zero: %s\n", strerror(errno));
close(fd[0]);
return AST_TEST_FAIL;
}
ast_test_status_update(test, "Creating handle that should block on read\n");
if (pipe(rdblocker) < 0) {
ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
close(fd[0]);
close(fd[1]);
return AST_TEST_FAIL;
}
#if FDNO > 3
ast_test_status_update(test, "Creating handle that should block on write\n");
if (pipe(wrblocker) < 0) {
ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
close(fd[0]);
close(fd[1]);
close(rdblocker[0]);
close(rdblocker[1]);
return AST_TEST_FAIL;
}
ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
ast_test_status_update(test, "Unable to start failsafe thread\n");
close(fd[0]);
close(fd[1]);
close(fd[2]);
close(rdblocker[0]);
close(rdblocker[1]);
close(wrblocker[0]);
close(wrblocker[1]);
return AST_TEST_FAIL;
}
/* Fill the pipe full of data */
ast_test_status_update(test, "Making pipe block on write\n");
for (i = 0; i < 4096; i++) { /* 1MB of data should be more than enough for any pipe */
errno = 0;
if (write(wrblocker[1], garbage, sizeof(garbage)) < sizeof(garbage)) {
ast_test_status_update(test, "Got %d\n", errno);
if (errno == EINTR && ++consec_interrupt > 1) {
break;
}
} else {
consec_interrupt = 0;
}
}
ast_test_status_update(test, "Cancelling failsafe thread.\n");
pthread_cancel(failsafe_tid);
pthread_kill(failsafe_tid, SIGURG);
pthread_join(failsafe_tid, NULL);
#endif
pfd[0].fd = fd[0];
pfd[1].fd = fd[1];
pfd[2].fd = rdblocker[0];
#if FDNO > 3
pfd[3].fd = wrblocker[1];
#endif
/* Need to ensure the infinite timeout doesn't stall the process */
ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
ast_test_status_update(test, "Unable to start failsafe thread\n");
close(fd[0]);
close(fd[1]);
close(rdblocker[0]);
close(rdblocker[1]);
#if FDNO > 3
close(wrblocker[0]);
close(wrblocker[1]);
#endif
return AST_TEST_FAIL;
}
RESET;
if ((res2 = ast_poll(pfd, FDNO, -1)) != 2) {
ast_test_status_update(test, "ast_poll does not return that only two handles are available (inf timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
RESET;
if ((res2 = ast_poll2(pfd, FDNO, NULL)) != 2) {
ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (inf timeout): %d %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
ast_test_status_update(test, "Cancelling failsafe thread.\n");
pthread_cancel(failsafe_tid);
pthread_kill(failsafe_tid, SIGURG);
pthread_join(failsafe_tid, NULL);
RESET;
if (ast_poll(pfd, FDNO, 0) != 2) {
ast_test_status_update(test, "ast_poll does not return that only two handles are available (0 timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
RESET;
if (ast_poll2(pfd, FDNO, &tv) != 2) {
ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (0 timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
RESET;
if (ast_poll(pfd, FDNO, 1) != 2) {
ast_test_status_update(test, "ast_poll does not return that only two handles are available (1ms timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
tv.tv_usec = 1000;
if (ast_poll2(pfd, FDNO, &tv) != 2) {
ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (1ms timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
res = AST_TEST_FAIL;
}
close(fd[0]);
close(fd[1]);
close(rdblocker[0]);
close(rdblocker[1]);
#if FDNO > 3
close(wrblocker[0]);
close(wrblocker[1]);
#endif
return res;
}
#endif
static int unload_module(void)
{
#ifndef HAVE_SBIN_LAUNCHD
AST_TEST_UNREGISTER(poll_test);
#endif
return 0;
}
static int load_module(void)
{
#ifndef HAVE_SBIN_LAUNCHD
AST_TEST_REGISTER(poll_test);
#endif
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Poll test");