SavedCondition(switch_memory_pool_t *pool=NULL):
        _pool(pool),
        _can_delete_pool(false)
     {
        if(!_pool)
        {
            switch_core_new_memory_pool(&_pool);
            _can_delete_pool = true;
        }

        switch_thread_cond_create(&_condition, _pool);
        switch_mutex_init(&_mutex, SWITCH_MUTEX_DEFAULT, _pool);
     }
Exemplo n.º 2
0
static switch_status_t timer_init(switch_timer_t *timer)
{
	timer_private_t *private_info;
	int sanity = 0;

	while (globals.STARTED == 0) {
		do_sleep(100000);
		if (++sanity == 300) {
			abort();
		}
	}

	if (globals.RUNNING != 1 || !globals.mutex || timer->interval < 1) {
		return SWITCH_STATUS_FALSE;
	}

	if ((private_info = switch_core_alloc(timer->memory_pool, sizeof(*private_info)))) {
		switch_mutex_lock(globals.mutex);
		if (!TIMER_MATRIX[timer->interval].mutex) {
			switch_mutex_init(&TIMER_MATRIX[timer->interval].mutex, SWITCH_MUTEX_NESTED, module_pool);
			switch_thread_cond_create(&TIMER_MATRIX[timer->interval].cond, module_pool);
		}
		TIMER_MATRIX[timer->interval].count++;
		switch_mutex_unlock(globals.mutex);
		timer->private_info = private_info;
		private_info->start = private_info->reference = TIMER_MATRIX[timer->interval].tick;
		private_info->start -= 2; /* switch_core_timer_init sets samplecount to samples, this makes first next() step once */
		private_info->roll = TIMER_MATRIX[timer->interval].roll;
		private_info->ready = 1;

		if (timer->interval > 0 && timer->interval < MS_PER_TICK) {
			MS_PER_TICK = timer->interval;
			STEP_MS = 1;
			STEP_MIC = 1000;
			TICK_PER_SEC = 10000;
			switch_time_sync();
		}

		switch_mutex_lock(globals.mutex);
		globals.timer_count++;
		if (globals.timer_count == (runtime.tipping_point + 1)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Crossed tipping point of %u, shifting into high-gear.\n", runtime.tipping_point);
		}
		switch_mutex_unlock(globals.mutex);

		return SWITCH_STATUS_SUCCESS;
	}

	return SWITCH_STATUS_MEMERR;
}
Exemplo n.º 3
0
static switch_status_t bind_fetch_agent(switch_xml_section_t section, switch_xml_binding_t **binding) {
    switch_memory_pool_t *pool = NULL;
    ei_xml_agent_t *agent;

    /* create memory pool for this xml search binging (lives for duration of mod_kazoo runtime) */
    if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: They're not people; they're hippies!\n");
        return SWITCH_STATUS_MEMERR;
    }

    /* allocate some memory to store the fetch bindings for this section */
    if (!(agent = switch_core_alloc(pool, sizeof (*agent)))) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: Oh, Jesus tap-dancing Christ!\n");
        return SWITCH_STATUS_MEMERR;
    }

    /* try to bind to the switch */
    if (switch_xml_bind_search_function_ret(fetch_handler, section, agent, binding) != SWITCH_STATUS_SUCCESS) {
        switch_core_destroy_memory_pool(&pool);
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not bind to FreeSWITCH %s XML requests\n"
                          ,xml_section_to_string(section));
        return SWITCH_STATUS_GENERR;
    }

    agent->pool = pool;
    agent->section = section;
    switch_thread_rwlock_create(&agent->lock, pool);
    agent->clients = NULL;
    switch_mutex_init(&agent->current_client_mutex, SWITCH_MUTEX_DEFAULT, pool);
    agent->current_client = NULL;
    switch_mutex_init(&agent->replies_mutex, SWITCH_MUTEX_DEFAULT, pool);
    switch_thread_cond_create(&agent->new_reply, pool);
    agent->replies = NULL;

    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Bound to %s XML requests\n"
                      ,xml_section_to_string(section));

    return SWITCH_STATUS_SUCCESS;
}
Exemplo n.º 4
0
static switch_status_t timerfd_start_interval(interval_timer_t *it, int interval)
{
	struct itimerspec val;
	struct epoll_event e;
	int fd;

	it->users++;
	if (it->users > 1)
		return SWITCH_STATUS_SUCCESS;

	it->tick = 0;
	switch_mutex_init(&it->mutex, SWITCH_MUTEX_NESTED, module_pool);
	switch_thread_cond_create(&it->cond, module_pool);

	fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
	if (fd < 0)
		return SWITCH_STATUS_GENERR;

	val.it_interval.tv_sec = interval / 1000;
	val.it_interval.tv_nsec = (interval % 1000) * 1000000;
	val.it_value.tv_sec = 0;
	val.it_value.tv_nsec = 100000;

	if (timerfd_settime(fd, 0, &val, NULL) < 0) {
		close(fd);
		return SWITCH_STATUS_GENERR;
	}

	e.events = EPOLLIN | EPOLLERR;
	e.data.ptr = it;
	if (epoll_ctl(interval_poll_fd, EPOLL_CTL_ADD, fd, &e) < 0) {
		close(fd);
		return SWITCH_STATUS_GENERR;
	}

	it->fd = fd;
	return SWITCH_STATUS_SUCCESS;
}
Exemplo n.º 5
0
/**
 * Start a new interval timer
 * @param it the timer
 * @param interval the timer interval
 * @return SWITCH_STATUS_SUCCESS if successful
 */
