Beispiel #1
0
struct stasis_app_control *control_create(struct ast_channel *channel)
{
    RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
    int res;

    control = ao2_alloc(sizeof(*control), control_dtor);
    if (!control) {
        return NULL;
    }

    res = ast_cond_init(&control->wait_cond, NULL);
    if (res != 0) {
        ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
                strerror(errno));
        return NULL;
    }

    control->command_queue = ao2_container_alloc_list(
                                 AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);

    if (!control->command_queue) {
        return NULL;
    }

    control->channel = channel;

    AST_LIST_HEAD_INIT(&control->add_rules);
    AST_LIST_HEAD_INIT(&control->remove_rules);

    ao2_ref(control, +1);
    return control;
}
Beispiel #2
0
struct stasis_subscription *internal_stasis_subscribe(
	struct stasis_topic *topic,
	stasis_subscription_cb callback,
	void *data,
	int needs_mailbox,
	int use_thread_pool)
{
	RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup);

	if (!topic) {
		return NULL;
	}

	/* The ao2 lock is used for join_cond. */
	sub = ao2_t_alloc(sizeof(*sub), subscription_dtor, stasis_topic_name(topic));
	if (!sub) {
		return NULL;
	}
	ast_uuid_generate_str(sub->uniqueid, sizeof(sub->uniqueid));

	if (needs_mailbox) {
		char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];

		/* Create name with seq number appended. */
		ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "sub%c:%s",
			use_thread_pool ? 'p' : 'm',
			stasis_topic_name(topic));

		/*
		 * With a small number of subscribers, a thread-per-sub is
		 * acceptable. For a large number of subscribers, a thread
		 * pool should be used.
		 */
		if (use_thread_pool) {
			sub->mailbox = ast_threadpool_serializer(tps_name, pool);
		} else {
			sub->mailbox = ast_taskprocessor_get(tps_name, TPS_REF_DEFAULT);
		}
		if (!sub->mailbox) {
			return NULL;
		}
		ast_taskprocessor_set_local(sub->mailbox, sub);
		/* Taskprocessor has a reference */
		ao2_ref(sub, +1);
	}

	ao2_ref(topic, +1);
	sub->topic = topic;
	sub->callback = callback;
	sub->data = data;
	ast_cond_init(&sub->join_cond, NULL);

	if (topic_add_subscription(topic, sub) != 0) {
		return NULL;
	}
	send_subscription_subscribe(topic, sub);

	ao2_ref(sub, +1);
	return sub;
}
Beispiel #3
0
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan)
{
	struct ast_datastore *datastore = NULL;
	struct mixmonitor_ds *mixmonitor_ds;

	if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
		return -1;
	}

	ast_mutex_init(&mixmonitor_ds->lock);
	ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);

	if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, NULL))) {
		ast_mutex_destroy(&mixmonitor_ds->lock);
		ast_cond_destroy(&mixmonitor_ds->destruction_condition);
		ast_free(mixmonitor_ds);
		return -1;
	}

	/* No need to lock mixmonitor_ds since this is still operating in the channel's thread */
	mixmonitor_ds->chan = chan;
	mixmonitor_ds->audiohook = &mixmonitor->audiohook;
	datastore->data = mixmonitor_ds;

	ast_channel_lock(chan);
	ast_channel_datastore_add(chan, datastore);
	ast_channel_unlock(chan);

	mixmonitor->mixmonitor_ds = mixmonitor_ds;
	return 0;
}
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id)
{
	struct ast_datastore *datastore = NULL;
	struct mixmonitor_ds *mixmonitor_ds;

	if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
		return -1;
	}

	if (ast_asprintf(datastore_id, "%p", mixmonitor_ds) == -1) {
		ast_log(LOG_ERROR, "Failed to allocate memory for MixMonitor ID.\n");
	}

	ast_mutex_init(&mixmonitor_ds->lock);
	ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);

	if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, *datastore_id))) {
		ast_mutex_destroy(&mixmonitor_ds->lock);
		ast_cond_destroy(&mixmonitor_ds->destruction_condition);
		ast_free(mixmonitor_ds);
		return -1;
	}


	mixmonitor_ds->samp_rate = 8000;
	mixmonitor_ds->audiohook = &mixmonitor->audiohook;
	datastore->data = mixmonitor_ds;

	ast_channel_lock(chan);
	ast_channel_datastore_add(chan, datastore);
	ast_channel_unlock(chan);

	mixmonitor->mixmonitor_ds = mixmonitor_ds;
	return 0;
}
Beispiel #5
0
static struct shutdown_data *shutdown_data_create(int dont_wait)
{
	RAII_VAR(struct shutdown_data *, shutdown_data, NULL, ao2_cleanup);

