Version 0.1.3 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@207 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2000-03-26 01:59:06 +00:00
parent c44f9f168a
commit 5e0525cc65
7 changed files with 365 additions and 12 deletions

View File

@@ -18,6 +18,7 @@
#include <asterisk/options.h> #include <asterisk/options.h>
#include <asterisk/module.h> #include <asterisk/module.h>
#include <asterisk/translate.h> #include <asterisk/translate.h>
#include <asterisk/say.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
@@ -25,14 +26,31 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/signal.h>
#include <pthread.h> #include <pthread.h>
static char *tdesc = "Dialing/Parking Application";
static char *tdesc = "Trivial Dialing Application";
static char *app = "Dial"; static char *app = "Dial";
static char *parkedcall = "ParkedCall";
/* No more than 90 seconds parked before you do something with them */
static int parkingtime = 90000;
/* Context for which parking is made accessible */
static char parking_con[AST_MAX_EXTENSION] = "default";
/* Extension you type to park the call */
static char parking_ext[AST_MAX_EXTENSION] = "700";
/* First available extension for parking */
static int parking_start = 701;
/* Last available extension for parking */
static int parking_stop = 750;
/* We define a customer "local user" structure because we /* We define a customer "local user" structure because we
use it not only for keeping track of what is in use but use it not only for keeping track of what is in use but
also for keeping track of who we're dialing. */ also for keeping track of who we're dialing. */
@@ -44,8 +62,164 @@ struct localuser {
struct localuser *next; struct localuser *next;
}; };
struct parkeduser {
struct ast_channel *chan;
struct timeval start;
int parkingnum;
/* Where to go if our parking time expires */
char context[AST_MAX_EXTENSION];
char exten[AST_MAX_EXTENSION];
int priority;
struct parkeduser *next;
};
static struct parkeduser *parkinglot;
static pthread_mutex_t parking_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t parking_thread;
LOCAL_USER_DECL; LOCAL_USER_DECL;
static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect);
static int park_call(struct ast_channel *chan, struct ast_channel *peer)
{
/* We put the user in the parking list, then wake up the parking thread to be sure it looks
after these channels too */
struct parkeduser *pu, *cur;
int x;
pu = malloc(sizeof(struct parkeduser));
if (pu) {
pthread_mutex_lock(&parking_lock);
for (x=parking_start;x<=parking_stop;x++) {
cur = parkinglot;
while(cur) {
if (cur->parkingnum == x)
break;
cur = cur->next;
}
if (!cur)
break;
}
if (x <= parking_stop) {
pu->chan = chan;
gettimeofday(&pu->start, NULL);
pu->parkingnum = x;
/* Remember what had been dialed, so that if the parking
expires, we try to come back to the same place */
strncpy(pu->context, chan->context, sizeof(pu->context));
strncpy(pu->exten, chan->exten, sizeof(pu->exten));
pu->priority = chan->priority;
pu->next = parkinglot;
parkinglot = pu;
pthread_mutex_unlock(&parking_lock);
/* Wake up the (presumably select()ing) thread */
pthread_kill(parking_thread, SIGURG);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d\n", pu->chan->name, pu->parkingnum);
ast_say_digits(peer, pu->parkingnum, peer->language);
return 0;
} else {
ast_log(LOG_WARNING, "No more parking spaces\n");
free(pu);
pthread_mutex_unlock(&parking_lock);
return -1;
}
} else {
ast_log(LOG_WARNING, "Out of memory\n");
return -1;
}
return 0;
}
static void *do_parking_thread(void *ignore)
{
int ms, tms, max;
struct parkeduser *pu, *pl, *pt = NULL;
struct timeval tv;
struct ast_frame *f;
fd_set rfds, efds;
fd_set nrfds, nefds;
FD_ZERO(&rfds);
FD_ZERO(&efds);
for (;;) {
ms = -1;
max = -1;
pthread_mutex_lock(&parking_lock);
pl = NULL;
pu = parkinglot;
gettimeofday(&tv, NULL);
FD_ZERO(&nrfds);
FD_ZERO(&nefds);
while(pu) {
tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
if (tms > parkingtime) {
/* They've been waiting too long, send them back to where they came. Theoretically they
should have their original extensions and such, but we copy to be on the safe side */
strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context));
pu->chan->priority = pu->priority;
/* Start up the PBX, or hang them up */
if (ast_pbx_start(pu->chan)) {
ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
ast_hangup(pu->chan);
}
/* And take them out of the parking lot */
if (pl)
pl->next = pu->next;
else
parkinglot = pu->next;
pt = pu;
pu = pu->next;
free(pt);
} else if (FD_ISSET(pu->chan->fd, &rfds) || FD_ISSET(pu->chan->fd, &efds)) {
/* See if they need servicing */
f = ast_read(pu->chan);
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
/* There's a problem, hang them up*/
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
ast_hangup(pu->chan);
/* And take them out of the parking lot */
if (pl)
pl->next = pu->next;
else
parkinglot = pu->next;
pt = pu;
pu = pu->next;
free(pt);
} else {
/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
ast_frfree(f);
goto std; /* XXX Ick: jumping into an else statement??? XXX */
}
} else {
/* Keep this one for next one */
std: FD_SET(pu->chan->fd, &nrfds);
FD_SET(pu->chan->fd, &nefds);
/* Keep track of our longest wait */
if ((tms < ms) || (ms < 0))
ms = tms;
if (pu->chan->fd > max)
max = pu->chan->fd;
pl = pu;
pu = pu->next;
}
}
pthread_mutex_unlock(&parking_lock);
rfds = nrfds;
efds = nefds;
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * 1000;
/* Wait for something to happen */
select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
pthread_testcancel();
}
return NULL; /* Never reached */
}
static void hanguptree(struct localuser *outgoing, struct ast_channel *exception) static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
{ {
/* Hang up a tree of stuff */ /* Hang up a tree of stuff */
@@ -222,15 +396,19 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
(f->subclass == AST_CONTROL_BUSY)))) (f->subclass == AST_CONTROL_BUSY))))
return -1; return -1;
if ((f->frametype == AST_FRAME_VOICE) || if ((f->frametype == AST_FRAME_VOICE) ||
(f->frametype == AST_FRAME_DTMF)) { (f->frametype == AST_FRAME_DTMF) ||
if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect) { (f->frametype == AST_FRAME_TEXT)) {
if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect &&
(f->subclass == '#')) {
if (f->subclass == '#') { if (f->subclass == '#') {
memset(newext, 0, sizeof(newext)); memset(newext, 0, sizeof(newext));
ptr = newext; ptr = newext;
len = ast_pbx_longest_extension(chan->context) + 1; len = ast_pbx_longest_extension(chan->context) + 1;
if (len < ast_pbx_longest_extension("default") + 1)
len = ast_pbx_longest_extension("default") + 1;
/* Transfer */ /* Transfer */
if ((res=ast_streamfile(peer, "pbx-transfer"))) if ((res=ast_streamfile(peer, "pbx-transfer", chan->language)))
break; break;
if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0) if ((res=ast_waitstream(peer, AST_DIGIT_ANY)) < 0)
break; break;
@@ -244,15 +422,35 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
res = ast_readstring(peer, ptr, len, 3000, 2000, "#"); res = ast_readstring(peer, ptr, len, 3000, 2000, "#");
if (res) if (res)
break; break;
if (ast_exists_extension(chan, chan->context, newext, 1)) { if (!strcmp(newext, parking_ext)) {
/* Set the channel's new extension, since it exists */ if (!park_call(chan, peer)) {
/* We return non-zero, but tell the PBX not to hang the channel when
the thread dies -- We have to be careful now though. We are responsible for
hanging up the channel, else it will never be hung up! */
res=AST_PBX_KEEPALIVE;
break;
} else {
ast_log(LOG_WARNING, "Unable to park call %s\n", chan->name);
}
/* XXX Maybe we should have another message here instead of invalid extension XXX */
} else if (ast_exists_extension(chan, peer->context, newext, 1)) {
/* Set the channel's new extension, since it exists, using peer context */
strncpy(chan->exten, newext, sizeof(chan->exten)); strncpy(chan->exten, newext, sizeof(chan->exten));
strncpy(chan->context, peer->context, sizeof(chan->context));
chan->priority = 0;
ast_frfree(f);
res=0;
break;
} else if (ast_exists_extension(chan, "default", newext, 1)) {
/* Set the channel's new extension, since it exists, using peer context */
strncpy(chan->exten, newext, sizeof(chan->exten));
strncpy(chan->context, "default", sizeof(chan->context));
chan->priority = 0; chan->priority = 0;
ast_frfree(f); ast_frfree(f);
res=0; res=0;
break; break;
} }
res = ast_streamfile(peer, "pbx-invalid"); res = ast_streamfile(peer, "pbx-invalid", chan->language);
if (res) if (res)
break; break;
res = ast_waitstream(peer, AST_DIGIT_ANY); res = ast_waitstream(peer, AST_DIGIT_ANY);
@@ -280,6 +478,63 @@ static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int a
return res; return res;
} }
static int park_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
struct ast_channel *peer=NULL, *nchan;
struct parkeduser *pu, *pl=NULL;
int park;
if (!data) {
ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
return -1;
}
LOCAL_USER_ADD(u);
park = atoi((char *)data);
pthread_mutex_lock(&parking_lock);
pu = parkinglot;
while(pu) {
if (pu->parkingnum == park) {
if (pl)
pl->next = pu->next;
else
parkinglot = pu->next;
break;
}
pu = pu->next;
}
pthread_mutex_unlock(&parking_lock);
if (pu) {
peer = pu->chan;
free(pu);
}
if (peer) {
/* Build a translator if necessary */
if (peer->format & chan->format)
nchan = chan;
else
nchan = ast_translator_create(chan, peer->format, AST_DIRECTION_BOTH);
/* This runs sorta backwards, since we give the incoming channel control, as if it
were the person called. */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
res = bridge_call(peer, nchan, 1);
if (nchan != chan)
ast_translator_destroy(nchan);
/* Simulate the PBX hanging up */
if (res != AST_PBX_KEEPALIVE)
ast_hangup(peer);
return -1;
} else {
/* XXX Play a message XXX */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static int dial_exec(struct ast_channel *chan, void *data) static int dial_exec(struct ast_channel *chan, void *data)
{ {
int res=-1; int res=-1;
@@ -414,7 +669,24 @@ int unload_module(void)
int load_module(void) int load_module(void)
{ {
return ast_register_application(app, dial_exec); int res;
int x;
struct ast_context *con;
char exten[AST_MAX_EXTENSION];
con = ast_context_find(parking_con);
if (!con) {
ast_log(LOG_ERROR, "Parking context '%s' does not exist\n", parking_con);
return -1;
}
for(x=parking_start; x<=parking_stop;x++) {
snprintf(exten, sizeof(exten), "%d", x);
ast_add_extension2(con, 1, exten, 1, parkedcall, strdup(exten), free);
}
pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
res = ast_register_application(parkedcall, park_exec);
if (!res)
res = ast_register_application(app, dial_exec);
return res;
} }
char *description(void) char *description(void)

View File

@@ -126,6 +126,7 @@ struct ast_channel *ast_channel_alloc(void)
tmp->data = NULL; tmp->data = NULL;
pthread_mutex_init(&tmp->lock, NULL); pthread_mutex_init(&tmp->lock, NULL);
strncpy(tmp->context, "default", sizeof(tmp->context)); strncpy(tmp->context, "default", sizeof(tmp->context));
strncpy(tmp->language, defaultlanguage, sizeof(tmp->language));
strncpy(tmp->exten, "s", sizeof(tmp->exten)); strncpy(tmp->exten, "s", sizeof(tmp->exten));
tmp->priority=1; tmp->priority=1;
tmp->next = channels; tmp->next = channels;
@@ -387,6 +388,16 @@ struct ast_frame *ast_read(struct ast_channel *chan)
return f; return f;
} }
int ast_sendtext(struct ast_channel *chan, char *text)
{
int res = 0;
CHECK_BLOCKING(chan);
if (chan->pvt->send_text)
res = chan->pvt->send_text(chan, text);
chan->blocking = 0;
return res;
}
int ast_write(struct ast_channel *chan, struct ast_frame *fr) int ast_write(struct ast_channel *chan, struct ast_frame *fr)
{ {
int res = -1; int res = -1;

View File

@@ -125,6 +125,7 @@ struct iax_peer {
char username[80]; char username[80];
char secret[80]; char secret[80];
struct sockaddr_in addr; struct sockaddr_in addr;
int formats;
struct in_addr mask; struct in_addr mask;
struct iax_peer *next; struct iax_peer *next;
}; };
@@ -668,8 +669,8 @@ static int attempt_transmit(void *data)
/* Attempt transmission */ /* Attempt transmission */
send_packet(f); send_packet(f);
f->retries++; f->retries++;
/* Try again later after 2 times as long */ /* Try again later after 10 times as long */
f->retrytime *= 2; f->retrytime *= 10;
if (f->retrytime > MAX_RETRY_TIME) if (f->retrytime > MAX_RETRY_TIME)
f->retrytime = MAX_RETRY_TIME; f->retrytime = MAX_RETRY_TIME;
ast_sched_add(sched, f->retrytime, attempt_transmit, f); ast_sched_add(sched, f->retrytime, attempt_transmit, f);
@@ -854,6 +855,13 @@ static int iax_digit(struct ast_channel *c, char digit)
return send_command(c->pvt->pvt, AST_FRAME_DTMF, digit, 0, NULL, 0, -1); return send_command(c->pvt->pvt, AST_FRAME_DTMF, digit, 0, NULL, 0, -1);
} }
static int iax_sendtext(struct ast_channel *c, char *text)
{
return send_command(c->pvt->pvt, AST_FRAME_TEXT,
0, 0, text, strlen(text) + 1, -1);
}
static int create_addr(struct sockaddr_in *sin, char *peer) static int create_addr(struct sockaddr_in *sin, char *peer)
{ {
struct hostent *hp; struct hostent *hp;
@@ -1023,6 +1031,7 @@ static struct ast_channel *ast_iax_new(struct chan_iax_pvt *i, int state)
tmp->format = iax_capability; tmp->format = iax_capability;
tmp->pvt->pvt = i; tmp->pvt->pvt = i;
tmp->pvt->send_digit = iax_digit; tmp->pvt->send_digit = iax_digit;
tmp->pvt->send_text = iax_sendtext;
tmp->pvt->call = iax_call; tmp->pvt->call = iax_call;
tmp->pvt->hangup = iax_hangup; tmp->pvt->hangup = iax_hangup;
tmp->pvt->answer = iax_answer; tmp->pvt->answer = iax_answer;

View File

@@ -57,6 +57,7 @@ static int silencesuppression = 0;
static int silencethreshold = 1000; static int silencethreshold = 1000;
static char digits[80] = ""; static char digits[80] = "";
static char text2send[80] = "";
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -66,6 +67,7 @@ static char *tdesc = "OSS Console Channel Driver";
static char *config = "oss.conf"; static char *config = "oss.conf";
static char context[AST_MAX_EXTENSION] = "default"; static char context[AST_MAX_EXTENSION] = "default";
static char language[MAX_LANGUAGE] = "";
static char exten[AST_MAX_EXTENSION] = "s"; static char exten[AST_MAX_EXTENSION] = "s";
/* Some pipes to prevent overflow */ /* Some pipes to prevent overflow */
@@ -341,6 +343,12 @@ static int oss_digit(struct ast_channel *c, char digit)
return 0; return 0;
} }
static int oss_text(struct ast_channel *c, char *text)
{
ast_verbose( " << Console Received text %s >> \n", text);
return 0;
}
static int oss_call(struct ast_channel *c, char *dest, int timeout) static int oss_call(struct ast_channel *c, char *dest, int timeout)
{ {
ast_verbose( " << Call placed to '%s' on console >> \n", dest); ast_verbose( " << Call placed to '%s' on console >> \n", dest);
@@ -477,6 +485,14 @@ static struct ast_frame *oss_read(struct ast_channel *chan)
if (needhangup) { if (needhangup) {
return NULL; return NULL;
} }
if (strlen(text2send)) {
f.frametype = AST_FRAME_TEXT;
f.subclass = 0;
f.data = text2send;
f.datalen = strlen(text2send);
strcpy(text2send,"");
return &f;
}
if (strlen(digits)) { if (strlen(digits)) {
f.frametype = AST_FRAME_DTMF; f.frametype = AST_FRAME_DTMF;
f.subclass = digits[0]; f.subclass = digits[0];
@@ -535,14 +551,18 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
tmp->format = AST_FORMAT_SLINEAR; tmp->format = AST_FORMAT_SLINEAR;
tmp->pvt->pvt = p; tmp->pvt->pvt = p;
tmp->pvt->send_digit = oss_digit; tmp->pvt->send_digit = oss_digit;
tmp->pvt->send_text = oss_text;
tmp->pvt->hangup = oss_hangup; tmp->pvt->hangup = oss_hangup;
tmp->pvt->answer = oss_answer; tmp->pvt->answer = oss_answer;
tmp->pvt->read = oss_read; tmp->pvt->read = oss_read;
tmp->pvt->call = oss_call;
tmp->pvt->write = oss_write; tmp->pvt->write = oss_write;
if (strlen(p->context)) if (strlen(p->context))
strncpy(tmp->context, p->context, sizeof(tmp->context)); strncpy(tmp->context, p->context, sizeof(tmp->context));
if (strlen(p->exten)) if (strlen(p->exten))
strncpy(tmp->exten, p->exten, sizeof(tmp->exten)); strncpy(tmp->exten, p->exten, sizeof(tmp->exten));
if (strlen(language))
strncpy(tmp->language, language, sizeof(tmp->language));
p->owner = tmp; p->owner = tmp;
tmp->state = state; tmp->state = state;
pthread_mutex_lock(&usecnt_lock); pthread_mutex_lock(&usecnt_lock);
@@ -563,6 +583,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
static struct ast_channel *oss_request(char *type, int format, void *data) static struct ast_channel *oss_request(char *type, int format, void *data)
{ {
int oldformat = format; int oldformat = format;
struct ast_channel *tmp;
format &= AST_FORMAT_SLINEAR; format &= AST_FORMAT_SLINEAR;
if (!format) { if (!format) {
ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat); ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);
@@ -572,7 +593,11 @@ static struct ast_channel *oss_request(char *type, int format, void *data)
ast_log(LOG_NOTICE, "Already have a call on the OSS channel\n"); ast_log(LOG_NOTICE, "Already have a call on the OSS channel\n");
return NULL; return NULL;
} }
return oss_new(&oss, AST_STATE_DOWN); tmp= oss_new(&oss, AST_STATE_DOWN);
if (!tmp) {
ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
}
return tmp;
} }
static int console_autoanswer(int fd, int argc, char *argv[]) static int console_autoanswer(int fd, int argc, char *argv[])
@@ -629,6 +654,30 @@ static int console_answer(int fd, int argc, char *argv[])
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static char sendtext_usage[] =
"Usage: send text <message>\n"
" Sends a text message for display on the remote terminal.\n";
static int console_sendtext(int fd, int argc, char *argv[])
{
int tmparg = 1;
if (argc < 1)
return RESULT_SHOWUSAGE;
if (!oss.owner) {
ast_cli(fd, "No one is calling us\n");
return RESULT_FAILURE;
}
if (strlen(text2send))
ast_cli(fd, "Warning: message already waiting to be sent, overwriting\n");
strcpy(text2send, "");
while(tmparg <= argc) {
strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send));
strncat(text2send, " ", sizeof(text2send) - strlen(text2send));
}
needanswer++;
return RESULT_SUCCESS;
}
static char answer_usage[] = static char answer_usage[] =
"Usage: answer\n" "Usage: answer\n"
" Answers an incoming call on the console (OSS) channel.\n"; " Answers an incoming call on the console (OSS) channel.\n";
@@ -694,6 +743,7 @@ static struct ast_cli_entry myclis[] = {
{ { "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage }, { { "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage },
{ { "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage }, { { "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage },
{ { "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage }, { { "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage },
{ { "send text", NULL }, console_sendtext, "Send text to the remote device", sendtext_usage },
{ { "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete } { { "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete }
}; };
@@ -744,6 +794,8 @@ int load_module()
silencethreshold = atoi(v->value); silencethreshold = atoi(v->value);
else if (!strcasecmp(v->name, "context")) else if (!strcasecmp(v->name, "context"))
strncpy(context, v->value, sizeof(context)); strncpy(context, v->value, sizeof(context));
else if (!strcasecmp(v->name, "language"))
strncpy(language, v->value, sizeof(language));
else if (!strcasecmp(v->name, "extension")) else if (!strcasecmp(v->name, "extension"))
strncpy(exten, v->value, sizeof(exten)); strncpy(exten, v->value, sizeof(exten));
v=v->next; v=v->next;

View File

@@ -28,11 +28,14 @@ extern "C" {
#define AST_CHANNEL_NAME 80 #define AST_CHANNEL_NAME 80
#define AST_CHANNEL_MAX_STACK 32 #define AST_CHANNEL_MAX_STACK 32
#define MAX_LANGUAGE 20
/* Max length an extension can be (unique) is this number */ /* Max length an extension can be (unique) is this number */
#define AST_MAX_EXTENSION 80 #define AST_MAX_EXTENSION 80
struct ast_channel { struct ast_channel {
char name[AST_CHANNEL_NAME]; /* ASCII Description of channel name */ char name[AST_CHANNEL_NAME]; /* ASCII Description of channel name */
char language[MAX_LANGUAGE]; /* Language requested */
pthread_t blocker; /* If anyone is blocking, this is them */ pthread_t blocker; /* If anyone is blocking, this is them */
pthread_mutex_t lock; /* Lock, can be used to lock a channel for some operations */ pthread_mutex_t lock; /* Lock, can be used to lock a channel for some operations */
char *blockproc; /* Procedure causing blocking */ char *blockproc; /* Procedure causing blocking */
@@ -132,6 +135,9 @@ struct ast_frame *ast_read(struct ast_channel *chan);
/* Write a frame to a channel */ /* Write a frame to a channel */
int ast_write(struct ast_channel *chan, struct ast_frame *frame); int ast_write(struct ast_channel *chan, struct ast_frame *frame);
/* Write text to a display on a channel */
int ast_sendtext(struct ast_channel *chan, char *text);
/* Browse the channels currently in use */ /* Browse the channels currently in use */
struct ast_channel *ast_channel_walk(struct ast_channel *prev); struct ast_channel *ast_channel_walk(struct ast_channel *prev);

View File

@@ -37,6 +37,8 @@ struct ast_channel_pvt {
struct ast_frame * (*read)(struct ast_channel *chan); struct ast_frame * (*read)(struct ast_channel *chan);
/* Write a frame, in standard format */ /* Write a frame, in standard format */
int (*write)(struct ast_channel *chan, struct ast_frame *frame); int (*write)(struct ast_channel *chan, struct ast_frame *frame);
/* Display or transmit text */
int (*send_text)(struct ast_channel *chan, char *text);
}; };
/* Create a channel structure */ /* Create a channel structure */

View File

@@ -55,6 +55,7 @@ struct ast_frame_chain {
#define AST_FRAME_CONTROL 4 /* A control frame, subclass is AST_CONTROL_* */ #define AST_FRAME_CONTROL 4 /* A control frame, subclass is AST_CONTROL_* */
#define AST_FRAME_NULL 5 /* An empty, useless frame */ #define AST_FRAME_NULL 5 /* An empty, useless frame */
#define AST_FRAME_IAX 6 /* Inter Aterisk Exchange private frame type */ #define AST_FRAME_IAX 6 /* Inter Aterisk Exchange private frame type */
#define AST_FRAME_TEXT 7 /* Text messages */
/* Data formats for capabilities and frames alike */ /* Data formats for capabilities and frames alike */
#define AST_FORMAT_G723_1 (1 << 0) /* G.723.1 compression */ #define AST_FORMAT_G723_1 (1 << 0) /* G.723.1 compression */