static modem_t *acquire_modem(int index)
{
    modem_t *modem = NULL;
	switch_time_t now = switch_time_now();
	int64_t idle_debounce = 2000000;

    switch_mutex_lock(globals.mutex);
    if (index > -1 && index < globals.SOFT_MAX_MODEMS) {
        modem = &globals.MODEM_POOL[index];
    } else {
        int x;

        for(x = 0; x < globals.SOFT_MAX_MODEMS; x++) {
            if (globals.MODEM_POOL[x].state == MODEM_STATE_ONHOOK && (now - globals.MODEM_POOL[x].last_event) > idle_debounce) {
                modem = &globals.MODEM_POOL[x];
                break;
            }
        }
    }

    if (modem && (modem->state != MODEM_STATE_ONHOOK || (now - modem->last_event) < idle_debounce)) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Modem %s In Use!\n", modem->devlink);
        modem = NULL;
    }

    if (modem) {
        modem_set_state(modem, MODEM_STATE_ACQUIRED);
		modem->last_event = switch_time_now();
    } else {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Modems Available!\n");
    }

    switch_mutex_unlock(globals.mutex);

    return modem;
}
Example #2
0
static switch_time_t time_now(int64_t offset)
{
	switch_time_t now;

#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
	if (MONO) {
		struct timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		now = ts.tv_sec * APR_USEC_PER_SEC + (ts.tv_nsec / 1000) + offset;
	} else {
#endif
		now = switch_time_now();

#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
	}
#endif

	return now;
}
Example #3
0
static switch_time_t time_now(int64_t offset)
{
	switch_time_t now;

#if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32)
	if (MONO) {
#ifndef WIN32
		struct timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		now = ts.tv_sec * APR_USEC_PER_SEC + (ts.tv_nsec / 1000) + offset;
#else
		DWORD tick_now;
		DWORD tick_diff;

		tick_now = timeGetTime();
		if (win32_tick_time_since_start != -1) {
			EnterCriticalSection(&timer_section);
			/* just add diff (to make it work more than 50 days). */
			tick_diff = tick_now - win32_last_get_time_tick;
			win32_tick_time_since_start += tick_diff;

			win32_last_get_time_tick = tick_now;
			now = (win32_tick_time_since_start * 1000) + offset;
			LeaveCriticalSection(&timer_section);
		} else {
			/* If someone is calling us before timer is initialized,
			 * return the current tick + offset
			 */
			now = (tick_now * 1000) + offset;
		}
#endif
	} else {
#endif
		now = switch_time_now();

#if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)) || defined(WIN32)
	}
#endif

	return now;
}
Example #4
0
/**
 * Get a URL from the cache, add it if it does not exist
 * @param cache The cache
 * @param session the (optional) session requesting the URL
 * @param url The URL
 * @param download If true, the file will be downloaded if it does not exist in the cache.
 * @param pool The pool to use for allocating the filename
 * @return The filename or NULL if there is an error
 */
