Merged from trunk for next stable release.

This commit is contained in:
MelwareDE 2009-08-03 16:25:43 +00:00
parent 28ff6d6cdf
commit 4a11dc0e14
10 changed files with 166 additions and 44 deletions

View File

@ -24,6 +24,8 @@ HEAD
- play message to conference and music on hold to caller
- add commands to remove users from chat
- allow to specity the 'ETS 300 102-1' called party number octet 3
- fixed possible buffer overflow in 'deflect'
- added 'h' option to chat to auto-hangup caller if alone in conference too long
chan_capi-1.1.2

2
README
View File

@ -288,6 +288,7 @@ Deactivate CCBS:
exten => s,1,capicommand(ccbsstop|${CCLINKAGEID})
Chat (MeetMe/Conference):
See also README.media for details!
If the CAPI card/driver supports it, the caller can be put into a chat-room:
(This uses the DSPs onboard a Dialogic(R) Diva(R) Rev.2 Media Board.)
exten => s,1,capicommand(chat|<roomname>|<options>|controller)
@ -295,6 +296,7 @@ Chat (MeetMe/Conference):
exten => s,1,capicommand(chat|salesmeeting|m|1,3-6)
Possible options:
'm' = The first caller will get music-on-hold until second caller arrives.
'h<sec>' = Hangup after <sec> seconds if caller is alone in conference.
'o' = The caller is operator
'l' = The caller is listener

View File

@ -254,15 +254,15 @@ exten => i,1,Hangup() ; Received unexpected event
[handle_fax]
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}[|<stationid>|<headline>|<options>])
exten => s,2,Hangup()
exten => s,n,Hangup()
exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it
Example with Clear Channel fax support:
[handle_fax]
exten => s,1,capicommand(resource|1-4) ; Assign resource PLCI
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}[|<stationid>|<headline>|<options>])
exten => s,2,Hangup()
exten => s,1,capicommand(resource|1-4) ; Assign resource PLCI (use controllers 1 to 4)
exten => s,n,capicommand(receivefax|/tmp/${UNIQUEID}[|<stationid>|<headline>|<options>])
exten => s,n,Hangup()
exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it

View File

@ -684,7 +684,7 @@ stoptonedetection
Tone identifier:
0x82 - Dial tone detected
0x83 - PABX internal dial tone detected
0x83 - PABX internal dial tone detected
0x84 - Special dial tone (stutter dial tone) detected
0x85 - Second dial tone detected
0x86 - Ringing tone detected
@ -874,6 +874,7 @@ capicommand(chat|<roomname>|<options>|controller)
roomname - conference room name
options
m - The first caller will get music-on-hold until the second caller arrives
h<sec> - Hangup after <sec> seconds if caller is alone in conference.
l - The caller is listener (passive) conference member and cannot be unmuted by 'chat_mute' command
o - The caller is conference operator and cannot be muted by 'chat_mute' command
controller - CAPI controller
@ -884,6 +885,7 @@ exten => s,n,capicommand(chat|test|m|1,3)
exten => s,n,capicommand(chat|test|m|1-4)
exten => s,n,capicommand(chat|test|m|1-4,7)
exten => s,n,capicommand(chat|test|m|1-4,7-10)
exten => s,n,capicommand(chat|test|mh300|1-4)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -904,7 +906,7 @@ exten => 1,n,capicommand(vc|txdgain|3|0) ; Install voice command menu for volume
exten => 1,n,capicommand(chat|test1|m|1-4) ; Create/enter conference room 'test1'
exten => 2,1,capicommand(clamping|100) ; Activate suppression of DTMF tones
exten => 2,1,capicommand(txdgain|-128) ; Deactivate tx path
exten => 2,n,capicommand(txdgain|-128) ; Deactivate tx path
exten => 2,n,capicommand(vc|incrxdgain|0|1.5) ; Install voice command menu for volume control, '0' to increase volume
exten => 2,n,capicommand(vc|incrxdgain|1|-1.5) ; Install voice command menu for volume control, '1' to decrease volume
exten => 2,n,capicommand(vc|txdgain|2|-128) ; Install voice command menu for volume control, '2' to mute tx path
@ -1144,6 +1146,7 @@ capicommand(chat_play|<roomname>|<options>|<filename>|controller)
roomname - conference room name
options
m - The caller will get music-on-hold while message is played
s - The caller will hear the same message that is played
filename - Voice message file name. Should be in aLaw (uLaw) format.
controller - CAPI controller
@ -1184,9 +1187,9 @@ capicommand(chat_command|<options>|<roomname>)
Command does not apply to calling member and be used by operators only.
l - Remove all listeners from conference.
Command does not apply to calling member and be used by operators only.
o - Remove all operators from conference.
o - Remove all operators from conference.
Command does not apply to calling member and be used by operators only.
a - Remove all users from conference.
a - Remove all users from conference.
Command does not apply to calling member and be used by operators only.
roomname - optional, room caller assigned to is used if not present

