void cw_sched_dump(const struct sched_context *con) { /* * Dump the contents of the scheduler to * stderr */ struct sched *q; struct timeval tv = cw_tvnow(); #ifdef SCHED_MAX_CACHE cw_log(LOG_DEBUG, "CallWeaver Schedule Dump (%d in Q, %d Total, %d Cache)\n", con->schedcnt, con->eventcnt - 1, con->schedccnt); #else cw_log(LOG_DEBUG, "CallWeaver Schedule Dump (%d in Q, %d Total)\n", con->schedcnt, con->eventcnt - 1); #endif cw_log(LOG_DEBUG, "=============================================================\n"); cw_log(LOG_DEBUG, "|ID Callback Data Time (sec:ms) |\n"); cw_log(LOG_DEBUG, "+-----+-----------------+-----------------+-----------------+\n"); for (q = con->schedq; q; q = q->next) { struct timeval delta = cw_tvsub(q->when, tv); cw_log(LOG_DEBUG, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n", q->id, q->callback, q->data, delta.tv_sec, (long int)delta.tv_usec); } cw_log(LOG_DEBUG, "=============================================================\n"); }
static char *acf_strftime(struct cw_channel *chan, int argc, char **argv, char *buf, size_t len) { char *epoch = NULL; char *timezone = NULL; char *format = "%c"; long epochi; struct tm time; if ( (argc>0) && (!cw_strlen_zero(argv[0])) ) epoch=argv[0]; if ( (argc>1) && (!cw_strlen_zero(argv[1])) ) timezone=argv[1]; if ( (argc>2) && (!cw_strlen_zero(argv[2])) ) format=argv[2]; if (argc < 1 || !argv[0][0] || !sscanf(epoch, "%ld", &epochi)) { struct timeval tv = cw_tvnow(); epochi = tv.tv_sec; } buf[0] = '\0'; cw_localtime(&epochi, &time, timezone ); if (!strftime(buf, len, format, &time)) { cw_log(LOG_WARNING, "C function strftime() output nothing?!!\n"); /* AGX: return empty string buffer in case of error */ buf[0] = '\0'; return buf; } /* AGX: strfttime man page says it should already add 0 at the end of the string, * is this something OS specific ? */ buf[len - 1] = '\0'; return buf; }
int cw_sched_add_variable(struct sched_context *con, int when, cw_sched_cb callback, void *data, int variable) { /* * Schedule callback(data) to happen when ms into the future */ struct sched *tmp; int res = -1; #ifdef DEBUG_SCHED DEBUG_LOG(cw_log(LOG_DEBUG, "cw_sched_add_variable()\n")); #endif cw_mutex_lock(&con->lock); if ((tmp = sched_alloc(con))) { if ((tmp->id = con->eventcnt++) < 0) tmp->id = con->eventcnt = 0; tmp->callback = callback; tmp->data = data; tmp->resched = when; tmp->variable = variable; tmp->when = cw_tvadd(cw_tvnow(), cw_samp2tv(when, 1000)); schedule(con, tmp); res = tmp->id; } #ifdef DUMP_SCHEDULER /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */ cw_sched_dump(con); #endif cw_mutex_unlock(&con->lock); return res; }
int cw_sched_runq(struct sched_context *con) { /* * Launch all events which need to be run at this time. */ struct sched *runq, **endq, *current; struct timeval tv; int x=0; int res; #ifdef DEBUG_SCHED DEBUG_LOG(cw_log(LOG_DEBUG, "cw_sched_runq()\n")); #endif cw_mutex_lock(&con->lock); /* schedule all events which are going to expire within 1ms. * We only care about millisecond accuracy anyway, so this will * help us get more than one event at one time if they are very * close together. */ tv = cw_tvadd(cw_tvnow(), cw_tv(0, 1000)); runq = con->schedq; endq = &runq; while (con->schedq && SOONER(con->schedq->when, tv)) { endq = &con->schedq->next; con->schedq = con->schedq->next; con->schedcnt--; } *endq = NULL; cw_mutex_unlock(&con->lock); while ((current = runq)) { runq = runq->next; x++; res = current->callback(current->data); if (res) { /* * If they return non-zero, we should schedule them to be * run again. */ current->when = cw_tvadd(current->when, cw_samp2tv((current->variable ? res : current->resched), 1000)); schedule(con, current); } else { /* No longer needed, so release it */ sched_release(con, current); } } return x; }
long cw_sched_when(struct sched_context *con,int id) { struct sched *s; long secs; #ifdef DEBUG_SCHED DEBUG_LOG(cw_log(LOG_DEBUG, "cw_sched_when()\n")); #endif cw_mutex_lock(&con->lock); s=con->schedq; while (s!=NULL) { if (s->id==id) break; s=s->next; } secs=-1; if (s!=NULL) { struct timeval now = cw_tvnow(); secs=s->when.tv_sec-now.tv_sec; } cw_mutex_unlock(&con->lock); return secs; }
int cw_sched_wait(struct sched_context *con) { /* * Return the number of milliseconds * until the next scheduled event */ int ms; #ifdef DEBUG_SCHED DEBUG_LOG(cw_log(LOG_DEBUG, "cw_sched_wait()\n")); #endif cw_mutex_lock(&con->lock); if (!con->schedq) { ms = -1; } else { ms = cw_tvdiff_ms(con->schedq->when, cw_tvnow()); if (ms < 0) ms = 0; } cw_mutex_unlock(&con->lock); return ms; }
static int sayunixtime_exec(struct cw_channel *chan, int argc, char **argv) { struct timeval tv; time_t unixtime; struct localuser *u; char *format; int res=0; if (argc > 3) { cw_log(LOG_ERROR, "Syntax: %s\n", sayunixtime_syntax); return -1; } LOCAL_USER_ADD(u); if (argc < 1 || !(unixtime = (time_t)atol(argv[0]))) { tv = cw_tvnow(); unixtime = (time_t)tv.tv_sec; } if (argc > 2 && argv[2][0]) { format = argv[2]; } else if (!strcasecmp(chan->language, "da")) { format = "A dBY HMS"; } else if (!strcasecmp(chan->language, "de")) { format = "A dBY HMS"; } else { format = "ABdY 'digits/at' IMp"; } if (chan->_state != CW_STATE_UP) res = cw_answer(chan); if (!res) res = cw_say_date_with_format(chan, unixtime, CW_DIGIT_ANY, chan->language, format, (argc > 1 && argv[1][0] ? argv[1] : NULL)); LOCAL_USER_REMOVE(u); return res; }
static int pipe_exec(struct cw_channel *chan, int argc, char **argv) { int res=0; struct localuser *u; int fds[2]; int ms = -1; int pid = -1; int owriteformat; int oreadformat; int timeout = 2000; struct timeval last; struct cw_frame *f; struct myframe { struct cw_frame f; char offset[CW_FRIENDLY_OFFSET]; short frdata[160]; } myf; last.tv_usec = 0; last.tv_sec = 0; if (argc < 2 || argc > 3) { cw_log(LOG_ERROR, "Syntax: %s\n", pipe_syntax); return -1; } LOCAL_USER_ADD(u); if (pipe(fds)) { cw_log(LOG_WARNING, "Unable to create pipe\n"); LOCAL_USER_REMOVE(u); return -1; } // MOC: Setting non blocking doesn't seem to change anything // flags = fcntl(fds[1], F_GETFL); // fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); // flags = fcntl(fds[0], F_GETFL); // fcntl(fds[0], F_SETFL, flags | O_NONBLOCK); cw_stopstream(chan); if (chan->_state != CW_STATE_UP) res = cw_answer(chan); if (res) { close(fds[0]); close(fds[1]); cw_log(LOG_WARNING, "Answer failed!\n"); LOCAL_USER_REMOVE(u); return -1; } oreadformat = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); owriteformat = chan->writeformat; res += cw_set_write_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { close(fds[0]); close(fds[1]); cw_log(LOG_WARNING, "Unable to set write format to signed linear\n"); LOCAL_USER_REMOVE(u); return -1; } res = pipeencode(argv[1], argv[2], fds[0], fds[1]); if (res >= 0) { last = cw_tvnow(); last.tv_sec += 1; pid = res; for (;;) { /* Wait for audio, and stream */ if (argv[0][0] == '0') { /* START WRITE TO FD */ ms = cw_waitfor(chan, 10); if (ms < 0) { cw_log(LOG_DEBUG, "Hangup detected\n"); res = -1; break; } else if (ms > 0) { f = cw_read(chan); if (!f) { cw_log(LOG_DEBUG, "Null frame == hangup() detected\n"); res = -1; break; } if (f->frametype == CW_FRAME_DTMF) { cw_log(LOG_DEBUG, "User pressed a key\n"); cw_fr_free(f); res = 0; break; } if (f->frametype == CW_FRAME_VOICE) { res = write(fds[1], f->data, f->datalen); if (res < 0) { if (errno != EAGAIN) { cw_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); cw_fr_free(f); res = -1; break; } } } cw_fr_free(f); } /* END WRITE TO FD */ } else { /* START WRITE CHANNEL */ ms = cw_tvdiff_ms(last, cw_tvnow()); if (ms <= 0) { res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); if (res > 0) { cw_fr_init_ex(&myf.f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, __PRETTY_FUNCTION__); myf.f.datalen = res; myf.f.samples = res/sizeof(int16_t); myf.f.offset = CW_FRIENDLY_OFFSET; myf.f.data = myf.frdata; if (cw_write(chan, &myf.f) < 0) { res = -1; break; } } else { cw_log(LOG_DEBUG, "No more stream\n"); res = 0; break; } last = cw_tvadd(last, cw_samp2tv(myf.f.samples, 8000)); } else { ms = cw_waitfor(chan, ms); if (ms < 0) { cw_log(LOG_DEBUG, "Hangup detected\n"); res = -1; break; } if (ms) { f = cw_read(chan); if (!f) { cw_log(LOG_DEBUG, "Null frame == hangup() detected\n"); res = -1; break; } if (f->frametype == CW_FRAME_DTMF) { cw_log(LOG_DEBUG, "User pressed a key\n"); cw_fr_free(f); res = 0; break; } cw_fr_free(f); } } /* END WRITE CHANNEL */ } } } close(fds[0]); close(fds[1]); LOCAL_USER_REMOVE(u); if (pid > -1) kill(pid, SIGKILL); if (!res && oreadformat) cw_set_read_format(chan, oreadformat); if (!res && owriteformat) cw_set_write_format(chan, owriteformat); return res; }
static int cw_serialize_showchan(struct cw_channel *c, char *buf, size_t size) { struct timeval now; long elapsed_seconds=0; int hour=0, min=0, sec=0; char cgrp[256]; char pgrp[256]; now = cw_tvnow(); memset(buf,0,size); if (!c) return 0; if (c->cdr) { elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; hour = elapsed_seconds / 3600; min = (elapsed_seconds % 3600) / 60; sec = elapsed_seconds % 60; } snprintf(buf,size, "Name= %s\n" "Type= %s\n" "UniqueID= %s\n" "CallerID= %s\n" "CallerIDName= %s\n" "DNIDDigits= %s\n" "State= %s (%d)\n" "Rings= %d\n" "NativeFormat= %d\n" "WriteFormat= %d\n" "ReadFormat= %d\n" "1stFileDescriptor= %d\n" "Framesin= %d %s\n" "Framesout= %d %s\n" "TimetoHangup= %ld\n" "ElapsedTime= %dh%dm%ds\n" "Context= %s\n" "Extension= %s\n" "Priority= %d\n" "CallGroup= %s\n" "PickupGroup= %s\n" "Application= %s\n" "Blocking_in= %s\n", c->name, c->type, c->uniqueid, (c->cid.cid_num ? c->cid.cid_num : "(N/A)"), (c->cid.cid_name ? c->cid.cid_name : "(N/A)"), (c->cid.cid_dnid ? c->cid.cid_dnid : "(N/A)" ), cw_state2str(c->_state), c->_state, c->rings, c->nativeformats, c->writeformat, c->readformat, c->fds[0], c->fin & 0x7fffffff, (c->fin & 0x80000000) ? " (DEBUGGED)" : "", c->fout & 0x7fffffff, (c->fout & 0x80000000) ? " (DEBUGGED)" : "", (long)c->whentohangup, hour, min, sec, c->context, c->exten, c->priority, cw_print_group(cgrp, sizeof(cgrp), c->callgroup), cw_print_group(pgrp, sizeof(pgrp), c->pickupgroup), ( c->appl ? c->appl : "(N/A)" ), (cw_test_flag(c, CW_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)")); return 0; }
int cw_control_streamfile(struct cw_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms) { long elapsed = 0, last_elapsed = 0; char *breaks = NULL; char *end = NULL; int blen = 2; int res; if (stop) blen += strlen(stop); if (pause) blen += strlen(pause); if (restart) blen += strlen(restart); if (blen > 2) { breaks = alloca(blen + 1); breaks[0] = '\0'; if (stop) strcat(breaks, stop); if (pause) strcat(breaks, pause); if (restart) strcat(breaks, restart); } if (chan->_state != CW_STATE_UP) res = cw_answer(chan); if (chan) cw_stopstream(chan); if (file) { if ((end = strchr(file,':'))) { if (!strcasecmp(end, ":end")) { *end = '\0'; end++; } } } for (;;) { struct timeval started = cw_tvnow(); if (chan) cw_stopstream(chan); res = cw_streamfile(chan, file, chan->language); if (!res) { if (end) { cw_seekstream(chan->stream, 0, SEEK_END); end=NULL; } res = 1; if (elapsed) { cw_stream_fastforward(chan->stream, elapsed); last_elapsed = elapsed - 200; } if (res) res = cw_waitstream_fr(chan, breaks, fwd, rev, skipms); else break; } if (res < 1) break; /* We go at next loop if we got the restart char */ if (restart && strchr(restart, res)) { cw_log(LOG_DEBUG, "we'll restart the stream here at next loop\n"); elapsed=0; /* To make sure the next stream will start at beginning */ continue; } if (pause != NULL && strchr(pause, res)) { elapsed = cw_tvdiff_ms(cw_tvnow(), started) + last_elapsed; for(;;) { if (chan) cw_stopstream(chan); res = cw_waitfordigit(chan, 1000); if (res == 0) continue; else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res))) break; } if (res == *pause) { res = 0; continue; } } if (res == -1) break; /* if we get one of our stop chars, return it to the calling function */ if (stop && strchr(stop, res)) { /* res = 0; */ break; } } if (chan) cw_stopstream(chan); return res; }