static switch_status_t interval_timer_start(interval_timer_t *it, int interval)
{
	if (globals.shutdown) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "module is shutting down, ignoring request\n");
		return SWITCH_STATUS_GENERR;
	}

	if (it->users <= 0) {
		struct sigevent sigev;
		struct itimerspec val;
		int active_id = -1;
		int i;

		/* find an available id for this timer */
		for (i = 0; i < MAX_ACTIVE_TIMERS && active_id == -1; i++) {
			switch_mutex_lock(globals.active_timers_mutex);
			if(globals.active_interval_timers[i] == NULL) {
				active_id = i;
			}
			switch_mutex_unlock(globals.active_timers_mutex);
		}
		if (active_id == -1) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no more timers can be created!\n");
			return SWITCH_STATUS_GENERR;
		}
		it->active_id = active_id;

		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "starting %d ms timer #%d (%d)\n", it->interval, it->num + 1, it->active_id);

		/* reset timer data */
		it->tick = 0;
		it->users = 0;

		/* reuse mutex/condvar */
		if (it->mutex == NULL) {
			switch_mutex_init(&it->mutex, SWITCH_MUTEX_NESTED, globals.pool);
			switch_thread_cond_create(&it->cond, globals.pool);
		}

		/* create the POSIX timer.  Will send SIG on each tick. */
		memset(&sigev, 0, sizeof(sigev));
		sigev.sigev_notify = SIGEV_SIGNAL;
		sigev.sigev_signo = SIG;
		sigev.sigev_value.sival_int = active_id;
		if (timer_create(CLOCK_MONOTONIC, &sigev, &it->timer) == -1) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create timer: %s\n", strerror(errno));
			return SWITCH_STATUS_GENERR;
		}

		switch_mutex_lock(globals.active_timers_mutex);
		globals.active_interval_timers[it->active_id] = it;
		globals.active_timers_count++;
		switch_mutex_unlock(globals.active_timers_mutex);

		/* start the timer to tick at interval */
		memset(&val, 0, sizeof(val));
		val.it_interval.tv_sec = interval / 1000;
		val.it_interval.tv_nsec = (interval % 1000) * 1000000;
		val.it_value.tv_sec = 0;
		val.it_value.tv_nsec = 100000;
		if (timer_settime(it->timer, 0, &val, NULL) == -1) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to start timer: %s\n", strerror(errno));
			switch_mutex_lock(globals.active_timers_mutex);
			globals.active_interval_timers[it->active_id] = NULL;
			globals.active_timers_count--;
			switch_mutex_unlock(globals.active_timers_mutex);
			return SWITCH_STATUS_GENERR;
		}
	}

	it->users++;
	return SWITCH_STATUS_SUCCESS;
}
Exemplo n.º 6
0
static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *path)
{
	vlc_file_context_t *context;
	libvlc_event_manager_t *mp_event_manager, *m_event_manager;
	
	context = switch_core_alloc(handle->memory_pool, sizeof(*context));
	context->pool = handle->memory_pool;

	context->path = switch_core_strdup(context->pool, path);

	switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0);
	switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
	switch_thread_cond_create(&(context->started), context->pool);

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
		
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for reading\n", path);
		
		/* Determine if this is a url or a path */
		/* TODO: Change this so that it tries local files first, and then if it fails try location. */
		if(! strncmp(context->path, "http", 4)){
			context->m = libvlc_media_new_location(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is http %s\n", context->path);
		} else if (! strncmp(context->path, "mms", 3)){
			context->m = libvlc_media_new_path(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is mms %s\n", context->path);
		} else if (! strncmp(context->path, "/", 1)){
			context->m = libvlc_media_new_path(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is file %s\n", context->path);
		} else {
			context->m = libvlc_media_new_location(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is unknown type %s\n", context->path);
		}

		if ( context->m == NULL ) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error opening %s for reading\n", path);
			return SWITCH_STATUS_GENERR;
		}
		
		context->playing = 0;
		context->err = 0;
		
		context->mp = libvlc_media_player_new_from_media(context->m);
		
		if (!handle->samplerate) {
			handle->samplerate = 16000;
		}

		context->samplerate = handle->samplerate;
		context->channels = handle->channels;

		libvlc_audio_set_format(context->mp, "S16N", context->samplerate, handle->channels);
		
		m_event_manager = libvlc_media_event_manager(context->m);
		libvlc_event_attach(m_event_manager, libvlc_MediaStateChanged, vlc_media_state_callback, (void *) context);

		mp_event_manager = libvlc_media_player_event_manager(context->mp);
		libvlc_event_attach(mp_event_manager, libvlc_MediaPlayerEncounteredError, vlc_mediaplayer_error_callback, (void *) context);
		
		libvlc_audio_set_callbacks(context->mp, vlc_auto_play_callback, NULL,NULL,NULL,NULL, (void *) context);

		libvlc_media_player_play(context->mp);
		
	} else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		const char * opts[10] = {
			vlc_args,
			switch_mprintf("--sout=%s", path)
		};
		int opts_count = 10;
		
		if ( !handle->samplerate)
			handle->samplerate = 16000;
		
		context->samplerate = handle->samplerate;

		opts[2] = switch_mprintf("--imem-get=%ld", vlc_imem_get_callback);
		opts[3] = switch_mprintf("--imem-release=%ld", vlc_imem_release_callback);
		opts[4] = switch_mprintf("--imem-cat=%d", 4);
		opts[5] = "--demux=rawaud";
		opts[6] = "--rawaud-fourcc=s16l";
		opts[7] = switch_mprintf("--rawaud-samplerate=%d", context->samplerate);
		opts[8] = switch_mprintf("--imem-data=%ld", context);
		//opts[9] = "--rawaud-channels=1";

		/* Prepare to write to an output stream. */
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for writing\n", path);

		/* load the vlc engine. */
		context->inst_out = libvlc_new(opts_count, opts);
		
		/* Tell VLC the audio will come from memory, and to use the callbacks to fetch it. */
		context->m = libvlc_media_new_location(context->inst_out, "imem/rawaud://");
		context->mp = libvlc_media_player_new_from_media(context->m);
		context->samples = 0;
		context->pts = 0;
		context->playing = 1;		
		libvlc_media_player_play(context->mp);
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC tried to open %s for unknown reason\n", path);
		return SWITCH_STATUS_GENERR;
	}

	handle->private_info = context;
	
	return SWITCH_STATUS_SUCCESS;
}
int modem_close(modem_t *modem) 
{
	int r = 0;
	switch_status_t was_running = switch_test_flag(modem, MODEM_FLAG_RUNNING);

	switch_clear_flag(modem, MODEM_FLAG_RUNNING);

#ifndef WIN32
	if (modem->master > -1) {
		shutdown(modem->master, 2);
		close(modem->master);
		modem->master = -1;
#else
	if (modem->master) {
		SetEvent(modem->threadAbort);
		CloseHandle(modem->threadAbort);
		CloseHandle(modem->master);
		modem->master = 0;
#endif
		
		r++;
	}

	if (modem->slave > -1) {
		shutdown(modem->slave, 2);
		close(modem->slave);
		modem->slave = -1;
		r++;
	}


   	if (modem->t31_state) {
		t31_free(modem->t31_state);
		modem->t31_state = NULL;
	}

	unlink(modem->devlink);

	if (was_running) {
		switch_mutex_lock(globals.mutex);
		globals.REF_COUNT--;
		switch_mutex_unlock(globals.mutex);
	}

	return r;
}


switch_status_t modem_init(modem_t *modem, modem_control_handler_t control_handler)
{
	switch_status_t status = SWITCH_STATUS_SUCCESS;
#ifdef WIN32
	COMMTIMEOUTS timeouts={0};
#endif
	
	memset(modem, 0, sizeof(*modem));

	modem->master = -1;
	modem->slave = -1;

	/* windows will have to try something like:
	   http://com0com.cvs.sourceforge.net/viewvc/com0com/com0com/ReadMe.txt?revision=RELEASED

	 */

#if USE_OPENPTY
    if (openpty(&modem->master, &modem->slave, NULL, NULL, NULL)) {

	if (modem->master < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to initialize pty\n");
		status = SWITCH_STATUS_FALSE;
		goto end;
    }

	modem->stty = ttyname(modem->slave);
#else
#if WIN32
	modem->slot = 4+globals.NEXT_ID++; /* need work here we start at COM4 for now*/
	snprintf(modem->devlink, sizeof(modem->devlink), "COM%d", modem->slot);

	modem->master = CreateFile(modem->devlink,
	GENERIC_READ | GENERIC_WRITE,
	0,
	0,
	OPEN_EXISTING,
	FILE_FLAG_OVERLAPPED,
	0);
	if(modem->master==INVALID_HANDLE_VALUE) {
		status = SWITCH_STATUS_FALSE;
		if(GetLastError()==ERROR_FILE_NOT_FOUND) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: Serial port does not exist\n");
			goto end;
		}
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: Serial port open error\n");
		goto end;
	}
#elif !defined(HAVE_POSIX_OPENPT)
    modem->master = open("/dev/ptmx", O_RDWR);
#else
    modem->master = posix_openpt(O_RDWR | O_NOCTTY);
#endif

#ifndef WIN32
    if (modem->master < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to initialize UNIX98 master pty\n");
		
    }

    if (grantpt(modem->master) < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to grant access to slave pty\n");
		
    }

    if (unlockpt(modem->master) < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to unlock slave pty\n");
		
    }

    modem->stty = ptsname(modem->master);

    if (modem->stty == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to obtain slave pty filename\n");
		
    }

    modem->slave = open(modem->stty, O_RDWR);

    if (modem->slave < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to open slave pty %s\n", modem->stty);
    }
#endif

#ifdef SOLARIS
    ioctl(modem->slave, I_PUSH, "ptem");  /* push ptem */
    ioctl(modem->slave, I_PUSH, "ldterm");    /* push ldterm*/
#endif
#endif

#ifndef WIN32
	modem->slot = globals.NEXT_ID++;
	snprintf(modem->devlink, sizeof(modem->devlink), "/dev/FS%d", modem->slot);
	
    unlink(modem->devlink);

    if (symlink(modem->stty, modem->devlink)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to create %s symbolic link\n", modem->devlink);
		modem_close(modem);
		status = SWITCH_STATUS_FALSE;
		goto end;
    }

    if (fcntl(modem->master, F_SETFL, fcntl(modem->master, F_GETFL, 0) | O_NONBLOCK)) {
	    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot set up non-blocking read on %s\n", ttyname(modem->master));
	    modem_close(modem);
	    status = SWITCH_STATUS_FALSE;
	    goto end;
    }
#else
	timeouts.ReadIntervalTimeout=50;
	timeouts.ReadTotalTimeoutConstant=50;
	timeouts.ReadTotalTimeoutMultiplier=10;

	timeouts.WriteTotalTimeoutConstant=50;
	timeouts.WriteTotalTimeoutMultiplier=10;

	SetCommMask(modem->master, EV_RXCHAR);

	if(!SetCommTimeouts(modem->master, &timeouts)){
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot set up non-blocking read on %s\n", modem->devlink);
		modem_close(modem);
		status = SWITCH_STATUS_FALSE;
		goto end;
	}
	modem->threadAbort = CreateEvent(NULL, TRUE, FALSE, NULL);
#endif
	
	if (!(modem->t31_state = t31_init(NULL, t31_at_tx_handler, modem, t31_call_control_handler, modem, NULL, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot initialize the T.31 modem\n");
		modem_close(modem);
		status = SWITCH_STATUS_FALSE;
		goto end;
	}

	if (spandsp_globals.modem_verbose) {
		span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message, NULL);
		span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v17_rx.logging, spanfax_log_message, NULL);
		span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v29_rx.logging, spanfax_log_message, NULL);
		span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging, spanfax_log_message, NULL);

		modem->t31_state->logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
		modem->t31_state->audio.modems.fast_modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
		modem->t31_state->audio.modems.fast_modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
		modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
	}

	modem->control_handler = control_handler;
	modem->flags = 0;
	switch_set_flag(modem, MODEM_FLAG_RUNNING);

	switch_mutex_init(&modem->mutex, SWITCH_MUTEX_NESTED, globals.pool);
	switch_mutex_init(&modem->cond_mutex, SWITCH_MUTEX_NESTED, globals.pool);
	switch_thread_cond_create(&modem->cond, globals.pool);

	modem_set_state(modem, MODEM_STATE_INIT);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Modem [%s]->[%s] Ready\n", modem->devlink, modem->stty);

	switch_mutex_lock(globals.mutex);
	globals.REF_COUNT++;
	switch_mutex_unlock(globals.mutex);

