Exemple #1
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;
}
Exemple #2
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);
}
/*!
 * \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;
}
/*
 * 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;
}
Exemple #5
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);
}
Exemple #6
0
/*!
 * \brief Idle function for worker threads
 *
 * The worker waits here until it gets told by the threadpool
 * to wake up.
 *
 * worker is locked before entering this function.
 *
 * \param worker The idle worker
 * \retval 0 The thread is being woken up so that it can conclude.
 * \retval non-zero The thread is being woken up to do more work.
 */
static int worker_idle(struct worker_thread *worker)
{
	struct timeval start = ast_tvnow();
	struct timespec end = {
		.tv_sec = start.tv_sec + worker->options.idle_timeout,
		.tv_nsec = start.tv_usec * 1000,
	};
	while (!worker->wake_up) {
		if (worker->options.idle_timeout <= 0) {
			ast_cond_wait(&worker->cond, &worker->lock);
		} else if (ast_cond_timedwait(&worker->cond, &worker->lock, &end) == ETIMEDOUT) {
			break;
		}
	}

	if (!worker->wake_up) {
		ast_debug(1, "Worker thread idle timeout reached. Dying.\n");
		threadpool_idle_thread_dead(worker->pool, worker);
		worker->state = DEAD;
	}
	worker->wake_up = 0;
	return worker->state == ALIVE;
}

/*!
 * \brief Change a worker's state
 *
 * The threadpool calls into this function in order to let a worker know
 * how it should proceed.
 *
 * \retval -1 failure (state transition not permitted)
 * \retval 0 success
 */
static int worker_set_state(struct worker_thread *worker, enum worker_state state)
{
	SCOPED_MUTEX(lock, &worker->lock);

	switch (state) {
	case ALIVE:
		/* This can occur due to a race condition between being told to go active
		 * and an idle timeout happening.
		 */
		if (worker->state == DEAD) {
			return -1;
		}
		ast_assert(worker->state != ZOMBIE);
		break;
	case DEAD:
		break;
	case ZOMBIE:
		ast_assert(worker->state != DEAD);
		break;
	}

	worker->state = state;
	worker->wake_up = 1;
	ast_cond_signal(&worker->cond);

	return 0;
}
/*! \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);
}
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;
}
static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
{
	struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
	struct timeval tv = ast_tvnow();
	const char *severity_str;

	if (check_event_type(sec->event_type)) {
		return NULL;
	}

	encode_timestamp(&str, &tv);

	severity_str = S_OR(
		ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
		"Unknown"
	);

	return ast_event_new(AST_EVENT_SECURITY,
		AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
		AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
		AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, ast_str_buffer(str),
		AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
		AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
		AST_EVENT_IE_END);
}
Exemple #10
0
/*! \brief add an entry to the video_device table,
 * ignoring duplicate names.
 * The table is a static array of 9 elements.
 * The last_frame field of each entry of the table is initialized to
 * the current time (we need a value inside this field, on stop of the
 * GUI the last_frame value is not changed, to avoid checking if it is 0 we
 * set the initial value on current time) XXX
 *
 * PARAMETERS:
 * \param devices_p = pointer to the table of devices
 * \param device_num_p = pointer to the number of devices
 * \param s = name of the new device to insert
 *
 * returns 0 on success, 1 on error
 */
