Esempio n. 1
0
/*!
 * \brief Get the next SMDI message from the queue.
 * \param iface a pointer to the interface to use.
 *
 * This function pulls the first unexpired message from the SMDI message queue
 * on the specified interface.  It will purge all expired SMDI messages before
 * returning.
 *
 * \return the next SMDI message, or NULL if there were no pending messages.
 */
extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_pop(struct ast_smdi_interface *iface)
{
	struct ast_smdi_mwi_message *mwi_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q);
	struct timeval now;
	long elapsed = 0;

	/* purge old messages */
	now = ast_tvnow();
	while (mwi_msg)	{
		elapsed = ast_tvdiff_ms(now, mwi_msg->timestamp);

		if (elapsed > iface->msg_expiry) {
			/* found an expired message */
			ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
			ast_log(LOG_NOTICE, "Purged expired message from %s SMDI MWI message queue.  Message was %ld milliseconds too old.",
				iface->name, elapsed - iface->msg_expiry);
			mwi_msg = ASTOBJ_CONTAINER_UNLINK_START(&iface->mwi_q);
		}
		else {
			/* good message, return it */
			break;
		}
	}

	return mwi_msg;
}
Esempio n. 2
0
static int waituntil_exec(struct ast_channel *chan, void *data)
{
	int res;
	double fraction;
	struct timeval future = { 0, };
	struct timeval tv = ast_tvnow();
	int msec;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "WaitUntil requires an argument(epoch)\n");
		pbx_builtin_setvar_helper(chan, "WAITUNTILSTATUS", "FAILURE");
		return 0;
	}

	if (sscanf(data, "%ld%lf", (long *)&future.tv_sec, &fraction) == 0) {
		ast_log(LOG_WARNING, "WaitUntil called with non-numeric argument\n");
		pbx_builtin_setvar_helper(chan, "WAITUNTILSTATUS", "FAILURE");
		return 0;
	}

	future.tv_usec = fraction * 1000000;

	if ((msec = ast_tvdiff_ms(future, tv)) < 0) {
		ast_log(LOG_NOTICE, "WaitUntil called in the past (now %ld, arg %ld)\n", (long)tv.tv_sec, (long)future.tv_sec);
		pbx_builtin_setvar_helper(chan, "WAITUNTILSTATUS", "PAST");
		return 0;
	}

	if ((res = ast_safe_sleep(chan, msec)))
		pbx_builtin_setvar_helper(chan, "WAITUNTILSTATUS", "HANGUP");
	else
		pbx_builtin_setvar_helper(chan, "WAITUNTILSTATUS", "OK");

	return res;
}
Esempio n. 3
0
/*!
 * \brief Set a dial timeout interval hook on the channel.
 *
 * The absolute time that the timeout should occur is stored on
 * a datastore on the channel. This time is converted into a relative
 * number of milliseconds in the future. Then an interval hook is set
 * to trigger in that number of milliseconds.
 *
 * \pre chan is locked
 *
 * \param chan The channel on which to set the interval hook
 */