end:
	return status;
}

static switch_endpoint_interface_t *modem_endpoint_interface = NULL;

struct private_object {
	switch_mutex_t *mutex;
	switch_core_session_t *session;
	switch_channel_t *channel;
	switch_codec_t read_codec;
	switch_codec_t write_codec;
	switch_frame_t read_frame;
	unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
	switch_timer_t timer;
	modem_t *modem;
	switch_caller_profile_t *caller_profile;
	int dead;
};

typedef struct private_object private_t;

static switch_status_t channel_on_init(switch_core_session_t *session);
static switch_status_t channel_on_hangup(switch_core_session_t *session);
static switch_status_t channel_on_destroy(switch_core_session_t *session);
static switch_status_t channel_on_routing(switch_core_session_t *session);
static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
													switch_caller_profile_t *outbound_profile,
													switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
													switch_call_cause_t *cancel_cause);
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);


/* 
   State methods they get called when the state changes to the specific state 
   returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
   so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
*/
static switch_status_t channel_on_init(switch_core_session_t *session)
{
	switch_channel_t *channel;
	private_t *tech_pvt = NULL;
	int to_ticks = 60, ring_ticks = 10, rt = ring_ticks;
	int rest = 500000;
	
	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);

	if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
#ifndef WIN32
		int tioflags;