	shutdown_data = ao2_alloc(sizeof(*shutdown_data), shutdown_data_dtor);
	if (!shutdown_data) {
		return NULL;
	}

	ast_mutex_init(&shutdown_data->lock);
	ast_cond_init(&shutdown_data->in, NULL);
	ast_cond_init(&shutdown_data->out, NULL);
	shutdown_data->task_stop_waiting = dont_wait;
	ao2_ref(shutdown_data, +1);
	return shutdown_data;
}
Beispiel #6
0
/*!
 * \brief Initialize global mock resolver data.
 *
 * This must be called at the beginning of tests that use the mock resolver
 */
static void resolver_data_init(void)
{
	test_resolver_data.resolve_called = 0;
	test_resolver_data.canceled = 0;
	test_resolver_data.resolution_complete = 0;

	ast_mutex_init(&test_resolver_data.lock);
	ast_cond_init(&test_resolver_data.cancel_cond, NULL);
}
Beispiel #7
0
struct ast_serializer_shutdown_group *ast_serializer_shutdown_group_alloc(void)
{
	struct ast_serializer_shutdown_group *shutdown_group;

	shutdown_group = ao2_alloc(sizeof(*shutdown_group), serializer_shutdown_group_dtor);
	if (!shutdown_group) {
		return NULL;
	}
	ast_cond_init(&shutdown_group->cond, NULL);
	return shutdown_group;
}
Beispiel #8
0
struct stasis_subscription *internal_stasis_subscribe(
	struct stasis_topic *topic,
	stasis_subscription_cb callback,
	void *data,
	int needs_mailbox,
	int use_thread_pool)
{
	RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup);

	if (!topic) {
		return NULL;
	}

	/* The ao2 lock is used for join_cond. */
	sub = ao2_t_alloc(sizeof(*sub), subscription_dtor, topic->name);
	if (!sub) {
		return NULL;
	}
	ast_uuid_generate_str(sub->uniqueid, sizeof(sub->uniqueid));

	if (needs_mailbox) {
		/* With a small number of subscribers, a thread-per-sub is
		 * acceptable. For larger number of subscribers, a thread
		 * pool should be used.
		 */
		if (use_thread_pool) {
			sub->mailbox = ast_threadpool_serializer(sub->uniqueid, pool);
		} else {
			sub->mailbox = ast_taskprocessor_get(sub->uniqueid,
				TPS_REF_DEFAULT);
		}
		if (!sub->mailbox) {
			return NULL;
		}
		ast_taskprocessor_set_local(sub->mailbox, sub);
		/* Taskprocessor has a reference */
		ao2_ref(sub, +1);
	}

	ao2_ref(topic, +1);
	sub->topic = topic;
	sub->callback = callback;
	sub->data = data;
	ast_cond_init(&sub->join_cond, NULL);

	if (topic_add_subscription(topic, sub) != 0) {
		return NULL;
	}
	send_subscription_subscribe(topic, sub);

	ao2_ref(sub, +1);
	return sub;
}
Beispiel #9
0
static int init_timing_thread(void)
{
	ast_mutex_init(&timing_thread.lock);
	ast_cond_init(&timing_thread.cond, NULL);

	if (ast_pthread_create_background(&timing_thread.thread, NULL, do_timing, NULL)) {
		ast_log(LOG_ERROR, "Unable to start timing thread.\n");
		return -1;
	}

	return 0;
}
static struct consumer *consumer_create(void)
{
    struct consumer *consumer;

    consumer = ao2_alloc(sizeof(*consumer), consumer_dtor);
    if (!consumer) {
        return NULL;
    }