static void set_interval_hook(struct ast_channel *chan)
{
	struct ast_datastore *datastore;
	struct timeval *hangup_time;
	int64_t ms;
	struct ast_bridge_channel *bridge_channel;

	datastore = ast_channel_datastore_find(chan, &timeout_datastore, NULL);
	if (!datastore) {
		return;
	}

	hangup_time = datastore->data;

	ms = ast_tvdiff_ms(*hangup_time, ast_tvnow());
	bridge_channel = ast_channel_get_bridge_channel(chan);
	if (!bridge_channel) {
		return;
	}

	if (ast_bridge_interval_hook(bridge_channel->features, 0, ms > 0 ? ms : 1,
			bridge_timeout, NULL, NULL, 0)) {
		return;
	}

	ast_queue_frame(bridge_channel->chan, &ast_null_frame);
}
Esempio n. 4
0
/*
* Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
* treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
* digits.
*
* Returns 0 if all digits successfully received.
* Returns 1 if a digit time out occurred
* Returns -1 if the caller hung up or there was a channel error.
*
*/
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
{
	int res = 0;
	int i = 0;
	int r;
	struct ast_frame *f;
	struct timeval lastdigittime;

	lastdigittime = ast_tvnow();
	for (;;) {
		/* if outa time, leave */
		if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((i > 0) ? sdto : fdto)) {
			ast_verb(4, "AlarmReceiver: DTMF Digit Timeout on %s\n", ast_channel_name(chan));
			ast_debug(1,"AlarmReceiver: DTMF timeout on chan %s\n",ast_channel_name(chan));
			res = 1;
			break;
		}

		if ((r = ast_waitfor(chan, -1)) < 0) {
			ast_debug(1, "Waitfor returned %d\n", r);
			continue;
		}

		f = ast_read(chan);

		if (f == NULL) {
			res = -1;
			break;
		}

		/* If they hung up, leave */
		if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP)) {
			if (f->data.uint32) {
				ast_channel_hangupcause_set(chan, f->data.uint32);
			}
			ast_frfree(f);
			res = -1;
			break;
		}

		/* if not DTMF, just do it again */
		if (f->frametype != AST_FRAME_DTMF) {
			ast_frfree(f);
			continue;
		}

		digit_string[i++] = f->subclass.integer;  /* save digit */

		ast_frfree(f);

		/* If we have all the digits we expect, leave */
		if(i >= length)
			break;

		lastdigittime = ast_tvnow();
	}

	digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
	return res;
}
Esempio n. 5
0
int ast_sip_sched_task_get_next_run(struct ast_sip_sched_task *schtd)
{
	int delay;
	struct timeval since_when;
	struct timeval now;

	if (!ao2_ref_and_lock(schtd)) {
		return -1;
	}

	if (schtd->interval) {
		delay = schtd->interval;
		now = ast_tvnow();

		if (schtd->flags & AST_SIP_SCHED_TASK_DELAY) {
			since_when = schtd->is_running ? now : schtd->last_end;
		} else {
			since_when = schtd->last_start.tv_sec ? schtd->last_start : schtd->when_queued;
		}

		delay -= ast_tvdiff_ms(now, since_when);

		delay = delay < 0 ? 0 : delay;
	} else {
		delay = -1;
	}

	ao2_unlock_and_unref(schtd);

	return delay;
}
static void __verboser(const char *stuff, int opos, int replacelast, int complete)
{
	char *s2[2];
	struct timeval tv;
	int ms;
	s2[0] = (char *)stuff;
	s2[1] = NULL;
	gtk_clist_freeze(GTK_CLIST(verb));
	if (replacelast) 
		gtk_clist_remove(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1);
	gtk_clist_append(GTK_CLIST(verb), s2);
	if (!ast_tvzero(last)) {
		gdk_threads_leave();
		gettimeofday(&tv, NULL);
		if (cleanupid > -1)
			gtk_timeout_remove(cleanupid);
		ms = ast_tvdiff_ms(tv, last);
		if (ms < 100) {
			/* We just got a message within 100ms, so just schedule an update
			   in the near future */
			cleanupid = gtk_timeout_add(200, cleanup, NULL);
		} else {
			cleanup(&cleanupid);
		}
		last = tv;
	} else {
		gettimeofday(&last, NULL);
	}
}
/*! \brief Observer callback for when a contact is created */
static void contact_expiration_observer_created(const void *object)
{
	const struct ast_sip_contact *contact = object;
	struct contact_expiration *expiration;
	int expires = MAX(0, ast_tvdiff_ms(contact->expiration_time, ast_tvnow()));

	if (ast_tvzero(contact->expiration_time)) {
		return;
	}

	expiration = ao2_alloc_options(sizeof(*expiration), contact_expiration_destroy,
		AO2_ALLOC_OPT_LOCK_NOLOCK);
	if (!expiration) {
		return;
	}

	expiration->contact = (struct ast_sip_contact*)contact;
	ao2_ref(expiration->contact, +1);

	ao2_ref(expiration, +1);
	if ((expiration->sched = ast_sched_add(sched, expires, contact_expiration_expire, expiration)) < 0) {
		ao2_ref(expiration, -1);
		ast_log(LOG_ERROR, "Scheduled expiration for contact '%s' could not be performed, contact may persist past life\n",
			ast_sorcery_object_get_id(contact));
	} else {
		ao2_link(contact_autoexpire, expiration);
	}
	ao2_ref(expiration, -1);
}
Esempio n. 8
0
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;

	rformat = ao2_bump(ast_channel_readformat(chan));
	if (ast_set_read_format(chan, ast_format_slin)) {
		ast_log(LOG_NOTICE, "Unable to set to linear mode!\n");
		ao2_cleanup(rformat);
		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) &&
			(ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
			foo = (short *)f->data.ptr;
			for (x=0;x<f->samples;x++) {
				noise += abs(foo[x]);
				samples++;
			}
		}
		ast_frfree(f);
	}

	if (rformat) {
		if (ast_set_read_format(chan, rformat)) {
			ast_log(LOG_NOTICE, "Unable to restore original format!\n");
			ao2_ref(rformat, -1);
			return -1;
		}
		ao2_ref(rformat, -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);
}
Esempio n. 9
0
/*!
 * \brief Receive a fixed length DTMF string.
 *
 * \note Doesn't give preferential treatment to any digit,
 * \note allow different timeout values for the first and all subsequent digits
 *
 * \param chan Asterisk Channel
 * \param digit_string Digits String
 * \param buf_size The size of the Digits String buffer
 * \param expected Digits expected for this message type
 * \param received Pointer to number of digits received so far
 *
 * \retval 0 if all digits were successfully received
 * \retval 1 if a timeout occurred
 * \retval -1 if the caller hung up or on channel errors
 */
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int buf_size, int expected, int *received)
{
	int rtn = 0;
	int r;
	struct ast_frame *f;
	struct timeval lastdigittime;

	lastdigittime = ast_tvnow();
	while (*received < expected && *received < buf_size - 1) {
		/* If timed out, leave */
		if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((*received > 0) ? sdtimeout : fdtimeout)) {
			ast_verb(4, "AlarmReceiver: DTMF Digit Timeout on %s\n", ast_channel_name(chan));
			ast_debug(1, "AlarmReceiver: DTMF timeout on chan %s\n", ast_channel_name(chan));
			rtn = 1;
			break;
		}

		if ((r = ast_waitfor(chan, -1)) < 0) {
			ast_debug(1, "Waitfor returned %d\n", r);
			continue;
		}

		if ((f = ast_read(chan)) == NULL) {
			rtn = -1;
			break;
		}

		/* If they hung up, leave */
		if ((f->frametype == AST_FRAME_CONTROL)
			&& (f->subclass.integer == AST_CONTROL_HANGUP)) {
			if (f->data.uint32) {
				ast_channel_hangupcause_set(chan, f->data.uint32);
			}
			ast_frfree(f);
			rtn = -1;
			break;
		}

		/* If not DTMF, just do it again */
		if (f->frametype != AST_FRAME_DTMF) {
			ast_frfree(f);
			continue;
		}

		/* Save digit */
		digit_string[(*received)++] = f->subclass.integer;
		ast_frfree(f);

		lastdigittime = ast_tvnow();
	}

	/* Null terminate the end of the digit_string */
	digit_string[*received] = '\0';

	return rtn;
}
Esempio n. 10
0
static long get_now(struct ast_jb *jb, struct timeval *when)
{
	struct timeval now;

	if (!when) {
		when = &now;
		gettimeofday(when, NULL);
	}

	return ast_tvdiff_ms(*when, jb->timebase);
}
Esempio n. 11
0
static int expire_requests(void *object, void *arg, int flags)
{
	struct unidentified_request *unid = object;
	int *maxage = arg;
	int64_t ms = ast_tvdiff_ms(ast_tvnow(), unid->first_seen);

	if (ms > (*maxage) * 2 * 1000) {
		return CMP_MATCH;
	}

	return 0;
}
/*! \brief Callback function which deletes a contact if it has expired or sets up auto-expiry */
static int contact_expiration_setup(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;
	int expires = MAX(0, ast_tvdiff_ms(contact->expiration_time, ast_tvnow()));

	if (!expires) {
		ast_sorcery_delete(ast_sip_get_sorcery(), contact);
	} else {
		contact_expiration_observer_created(contact);
	}

	return 0;
}
Esempio n. 13
0
/*! \brief Internal callback function which deletes and unlinks any expired contacts */
static int contact_expire(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;

	/* If the contact has not yet expired it is valid */
	if (ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) > 0) {
		return 0;
	}

	ast_sip_location_delete_contact(contact);

	return CMP_MATCH;
}
Esempio n. 14
0
/*
 * This function is run in the context of the serializer.
 * It runs the task with a simple call and reschedules based on the result.
 */
