Skip to content
Snippets Groups Projects
channel.c 74.8 KiB
Newer Older
Mark Spencer's avatar
Mark Spencer committed
 * Asterisk -- A telephony toolkit for Linux.
 *
 * Channel Management
 * 
Mark Spencer's avatar
Mark Spencer committed
 * Copyright (C) 1999, Mark Spencer
Mark Spencer's avatar
Mark Spencer committed
 *
 * Mark Spencer <markster@linux-support.net>
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
Mark Spencer's avatar
Mark Spencer committed
#include <unistd.h>
Mark Spencer's avatar
Mark Spencer committed
#include <math.h>			/* For PI */
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/pbx.h>
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/frame.h>
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/sched.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/logger.h>
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/file.h>
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/translate.h>
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/manager.h>
#include <asterisk/chanvars.h>
#include <asterisk/linkedlists.h>
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/indications.h>
#include <asterisk/monitor.h>
Martin Pycko's avatar
 
Martin Pycko committed
#include <asterisk/causes.h>
#include <asterisk/utils.h>
#ifdef ZAPTEL_OPTIMIZATIONS
#include <sys/ioctl.h>
#ifdef __linux__
#include <linux/zaptel.h>
#else
#include <zaptel.h>
#endif /* __linux__ */
#error "You need newer zaptel!  Please cvs update zaptel"
Martin Pycko's avatar
 
Martin Pycko committed
/* uncomment if you have problems with 'monitoring' synchronized files */
#if 0
#define MONITOR_CONSTANT_DELAY
#define MONITOR_DELAY	150 * 8		/* 150 ms of MONITORING DELAY */
#endif
Mark Spencer's avatar
Mark Spencer committed
static int shutting_down = 0;
Mark Spencer's avatar
Mark Spencer committed
static int uniqueint = 0;
Mark Spencer's avatar
Mark Spencer committed
/* XXX Lock appropriately in more functions XXX */
Mark Spencer's avatar
Mark Spencer committed
struct chanlist {
	char type[80];
	char description[80];
	int capabilities;
	struct ast_channel * (*requester)(char *type, int format, void *data);
	int (*devicestate)(void *data);
Mark Spencer's avatar
Mark Spencer committed
	struct chanlist *next;
} *backends = NULL;
Mark Spencer's avatar
Mark Spencer committed
struct ast_channel *channels = NULL;

Mark Spencer's avatar
Mark Spencer committed
/* Protect the channel list (highly unlikely that two things would change
   it at the same time, but still! */
   
AST_MUTEX_DEFINE_STATIC(chlock);
Mark Spencer's avatar
Mark Spencer committed
int ast_check_hangup(struct ast_channel *chan)
{
time_t	myt;

	  /* if soft hangup flag, return true */
Mark Spencer's avatar
Mark Spencer committed
	if (chan->_softhangup) return 1;
	  /* if no private structure, return true */
	if (!chan->pvt->pvt) return 1;
Mark Spencer's avatar
Mark Spencer committed
	  /* if no hangup scheduled, just return here */
	if (!chan->whentohangup) return 0;
	time(&myt); /* get current time */
	  /* return, if not yet */
	if (chan->whentohangup > myt) return 0;
Mark Spencer's avatar
Mark Spencer committed
	chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
Mark Spencer's avatar
Mark Spencer committed
	return 1;
}

static int ast_check_hangup_locked(struct ast_channel *chan)
{
	int res;
	res = ast_check_hangup(chan);
Mark Spencer's avatar
Mark Spencer committed
void ast_begin_shutdown(int hangup)
{
	struct ast_channel *c;
	shutting_down = 1;
	if (hangup) {
Mark Spencer's avatar
Mark Spencer committed
		c = channels;
		while(c) {
Mark Spencer's avatar
Mark Spencer committed
			ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
Mark Spencer's avatar
Mark Spencer committed
			c = c->next;
		}
Mark Spencer's avatar
Mark Spencer committed
	}
}

int ast_active_channels(void)
{
	struct ast_channel *c;
	int cnt = 0;
Mark Spencer's avatar
Mark Spencer committed
	c = channels;
	while(c) {
		cnt++;
		c = c->next;
	}
Mark Spencer's avatar
Mark Spencer committed
	return cnt;
}

void ast_cancel_shutdown(void)
{
	shutting_down = 0;
}

int ast_shutting_down(void)
{
	return shutting_down;
}

Mark Spencer's avatar
Mark Spencer committed
void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
{
James Golovich's avatar
James Golovich committed
	time_t	myt;
Mark Spencer's avatar
Mark Spencer committed

	time(&myt);
James Golovich's avatar
James Golovich committed
	if (offset)
		chan->whentohangup = myt + offset;
	else
		chan->whentohangup = 0;
Mark Spencer's avatar
Mark Spencer committed
int ast_channel_register(char *type, char *description, int capabilities,
		struct ast_channel *(*requester)(char *type, int format, void *data))
James Golovich's avatar
James Golovich committed
	return ast_channel_register_ex(type, description, capabilities, requester, NULL);
}

int ast_channel_register_ex(char *type, char *description, int capabilities,
		struct ast_channel *(*requester)(char *type, int format, void *data),
		int (*devicestate)(void *data))
Mark Spencer's avatar
Mark Spencer committed
{
	struct chanlist *chan, *last=NULL;
Mark Spencer's avatar
Mark Spencer committed
		ast_log(LOG_WARNING, "Unable to lock channel list\n");
		return -1;
	}
	chan = backends;
James Golovich's avatar
James Golovich committed
	while (chan) {
Mark Spencer's avatar
Mark Spencer committed
		if (!strcasecmp(type, chan->type)) {
			ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
Mark Spencer's avatar
Mark Spencer committed
			return -1;
		}
		last = chan;
		chan = chan->next;
	}
	chan = malloc(sizeof(struct chanlist));
	if (!chan) {
		ast_log(LOG_WARNING, "Out of memory\n");
Mark Spencer's avatar
Mark Spencer committed
		return -1;
	}
Mark Spencer's avatar
Mark Spencer committed
	strncpy(chan->type, type, sizeof(chan->type)-1);
	strncpy(chan->description, description, sizeof(chan->description)-1);
Mark Spencer's avatar
Mark Spencer committed
	chan->capabilities = capabilities;
	chan->requester = requester;
	chan->devicestate = devicestate;
Mark Spencer's avatar
Mark Spencer committed
	chan->next = NULL;
	if (last)
		last->next = chan;
	else
		backends = chan;
	if (option_debug)
		ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
	else if (option_verbose > 1)
		ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
Loading
Loading full blame...