static char *url_cache_get(url_cache_t *cache, switch_core_session_t *session, const char *url, int download, switch_memory_pool_t *pool)
{
	char *filename = NULL;
	cached_url_t *u = NULL;
	if (zstr(url)) {
		return NULL;
	}

	url_cache_lock(cache, session);
	u = switch_core_hash_find(cache->map, url);

	if (u && u->status == CACHED_URL_AVAILABLE) {
		if (switch_time_now() >= (u->download_time + u->max_age)) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Cached URL has expired.\n");
			url_cache_remove_soft(cache, session, u); /* will get permanently deleted upon replacement */
			u = NULL;
		} else if (switch_file_exists(u->filename, pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Cached URL file is missing.\n");
			url_cache_remove_soft(cache, session, u); /* will get permanently deleted upon replacement */
			u = NULL;
		}
	}

	if (!u && download) {
		/* URL is not cached, let's add it.*/
		/* Set up URL entry and add to map to prevent simultaneous downloads */
		cache->misses++;
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Cache MISS: size = %zu (%zu MB), hit ratio = %d/%d\n", cache->queue.size, cache->size / 1000000, cache->hits, cache->hits + cache->misses);
		u = cached_url_create(cache, url);
		if (url_cache_add(cache, session, u) != SWITCH_STATUS_SUCCESS) {
			/* This error should never happen */
			url_cache_unlock(cache, session);
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to add URL to cache!\n");
			cached_url_destroy(u, cache->pool);
			return NULL;
		}

		/* download the file */
		url_cache_unlock(cache, session);
		if (http_get(cache, u, session) == SWITCH_STATUS_SUCCESS) {
			/* Got the file, let the waiters know it is available */
			url_cache_lock(cache, session);
			u->status = CACHED_URL_AVAILABLE;
			filename = switch_core_strdup(pool, u->filename);
			cache->size += u->size;
		} else {
			/* Did not get the file, flag for replacement */
			url_cache_lock(cache, session);
			url_cache_remove_soft(cache, session, u);
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Failed to download URL %s\n", url);
			cache->errors++;
		}
	} else if (!u) {
		filename = DOWNLOAD_NEEDED;
	} else {
		/* Wait until file is downloaded */
		if (u->status == CACHED_URL_RX_IN_PROGRESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Waiting for URL %s to be available\n", url);
			u->waiters++;
			url_cache_unlock(cache, session);
			while(u->status == CACHED_URL_RX_IN_PROGRESS) {
				switch_sleep(10 * 1000); /* 10 ms */
			}
			url_cache_lock(cache, session);
			u->waiters--;
		}

		/* grab filename if everything is OK */
		if (u->status == CACHED_URL_AVAILABLE) {
			filename = switch_core_strdup(pool, u->filename);
			cache->hits++;
			u->used = 1;
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Cache HIT: size = %zu (%zu MB), hit ratio = %d/%d\n", cache->queue.size, cache->size / 1000000, cache->hits, cache->hits + cache->misses);
		}
	}
	url_cache_unlock(cache, session);
	return filename;
}
Example #5
0
SWITCH_DECLARE(void) switch_time_sync(void)
{
	runtime.reference = switch_time_now();
	runtime.offset = runtime.reference - time_now(0);
	runtime.reference = time_now(runtime.offset);
}
Example #6
0
SWITCH_DECLARE(switch_time_t) switch_micro_time_now(void)
{
	return (globals.RUNNING == 1 && runtime.timestamp) ? runtime.timestamp : switch_time_now();
}
Example #7
0
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int msec)
{
#ifdef SWITCH_HAVE_PGSQL
	switch_pgsql_result_t *res;
	switch_time_t start;
	switch_time_t ctime;
	unsigned int usec = msec * 1000;
	char *err_str;
	struct pollfd fds[2] = { {0} };
	int poll_res = 0;
	
	if(!handle) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "**BUG** Null handle passed to switch_pgsql_next_result.\n");
		return SWITCH_PGSQL_FAIL;
	}

	/* Try to consume input that might be waiting right away */
	if (PQconsumeInput(handle->con)) {
		/* And check to see if we have a full result ready for reading */
		if (PQisBusy(handle->con)) {

			/* Wait for a result to become available, up to msec milliseconds */
			start = switch_time_now();
			while((ctime = switch_micro_time_now()) - start <= usec) {
				int wait_time = (usec - (ctime - start)) / 1000;
				fds[0].fd = handle->sock;
				fds[0].events |= POLLIN;
				fds[0].events |= POLLERR;

				/* Wait for the PostgreSQL socket to be ready for data reads. */
				if ((poll_res = poll(&fds[0], 1, wait_time)) > -1 ) {
					if (fds[0].revents & POLLIN) {
						/* Then try to consume any input waiting. */
						if (PQconsumeInput(handle->con)) {
							/* And check to see if we have a full result ready for reading */
							if (!PQisBusy(handle->con)) {
								/* If we can pull a full result without blocking, then break this loop */
								break;
							}
						} else {
							/* If we had an error trying to consume input, report it and cancel the query. */
							err_str = switch_pgsql_handle_get_error(handle);
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
							switch_safe_free(err_str);
							switch_pgsql_cancel(handle);
							goto error;
						}
					} else if (fds[0].revents & POLLERR) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql);
						goto error;
					}
				} else {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll failed trying to read PGSQL socket for query (%s)\n", handle->sql);
					goto error;
				}
			}

			/* If we broke the loop above because of a timeout, report that and cancel the query. */
			if (ctime - start > usec) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Query (%s) took too long to complete or database not responding.\n", handle->sql);
				switch_pgsql_cancel(handle);
				goto error;
			}



		}
	} else {
		/* If we had an error trying to consume input, report it and cancel the query. */
		err_str = switch_pgsql_handle_get_error(handle);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
		switch_safe_free(err_str);
		switch_pgsql_cancel(handle);
		goto error;
	}


	/* At this point, we know we can read a full result without blocking. */
	if(!(res = malloc(sizeof(switch_pgsql_result_t)))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Malloc failed!\n");
		goto error;
	}
	memset(res, 0, sizeof(switch_pgsql_result_t));

	
	res->result = PQgetResult(handle->con);
	if (res->result) {
		*result_out = res;
		res->status = PQresultStatus(res->result);
		switch(res->status) {
		case PGRES_TUPLES_OK:
			{
				res->rows = PQntuples(res->result);
				handle->affected_rows = res->rows;
				res->cols = PQnfields(res->result);
			}
			break;
		case PGRES_COPY_OUT:
		case PGRES_COPY_IN:
		case PGRES_COMMAND_OK:
			break;
		case PGRES_EMPTY_QUERY:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_EMPTY_QUERY\n", handle->sql);
		case PGRES_BAD_RESPONSE:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_BAD_RESPONSE\n", handle->sql);
		case PGRES_NONFATAL_ERROR:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_NONFATAL_ERROR\n", handle->sql);
		case PGRES_FATAL_ERROR:
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_FATAL_ERROR\n", handle->sql);
			res->err = PQresultErrorMessage(res->result);
			goto error;
			break;
		}
	} else {
		free(res);
		res = NULL;
		*result_out = NULL;
		goto error;
	}

	return SWITCH_PGSQL_SUCCESS;
 error:
#endif
	return SWITCH_PGSQL_FAIL;
}
static void *SWITCH_THREAD_FUNC modem_thread(switch_thread_t *thread, void *obj)
{
	modem_t *modem = obj;
	int r, avail;
#ifdef WIN32
	DWORD readBytes;
	OVERLAPPED o;
#endif
	char buf[T31_TX_BUF_LEN], tmp[80];

	switch_mutex_lock(globals.mutex);
	modem_init(modem, control_handler);
	globals.THREADCOUNT++;
	switch_mutex_unlock(globals.mutex);

	if (switch_test_flag(modem, MODEM_FLAG_RUNNING)) {
		switch_mutex_lock(modem->cond_mutex);

		while (switch_test_flag(modem, MODEM_FLAG_RUNNING)) {

#ifndef WIN32
			r = modem_wait_sock(modem->master, -1, MODEM_POLL_READ | MODEM_POLL_ERROR);
#else
			r = modem_wait_sock(modem, -1, MODEM_POLL_READ | MODEM_POLL_ERROR);
#endif

			if (!switch_test_flag(modem, MODEM_FLAG_RUNNING)) {
				break;
			}

			if (r < 0 || !(r & MODEM_POLL_READ) || (r & MODEM_POLL_ERROR)) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bad Read on master [%s] [%d]\n", modem->devlink, r);
				break;
			}

			modem->last_event = switch_time_now();

			if (switch_test_flag(modem, MODEM_FLAG_XOFF)) {
				switch_thread_cond_wait(modem->cond, modem->cond_mutex);
				modem->last_event = switch_time_now();
			}

			avail = sizeof(buf) - modem->t31_state->tx.in_bytes + modem->t31_state->tx.out_bytes - 1;

			if (avail == 0) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Buffer Full, retrying....\n");
				switch_yield(10000);
				continue;
			}

#ifndef WIN32		
			r = read(modem->master, buf, avail);
#else
			o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

			/* Initialize the rest of the OVERLAPPED structure to zero. */
			o.Internal = 0;
			o.InternalHigh = 0;
			o.Offset = 0;
			o.OffsetHigh = 0;
			assert(o.hEvent);
			if (!ReadFile(modem->master, buf, avail, &readBytes, &o)) {
				GetOverlappedResult(modem->master,&o,&readBytes,TRUE);
			}
			CloseHandle (o.hEvent);
			r = readBytes;
#endif

			t31_at_rx(modem->t31_state, buf, r);

			memset(tmp, 0, sizeof(tmp));
			if (!strncasecmp(buf, "AT", 2)) {
				int x;
				strncpy(tmp, buf, r);
				for(x = 0; x < r; x++) {
					if(tmp[x] == '\r' || tmp[x] == '\n') {
						tmp[x] = '\0';
					}
				}

				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1,   "Command on %s [%s]\n", modem->devlink, tmp);
			}
		}

		switch_mutex_unlock(modem->cond_mutex);

		if (switch_test_flag(modem, MODEM_FLAG_RUNNING)) {
			modem_close(modem);
		}
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,   "Thread ended for %s\n", modem->devlink);

	switch_mutex_lock(globals.mutex);
	globals.THREADCOUNT--;
	switch_mutex_unlock(globals.mutex);

	return NULL;
}
Example #9
0
switch_status_t mod_xml_radius_add_params(switch_core_session_t *session, switch_event_t *params, rc_handle *handle, VALUE_PAIR **send, switch_xml_t fields) 
{
	switch_xml_t param;
	void *av_value = NULL;
	
	if ( (param = switch_xml_child(fields, "param")) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a param under the fields section\n");
		goto err;		
	}
	
	for (; param; param = param->next) {
		DICT_ATTR *attribute = NULL;
		DICT_VENDOR *vendor = NULL;
		int attr_num = 0, vend_num = 0;
		
		char *var = (char *) switch_xml_attr(param, "name");
		char *vend = (char *) switch_xml_attr(param, "vendor");
		char *variable = (char *) switch_xml_attr(param, "variable");
		char *variable_secondary = (char *) switch_xml_attr(param, "variable_secondary");
		char *val_default = (char *) switch_xml_attr(param, "default");
		char *format = (char *) switch_xml_attr(param, "format");
		char *other_leg = (char *) switch_xml_attr(param, "other_leg");

		attribute = rc_dict_findattr(handle, var);
		
		if ( attribute == NULL ) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Could not locate attribute '%s' in the configured dictionary\n", var);
			goto err;
		}
		
		if ( GLOBAL_DEBUG ) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: dict attr '%s' value '%d' type '%d'\n", 
							  attribute->name, attribute->value, attribute->type);
		}
		
		attr_num = attribute->value;
		
		if ( vend ) {
			vendor = rc_dict_findvend(handle, vend);
			
			if ( vendor == NULL ) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Could not locate vendor '%s' in the configured dictionary %p\n", 
								  vend, vend);
				goto err;
			}			

			if ( GLOBAL_DEBUG ) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: dict vend name '%s' vendorpec '%d'\n", 
								  vendor->vendorname, vendor->vendorpec);
			}
			
			vend_num = vendor->vendorpec;
		} 
		
		if ( var ) {
			if ( session ) {
				switch_channel_t *channel = switch_core_session_get_channel(session);
				
				/*  Accounting only */
				if ( strncmp( var, "h323-setup-time", 15) == 0 ) {
					switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
					switch_time_t time = profile->times->created;
					switch_time_exp_t tm;
					
					if ( !time ) {
						goto end_loop;
					}
					
					switch_time_exp_lt(&tm, time);
					
					if ( GLOBAL_TIME_FORMAT == 1 ) {
						av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
												  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
												  GLOBAL_TIME_ZONE, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
												  tm.tm_mday, tm.tm_year + 1900);
					} else {
						av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
												  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
												  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
												  tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
					}

					if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
						goto err;
					} 
					if ( GLOBAL_DEBUG ) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
					}
				} else if ( strncmp( var, "h323-connect-time", 17) == 0 ) {
					switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
					switch_time_t time = profile->times->answered;
					switch_time_exp_t tm;

					if ( !time ) {
						goto end_loop;
					}
					
					switch_time_exp_lt(&tm, time);

					if ( GLOBAL_TIME_FORMAT == 1 ) {
						av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
												  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
												  GLOBAL_TIME_ZONE, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
												  tm.tm_mday, tm.tm_year + 1900);
					} else {
						av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
												  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
												  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
												  tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
					}

					if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
						goto err;
					} 
					if ( GLOBAL_DEBUG ) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
					}
				} else if ( strncmp( var, "h323-disconnect-time", 20) == 0 ) {
					switch_caller_profile_t *profile = switch_channel_get_caller_profile(channel);
					switch_time_t time = profile->times->hungup;
					switch_time_exp_t tm;

					if ( !time ) {
						if ( variable_secondary != NULL && strncmp(variable_secondary, "now", 3) == 0 ) {
							time = switch_time_now();
						} else {
							goto end_loop;
						}
					}
					
					switch_time_exp_lt(&tm, time);

					if ( GLOBAL_TIME_FORMAT == 1 ) {
						av_value = switch_mprintf("%02u:%02u:%02u.%03u %s %s %s %02u %04u",
												  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000,
												  GLOBAL_TIME_FORMAT, radattrdays[tm.tm_wday], radattrmonths[tm.tm_mon],
												  tm.tm_mday, tm.tm_year + 1900);
					} else {
						av_value = switch_mprintf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
												  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
												  tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec,
												  tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
					}

					if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
						goto err;
					} 
					if ( GLOBAL_DEBUG ) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
					}
				} else if ( strncmp( var, "h323-disconnect-cause", 21) == 0 ) {
					switch_call_cause_t cause = switch_channel_get_cause(channel);
					av_value = switch_mprintf("h323-disconnect-cause=%x", cause);
					if (rc_avpair_add(handle, send, 30, av_value, -1, 9) == NULL) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add disconnect cause \n");
						goto err;
					}			
					
				} else {
					if ( format == NULL ) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing format attribute for %s variable\n", variable);
						goto err;
					}

					if ( attribute->type == 0 ) {
						const char *val = NULL;
						
						if ( other_leg ) {
							val = switch_channel_get_variable_partner(channel, variable);
							if ( val == NULL && variable_secondary != NULL) {
								val = switch_channel_get_variable_partner(channel, variable_secondary);
							}
						} else {
							val = switch_channel_get_variable(channel, variable);
							if ( val == NULL && variable_secondary != NULL) {
								val = switch_channel_get_variable(channel, variable_secondary);
							}
						}
						
						if ( val == NULL && val_default != NULL) {
							av_value = switch_mprintf(format, val_default);							
						} else {
							av_value = switch_mprintf(format, val);
						}
						
						if ( GLOBAL_DEBUG ) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: value: %s\n", (char *) av_value);
						}
				
						if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, 
											  "mod_xml_radius: failed to add option with val '%s' to handle\n", (char *) av_value);
							goto err;
						}			
					} else if ( attribute->type == 1 ) {
						int number = atoi(switch_channel_get_variable(channel, variable));
						
						if (rc_avpair_add(handle, send, attr_num, &number, -1, vend_num) == NULL) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, 
											  "mod_xml_radius: failed to add option with value '%d' to handle\n", number);
							goto err;
						}						
					}
				}			
			} else if ( params ) {
				/* Auth only */
				char *tmp = switch_event_get_header(params, variable);

				if ( GLOBAL_DEBUG ) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: param var '%s' val: %s\n", variable, tmp);
				}
				
				if ( tmp == NULL ) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Unable to locate '%s' on the event\n", variable);
					goto err;					
				}
				
				av_value = switch_mprintf(format, tmp);
				if (rc_avpair_add(handle, send, attr_num, av_value, -1, vend_num) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
					goto err;
				}				
			} else {
				goto err;
			}
		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: all params must have a name attribute\n");
			goto err;
		}

	end_loop:
		if ( av_value != NULL ) {
			free(av_value);
			av_value  = NULL;
		}
	}
	
	return SWITCH_STATUS_SUCCESS;
 err:
	if ( av_value != NULL ) {
		free(av_value);
		av_value  = NULL;
	}
	return SWITCH_STATUS_GENERR;
	
}
static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *frame)
{
	vpx_context_t *context = (vpx_context_t *)codec->private_info;
	int width = 0;
	int height = 0;
	uint32_t dur;
	int64_t pts;
	vpx_enc_frame_flags_t vpx_flags = 0;
	switch_time_t now;
	int err;

	if (frame->flags & SFF_SAME_IMAGE) {
		return consume_partition(context, frame);
	}

	if (context->need_encoder_reset != 0) {
		reset_codec_encoder(codec);
		context->need_encoder_reset = 0;
	}

	if (frame->img->d_h > 1) {
		width = frame->img->d_w;
		height = frame->img->d_h;
	} else {
		width = frame->img->w;
		height = frame->img->h;
	}

	if (context->config.g_w != width || context->config.g_h != height) {
		context->codec_settings.video.width = width;
		context->codec_settings.video.height = height;
		reset_codec_encoder(codec);
		frame->flags |= SFF_PICTURE_RESET;
		context->need_key_frame = 1;
	}

	
	if (!context->encoder_init) {
		init_encoder(codec);
	}

	if (context->change_bandwidth) {
		context->codec_settings.video.bandwidth = context->change_bandwidth;
		context->change_bandwidth = 0;
		init_encoder(codec);
	}

	now = switch_time_now();

	if (context->need_key_frame != 0) {
		// force generate a key frame

		if (!context->last_key_frame || (now - context->last_key_frame) > KEY_FRAME_MIN_FREQ) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "VPX KEYFRAME GENERATED\n");
			vpx_flags |= VPX_EFLAG_FORCE_KF;
			context->need_key_frame = 0;
			context->last_key_frame = now;
		}
	}

	context->framecount++;

	pts = (now - context->start_time) / 1000;

	dur = context->last_ms ? (now - context->last_ms) / 1000 : pts;

	if ((err = vpx_codec_encode(&context->encoder,
						 (vpx_image_t *) frame->img,
						 pts,
						 dur, 
						 vpx_flags,
						 VPX_DL_REALTIME)) != VPX_CODEC_OK) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VPX encode error %d:%s:%s\n",
			err, vpx_codec_error(&context->encoder), vpx_codec_error_detail(&context->encoder));
		frame->datalen = 0;
		return SWITCH_STATUS_FALSE;
	}

	context->enc_iter = NULL;
	context->last_ts = frame->timestamp;
	context->last_ms = now;
		
	return consume_partition(context, frame);
}