static int run_task(void *data)
{
	RAII_VAR(struct ast_sip_sched_task *, schtd, ao2_bump(data), ao2_cleanup);
	int res;
	int delay;

	ao2_lock(schtd);
	schtd->last_start = ast_tvnow();
	schtd->is_running = 1;
	schtd->run_count++;
	ao2_unlock(schtd);

	res = schtd->task(schtd->task_data);

	ao2_lock(schtd);
	schtd->is_running = 0;
	schtd->last_end = ast_tvnow();

	/*
	 * Don't restart if the task returned 0 or if the interval
	 * was set to 0 while the task was running
	 */
	if (!res || !schtd->interval) {
		schtd->interval = 0;
		ao2_unlock(schtd);
		ao2_unlink(tasks, schtd);
		return -1;
	}

	if (schtd->flags & AST_SIP_SCHED_TASK_VARIABLE) {
		schtd->interval = res;
	}

	if (schtd->flags & AST_SIP_SCHED_TASK_DELAY) {
		delay = schtd->interval;
	} else {
		delay = schtd->interval - (ast_tvdiff_ms(schtd->last_end, schtd->last_start) % schtd->interval);
	}

	schtd->current_scheduler_id = ast_sched_add(scheduler_context, delay, push_to_serializer, (const void *)schtd);
	if (schtd->current_scheduler_id < 0) {
		schtd->interval = 0;
		ao2_unlock(schtd);
		ao2_unlink(tasks, schtd);
		return -1;
	}

	ao2_unlock(schtd);

	return 0;
}
Esempio n. 15
0
static void check_endpoint(pjsip_rx_data *rdata, struct unidentified_request *unid,
	const char *name)
{
	int64_t ms = ast_tvdiff_ms(ast_tvnow(), unid->first_seen);

	ao2_wrlock(unid);
	unid->count++;

	if (ms < (unidentified_period * 1000) && unid->count >= unidentified_count) {
		log_failed_request(rdata, "No matching endpoint found", unid->count, ms);
		ast_sip_report_invalid_endpoint(name, rdata);
	}
	ao2_unlock(unid);
}
Esempio n. 16
0
/*! \brief complete a buffer from the local video source.
 * Called by get_video_frames(), in turn called by the video thread.
 */