static int device_table_fill(struct video_device *devices, int *device_num_p, const char *s)
{
	int i;
	struct video_device *p;

	/* with the current implementation, we support a maximum of 9 devices.*/
	if (*device_num_p >= 9)
		return 0; /* more devices will be ignored */
	/* ignore duplicate names */
	for (i = 0; i < *device_num_p; i++) {
		if (!strcmp(devices[i].name, s))
			return 0;
	}
	/* inserts the new video device */
	p = &devices[*device_num_p];
	/* XXX the string is allocated but NEVER deallocated,
	the good time to do that is when the module is unloaded, now we skip the problem */
	p->name = ast_strdup(s);		/* copy the name */
	/* other fields initially NULL */
	p->grabber = NULL;
	p->grabber_data = NULL;
	p->dev_buf = NULL;
	p->last_frame = ast_tvnow();
	p->status_index = 0;
	(*device_num_p)++;			/* one device added */
	return 0;
}
Exemple #11
0
static int pthread_timer_set_rate(void *data, unsigned int rate)
{
	struct pthread_timer *timer = data;

	if (rate > MAX_RATE) {
		ast_log(LOG_ERROR, "res_timing_pthread only supports timers at a "
				"max rate of %d / sec\n", MAX_RATE);
		errno = EINVAL;
		return -1;
	}

	ao2_lock(timer);

	if ((timer->rate = rate)) {
		timer->interval = roundf(1000.0 / ((float) rate));
		timer->start = ast_tvnow();
		timer->state = TIMER_STATE_TICKING;
	} else {
		timer->interval = 0;
		timer->start = ast_tv(0, 0);
		timer->state = TIMER_STATE_IDLE;
	}
	timer->tick_count = 0;

	ao2_unlock(timer);

	return 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;
}
Exemple #13
0
/* set defaults */
static int jb_framedata_init(struct jb_framedata *framedata, struct ast_jb_conf *jb_conf)
{
	int jb_impl_type = DEFAULT_TYPE;
	/* Initialize defaults */
	framedata->timer_fd = -1;
	memcpy(&framedata->jb_conf, jb_conf, sizeof(*jb_conf));

	/* Figure out implementation type from the configuration implementation string */
	if (!ast_strlen_zero(jb_conf->impl)) {
		if (!strcasecmp(jb_conf->impl, "fixed")) {
			jb_impl_type = AST_JB_FIXED;
		} else if (!strcasecmp(jb_conf->impl, "adaptive")) {
			jb_impl_type = AST_JB_ADAPTIVE;
		} else {
			ast_log(LOG_WARNING, "Unknown Jitterbuffer type %s. Failed to create jitterbuffer.\n", jb_conf->impl);
			return -1;
		}
	}

	if (!(framedata->jb_impl = ast_jb_get_impl(jb_impl_type))) {
		return -1;
	}

	if (!(framedata->timer = ast_timer_open())) {
		return -1;
	}

	framedata->timer_fd = ast_timer_fd(framedata->timer);
	framedata->timer_interval = DEFAULT_TIMER_INTERVAL;
	ast_timer_set_rate(framedata->timer, 1000 / framedata->timer_interval);
	framedata->start_tv = ast_tvnow();

	framedata->jb_obj = framedata->jb_impl->create(&framedata->jb_conf);
	return 0;
}
Exemple #14
0
/*!
 * \internal
 * \brief Initialize the start time on a contact status so the round
 *        trip time can be calculated upon a valid response.
 */
static void init_start_time(const struct ast_sip_contact *contact)
{
	struct ast_sip_contact_status *status;
	struct ast_sip_contact_status *update;

	status = ast_res_pjsip_find_or_create_contact_status(contact);
	if (!status) {
		ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s\n",
			contact->uri);
		return;
	}

	update = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(status));
	if (!update) {
		ast_log(LOG_ERROR, "Unable to copy ast_sip_contact_status for contact %s\n",
			contact->uri);
		return;
	}

	update->status = status->status;
	update->last_status = status->last_status;
	update->rtt = status->rtt;
	update->rtt_start = ast_tvnow();

	if (ast_sorcery_update(ast_sip_get_sorcery(), update)) {
		ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
			contact->uri);
	}

	ao2_ref(status, -1);
	ao2_ref(update, -1);
}
void ast_sched_dump(const struct sched_context *con)
{
	/*
	 * Dump the contents of the scheduler to
	 * stderr
	 */
	struct sched *q;
	struct timeval tv = ast_tvnow();
#ifdef SCHED_MAX_CACHE
	ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%d in Q, %d Total, %d Cache)\n", con->schedcnt, con->eventcnt - 1, con->schedccnt);
#else
	ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%d in Q, %d Total)\n", con->schedcnt, con->eventcnt - 1);
#endif

	ast_log(LOG_DEBUG, "=============================================================\n");
	ast_log(LOG_DEBUG, "|ID    Callback          Data              Time  (sec:ms)   |\n");
	ast_log(LOG_DEBUG, "+-----+-----------------+-----------------+-----------------+\n");
 	for (q = con->schedq; q; q = q->next) {
 		struct timeval delta =  ast_tvsub(q->when, tv);

		ast_log(LOG_DEBUG, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n", 
			q->id,
			q->callback,
			q->data,
			delta.tv_sec,
			(long int)delta.tv_usec);
	}
	ast_log(LOG_DEBUG, "=============================================================\n");
	
}
int ast_sched_runq(struct sched_context *con)
{
	/*
	 * Launch all events which need to be run at this time.
	 */
	struct sched *current;
	struct timeval tv;
	int x=0;
	int res;
	DEBUG(ast_log(LOG_DEBUG, "ast_sched_runq()\n"));
		
	ast_mutex_lock(&con->lock);
	tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
	for(;;) {
		if (!con->schedq)
			break;
		
		/* 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.
		 */
		if (SOONER(con->schedq->when, tv)) {
			current = con->schedq;
			con->schedq = con->schedq->next;
			con->schedcnt--;

			/*
			 * At this point, the schedule queue is still intact.  We
			 * have removed the first event and the rest is still there,
			 * so it's permissible for the callback to add new events, but
			 * trying to delete itself won't work because it isn't in
			 * the schedule queue.  If that's what it wants to do, it 
			 * should return 0.
			 */
			
			ast_mutex_unlock(&con->lock);
			res = current->callback(current->data);
			ast_mutex_lock(&con->lock);
			
			if (res) {
			 	/*
				 * If they return non-zero, we should schedule them to be
				 * run again.
				 */
				if (sched_settime(&current->when, current->variable? res : current->resched)) {
					sched_release(con, current);
				} else
					schedule(con, current);
			} else {
				/* No longer needed, so release it */
			 	sched_release(con, current);
			}
			x++;
		} else
			break;
	}
	ast_mutex_unlock(&con->lock);
	return x;
}
/*!
 * \internal
 * \brief Initialize the start time on a contact status so the round
 *        trip time can be calculated upon a valid response.
 */