View File

@ -20,20 +20,20 @@ None yet - you will be welcome here :-)
No support for Asterisk 1.0.x any more, you need at least
Asterisk 1.2.x , 1.4.x or 1.6.x.
What is Q.SIG
What is QSIG
=============
Q.SIG is a protocol extension for ISDN.
QSIG is a protocol extension for ISDN.
It is mainly used on connecting PBXs of different PBX vendors, which allows
better interoperability.
As example there can be a name of an extension transferred between different
PBXs, which is not possibile with standard ISDN.
These extensions will be transmitted as encoded facility information elements.
To use Q.SIG with Asterisk, you willll need a card such as a Dialogic(R) Diva(R)
To use QSIG with Asterisk, you willll need a card such as a Dialogic(R) Diva(R)
Media Board (BRI like PRI) that supports QSIG. Maybe others do also work, if so, let me now.
The Q.SIG support includes:
The QSIG support includes:
==========================
- Name presentation on Call SETUP incoming like outgoing
@ -50,7 +50,7 @@ The Q.SIG support includes:
at the moment only incoming handling is supported
- Possibility to inform Q.SIG switch about a call from the public network
- Possibility to inform QSIG switch about a call from the public network
If you set the variable QSIG_SETUP=X, then the QSIG switch on the other side will know,
that this call source is the public network - you will get a different ring tone, etc.
In dialplan use: Set(__QSIG_SETUP=X) command.
@ -110,11 +110,11 @@ Please visit: http://www.melware.org/ChanCapiConf
Simply enable Q.SIG with the following line in your capi.conf interface:
Simply enable QSIG with the following line in your capi.conf interface:
Here we go with new configuration
Set Q.SIG to one of the following values, which corresponds to your configuration.
Set QSIG to one of the following values, which corresponds to your configuration.
0 QSIG turned off
1 Alcatel (4400 & Enterprise - Maybe OXO/4200) ECMA (wrongly named ECMA - it is ETSI) variant

View File