static struct fbuf_t *grabber_read(struct video_out_desc *v)
{
	struct timeval now = ast_tvnow();

	if (v->grabber == NULL) /* not initialized */
		return 0;

	/* check if it is time to read */
	if (ast_tvzero(v->last_frame))
		v->last_frame = now;
	if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
		return 0;	/* too early */
	v->last_frame = now; /* XXX actually, should correct for drift */
	return v->grabber->read(v->grabber_data);
}
Esempio n. 17
0
/*! \brief Internal function which adds a contact to a response */
static int registrar_add_contact(void *obj, void *arg, int flags)
{
	struct ast_sip_contact *contact = obj;
	pjsip_tx_data *tdata = arg;
	pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(tdata->pool);
	pj_str_t uri;

	pj_strdup2_with_null(tdata->pool, &uri, contact->uri);
	hdr->uri = pjsip_parse_uri(tdata->pool, uri.ptr, uri.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
	hdr->expires = ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) / 1000;

	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);

	return 0;
}
/*! \brief Observer callback for when a contact is updated */
static void contact_expiration_observer_updated(const void *object)
{
	const struct ast_sip_contact *contact = object;
	struct contact_expiration *expiration;
	int expires = MAX(0, ast_tvdiff_ms(contact->expiration_time, ast_tvnow()));

	expiration = ao2_find(contact_autoexpire, ast_sorcery_object_get_id(contact),
		OBJ_SEARCH_KEY);
	if (!expiration) {
		return;
	}

	AST_SCHED_REPLACE_UNREF(expiration->sched, sched, expires, contact_expiration_expire,
		expiration, ao2_cleanup(expiration), ao2_cleanup(expiration), ao2_ref(expiration, +1));
	ao2_ref(expiration, -1);
}
Esempio n. 19
0
/*! \brief complete a buffer from the specified local video source.
 * Called by get_video_frames(), in turn called by the video thread.
 *
 * \param dev = video environment descriptor
 * \param fps = frame per seconds, for every device
 *
 * returns:
 * - NULL on falure
 * - reference to the device buffer on success
 */
static struct fbuf_t *grabber_read(struct video_device *dev, int fps)
{
	struct timeval now = ast_tvnow();

	if (dev->grabber == NULL) /* not initialized */
		return NULL;
	