static void init_start_time(const struct ast_sip_contact *contact)
{
	RAII_VAR(struct ast_sip_contact_status *, status, NULL, ao2_cleanup);
	RAII_VAR(struct ast_sip_contact_status *, update, NULL, ao2_cleanup);

	status = ast_res_pjsip_find_or_create_contact_status(contact);
	if (!status) {
		ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s\n",
			contact->uri);
		return;
	}

	update = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
		ast_sorcery_object_get_id(status));
	if (!update) {
		ast_log(LOG_ERROR, "Unable to copy ast_sip_contact_status for contact %s\n",
			contact->uri);
		return;
	}

	ast_string_field_set(status, uri, contact->uri);
	update->status = status->status;
	update->last_status = status->last_status;
	update->rtt = status->rtt;
	update->rtt_start = ast_tvnow();

	if (ast_sorcery_update(ast_sip_get_sorcery(), update)) {
		ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
			contact->uri);
	}
}
/*!
 * \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;
}
Exemple #19
0
struct stasis_message *stasis_message_create_full(struct stasis_message_type *type, void *data, const struct ast_eid *eid)
{
	struct stasis_message *message;

	if (type == NULL || data == NULL) {
		return NULL;
	}

	message = ao2_alloc(sizeof(*message), stasis_message_dtor);
	if (message == NULL) {
		return NULL;
	}

	message->timestamp = ast_tvnow();
	ao2_ref(type, +1);
	message->type = type;
	ao2_ref(data, +1);
	message->data = data;
	if (eid) {
		message->eid_ptr = &message->eid;
		message->eid = *eid;
	}

	return message;
}
static void evt_gen_failed_acl(void)
{
	struct sockaddr_in sin_local = {
		.sin_family = AF_INET
	};
	struct sockaddr_in sin_remote = {
		.sin_family = AF_INET
	};
	struct timeval session_tv = ast_tvnow();
	struct ast_security_event_failed_acl failed_acl_event = {
		.common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
		.common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
		.common.service    = "TEST",
		.common.module     = AST_MODULE,
		.common.account_id = "Username",
		.common.session_id = "Session123",
		.common.session_tv = &session_tv,
		.common.local_addr = {
			.sin  = &sin_local,
			.transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
		},
		.common.remote_addr = {
			.sin = &sin_remote,
			.transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
		},

		.acl_name   = "TEST_ACL",
Exemple #21
0
static void *do_timing(void *arg)
{
	struct timeval next_wakeup = ast_tvnow();

	while (!timing_thread.stop) {
		struct timespec ts = { 0, };

		ao2_callback(pthread_timers, OBJ_NODATA, run_timer, NULL);

		next_wakeup = ast_tvadd(next_wakeup, ast_tv(0, 5000));

		ts.tv_sec = next_wakeup.tv_sec;
		ts.tv_nsec = next_wakeup.tv_usec * 1000;

		ast_mutex_lock(&timing_thread.lock);
		if (!timing_thread.stop) {
			if (ao2_container_count(pthread_timers)) {
				ast_cond_timedwait(&timing_thread.cond, &timing_thread.lock, &ts);
			} else {
				ast_cond_wait(&timing_thread.cond, &timing_thread.lock);
			}
		}
		ast_mutex_unlock(&timing_thread.lock);
	}

	return 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;
}
static int task_1(void *data)
{
	struct test_data *test = data;

	test->done = 0;
	test->task_start = ast_tvnow();
	test->tid = pthread_self();
	test->is_servant = ast_sip_thread_is_servant();
	usleep(M2U(test->sleep));
	test->task_end = ast_tvnow();

	ast_mutex_lock(&test->lock);
	test->done = 1;
	ast_mutex_unlock(&test->lock);
	ast_cond_signal(&test->cond);

	return test->interval;
}
/*!
 * \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));
}
static int bridge_builtin_set_limits(struct ast_bridge_features *features,
	struct ast_bridge_features_limits *limits,
	enum ast_bridge_hook_remove_flags remove_flags)
{
	RAII_VAR(struct ast_bridge_features_limits *, feature_limits, NULL, ao2_cleanup);

	if (!limits->duration) {
		return -1;
	}

	/* Create limits hook_pvt data. */
	ast_module_ref(ast_module_info->self);
	feature_limits = ao2_alloc_options(sizeof(*feature_limits),
		bridge_features_limits_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
	if (!feature_limits) {
		ast_module_unref(ast_module_info->self);
		return -1;
	}
	if (ast_bridge_features_limits_construct(feature_limits)) {
		return -1;
	}
	bridge_features_limits_copy(feature_limits, limits);
	feature_limits->quitting_time = ast_tvadd(ast_tvnow(),
		ast_samp2tv(feature_limits->duration, 1000));

	/* Install limit hooks. */
	ao2_ref(feature_limits, +1);
	if (ast_bridge_interval_hook(features, AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA,
		feature_limits->duration,
		bridge_features_duration_callback, feature_limits, __ao2_cleanup, remove_flags)) {
		ast_log(LOG_ERROR, "Failed to schedule the duration limiter to the bridge channel.\n");
		ao2_ref(feature_limits, -1);
		return -1;
	}
	if (!ast_strlen_zero(feature_limits->connect_sound)) {
		ao2_ref(feature_limits, +1);
		if (ast_bridge_interval_hook(features, AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA, 1,
			bridge_features_connect_callback, feature_limits, __ao2_cleanup, remove_flags)) {
			ast_log(LOG_WARNING, "Failed to schedule connect sound to the bridge channel.\n");
			ao2_ref(feature_limits, -1);
		}
	}
	if (feature_limits->warning && feature_limits->warning < feature_limits->duration) {
		ao2_ref(feature_limits, +1);
		if (ast_bridge_interval_hook(features, AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA,
			feature_limits->duration - feature_limits->warning,
			bridge_features_warning_callback, feature_limits, __ao2_cleanup, remove_flags)) {
			ast_log(LOG_WARNING, "Failed to schedule warning sound playback to the bridge channel.\n");
			ao2_ref(feature_limits, -1);
		}
	}

	return 0;
}
static int is_timed_out(struct hash_test const *data) {
	struct timeval now = ast_tvnow();
	int val = ast_tvdiff_us(data->deadline, now) < 0;
	if (val) {
		/* tv_usec is suseconds_t, which could be int or long */
		ast_test_status_update(data->test, "Now: %ld.%06ld Deadline: %ld.%06ld\n",
			now.tv_sec, (long)now.tv_usec,
			data->deadline.tv_sec, (long)data->deadline.tv_usec);
	}
	return val;
}
Exemple #27
0
/*
* Write the metadata to the log file
*/
static int write_metadata( FILE *logfile, char *signalling_type, struct ast_channel *chan)
{
	int res = 0;
	struct timeval t;
	struct ast_tm now;
	char *cl;
	char *cn;
	char workstring[80];
	char timestamp[80];
	
	/* Extract the caller ID location */
	ast_copy_string(workstring,
		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
		sizeof(workstring));
	ast_shrink_phone_number(workstring);
	if (ast_strlen_zero(workstring)) {
		cl = "<unknown>";
	} else {
		cl = workstring;
	}
	cn = S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>");

	/* Get the current time */
	t = ast_tvnow();
	ast_localtime(&t, &now, NULL);

	/* Format the time */
	ast_strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);

	res = fprintf(logfile, "\n\n[metadata]\n\n");
	if (res >= 0) {
		res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
	}
	if (res >= 0) {
		res = fprintf(logfile, "CALLINGFROM=%s\n", cl);
	}
	if (res >= 0) {
		res = fprintf(logfile, "CALLERNAME=%s\n", cn);
	}
	if (res >= 0) {
		res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
	}
	if (res >= 0) {
		res = fprintf(logfile, "[events]\n\n");
	}
	if (res < 0) {
		ast_verb(3, "AlarmReceiver: can't write metadata\n");
		ast_debug(1,"AlarmReceiver: can't write metadata\n");
	} else {
		res = 0;
	}

	return res;
}
Exemple #28
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;
}
Exemple #29
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;
}
/*! \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;
}