    ast_cond_init(&consumer->out, NULL);
    consumer_reset(consumer);

    return consumer;
}
Beispiel #11
0
static struct recurring_data *recurring_data_alloc(void)
{
	struct recurring_data *rdata;

	rdata = ao2_alloc(sizeof(*rdata), recurring_data_destructor);
	if (!rdata) {
		return NULL;
	}

	ast_mutex_init(&rdata->lock);
	ast_cond_init(&rdata->cond, NULL);

	return rdata;
}
Beispiel #12
0
/*!
 * \brief Allocate and initialize a new worker thread
 *
 * This will create, initialize, and start the thread.
 *
 * \param pool The threadpool to which the worker will be added
 * \retval NULL Failed to allocate or start the worker thread
 * \retval non-NULL The newly-created worker thread
 */
static struct worker_thread *worker_thread_alloc(struct ast_threadpool *pool)
{
	struct worker_thread *worker = ao2_alloc(sizeof(*worker), worker_thread_destroy);
	if (!worker) {
		return NULL;
	}
	worker->id = ast_atomic_fetchadd_int(&worker_id_counter, 1);
	ast_mutex_init(&worker->lock);
	ast_cond_init(&worker->cond, NULL);
	worker->pool = pool;
	worker->thread = AST_PTHREADT_NULL;
	worker->state = ALIVE;
	worker->options = pool->options;
	return worker;
}
Beispiel #13
0
/*! \brief Create a task_data object */
static struct task_data *task_data_create(void)
{
	struct task_data *task_data =
		ao2_alloc(sizeof(*task_data), task_data_dtor);

	if (!task_data) {
		return NULL;
	}

	ast_cond_init(&task_data->cond, NULL);
	ast_mutex_init(&task_data->lock);
	task_data->task_complete = 0;
	task_data->wait_time = 0;

	return task_data;
}
Beispiel #14
0
/*!
 * \internal \brief Dispatch a message to a subscriber
 * \param sub The subscriber to dispatch to
 * \param message The message to send
 * \param synchronous If non-zero, synchronize on the subscriber receiving
 * the message
 */