	/* the last_frame field in this row of the device table (dev)
	is always initialized, it is set during the parsing of the config
	file, and never unset, function fill_device_table(). */
	/* check if it is time to read */
	if (ast_tvdiff_ms(now, dev->last_frame) < 1000/fps)
		return NULL; /* too early */
	dev->last_frame = now; /* XXX actually, should correct for drift */
	return dev->grabber->read(dev->grabber_data);
}
static void limits_interval_playback(struct ast_bridge_channel *bridge_channel, struct ast_bridge_features_limits *limits, const char *file)
{
	if (!strcasecmp(file, "timeleft")) {
		unsigned int remaining = ast_tvdiff_ms(limits->quitting_time, ast_tvnow()) / 1000;
		unsigned int min;
		unsigned int sec;

		if (remaining <= 0) {
			return;
		}

		if ((remaining / 60) > 1) {
			min = remaining / 60;
			sec = remaining % 60;
		} else {
			min = 0;
			sec = remaining;
		}

		ast_stream_and_wait(bridge_channel->chan, "vm-youhave", AST_DIGIT_NONE);
		if (min) {
			ast_say_number(bridge_channel->chan, min, AST_DIGIT_NONE,
				ast_channel_language(bridge_channel->chan), NULL);
			ast_stream_and_wait(bridge_channel->chan, "queue-minutes", AST_DIGIT_NONE);
		}
		if (sec) {
			ast_say_number(bridge_channel->chan, sec, AST_DIGIT_NONE,
				ast_channel_language(bridge_channel->chan), NULL);
			ast_stream_and_wait(bridge_channel->chan, "queue-seconds", AST_DIGIT_NONE);
		}
	} else {
		ast_stream_and_wait(bridge_channel->chan, file, AST_DIGIT_NONE);
	}

	/*
	 * It may be necessary to resume music on hold after we finish
	 * playing the announcment.
	 */
	if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_MOH)) {
		const char *latest_musicclass;

		ast_channel_lock(bridge_channel->chan);
		latest_musicclass = ast_strdupa(ast_channel_latest_musicclass(bridge_channel->chan));
		ast_channel_unlock(bridge_channel->chan);
		ast_moh_start(bridge_channel->chan, latest_musicclass, NULL);
	}
}
static void calc_cost(struct ast_translator *t, int samples)
{
	int sofar=0;
	struct ast_translator_pvt *pvt;
	struct ast_frame *f, *out;
	struct timeval start;
	int cost;

	if(!samples)
		samples = 1;
	
	/* If they don't make samples, give them a terrible score */
	if (!t->sample) {
		ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
		t->cost = 99999;
		return;
	}
	pvt = t->newpvt();
	if (!pvt) {
		ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
		t->cost = 99999;
		return;
	}
	start = ast_tvnow();
	/* Call the encoder until we've processed one second of time */
	while(sofar < samples * 8000) {
		f = t->sample();
		if (!f) {
			ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
			t->destroy(pvt);
			t->cost = 99999;
			return;
		}
		t->framein(pvt, f);
		ast_frfree(f);
		while((out = t->frameout(pvt))) {
			sofar += out->samples;
			ast_frfree(out);
		}
	}
	cost = ast_tvdiff_ms(ast_tvnow(), start);
	t->destroy(pvt);
	t->cost = cost / samples;
	if (!t->cost)
		t->cost = 1;
}
Esempio n. 22
0
static int timeout_read(struct ast_channel *chan, const char *cmd, char *data,
			char *buf, size_t len)
{
	struct timeval myt;

	if (!chan)
		return -1;

	if (!data) {
		ast_log(LOG_ERROR, "Must specify type of timeout to get.\n");
		return -1;
	}

	switch (*data) {
	case 'a':
	case 'A':
		if (ast_tvzero(*ast_channel_whentohangup(chan))) {
			ast_copy_string(buf, "0", len);
		} else {
			myt = ast_tvnow();
			snprintf(buf, len, "%.3f", ast_tvdiff_ms(*ast_channel_whentohangup(chan), myt) / 1000.0);
		}
		break;

	case 'r':
	case 'R':
		if (ast_channel_pbx(chan)) {
			snprintf(buf, len, "%.3f", ast_channel_pbx(chan)->rtimeoutms / 1000.0);
		}
		break;

	case 'd':
	case 'D':
		if (ast_channel_pbx(chan)) {
			snprintf(buf, len, "%.3f", ast_channel_pbx(chan)->dtimeoutms / 1000.0);
		}
		break;

	default:
		ast_log(LOG_ERROR, "Unknown timeout type specified.\n");
		return -1;
	}

	return 0;
}
Esempio n. 23
0
/*!
 * \brief Get the next SMDI message from the queue.
 * \param iface a pointer to the interface to use.
 * \param timeout the time to wait before returning in milliseconds.
 *
 * This function pulls a message from the SMDI message queue on the specified
 * interface.  If no message is available this function will wait the specified
 * amount of time before returning.
 *
 * \return the next SMDI message, or NULL if there were no pending messages and
 * the timeout has expired.
 */