#endif
		char call_time[16];
		char call_date[16];
		switch_size_t retsize;
		switch_time_exp_t tm;

		switch_time_exp_lt(&tm, switch_micro_time_now());
		switch_strftime(call_date, &retsize, sizeof(call_date), "%m%d", &tm);
		switch_strftime(call_time, &retsize, sizeof(call_time), "%H%M", &tm);

#ifndef WIN32
		ioctl(tech_pvt->modem->slave, TIOCMGET, &tioflags);
		tioflags |= TIOCM_RI;
		ioctl(tech_pvt->modem->slave, TIOCMSET, &tioflags);
#endif

		at_reset_call_info(&tech_pvt->modem->t31_state->at_state);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "DATE", call_date);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "TIME", call_time);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NAME", tech_pvt->caller_profile->caller_id_name);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NMBR", tech_pvt->caller_profile->caller_id_number);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "ANID", tech_pvt->caller_profile->ani);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "USER", tech_pvt->caller_profile->username);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "CDID", tech_pvt->caller_profile->context);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NDID", tech_pvt->caller_profile->destination_number);

		modem_set_state(tech_pvt->modem, MODEM_STATE_RINGING);
		t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ALERTING);
		
		while(to_ticks > 0 && switch_channel_up(channel) && modem_get_state(tech_pvt->modem) == MODEM_STATE_RINGING) {
			if (--rt <= 0) {
				t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ALERTING);
				rt = ring_ticks;
			}
			
			switch_yield(rest);
			to_ticks--;
		}
		
		if (to_ticks < 1 || modem_get_state(tech_pvt->modem) != MODEM_STATE_ANSWERED) {
			t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_NO_ANSWER);
			switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
		} else {
			t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ANSWERED);
			modem_set_state(tech_pvt->modem, MODEM_STATE_CONNECTED);
			switch_channel_mark_answered(channel);
		}
	}

	switch_channel_set_state(channel, CS_ROUTING);
	
	return SWITCH_STATUS_SUCCESS;
}