static void dispatch_message(struct stasis_subscription *sub,
	struct stasis_message *message,
	int synchronous)
{
	if (!sub->mailbox) {
		/* Dispatch directly */
		subscription_invoke(sub, message);
		return;
	}

	/* Bump the message for the taskprocessor push. This will get de-ref'd
	 * by the task processor callback.
	 */
	ao2_bump(message);
	if (!synchronous) {
		if (ast_taskprocessor_push_local(sub->mailbox, dispatch_exec_async, message)) {
			/* Push failed; ugh. */
			ast_log(LOG_ERROR, "Dropping async dispatch\n");
			ao2_cleanup(message);
		}
	} else {
		struct sync_task_data std;

		ast_mutex_init(&std.lock);
		ast_cond_init(&std.cond, NULL);
		std.complete = 0;
		std.task_data = message;

		if (ast_taskprocessor_push_local(sub->mailbox, dispatch_exec_sync, &std)) {
			/* Push failed; ugh. */
			ast_log(LOG_ERROR, "Dropping sync dispatch\n");
			ao2_cleanup(message);
			ast_mutex_destroy(&std.lock);
			ast_cond_destroy(&std.cond);
			return;
		}

		ast_mutex_lock(&std.lock);
		while (!std.complete) {
			ast_cond_wait(&std.cond, &std.lock);
		}
		ast_mutex_unlock(&std.lock);

		ast_mutex_destroy(&std.lock);
		ast_cond_destroy(&std.cond);
	}
}
Beispiel #15
0
int astdb_init(void)
{
	if (db_init()) {
		return -1;
	}

	ast_cond_init(&dbcond, NULL);
	if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
		return -1;
	}

	ast_register_atexit(astdb_atexit);
	ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
	ast_manager_register_xml_core("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
	ast_manager_register_xml_core("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
	ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
	ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
	return 0;
}
Beispiel #16
0
static struct stasis_message *caching_guarantee_create(void)
{
	RAII_VAR(struct caching_guarantee *, guarantee, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);

	if (!(guarantee = ao2_alloc(sizeof(*guarantee), caching_guarantee_dtor))) {
		return NULL;
	}

	ast_mutex_init(&guarantee->lock);
	ast_cond_init(&guarantee->cond, NULL);

	if (!(msg = stasis_message_create(cache_guarantee_type(), guarantee))) {
		return NULL;
	}

	ao2_ref(msg, +1);
	return msg;
}
Beispiel #17
0
int ast_sem_init(struct ast_sem *sem, int pshared, unsigned int value)
{
	if (pshared) {
		/* Don't need it... yet */
		errno = ENOSYS;
		return -1;
	}

	/* Since value is unsigned, this will also catch attempts to init with
	 * a negative value */
	if (value > AST_SEM_VALUE_MAX) {
		errno = EINVAL;
		return -1;
	}

	sem->count = value;
	sem->waiters = 0;
	ast_mutex_init(&sem->mutex);
	ast_cond_init(&sem->cond, NULL);
	return 0;
}
Beispiel #18
0
int astdb_init(void)
{
	ast_cond_init(&dbcond, NULL);
	if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
		return -1;
	}

	ast_mutex_lock(&dblock);
	/* Ignore check_return warning from Coverity for dbinit below */
	dbinit();
	ast_mutex_unlock(&dblock);

	ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
	ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
	ast_manager_register_xml("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
	ast_manager_register_xml("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
	ast_manager_register_xml("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);

	ast_register_atexit(astdb_shutdown);
	return 0;
}
Beispiel #19
0
static struct timespec make_deadline(int timeout_millis)
{
	struct timeval start = ast_tvnow();
	struct timeval delta = {
		.tv_sec = timeout_millis / 1000,
		.tv_usec = (timeout_millis % 1000) * 1000,
	};
	struct timeval deadline_tv = ast_tvadd(start, delta);
	struct timespec deadline = {
		.tv_sec = deadline_tv.tv_sec,
		.tv_nsec = 1000 * deadline_tv.tv_usec,
	};

	return deadline;
}

struct stasis_message_sink *stasis_message_sink_create(void)
{
	RAII_VAR(struct stasis_message_sink *, sink, NULL, ao2_cleanup);

	sink = ao2_alloc(sizeof(*sink), stasis_message_sink_dtor);
	if (!sink) {
		return NULL;
	}
	ast_mutex_init(&sink->lock);
	ast_cond_init(&sink->cond, NULL);
	sink->max_messages = 4;
	sink->messages =
		ast_malloc(sizeof(*sink->messages) * sink->max_messages);
	if (!sink->messages) {
		return NULL;
	}
	ao2_ref(sink, +1);
	return sink;
}

/*!
 * \brief Implementation of the stasis_message_sink_cb() callback.
 *
 * Why the roundabout way of exposing this via stasis_message_sink_cb()? Well,
 * it has to do with how we load modules.
 *
 * Modules have their own metadata compiled into them in the module info block
 * at the end of the file.  This includes dependency information in the
 * \c nonoptreq field.
 *
 * Asterisk loads the module, inspects the field, then loads any needed
 * dependencies. This works because Asterisk passes \c RTLD_LAZY to the initial
 * dlopen(), which defers binding function references until they are called.
 *
 * But when you take the address of a function, that function needs to be
 * available at load time. So if some module used the address of
 * message_sink_cb() directly, and \c res_stasis_test.so wasn't loaded yet, then
 * that module would fail to load.
 *
 * The stasis_message_sink_cb() function gives us a layer of indirection so that
 * the initial lazy binding will still work as expected.
 */
static void message_sink_cb(void *data, struct stasis_subscription *sub,
	struct stasis_message *message)
{
	struct stasis_message_sink *sink = data;

	SCOPED_MUTEX(lock, &sink->lock);

	if (stasis_subscription_final_message(sub, message)) {
		sink->is_done = 1;
		ast_cond_signal(&sink->cond);
		return;
	}

	if (stasis_subscription_change_type() == stasis_message_type(message)) {
		/* Ignore subscription changes */
		return;
	}

	if (sink->num_messages == sink->max_messages) {
		size_t new_max_messages = sink->max_messages * 2;
		struct stasis_message **new_messages = ast_realloc(
			sink->messages,
			sizeof(*new_messages) * new_max_messages);
		if (!new_messages) {
			return;
		}
		sink->max_messages = new_max_messages;
		sink->messages = new_messages;
	}

	ao2_ref(message, +1);
	sink->messages[sink->num_messages++] = message;
	ast_cond_signal(&sink->cond);
}

stasis_subscription_cb stasis_message_sink_cb(void)
{
	return message_sink_cb;
}


int stasis_message_sink_wait_for_count(struct stasis_message_sink *sink,
	int num_messages, int timeout_millis)
{
	struct timespec deadline = make_deadline(timeout_millis);

	SCOPED_MUTEX(lock, &sink->lock);
	while (sink->num_messages < num_messages) {
		int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline);

		if (r == ETIMEDOUT) {
			break;
		}
		if (r != 0) {
			ast_log(LOG_ERROR, "Unexpected condition error: %s\n",
				strerror(r));
			break;
		}
	}
	return sink->num_messages;
}

int stasis_message_sink_should_stay(struct stasis_message_sink *sink,
	int num_messages, int timeout_millis)
{
	struct timespec deadline = make_deadline(timeout_millis);

	SCOPED_MUTEX(lock, &sink->lock);
	while (sink->num_messages == num_messages) {
		int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline);

		if (r == ETIMEDOUT) {
			break;
		}
		if (r != 0) {
			ast_log(LOG_ERROR, "Unexpected condition error: %s\n",
				strerror(r));
			break;
		}
	}
	return sink->num_messages;
}

int stasis_message_sink_wait_for(struct stasis_message_sink *sink, int start,
	stasis_wait_cb cmp_cb, const void *data, int timeout_millis)
{
	struct timespec deadline = make_deadline(timeout_millis);

	SCOPED_MUTEX(lock, &sink->lock);

	/* wait for the start */
	while (sink->num_messages < start + 1) {
		int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline);

		if (r == ETIMEDOUT) {
			/* Timed out waiting for the start */
			return -1;
		}
		if (r != 0) {
			ast_log(LOG_ERROR, "Unexpected condition error: %s\n",
				strerror(r));
			return -2;
		}
	}


	while (!cmp_cb(sink->messages[start], data)) {
		++start;

		while (sink->num_messages < start + 1) {
			int r = ast_cond_timedwait(&sink->cond,
				&sink->lock, &deadline);

			if (r == ETIMEDOUT) {
				return -1;
			}
			if (r != 0) {
				ast_log(LOG_ERROR,
					"Unexpected condition error: %s\n",
					strerror(r));
				return -2;
			}
		}
	}

	return start;
}