extern struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait(struct ast_smdi_interface *iface, int timeout)
{
	struct timeval start;
	long diff = 0;
	struct ast_smdi_mwi_message *msg;

	start = ast_tvnow();
	while (diff < timeout) {

		if ((msg = ast_smdi_mwi_message_pop(iface)))
			return msg;

		/* check timeout */
		diff = ast_tvdiff_ms(ast_tvnow(), start);
	}

	return (ast_smdi_mwi_message_pop(iface));
}
int ast_sched_wait(struct sched_context *con)
{
	/*
	 * Return the number of milliseconds 
	 * until the next scheduled event
	 */
	int ms;
	DEBUG(ast_log(LOG_DEBUG, "ast_sched_wait()\n"));
	ast_mutex_lock(&con->lock);
	if (!con->schedq) {
		ms = -1;
	} else {
		ms = ast_tvdiff_ms(con->schedq->when, ast_tvnow());
		if (ms < 0)
			ms = 0;
	}
	ast_mutex_unlock(&con->lock);
	return ms;
	
}
Esempio n. 25
0
static int cli_unid_print_body(void *obj, void *arg, int flags)
{
	struct unidentified_request *unid = obj;
	struct ast_sip_cli_context *context = arg;
	int indent;
	int flexwidth;
	int64_t ms = ast_tvdiff_ms(ast_tvnow(), unid->first_seen);

	ast_assert(context->output_buffer != NULL);

	indent = CLI_INDENT_TO_SPACES(context->indent_level);
	flexwidth = CLI_LAST_TABSTOP - 4;

	ast_str_append(&context->output_buffer, 0, "%*s:  %-*.*s  %7d %10.3f\n",
		indent,
		"Request",
		flexwidth, flexwidth,
		unid->src_name, unid->count,  ms / 1000.0);

	return 0;
}
Esempio n. 26
0
/*!
 * \retval 0 no timer tick needed
 * \retval non-zero write to the timing pipe needed
 */
static int check_timer(struct pthread_timer *timer)
{
	struct timeval now;

	if (timer->state == TIMER_STATE_IDLE) {
		return 0;
	}

	now = ast_tvnow();

	if (timer->tick_count < (ast_tvdiff_ms(now, timer->start) / timer->interval)) {
		timer->tick_count++;
		if (!timer->tick_count) {
			/* Handle overflow. */
			timer->start = now;
		}
		return 1;
	}

	return 0;
}
Esempio n. 27
0
/*!
 * \brief Router callback for \ref stasis_cache_update messages.
 * \param data Data pointer given when added to router.
 * \param sub This subscription.
 * \param topic The topic the message was posted to. This is not necessarily the
 *              topic you subscribed to, since messages may be forwarded between
 *              topics.
 * \param message The message itself.
 */
static void updates(void *data, struct stasis_subscription *sub,
	struct stasis_message *message)
{
	/* Since this came from a message router, we know the type of the
	 * message. We can cast the data without checking its type.
	 */
	struct stasis_cache_update *update = stasis_message_data(message);

	/* We're only interested in channel snapshots, so check the type
	 * of the underlying message.
	 */
	if (ast_channel_snapshot_type() != update->type) {
		return;
	}

	/* There are three types of cache updates.
	 * !old && new -> Initial cache entry
	 * old && new -> Updated cache entry
	 * old && !new -> Cache entry removed.
	 */