@ -2112,7 +2112,7 @@ static CC_BRIDGE_RETURN pbx_capi_bridge(
/*
* a new channel is needed
*/
static struct ast_channel *capi_new(struct capi_pvt *i, int state)
static struct ast_channel *capi_new(struct capi_pvt *i, int state, const char *linkedid)
{
struct ast_channel *tmp;
int fmt;
@ -2120,7 +2120,11 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state)
#ifdef CC_AST_HAS_EXT_CHAN_ALLOC
tmp = ast_channel_alloc(0, state, i->cid, NULL,
#ifdef CC_AST_HAS_EXT2_CHAN_ALLOC
i->accountcode, i->dnid, i->context, i->amaflags,
i->accountcode, i->dnid, i->context,
#ifdef CC_AST_HAS_LINKEDID_CHAN_ALLOC
linkedid,
#endif
i->amaflags,
#endif
CC_MESSAGE_BIGNAME "/%s/%s-%x", i->vname, i->dnid, capi_counter++);
#else
@ -2146,7 +2150,7 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state)
#endif
if (!(capi_create_reader_writer_pipe(i))) {
ast_channel_free(tmp);
ast_channel_release(tmp);
return NULL;
}
tmp->fds[0] = i->readerfd;
@ -2286,8 +2290,14 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state)
/*
* PBX wants us to dial ...
*/
#ifdef CC_AST_HAS_REQUEST_REQUESTOR
static struct ast_channel *
pbx_capi_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause)
/* TODO: new field requestor to link to called channel */
#else
static struct ast_channel *
pbx_capi_request(const char *type, int format, void *data, int *cause)
#endif
{
struct capi_pvt *i;
struct ast_channel *tmp = NULL;
@ -2359,7 +2369,13 @@ pbx_capi_request(const char *type, int format, void *data, int *cause)
}
/* when we come here, we found a free controller match */
cc_copy_string(i->dnid, dest, sizeof(i->dnid));
tmp = capi_new(i, AST_STATE_RESERVED);
tmp = capi_new(i, AST_STATE_RESERVED,
#ifdef CC_AST_HAS_REQUEST_REQUESTOR
requestor ? requestor->linkedid : NULL
#else
NULL
#endif
);
if (!tmp) {
cc_log(LOG_ERROR, "cannot create new " CC_MESSAGE_NAME " channel\n");
interface_cleanup(i);
@ -4392,7 +4408,7 @@ static void capidev_handle_connect_indication(_cmsg *CMSG, unsigned int PLCI, un
i->MessageNumber = HEADER_MSGNUM(CMSG);
i->cid_ton = callernplan;
capi_new(i, AST_STATE_DOWN);
capi_new(i, AST_STATE_DOWN, NULL);
if (i->isdnmode == CAPI_ISDNMODE_DID) {
i->state = CAPI_STATE_DID;
} else {
@ -4861,10 +4877,11 @@ static struct capi_pvt* get_active_plci (struct ast_channel *c) {
*/
static int pbx_capi_call_deflect(struct ast_channel *c, char *param)
{
#define DEFLECT_NUMBER_MAX_LEN 35
struct capi_pvt *i = CC_CHANNEL_PVT(c);
char *number;
int numberlen;
char facnumber[32];
char facnumber[DEFLECT_NUMBER_MAX_LEN + 4];
if (!param) {
cc_log(LOG_WARNING, CC_MESSAGE_NAME
@ -4879,9 +4896,10 @@ static int pbx_capi_call_deflect(struct ast_channel *c, char *param)
" deflection requires an argument (destination phone number)\n");
return -1;
}
if (numberlen > 35) {
if (numberlen > DEFLECT_NUMBER_MAX_LEN) {
cc_log(LOG_WARNING, CC_MESSAGE_NAME
" deflection does only support phone number up to 35 digits\n");
" deflection does only support phone number up to %d digits\n",
DEFLECT_NUMBER_MAX_LEN);
return -1;
}
if (!(capi_controllers[i->controller]->CD)) {
@ -6274,7 +6292,11 @@ pbx_capi_command_proc_t pbx_capi_lockup_command_by_name(const char* name)
/*
* capi command interface
*/
#ifdef CC_AST_HAS_CONST_CHAR_IN_REGAPPL
static int pbx_capicommand_exec(struct ast_channel *chan, const char *data)
#else
static int pbx_capicommand_exec(struct ast_channel *chan, void *data)
#endif
{
int res = 0;
#ifdef CC_AST_HAS_VERSION_1_4
@ -6533,7 +6555,7 @@ static int pbx_capi_devicestate(void *data)
/* AST_DEVICE_UNAVAILABLE */
}
cc_verbose(3, 1, VERBOSE_PREFIX_4 "chan_capi devicestate requested for %s is '%s'\n",
(char *)data, devstate2str(res));
(char *)data, ast_devstate2str(res));
}
return res;

View File

@ -126,6 +126,14 @@ static inline unsigned int read_capi_dword(void *m)
#define FRAME_DATA_PTR data
#endif
#ifndef CC_AST_HAS_CHANNEL_RELEASE
#define ast_channel_release(x) ast_channel_free(x)
#endif
#ifndef CC_AST_HAS_AST_DEVSTATE2STR
#define ast_devstate2str(x) devstate2str(x)
#endif
/* */
#define return_on_no_interface(x) \
if (!i) { \

View File

@ -15,6 +15,7 @@
#include <time.h>
#include <errno.h>
#include <sys/signal.h>
#include <sys/time.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
@ -24,6 +25,7 @@
#include "chan_capi_command.h"
#define CHAT_FLAG_MOH 0x0001
#define CHAT_FLAG_SAMEMSG 0x0002
typedef enum {
RoomMemberDefault = 0, /* Rx/Tx by default, muted by operator */
@ -321,7 +323,7 @@ static void update_all_capi_mixers(unsigned int roomnumber)
}
}
free (segments);
free(segments);
}
}
@ -403,7 +405,7 @@ static struct capichat_s *add_chat_member(char *roomname, struct capi_pvt *i, ro
}
}
room->info |= PBX_CHAT_MEMBER_INFO_RECENT;
room->time = time(0);
room->time = time(NULL);
room->next = chat_list;
chat_list = room;
@ -422,7 +424,8 @@ static struct capichat_s *add_chat_member(char *roomname, struct capi_pvt *i, ro
* loop during chat
*/
static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
struct capichat_s *room, unsigned int flags, struct capi_pvt* iline, FILE* voice_message)
struct capichat_s *room, unsigned int flags, struct capi_pvt* iline,
FILE* voice_message, unsigned int hangup_timeout)
{
struct ast_frame *f;
int ms;
@ -434,6 +437,7 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
struct ast_channel *chan = c;
int moh_active = 0, voice_message_moh_active = 0;
int write_block_nr = 2;
time_t alone_since = time(NULL);
if (voice_message == NULL) {
ast_indicate(chan, -1);
@ -442,19 +446,17 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
waitfd = i->readerfd;
if (i->channeltype == CAPI_CHANNELTYPE_NULL) {
nfds = 1;
if (voice_message == NULL) {
ast_set_read_format(chan, capi_capability);
ast_set_write_format(chan, capi_capability);
}
ast_set_read_format(chan, capi_capability);
ast_set_write_format(chan, capi_capability);
}
if ((flags & CHAT_FLAG_MOH) && ((room->active < 2) || (voice_message != 0))) {
if ((flags & CHAT_FLAG_MOH) && ((room->active < 2) || (voice_message != NULL))) {
#if defined(CC_AST_HAS_VERSION_1_6) || defined(CC_AST_HAS_VERSION_1_4)
ast_moh_start(chan, NULL, NULL);
#else
ast_moh_start(chan, NULL);
#endif
if (voice_message == 0) {
if (voice_message == NULL) {
moh_active = 1;
} else {
voice_message_moh_active = 1;
@ -476,6 +478,8 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
if (rchan) {
f = ast_read(chan);
if (!f) {
if (voice_message != NULL)
continue;
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: chat: no frame, hangup.\n",
i->vname);
break;
@ -488,16 +492,16 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
} else if (f->frametype == AST_FRAME_VOICE) {
cc_verbose(5, 1, VERBOSE_PREFIX_3 "%s: chat: voice frame.\n",
i->vname);
if ((voice_message == 0) && (i->channeltype == CAPI_CHANNELTYPE_NULL)) {
if ((voice_message == NULL) && (i->channeltype == CAPI_CHANNELTYPE_NULL)) {
capi_write_frame(i, f);
} else if (iline != 0) {
} else if ((iline != NULL) && (!(flags & CHAT_FLAG_SAMEMSG))) {
capi_write_frame(iline, f);
}
} else if (f->frametype == AST_FRAME_NULL) {
/* ignore NULL frame */
cc_verbose(5, 1, VERBOSE_PREFIX_3 "%s: chat: NULL frame, ignoring.\n",
i->vname);
} else if ((f->frametype == AST_FRAME_DTMF_END) && (voice_message == 0)) {
} else if ((f->frametype == AST_FRAME_DTMF_END) && (voice_message == NULL)) {
pbx_capi_voicecommand_process_digit (i, c, f->subclass);
} else {
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: chat: unhandled frame %d/%d.\n",
@ -512,9 +516,10 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
}
f = capi_read_pipeframe(i);
if (f->frametype == AST_FRAME_VOICE) {
if (voice_message == 0) {
if (voice_message == NULL) {
ast_write(chan, f);
} else {
struct ast_frame *fr2;
char* p = f->FRAME_DATA_PTR;
int len;
@ -524,6 +529,15 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
memset (&p[len], 0x00, f->datalen-len);
len = 0;
}
if (flags & CHAT_FLAG_SAMEMSG) {
fr2 = ast_frdup(f);
if (iline != NULL) {
capi_write_frame(iline, fr2);
} else {
ast_write(chan, fr2);
ast_frfree(fr2);
}
}
capi_write_frame(i, f);
}
} while ((write_block_nr-- != 0) && (len > 0));
@ -549,6 +563,17 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i,
ast_moh_stop(chan);
moh_active = 0;
}
if (hangup_timeout > 0) {
if (room->active > 1) {
alone_since = time(NULL);
} else {
if ((alone_since + hangup_timeout) < time(NULL)) {
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: chat: reached (alone) hangup timeout.\n",
i->vname);
break;
}
}
}
}
if (voice_message_moh_active != 0) {
ast_moh_stop(chan);
@ -567,6 +592,7 @@ int pbx_capi_chat(struct ast_channel *c, char *param)
ast_group_t tmpcntr;
unsigned long long contr = 0;
unsigned int flags = 0;
unsigned int hangup_timeout = 0;
room_member_type_t room_member_type = RoomMemberDefault;
roomname = strsep(&param, "|");
@ -591,6 +617,14 @@ int pbx_capi_chat(struct ast_channel *c, char *param)
case 'm':
flags |= CHAT_FLAG_MOH;
break;
case 'h':
hangup_timeout = 0;
while (isdigit(options[1])) {
hangup_timeout *= 10;
hangup_timeout += (options[1] - '0');
options++;
}
break;
case 'l':
room_member_type = RoomMemberListener;
break;
@ -607,8 +641,8 @@ int pbx_capi_chat(struct ast_channel *c, char *param)
}
cc_verbose(3, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME " chat: %s: roomname=%s "
"options=%s controller=%s (0x%llx)\n",
c->name, roomname, options, controller, contr);
"options=%s hangup_timeout=%d controller=%s (0x%llx)\n",
c->name, roomname, options, hangup_timeout, controller, contr);
if (c->tech == &capi_tech) {
i = CC_CHANNEL_PVT(c);
@ -641,7 +675,7 @@ int pbx_capi_chat(struct ast_channel *c, char *param)
}
/* main loop */
chat_handle_events(c, i, room, flags, 0, 0);
chat_handle_events(c, i, room, flags, 0, 0, hangup_timeout);
del_chat_member(room);
@ -701,7 +735,9 @@ int pbx_capi_chat_play(struct ast_channel *c, char *param)
case 'm':
flags |= CHAT_FLAG_MOH;
break;
case 's':
flags |= CHAT_FLAG_SAMEMSG;
break;
default:
cc_log(LOG_WARNING, "Unknown chat option '%c'.\n",
*options);
@ -710,6 +746,11 @@ int pbx_capi_chat_play(struct ast_channel *c, char *param)
options++;
}
if ((flags & (CHAT_FLAG_MOH | CHAT_FLAG_SAMEMSG)) == (CHAT_FLAG_MOH | CHAT_FLAG_SAMEMSG)) {
cc_log(LOG_WARNING, "chat_play: option 's' overrides 'm'.\n");
flags &= ~CHAT_FLAG_MOH;
}
f = fopen(file_name, "rb");
if (f == NULL) {
cc_log(LOG_WARNING, "can't open voice file (%s)\n", strerror(errno));
@ -765,7 +806,7 @@ int pbx_capi_chat_play(struct ast_channel *c, char *param)
}
/* main loop */
chat_handle_events(c, i, room, flags, (c->tech == &capi_tech) ? (CC_CHANNEL_PVT(c)) : 0, f);
chat_handle_events(c, i, room, flags, (c->tech == &capi_tech) ? (CC_CHANNEL_PVT(c)) : 0, f, 0);
del_chat_member(room);
@ -776,7 +817,7 @@ out:
return 0;
}
int pbx_capi_chat_command (struct ast_channel *c, char *param)
int pbx_capi_chat_command(struct ast_channel *c, char *param)
{
struct capichat_s *room, *tmproom;
struct capi_pvt *i;

View File

@ -369,7 +369,11 @@ static void ccbsnr_remote_user_free(_cmsg *CMSG, char type, unsigned int PLCI, _
#ifdef CC_AST_HAS_EXT_CHAN_ALLOC
c = ast_channel_alloc(0, state, handlename, NULL,
#ifdef CC_AST_HAS_EXT2_CHAN_ALLOC
0, ccbsnr->exten, ccbsnr->context, 0,
0, ccbsnr->exten, ccbsnr->context,
#ifdef CC_AST_HAS_LINKEDID_CHAN_ALLOC
NULL,
#endif
0,
#endif
"CCBSNR/%x", ccbsnr->handle);
#else

View File

@ -60,6 +60,11 @@ case "$AVERSIONNUM" in
echo " * assuming Asterisk version 1.4"
VER=1_4
;;
999999)
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
echo " * assuming Asterisk version 1.6"
VER=1_6
;;
*)
if [ "$VER" = "1_6" ]; then
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
@ -158,6 +163,41 @@ check_version_onesix()
echo "#undef CC_AST_HAS_UNION_DATA_IN_FRAME" >>$CONFIGFILE
echo " * no new union data in ast_frame structure"
fi
if grep -q "ast_channel_release.*struct" $INCLUDEDIR/channel.h; then
echo "#define CC_AST_HAS_CHANNEL_RELEASE" >>$CONFIGFILE
echo " * found ast_channel_release function"
else
echo "#undef CC_AST_HAS_CHANNEL_RELEASE" >>$CONFIGFILE
echo " * no new ast_channel_release function"
fi
if grep -q "ast_devstate2str.*enum" $INCLUDEDIR/devicestate.h; then
echo "#define CC_AST_HAS_AST_DEVSTATE2STR" >>$CONFIGFILE
echo " * found new ast_devstate2str function"
else
echo "#undef CC_AST_HAS_AST_DEVSTATE2STR" >>$CONFIGFILE
echo " * obsolete devstate2str function"
fi
if grep -q "ast_request.*requestor" $INCLUDEDIR/channel.h; then
echo "#define CC_AST_HAS_REQUEST_REQUESTOR" >>$CONFIGFILE
echo " * found requestor in ast_request"
else
echo "#undef CC_AST_HAS_REQUEST_REQUESTOR" >>$CONFIGFILE
echo " * no requestor in ast_request"
fi
if grep -q "ast_register_application2.*void " $INCLUDEDIR/module.h; then
echo "#undef CC_AST_HAS_CONST_CHAR_IN_REGAPPL" >>$CONFIGFILE
echo " * no const char in ast_register_application"
else
echo "#define CC_AST_HAS_CONST_CHAR_IN_REGAPPL" >>$CONFIGFILE
echo " * found const char in ast_register_application"
fi
if grep -q "ast_channel_alloc.*linkedid" $INCLUDEDIR/channel.h; then
echo "#define CC_AST_HAS_LINKEDID_CHAN_ALLOC" >>$CONFIGFILE
echo " * found linkedid in ast_channel_alloc"
else
echo "#undef CC_AST_HAS_LINKEDID_CHAN_ALLOC" >>$CONFIGFILE
echo " * no linkedid in ast_channel_alloc"
fi
}
case $VER in