struct stasis_message *stasis_test_message_create(void)
{
	RAII_VAR(void *, data, NULL, ao2_cleanup);

	if (!stasis_test_message_type()) {
		return NULL;
	}

	/* We just need the unique pointer; don't care what's in it */
	data = ao2_alloc(1, NULL);
	if (!data) {
		return NULL;
	}

	return stasis_message_create(stasis_test_message_type(), data);
}
static int scheduler(struct ast_test *test, int serialized)
{
	RAII_VAR(struct ast_taskprocessor *, tp1, NULL, ast_taskprocessor_unreference);
	RAII_VAR(struct test_data *, test_data1, ao2_alloc(sizeof(*test_data1), data_cleanup), ao2_cleanup);
	RAII_VAR(struct test_data *, test_data2, ao2_alloc(sizeof(*test_data2), data_cleanup), ao2_cleanup);
	RAII_VAR(struct ast_sip_sched_task *, task1, NULL, ao2_cleanup);
	RAII_VAR(struct ast_sip_sched_task *, task2, NULL, ao2_cleanup);
	int duration;
	int delay;
	struct timeval task1_start;

	ast_test_validate(test, test_data1 != NULL);
	ast_test_validate(test, test_data2 != NULL);

	test_data1->test = test;
	test_data1->test_start = ast_tvnow();
	test_data1->interval = 2000;
	test_data1->sleep = 1000;
	ast_mutex_init(&test_data1->lock);
	ast_cond_init(&test_data1->cond, NULL);

	test_data2->test = test;
	test_data2->test_start = ast_tvnow();
	test_data2->interval = 2000;
	test_data2->sleep = 1000;
	ast_mutex_init(&test_data2->lock);
	ast_cond_init(&test_data2->cond, NULL);

	if (serialized) {
		ast_test_status_update(test, "This test will take about %3.1f seconds\n",
			(test_data1->interval + test_data1->sleep + (MAX(test_data1->interval - test_data2->interval, 0)) + test_data2->sleep) / 1000.0);
		tp1 = ast_sip_create_serializer("test-scheduler-serializer");
		ast_test_validate(test, (tp1 != NULL));
	} else {
		ast_test_status_update(test, "This test will take about %3.1f seconds\n",
			((MAX(test_data1->interval, test_data2->interval) + MAX(test_data1->sleep, test_data2->sleep)) / 1000.0));
	}

	task1 = ast_sip_schedule_task(tp1, test_data1->interval, task_1, NULL, test_data1, AST_SIP_SCHED_TASK_FIXED);
	ast_test_validate(test, task1 != NULL);

	task2 = ast_sip_schedule_task(tp1, test_data2->interval, task_1, NULL, test_data2, AST_SIP_SCHED_TASK_FIXED);
	ast_test_validate(test, task2 != NULL);

	waitfor(test_data1);
	ast_sip_sched_task_cancel(task1);
	ast_test_validate(test, test_data1->is_servant);

	duration = ast_tvdiff_ms(test_data1->task_end, test_data1->test_start);
	ast_test_validate(test, (duration > ((test_data1->interval + test_data1->sleep) * 0.9))
		&& (duration < ((test_data1->interval + test_data1->sleep) * 1.1)));

	ast_sip_sched_task_get_times(task1, NULL, &task1_start, NULL);
	delay = ast_tvdiff_ms(task1_start, test_data1->test_start);
	ast_test_validate(test, (delay > (test_data1->interval * 0.9)
		&& (delay < (test_data1->interval * 1.1))));

	waitfor(test_data2);
	ast_sip_sched_task_cancel(task2);
	ast_test_validate(test, test_data2->is_servant);

	if (serialized) {
		ast_test_validate(test, test_data1->tid == test_data2->tid);
		ast_test_validate(test, ast_tvdiff_ms(test_data2->task_start, test_data1->task_end) >= 0);
	} else {
		ast_test_validate(test, test_data1->tid != test_data2->tid);
	}

	return AST_TEST_PASS;
}
Beispiel #21
0
OOH323CallData* ooCreateCall(char* type, char*callToken)
{
   OOH323CallData *call=NULL;
   OOCTXT *pctxt=NULL;
   OOCTXT *msgctxt=NULL;

   pctxt = newContext();
   if(!pctxt)
   {
      OOTRACEERR1("ERROR:Failed to create OOCTXT for new call\n");
      return NULL;
   }
   msgctxt = newContext();
   if(!msgctxt)
   {
      OOTRACEERR1("ERROR:Failed to create OOCTXT for new call\n");
      return NULL;
   }
   ast_mutex_lock(&newCallLock);
   /* call = (OOH323CallData*)memAlloc(&gH323ep.ctxt, sizeof(OOH323CallData));  */
   call = (OOH323CallData*)memAlloc(pctxt, sizeof(OOH323CallData));
   ast_mutex_unlock(&newCallLock);
   if(!call)
   {
      OOTRACEERR1("ERROR:Memory - ooCreateCall - call\n");
      return NULL;
   } 
   memset(call, 0, sizeof(OOH323CallData));
   ast_cond_init(&call->gkWait, NULL);
   ast_mutex_init(&call->GkLock);
   ast_mutex_init(&call->Lock);
   call->pctxt = pctxt;
   call->msgctxt = msgctxt;
   call->callMode = gH323ep.callMode;
   sprintf(call->callToken, "%s", callToken);
   sprintf(call->callType, "%s", type);
   call->callReference = 0;
   if(gH323ep.callerid) {
     strncpy(call->ourCallerId, gH323ep.callerid, sizeof(call->ourCallerId)-1);
     call->ourCallerId[sizeof(call->ourCallerId)-1] = '\0';
   }
   else {
      call->ourCallerId[0] = '\0';
   }
   
   memset(&call->callIdentifier, 0, sizeof(H225CallIdentifier));
   memset(&call->confIdentifier, 0, sizeof(H225ConferenceIdentifier));

   call->flags = 0;
   if (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING))
      OO_SETFLAG (call->flags, OO_M_TUNNELING);

   if(gH323ep.gkClient)
   {
      if(OO_TESTFLAG(gH323ep.flags, OO_M_GKROUTED))
      {
         OO_SETFLAG(call->flags, OO_M_GKROUTED);
      }
   }

   if (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART))
      OO_SETFLAG (call->flags, OO_M_FASTSTART);

   if (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN))
      OO_SETFLAG (call->flags, OO_M_MEDIAWAITFORCONN);

   call->fsSent = FALSE;