	if (!update->old_snapshot && update->new_snapshot) {
		/* Initial cache entry; count a channel creation */
		ast_statsd_log("channels.count", AST_STATSD_COUNTER, 1);
	} else if (update->old_snapshot && !update->new_snapshot) {
		/* Cache entry removed. Compute the age of the channel and post
		 * that, as well as decrementing the channel count.
		 */
		struct ast_channel_snapshot *last;
		int64_t age;

		last = stasis_message_data(update->old_snapshot);
		age = ast_tvdiff_ms(*stasis_message_timestamp(message),
			last->creationtime);
		ast_statsd_log("channels.calltime", AST_STATSD_TIMER, age);

		/* And decrement the channel count */
		ast_statsd_log("channels.count", AST_STATSD_COUNTER, -1);
	}
}
Esempio n. 28
0
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
{
#if !defined(AST_POLL_COMPAT)
	struct timeval start = ast_tvnow();
#if defined(HAVE_PPOLL)
	struct timespec ts = { tv ? tv->tv_sec : 0, tv ? tv->tv_usec * 1000 : 0 };
	int res = ppoll(pArray, n_fds, tv ? &ts : NULL, NULL);
#else
	int res = poll(pArray, n_fds, tv ? tv->tv_sec * 1000 + tv->tv_usec / 1000 : -1);
#endif
	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
}
Esempio n. 29
0
static void *hook_launch_thread(void *data)
{
	struct hook_thread_arg *arg = data;
	struct ast_variable hook_id = {
		.name = "HOOK_ID",
		.value = arg->hook_id,
	};
	struct ast_variable chan_name_var = {
		.name = "HOOK_CHANNEL",
		.value = arg->chan_name,
		.next = &hook_id,
	};

	ast_pbx_outgoing_exten("Local", NULL, full_exten_name, 60,
			arg->context, arg->exten, 1, NULL, AST_OUTGOING_NO_WAIT,
			NULL, NULL, &chan_name_var, NULL, NULL, 1, NULL);

	hook_thread_arg_destroy(arg);

	return NULL;
}

static struct hook_thread_arg *hook_thread_arg_alloc(struct ast_channel *chan,
		struct hook_state *state)
{
	struct hook_thread_arg *arg;

	if (!(arg = ast_calloc(1, sizeof(*arg)))) {
		return NULL;
	}

	ast_channel_lock(chan);
	arg->chan_name = ast_strdup(ast_channel_name(chan));
	ast_channel_unlock(chan);
	if (!arg->chan_name) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	if (ast_asprintf(&arg->hook_id, "%u", state->hook_id) == -1) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	if (!(arg->context = ast_strdup(state->context))) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	if (!(arg->exten = ast_strdup(state->exten))) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	return arg;
}

static int do_hook(struct ast_channel *chan, struct hook_state *state)
{
	pthread_t t;
	struct hook_thread_arg *arg;
	int res;

	if (!(arg = hook_thread_arg_alloc(chan, state))) {
		return -1;
	}

	/*
	 * We don't want to block normal frame processing *at all* while we kick
	 * this off, so do it in a new thread.
	 */
	res = ast_pthread_create_detached_background(&t, NULL, hook_launch_thread, arg);
	if (res != 0) {
		hook_thread_arg_destroy(arg);
	}

	return res;
}

static int hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan,
		struct ast_frame *frame, enum ast_audiohook_direction direction)
{
	struct hook_state *state = (struct hook_state *) audiohook; /* trust me. */
	struct timeval now;
	int res = 0;

	if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || state->disabled) {
		return 0;
	}

	now = ast_tvnow();
	if (ast_tvdiff_ms(now, state->last_hook) > state->interval * 1000) {
		if ((res = do_hook(chan, state))) {
			const char *name;
			ast_channel_lock(chan);
			name = ast_strdupa(ast_channel_name(chan));
			ast_channel_unlock(chan);
			ast_log(LOG_WARNING, "Failed to run hook on '%s'\n", name);
		}
		state->last_hook = now;
	}

	return res;
}

