static int measurenoise(struct ast_channel *chan, int ms, char *who) { int res=0; int mssofar; int noise=0; int samples=0; int x; short *foo; struct timeval start; struct ast_frame *f; struct ast_format rformat; ast_format_copy(&rformat, ast_channel_readformat(chan)); if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) { ast_log(LOG_NOTICE, "Unable to set to linear mode!\n"); return -1; } start = ast_tvnow(); for(;;) { mssofar = ast_tvdiff_ms(ast_tvnow(), start); if (mssofar > ms) break; res = ast_waitfor(chan, ms - mssofar); if (res < 1) break; f = ast_read(chan); if (!f) { res = -1; break; } if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id == AST_FORMAT_SLINEAR)) { foo = (short *)f->data.ptr; for (x=0; x<f->samples; x++) { noise += abs(foo[x]); samples++; } } ast_frfree(f); } if (rformat.id) { if (ast_set_read_format(chan, &rformat)) { ast_log(LOG_NOTICE, "Unable to restore original format!\n"); return -1; } } if (res < 0) return res; if (!samples) { ast_log(LOG_NOTICE, "No samples were received from the other side!\n"); return -1; } ast_debug(1, "%s: Noise: %d, samples: %d, avg: %d\n", who, noise, samples, noise / samples); return (noise / samples); }
static int old_milliwatt_exec(struct ast_channel *chan) { ast_set_write_format_by_id(chan, AST_FORMAT_ULAW); ast_set_read_format_by_id(chan, AST_FORMAT_ULAW); if (ast_channel_state(chan) != AST_STATE_UP) { ast_answer(chan); } if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0) { ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",ast_channel_name(chan)); return -1; } while (!ast_safe_sleep(chan, 10000)) ; ast_deactivate_generator(chan); return -1; }
static int transmit_audio(fax_session *s) { int res = -1; struct ast_format original_read_fmt; struct ast_format original_write_fmt; fax_state_t fax; t30_state_t *t30state; struct ast_frame *inf = NULL; int last_state = 0; struct timeval now, start, state_change; enum ast_t38_state t38_state; struct ast_control_t38_parameters t38_parameters = { .version = 0, .max_ifp = 800, .rate = AST_T38_RATE_14400, .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, .fill_bit_removal = 1, /* * spandsp has API calls to support MMR and JBIG transcoding, but they aren't * implemented quite yet... so don't offer them to the remote endpoint * .transcoding_mmr = 1, * .transcoding_jbig = 1, */ }; ast_format_clear(&original_read_fmt); ast_format_clear(&original_write_fmt); /* if in called party mode, try to use T.38 */ if (s->caller_mode == FALSE) { /* check if we are already in T.38 mode (unlikely), or if we can request * a switch... if so, request it now and wait for the result, rather * than starting an audio FAX session that will have to be cancelled */ if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) { return 1; } else if ((t38_state != T38_STATE_UNAVAILABLE) && (t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE, (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) { /* wait up to five seconds for negotiation to complete */ unsigned int timeout = 5000; int ms; ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(s->chan)); while (timeout > 0) { ms = ast_waitfor(s->chan, 1000); if (ms < 0) { ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan)); return -1; } if (!ms) { /* nothing happened */ if (timeout > 0) { timeout -= 1000; continue; } else { ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(s->chan)); break; } } if (!(inf = ast_read(s->chan))) { return -1; } if ((inf->frametype == AST_FRAME_CONTROL) && (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) && (inf->datalen == sizeof(t38_parameters))) { struct ast_control_t38_parameters *parameters = inf->data.ptr; switch (parameters->request_response) { case AST_T38_NEGOTIATED: ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(s->chan)); res = 1; break; case AST_T38_REFUSED: ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(s->chan)); break; default: ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(s->chan)); break; } ast_frfree(inf); if (res == 1) { return 1; } else { break; } } ast_frfree(inf); } } } #if SPANDSP_RELEASE_DATE >= 20080725 /* for spandsp shaphots 0.0.6 and higher */ t30state = &fax.t30; #else /* for spandsp release 0.0.5 */ t30state = &fax.t30_state; #endif ast_format_copy(&original_read_fmt, ast_channel_readformat(s->chan)); if (original_read_fmt.id != AST_FORMAT_SLINEAR) { res = ast_set_read_format_by_id(s->chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n"); goto done; } } ast_format_copy(&original_write_fmt, ast_channel_writeformat(s->chan)); if (original_write_fmt.id != AST_FORMAT_SLINEAR) { res = ast_set_write_format_by_id(s->chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n"); goto done; } } /* Initialize T30 terminal */ fax_init(&fax, s->caller_mode); /* Setup logging */ set_logging(&fax.logging); set_logging(&t30state->logging); /* Configure terminal */ set_local_info(t30state, s); set_file(t30state, s); set_ecm(t30state, TRUE); fax_set_transmit_on_idle(&fax, TRUE); t30_set_phase_e_handler(t30state, phase_e_handler, s); start = state_change = ast_tvnow(); ast_activate_generator(s->chan, &generator, &fax); while (!s->finished) { inf = NULL; if ((res = ast_waitfor(s->chan, 25)) < 0) { ast_debug(1, "Error waiting for a frame\n"); break; } /* Watchdog */ now = ast_tvnow(); if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) { ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n"); res = -1; break; } if (!res) { /* There was timeout waiting for a frame. Loop around and wait again */ continue; } /* There is a frame available. Get it */ res = 0; if (!(inf = ast_read(s->chan))) { ast_debug(1, "Channel hangup\n"); res = -1; break; } ast_debug(10, "frame %d/%u, len=%d\n", inf->frametype, (unsigned int) inf->subclass.format.id, inf->datalen); /* Check the frame type. Format also must be checked because there is a chance that a frame in old format was already queued before we set channel format to slinear so it will still be received by ast_read */ if (inf->frametype == AST_FRAME_VOICE && inf->subclass.format.id == AST_FORMAT_SLINEAR) { if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) { /* I know fax_rx never returns errors. The check here is for good style only */ ast_log(LOG_WARNING, "fax_rx returned error\n"); res = -1; break; } if (last_state != t30state->state) { state_change = ast_tvnow(); last_state = t30state->state; } } else if ((inf->frametype == AST_FRAME_CONTROL) && (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS)) { struct ast_control_t38_parameters *parameters = inf->data.ptr; if (parameters->request_response == AST_T38_NEGOTIATED) { /* T38 switchover completed */ s->t38parameters = *parameters; ast_debug(1, "T38 negotiated, finishing audio loop\n"); res = 1; break; } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) { t38_parameters.request_response = AST_T38_NEGOTIATED; ast_debug(1, "T38 request received, accepting\n"); /* Complete T38 switchover */ ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); /* Do not break audio loop, wait until channel driver finally acks switchover * with AST_T38_NEGOTIATED */ } } ast_frfree(inf); inf = NULL; } ast_debug(1, "Loop finished, res=%d\n", res); if (inf) ast_frfree(inf); ast_deactivate_generator(s->chan); /* If we are switching to T38, remove phase E handler. Otherwise it will be executed by t30_terminate, display diagnostics and set status variables although no transmittion has taken place yet. */ if (res > 0) { t30_set_phase_e_handler(t30state, NULL, NULL); } t30_terminate(t30state); fax_release(&fax); done: if (original_write_fmt.id != AST_FORMAT_SLINEAR) { if (ast_set_write_format(s->chan, &original_write_fmt) < 0) ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", ast_channel_name(s->chan)); } if (original_read_fmt.id != AST_FORMAT_SLINEAR) { if (ast_set_read_format(s->chan, &original_read_fmt) < 0) ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(s->chan)); } return res; } static int transmit_t38(fax_session *s) { int res = 0; t38_terminal_state_t t38; struct ast_frame *inf = NULL; int last_state = 0; struct timeval now, start, state_change, last_frame; t30_state_t *t30state; t38_core_state_t *t38state; #if SPANDSP_RELEASE_DATE >= 20080725 /* for spandsp shaphots 0.0.6 and higher */ t30state = &t38.t30; t38state = &t38.t38_fe.t38; #else /* for spandsp releases 0.0.5 */ t30state = &t38.t30_state; t38state = &t38.t38; #endif /* Initialize terminal */ memset(&t38, 0, sizeof(t38)); if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) { ast_log(LOG_WARNING, "Unable to start T.38 termination.\n"); res = -1; goto disable_t38; } t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp); if (s->t38parameters.fill_bit_removal) { t38_set_fill_bit_removal(t38state, TRUE); } if (s->t38parameters.transcoding_mmr) { t38_set_mmr_transcoding(t38state, TRUE); } if (s->t38parameters.transcoding_jbig) { t38_set_jbig_transcoding(t38state, TRUE); } /* Setup logging */ set_logging(&t38.logging); set_logging(&t30state->logging); set_logging(&t38state->logging); /* Configure terminal */ set_local_info(t30state, s); set_file(t30state, s); set_ecm(t30state, TRUE); t30_set_phase_e_handler(t30state, phase_e_handler, s); now = start = state_change = ast_tvnow(); while (!s->finished) { inf = NULL; if ((res = ast_waitfor(s->chan, 25)) < 0) { ast_debug(1, "Error waiting for a frame\n"); break; } last_frame = now; /* Watchdog */ now = ast_tvnow(); if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) { ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n"); res = -1; break; } t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000)); if (!res) { /* There was timeout waiting for a frame. Loop around and wait again */ continue; } /* There is a frame available. Get it */ res = 0; if (!(inf = ast_read(s->chan))) { ast_debug(1, "Channel hangup\n"); res = -1; break; } ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass.integer, inf->datalen); if (inf->frametype == AST_FRAME_MODEM && inf->subclass.integer == AST_MODEM_T38) { t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno); if (last_state != t30state->state) { state_change = ast_tvnow(); last_state = t30state->state; } } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) { struct ast_control_t38_parameters *parameters = inf->data.ptr; if (parameters->request_response == AST_T38_TERMINATED) { ast_debug(1, "T38 down, finishing\n"); break; } } ast_frfree(inf); inf = NULL; } ast_debug(1, "Loop finished, res=%d\n", res); if (inf) ast_frfree(inf); t30_terminate(t30state); t38_terminal_release(&t38); disable_t38: /* if we are not the caller, it's our job to shut down the T.38 * session when the FAX transmisson is complete. */ if ((s->caller_mode == FALSE) && (ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) { struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, }; if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) { /* wait up to five seconds for negotiation to complete */ unsigned int timeout = 5000; int ms; ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(s->chan)); while (timeout > 0) { ms = ast_waitfor(s->chan, 1000); if (ms < 0) { ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan)); return -1; } if (!ms) { /* nothing happened */ if (timeout > 0) { timeout -= 1000; continue; } else { ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", ast_channel_name(s->chan)); break; } } if (!(inf = ast_read(s->chan))) { return -1; } if ((inf->frametype == AST_FRAME_CONTROL) && (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) && (inf->datalen == sizeof(t38_parameters))) { struct ast_control_t38_parameters *parameters = inf->data.ptr; switch (parameters->request_response) { case AST_T38_TERMINATED: ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(s->chan)); break; case AST_T38_REFUSED: ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(s->chan)); break; default: ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(s->chan)); break; } ast_frfree(inf); break; } ast_frfree(inf); } } } return res; }
int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message_full)(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait) { unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL }; int msglens[5], msgtypes[5], newdatamode = (ast_channel_adsicpe(chan) & ADSI_FLAG_DATAMODE), res, x, waitforswitch = 0; struct ast_format writeformat; struct ast_format readformat; ast_format_copy(&writeformat, ast_channel_writeformat(chan)); ast_format_copy(&readformat, ast_channel_readformat(chan)); for (x = 0; x < msglen; x += (msg[x+1]+2)) { if (msg[x] == ADSI_SWITCH_TO_DATA) { ast_debug(1, "Switch to data is sent!\n"); waitforswitch++; newdatamode = ADSI_FLAG_DATAMODE; } if (msg[x] == ADSI_SWITCH_TO_VOICE) { ast_debug(1, "Switch to voice is sent!\n"); waitforswitch++; newdatamode = 0; } } msgs[0] = msg; msglens[0] = msglen; msgtypes[0] = msgtype; if (msglen > 253) { ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen); return -1; } ast_stopstream(chan); if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "Unable to set write format to ULAW\n"); return -1; } if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "Unable to set read format to ULAW\n"); if (writeformat.id) { if (ast_set_write_format(chan, &writeformat)) { ast_log(LOG_WARNING, "Unable to restore write format to %s\n", ast_getformatname(&writeformat)); } } return -1; } res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes); if (dowait) { ast_debug(1, "Wait for switch is '%d'\n", waitforswitch); while (waitforswitch-- && ((res = ast_waitfordigit(chan, 1000)) > 0)) { res = 0; ast_debug(1, "Waiting for 'B'...\n"); } } if (!res) { ast_channel_adsicpe_set(chan, (ast_channel_adsicpe(chan) & ~ADSI_FLAG_DATAMODE) | newdatamode); } if (writeformat.id) { ast_set_write_format(chan, &writeformat); } if (readformat.id) { ast_set_read_format(chan, &readformat); } if (!res) { res = ast_safe_sleep(chan, 100 ); } return res; }
static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) { struct ast_frame *f = NULL; int dsptime = 0; struct ast_format rfmt; int res = 0; struct ast_dsp *sildet; /* silence detector dsp */ time_t now; /*Either silence or noise calc depending on wait_for_silence flag*/ int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) = wait_for_silence ? ast_dsp_silence : ast_dsp_noise; ast_format_copy(&rfmt, &chan->readformat); /* Set to linear mode */ if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) { ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n"); return -1; } /* Create the silence detector */ if (!(sildet = ast_dsp_new())) { ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE)); /* Await silence... */ for (;;) { /* Start with no silence received */ dsptime = 0; res = ast_waitfor(chan, timereqd); /* Must have gotten a hangup; let's exit */ if (res < 0) { pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP"); break; } /* We waited and got no frame; sounds like digital silence or a muted digital channel */ if (res == 0) { dsptime = timereqd; } else { /* Looks like we did get a frame, so let's check it out */ if (!(f = ast_read(chan))) { pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP"); break; } if (f->frametype == AST_FRAME_VOICE) { ast_dsp_func(sildet, f, &dsptime); } ast_frfree(f); } ast_verb(6, "Got %dms %s < %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd); if (dsptime >= timereqd) { ast_verb(3, "Exiting with %dms %s >= %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd); /* Ended happily with silence */ res = 1; pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for_silence ? "SILENCE" : "NOISE"); ast_debug(1, "WAITSTATUS was set to %s\n", wait_for_silence ? "SILENCE" : "NOISE"); break; } if (timeout && (difftime(time(&now), waitstart) >= timeout)) { pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT"); ast_debug(1, "WAITSTATUS was set to TIMEOUT\n"); res = 0; break; } } if (rfmt.id && ast_set_read_format(chan, &rfmt)) { ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(&rfmt), chan->name); } ast_dsp_free(sildet); return res; }
static int ices_exec(struct ast_channel *chan, const char *data) { int res = 0; int fds[2]; int ms = -1; int pid = -1; int flags; struct ast_format oreadformat; struct ast_frame *f; char filename[256]=""; char *c; ast_format_clear(&oreadformat); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n"); return -1; } if (pipe(fds)) { ast_log(LOG_WARNING, "Unable to create pipe\n"); return -1; } flags = fcntl(fds[1], F_GETFL); fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); ast_stopstream(chan); if (ast_channel_state(chan) != AST_STATE_UP) res = ast_answer(chan); if (res) { close(fds[0]); close(fds[1]); ast_log(LOG_WARNING, "Answer failed!\n"); return -1; } ast_format_copy(&oreadformat, ast_channel_readformat(chan)); res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR); if (res < 0) { close(fds[0]); close(fds[1]); ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); return -1; } if (((char *)data)[0] == '/') ast_copy_string(filename, (char *) data, sizeof(filename)); else snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data); /* Placeholder for options */ c = strchr(filename, '|'); if (c) *c = '\0'; res = icesencode(filename, fds[0]); if (res >= 0) { pid = res; for (;;) { /* Wait for audio, and stream */ ms = ast_waitfor(chan, -1); if (ms < 0) { ast_debug(1, "Hangup detected\n"); res = -1; break; } f = ast_read(chan); if (!f) { ast_debug(1, "Null frame == hangup() detected\n"); res = -1; break; } if (f->frametype == AST_FRAME_VOICE) { res = write(fds[1], f->data.ptr, f->datalen); if (res < 0) { if (errno != EAGAIN) { ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); res = -1; ast_frfree(f); break; } } } ast_frfree(f); } } close(fds[0]); close(fds[1]); if (pid > -1) kill(pid, SIGKILL); if (!res && oreadformat.id) ast_set_read_format(chan, &oreadformat); return res; }
/* * This is the main function called by Asterisk Core whenever the App is invoked in the extension logic. * This function will always return 0. */ static int alarmreceiver_exec(struct ast_channel *chan, const char *data) { int res = 0; event_node_t *elp, *efree; char signalling_type[64] = ""; event_node_t *event_head = NULL; /* Set write and read formats to ULAW */ ast_verb(4, "AlarmReceiver: Setting read and write formats to ULAW\n"); if (ast_set_write_format_by_id(chan,AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan)); return -1; } if (ast_set_read_format_by_id(chan,AST_FORMAT_ULAW)) { ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan)); return -1; } /* Set default values for this invocation of the application */ ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type)); /* Answer the channel if it is not already */ ast_verb(4, "AlarmReceiver: Answering channel\n"); if (ast_channel_state(chan) != AST_STATE_UP) { if ((res = ast_answer(chan))) return -1; } /* Wait for the connection to settle post-answer */ ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n"); res = ast_safe_sleep(chan, 1250); /* Attempt to receive the events */ if (!res) { /* Determine the protocol to receive in advance */ /* Note: Ademco contact is the only one supported at this time */ /* Others may be added later */ if(!strcmp(signalling_type, ADEMCO_CONTACT_ID)) receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head); else res = -1; } /* Events queued by receiver, write them all out here if so configured */ if ((!res) && (log_individual_events == 0)) res = log_events(chan, signalling_type, event_head); /* * Do we exec a command line at the end? */ if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) { ast_debug(1,"Alarmreceiver: executing: %s\n", event_app); ast_safe_system(event_app); } /* * Free up the data allocated in our linked list */ for (elp = event_head; (elp != NULL);) { efree = elp; elp = elp->next; ast_free(efree); } return 0; }
static int conf_run(struct ast_channel *chan, int confno, int confflags) { int fd; struct dahdi_confinfo dahdic; struct ast_frame *f; struct ast_channel *c; struct ast_frame fr; int outfd; int ms; int nfds; int res; int flags; int retrydahdi; int origfd; int ret = -1; struct dahdi_bufferinfo bi; char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; char *buf = __buf + AST_FRIENDLY_OFFSET; /* Set it into U-law mode (write) */ if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name); goto outrun; } /* Set it into U-law mode (read) */ if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); goto outrun; } ast_indicate(chan, -1); retrydahdi = strcasecmp(chan->tech->type, "DAHDI"); dahdiretry: origfd = chan->fds[0]; if (retrydahdi) { fd = open("/dev/dahdi/pseudo", O_RDWR); if (fd < 0) { ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); goto outrun; } /* Make non-blocking */ flags = fcntl(fd, F_GETFL); if (flags < 0) { ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); close(fd); goto outrun; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); close(fd); goto outrun; } /* Setup buffering information */ memset(&bi, 0, sizeof(bi)); bi.bufsize = CONF_SIZE; bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; bi.numbufs = 4; if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); close(fd); goto outrun; } nfds = 1; } else { /* XXX Make sure we're not running on a pseudo channel XXX */ fd = chan->fds[0]; nfds = 0; } memset(&dahdic, 0, sizeof(dahdic)); /* Check to see if we're in a conference... */ dahdic.chan = 0; if (ioctl(fd, DAHDI_GETCONF, &dahdic)) { ast_log(LOG_WARNING, "Error getting conference\n"); close(fd); goto outrun; } if (dahdic.confmode) { /* Whoa, already in a conference... Retry... */ if (!retrydahdi) { ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n"); retrydahdi = 1; goto dahdiretry; } } memset(&dahdic, 0, sizeof(dahdic)); /* Add us to the conference */ dahdic.chan = 0; dahdic.confno = confno; dahdic.confmode = DAHDI_CONF_MONITORBOTH; if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { ast_log(LOG_WARNING, "Error setting conference\n"); close(fd); goto outrun; } ast_debug(1, "Placed channel %s in DAHDI channel %d monitor\n", chan->name, confno); for(;;) { outfd = -1; ms = -1; c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); if (c) { if (c->fds[0] != origfd) { if (retrydahdi) { /* Kill old pseudo */ close(fd); } ast_debug(1, "Ooh, something swapped out under us, starting over\n"); retrydahdi = 0; goto dahdiretry; } f = ast_read(c); if (!f) break; if ((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '#')) { ret = 0; ast_frfree(f); break; } else if (fd != chan->fds[0]) { if (f->frametype == AST_FRAME_VOICE) { if (f->subclass.format.id == AST_FORMAT_ULAW) { /* Carefully write */ careful_write(fd, f->data.ptr, f->datalen); } else ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%s) frame in the conference\n", ast_getformatname(&f->subclass.format)); } } ast_frfree(f); } else if (outfd > -1) { res = read(outfd, buf, CONF_SIZE); if (res > 0) { memset(&fr, 0, sizeof(fr)); fr.frametype = AST_FRAME_VOICE; ast_format_set(&fr.subclass.format, AST_FORMAT_ULAW, 0); fr.datalen = res; fr.samples = res; fr.data.ptr = buf; fr.offset = AST_FRIENDLY_OFFSET; if (ast_write(chan, &fr) < 0) { ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); /* break; */ } } else ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); } } if (fd != chan->fds[0]) close(fd); else { /* Take out of conference */ /* Add us to the conference */ dahdic.chan = 0; dahdic.confno = 0; dahdic.confmode = 0; if (ioctl(fd, DAHDI_SETCONF, &dahdic)) { ast_log(LOG_WARNING, "Error setting conference\n"); } } outrun: return ret; }