// May 20090713. Fix it for Video session

   OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
   
   call->callState = OO_CALL_CREATED;
   call->callEndReason = OO_REASON_UNKNOWN;
   call->pCallFwdData = NULL;

   if(!strcmp(call->callType, "incoming"))
   {
      call->callingPartyNumber = NULL;
   }
   else{      
      if(ooUtilsIsStrEmpty(gH323ep.callingPartyNumber))
      {
         call->callingPartyNumber = NULL;
      }
      else{
         call->callingPartyNumber = (char*) memAlloc(call->pctxt, 
                                         strlen(gH323ep.callingPartyNumber)+1);
         if(call->callingPartyNumber)
         {
            strcpy(call->callingPartyNumber, gH323ep.callingPartyNumber);
         }
         else{
            OOTRACEERR3("Error:Memory - ooCreateCall - callingPartyNumber"
                        ".(%s, %s)\n", call->callType, call->callToken);
            freeContext(pctxt);
            return NULL;
         }
      }
   }

   call->calledPartyNumber = NULL;
   call->h245ConnectionAttempts = 0;
   call->h245SessionState = OO_H245SESSION_IDLE;
   call->dtmfmode = gH323ep.dtmfmode;
   call->mediaInfo = NULL;
   strcpy(call->localIP, gH323ep.signallingIP);
   call->pH225Channel = NULL;
   call->pH245Channel = NULL;
   call->h245listener = NULL;
   call->h245listenport = NULL;
   call->remoteIP[0] = '\0';
   call->remotePort = 0;
   call->remoteH245Port = 0;
   call->remoteDisplayName = NULL;
   call->remoteAliases = NULL;
   call->ourAliases = NULL;
   call->masterSlaveState = OO_MasterSlave_Idle;
   call->statusDeterminationNumber = 0;
   call->localTermCapState = OO_LocalTermCapExchange_Idle;
   call->remoteTermCapState = OO_RemoteTermCapExchange_Idle; 
   call->ourCaps = NULL;
   call->remoteCaps = NULL;
   call->jointCaps = NULL;
   dListInit(&call->remoteFastStartOLCs);
   call->remoteTermCapSeqNo =0;
   call->localTermCapSeqNo = 0;
   memcpy(&call->capPrefs, &gH323ep.capPrefs, sizeof(OOCapPrefs));    
   call->logicalChans = NULL;
   call->noOfLogicalChannels = 0;
   call->logicalChanNoBase = 1001;
   call->logicalChanNoMax = 1100;
   call->logicalChanNoCur = 1001;
   call->nextSessionID = 4; /* 1,2,3 are reserved for audio, video and data */
   dListInit(&call->timerList);
   call->msdRetries = 0;
   call->pFastStartRes = NULL;
   call->usrData = NULL;
   OOTRACEINFO3("Created a new call (%s, %s)\n", call->callType, 
                 call->callToken);
   /* Add new call to calllist */
   ooAddCallToList (call);
   if(gH323ep.h323Callbacks.onNewCallCreated)
     gH323ep.h323Callbacks.onNewCallCreated(call);
   return call;
}