static struct hook_state *hook_state_alloc(const char *context, const char *exten,
		unsigned int interval, unsigned int hook_id)
{
	struct hook_state *state;

	if (!(state = ast_calloc(1, sizeof(*state)))) {
		return NULL;
	}

	state->context = ast_strdup(context);
	state->exten = ast_strdup(exten);
	state->interval = interval;
	state->hook_id = hook_id;

	ast_audiohook_init(&state->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE,
			AST_MODULE, AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
	state->audiohook.manipulate_callback = hook_callback;

	return state;
}

static int init_hook(struct ast_channel *chan, const char *context, const char *exten,
		unsigned int interval, unsigned int hook_id)
{
	struct hook_state *state;
	struct ast_datastore *datastore;
	char uid[32];

	snprintf(uid, sizeof(uid), "%u", hook_id);

	if (!(datastore = ast_datastore_alloc(&hook_datastore, uid))) {
		return -1;
	}
	ast_module_ref(ast_module_info->self);
	if (!(state = hook_state_alloc(context, exten, interval, hook_id))) {
		ast_datastore_free(datastore);
		return -1;
	}
	datastore->data = state;

	ast_channel_lock(chan);
	ast_channel_datastore_add(chan, datastore);
	ast_audiohook_attach(chan, &state->audiohook);
	ast_channel_unlock(chan);

	return 0;
}

static int hook_on(struct ast_channel *chan, const char *data, unsigned int hook_id)
{
	char *parse = ast_strdupa(S_OR(data, ""));
	AST_DECLARE_APP_ARGS(args,
		AST_APP_ARG(context);
		AST_APP_ARG(exten);
		AST_APP_ARG(interval);
	);
Esempio n. 30
0
/*! 
 * \brief Convert a file from one format to another 
 * \param e CLI entry
 * \param cmd command number
 * \param a list of cli arguments
 * \retval CLI_SUCCESS on success.
 * \retval CLI_SHOWUSAGE or CLI_FAILURE on failure.
*/
static char *handle_cli_file_convert(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
	char *ret = CLI_FAILURE;
	struct ast_filestream *fs_in = NULL, *fs_out = NULL;
	struct ast_frame *f;
	struct timeval start;
	int cost;
	char *file_in = NULL, *file_out = NULL;
	char *name_in, *ext_in, *name_out, *ext_out;

	switch (cmd) {
	case CLI_INIT:
		e->command = "file convert";
		e->usage =
			"Usage: file convert <file_in> <file_out>\n"
			"       Convert from file_in to file_out. If an absolute path\n"
			"       is not given, the default Asterisk sounds directory\n"
			"       will be used.\n\n"
			"       Example:\n"
			"           file convert tt-weasels.gsm tt-weasels.ulaw\n";
		return NULL;
	case CLI_GENERATE:
		return NULL;
	}
	
	/* ugly, can be removed when CLI entries have ast_module pointers */
	ast_module_ref(ast_module_info->self);

	if (a->argc != 4 || ast_strlen_zero(a->argv[2]) || ast_strlen_zero(a->argv[3])) {
		ret = CLI_SHOWUSAGE;
		goto fail_out;	
	}

	file_in = ast_strdupa(a->argv[2]);
	file_out = ast_strdupa(a->argv[3]);

	if (split_ext(file_in, &name_in, &ext_in)) {
		ast_cli(a->fd, "'%s' is an invalid filename!\n", a->argv[2]);
		goto fail_out;
	}
	if (!(fs_in = ast_readfile(name_in, ext_in, NULL, O_RDONLY, 0, 0))) {
		ast_cli(a->fd, "Unable to open input file: %s\n", a->argv[2]);
		goto fail_out;
	}
	
	if (split_ext(file_out, &name_out, &ext_out)) {
		ast_cli(a->fd, "'%s' is an invalid filename!\n", a->argv[3]);
		goto fail_out;
	}
	if (!(fs_out = ast_writefile(name_out, ext_out, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
		ast_cli(a->fd, "Unable to open output file: %s\n", a->argv[3]);
		goto fail_out;
	}

	start = ast_tvnow();
	
	while ((f = ast_readframe(fs_in))) {
		if (ast_writestream(fs_out, f)) {
			ast_frfree(f);
			ast_cli(a->fd, "Failed to convert %s.%s to %s.%s!\n", name_in, ext_in, name_out, ext_out);
			goto fail_out;
		}
		ast_frfree(f);
	}

	cost = ast_tvdiff_ms(ast_tvnow(), start);
	ast_cli(a->fd, "Converted %s.%s to %s.%s in %dms\n", name_in, ext_in, name_out, ext_out, cost);
	ret = CLI_SUCCESS;

fail_out:
	if (fs_out) {
		ast_closestream(fs_out);
		if (ret != CLI_SUCCESS)
			ast_filedelete(name_out, ext_out);
	}

	if (fs_in) 
		ast_closestream(fs_in);

	ast_module_unref(ast_module_info->self);

	return ret;
}