- support for CALLEDNAME
 - support for CONNECTEDNAME
 - startet some code for sendtext, still disabled - i've to find an trick to implement this
This commit is contained in:
MelwareDE 2007-07-10 17:44:09 +00:00
parent 9ae64305da
commit 03cb7d3048
6 changed files with 218 additions and 13 deletions

View File

@ -84,6 +84,13 @@ The QSIG support includes:
- decoding of incoming Call Transfer feature - decoding of incoming Call Transfer feature
Enables inbound Path Replacement. If received, an automatic Path Replacement with asterisk internal bridging will be fired. Enables inbound Path Replacement. If received, an automatic Path Replacement with asterisk internal bridging will be fired.
- Support for sending CalledName
If in dialplan a variable CALLEDNAME was set, it will be sent out to the switch, while the asterisk extension is ringing.
- Support for sending ConnectedName
If in dialplan a variable CONNECTEDNAME was set, it will be sent out to the switch AFTER connection is answered by asterisk
Future Targets: Future Targets:
=============== ===============
- check code for buffer overflows - check code for buffer overflows
@ -91,7 +98,7 @@ Future Targets:
- Call Rerouting feature [ECMA-174] - Call Rerouting feature [ECMA-174]
- CCBS - CCBS
- AOC - AOC
- Sent out LEG_INFO3 - maybe this would allow an sendtext (display instructions on the connected set) - sendtext implementation (e.g. display instructions on the connected set)
- ... - ...
How to use: How to use:

View File

@ -779,6 +779,7 @@ static int pbx_capi_send_digit(struct ast_channel *c, char digit)
static int pbx_capi_alert(struct ast_channel *c) static int pbx_capi_alert(struct ast_channel *c)
{ {
struct capi_pvt *i = CC_CHANNEL_PVT(c); struct capi_pvt *i = CC_CHANNEL_PVT(c);
unsigned char *facilityarray = NULL;
if ((i->state != CAPI_STATE_INCALL) && if ((i->state != CAPI_STATE_INCALL) &&
(i->state != CAPI_STATE_DID)) { (i->state != CAPI_STATE_DID)) {
@ -787,8 +788,11 @@ static int pbx_capi_alert(struct ast_channel *c)
return -1; return -1;
} }
facilityarray = alloca(CAPI_MAX_FACILITYDATAARRAY_SIZE);
cc_qsig_add_call_alert_data(facilityarray, i, c);
if (capi_sendf(NULL, 0, CAPI_ALERT_REQ, i->PLCI, get_capi_MessageNumber(), if (capi_sendf(NULL, 0, CAPI_ALERT_REQ, i->PLCI, get_capi_MessageNumber(),
"()") != 0) { "(()()()s())", facilityarray) != 0) {
return -1; return -1;
} }
@ -1311,6 +1315,7 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf)
char buf[CAPI_MAX_STRING]; char buf[CAPI_MAX_STRING];
const char *dnid; const char *dnid;
const char *connectednumber; const char *connectednumber;
unsigned char *facilityarray = NULL;
if ((i->isdnmode == CAPI_ISDNMODE_DID) && if ((i->isdnmode == CAPI_ISDNMODE_DID) &&
((strlen(i->incomingmsn) < strlen(i->dnid)) && ((strlen(i->incomingmsn) < strlen(i->dnid)) &&
@ -1338,8 +1343,11 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf)
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: Answering for %s\n", cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: Answering for %s\n",
i->vname, dnid); i->vname, dnid);
facilityarray = alloca(CAPI_MAX_FACILITYDATAARRAY_SIZE);
cc_qsig_add_call_answer_data(facilityarray, i, c);
if (capi_sendf(NULL, 0, CAPI_CONNECT_RESP, i->PLCI, i->MessageNumber, if (capi_sendf(NULL, 0, CAPI_CONNECT_RESP, i->PLCI, i->MessageNumber,
"w(wwwssss)s()()()", "w(wwwssss)s()()(()()()s())",
0, /* accept call */ 0, /* accept call */
/* B protocol */ /* B protocol */
b_protocol_table[i->bproto].b1protocol, b_protocol_table[i->bproto].b1protocol,
@ -1349,10 +1357,11 @@ static int capi_send_answer(struct ast_channel *c, _cstruct b3conf)
b_protocol_table[i->bproto].b2configuration, b_protocol_table[i->bproto].b2configuration,
b3conf, b3conf,
capi_set_global_configuration(i), capi_set_global_configuration(i),
buf /* connected number */ buf, /* connected number */
/* connected subaddress */ /* connected subaddress */
/* LLC */ /* LLC */
/* Additional info */ /* Additional info */
facilityarray
) != 0) { ) != 0) {
return -1; return -1;
} }
@ -5189,7 +5198,7 @@ const struct ast_channel_tech capi_tech = {
#else #else
.send_digit = pbx_capi_send_digit, .send_digit = pbx_capi_send_digit,
#endif #endif
.send_text = NULL, .send_text = pbx_capi_qsig_sendtext,
.call = pbx_capi_call, .call = pbx_capi_call,
.hangup = pbx_capi_hangup, .hangup = pbx_capi_hangup,
.answer = pbx_capi_answer, .answer = pbx_capi_answer,

View File

@ -97,6 +97,7 @@
#define CCQSIG__ECMA__PRPROPOSE 1004 /* Path Replacement Propose */ #define CCQSIG__ECMA__PRPROPOSE 1004 /* Path Replacement Propose */
#define CCQSIG__ECMA__CTCOMPLETE 1012 /* Call Transfer Complete */ #define CCQSIG__ECMA__CTCOMPLETE 1012 /* Call Transfer Complete */
#define CCQSIG__ECMA__LEGINFO2 1021 /* LEG INFORMATION2 */ #define CCQSIG__ECMA__LEGINFO2 1021 /* LEG INFORMATION2 */
#define CCQSIG__ECMA__LEGINFO3 1022 /* LEG INFORMATION3 */
#define CCQSIG_TIMER_WAIT_PRPROPOSE 1 /* Wait x seconds */ #define CCQSIG_TIMER_WAIT_PRPROPOSE 1 /* Wait x seconds */
@ -167,6 +168,8 @@ extern signed int cc_qsig_fill_invokestruct(unsigned char *data, int *idx, struc
extern unsigned int cc_qsig_handle_capiind(unsigned char *data, struct capi_pvt *i); extern unsigned int cc_qsig_handle_capiind(unsigned char *data, struct capi_pvt *i);
extern unsigned int cc_qsig_handle_capi_facilityind(unsigned char *data, struct capi_pvt *i); extern unsigned int cc_qsig_handle_capi_facilityind(unsigned char *data, struct capi_pvt *i);
extern unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c); extern unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
extern unsigned int cc_qsig_add_call_answer_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
extern unsigned int cc_qsig_add_call_alert_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
extern unsigned int cc_qsig_add_call_facility_data(unsigned char *data, struct capi_pvt *i, int facility); extern unsigned int cc_qsig_add_call_facility_data(unsigned char *data, struct capi_pvt *i, int facility);
extern signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protocol); extern signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protocol);
@ -179,6 +182,7 @@ extern int pbx_capi_qsig_ssct(struct ast_channel *c, char *param);
extern int pbx_capi_qsig_ct(struct ast_channel *c, char *param); extern int pbx_capi_qsig_ct(struct ast_channel *c, char *param);
extern int pbx_capi_qsig_callmark(struct ast_channel *c, char *param); extern int pbx_capi_qsig_callmark(struct ast_channel *c, char *param);
extern int pbx_capi_qsig_bridge(struct capi_pvt *i0, struct capi_pvt *i1); extern int pbx_capi_qsig_bridge(struct capi_pvt *i0, struct capi_pvt *i1);
extern int pbx_capi_qsig_sendtext(struct ast_channel *c, const char *text);
extern void cc_qsig_interface_init(struct cc_capi_conf *conf, struct capi_pvt *tmp); extern void cc_qsig_interface_init(struct cc_capi_conf *conf, struct capi_pvt *tmp);

View File

@ -936,7 +936,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
} }
cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe); cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe);
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0); cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0, i->owner->cid.cid_name);
cc_qsig_add_invoke(data, &dataidx, &invoke, i); cc_qsig_add_invoke(data, &dataidx, &invoke, i);
if (add_externalinfo) { if (add_externalinfo) {
@ -950,6 +950,81 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
return 0; return 0;
} }
/*
* Handles outgoing Facilies on Call Answer
*/
unsigned int cc_qsig_add_call_answer_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c)
{
struct cc_qsig_invokedata invoke;
struct cc_qsig_nfe nfe;
unsigned int dataidx = 0;
int protocolvar = 0;
const char *connectedname;
if (!i->qsigfeat)
return 0;
connectedname = pbx_builtin_getvar_helper(c, "CONNECTEDNAME");
if (!strlen(connectedname))
return 0;
switch (i->qsigfeat) {
case QSIG_TYPE_ALCATEL_ECMA:
protocolvar = Q932_PROTOCOL_ROSE;
break;
case QSIG_TYPE_HICOM_ECMAV2:
protocolvar = Q932_PROTOCOL_EXTENSIONS;
break;
default:
cc_log(LOG_WARNING, " Unknown QSIG variant configured.\n");
return 0;
break;
}
cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe);
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 2, (char *)connectedname);
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
return 1;
}
/*
* Handles outgoing Facilies on Call Answer
*/
unsigned int cc_qsig_add_call_alert_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c)
{
struct cc_qsig_invokedata invoke;
struct cc_qsig_nfe nfe;
unsigned int dataidx = 0;
int protocolvar = 0;
const char *connectedname;
if (!i->qsigfeat)
return 0;
connectedname = pbx_builtin_getvar_helper(c, "CALLEDNAME");
if (!strlen(connectedname))
return 0;
switch (i->qsigfeat) {
case QSIG_TYPE_ALCATEL_ECMA:
protocolvar = Q932_PROTOCOL_ROSE;
break;
case QSIG_TYPE_HICOM_ECMAV2:
protocolvar = Q932_PROTOCOL_EXTENSIONS;
break;
default:
cc_log(LOG_WARNING, " Unknown QSIG variant configured.\n");
return 0;
break;
}
cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe);
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 1, (char *)connectedname);
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
return 1;
}
/* /*
* Handles outgoing Facilies on capicommand * Handles outgoing Facilies on capicommand
@ -1301,6 +1376,44 @@ int pbx_capi_qsig_bridge(struct capi_pvt *i0,struct capi_pvt *i1)
} }
int pbx_capi_qsig_sendtext(struct ast_channel *c, const char *text)
{
struct capi_pvt *i = CC_CHANNEL_PVT(c);
#if 0
/* suppress compiler warnings */
unsigned char *data = alloca(CAPI_MAX_FACILITYDATAARRAY_SIZE);
unsigned int dataidx = 0;
struct cc_qsig_invokedata invoke;
struct cc_qsig_nfe nfe;
#endif
int protocolvar = 0;
if (!i->qsigfeat)
return 0;
if (!strlen(text))
return 0;
switch (i->qsigfeat) {
case QSIG_TYPE_ALCATEL_ECMA:
protocolvar = Q932_PROTOCOL_ROSE;
break;
case QSIG_TYPE_HICOM_ECMAV2:
protocolvar = Q932_PROTOCOL_EXTENSIONS;
break;
default:
cc_log(LOG_WARNING, " Unknown QSIG variant configured.\n");
return 0;
break;
}
/* TODO: implement something - QSIG_LEG_INFO3 doesn't work here */
return 0;
}
/* /*
* CAPI INFO_IND (QSIG part) * CAPI INFO_IND (QSIG part)

View File

@ -116,15 +116,15 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap
* returns * returns
* always 0 * always 0
*/ */
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype) int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, char * name)
{ {
unsigned char namebuf[51]; unsigned char namebuf[51];
unsigned char data[255]; unsigned char data[255];
int dataidx = 0; int dataidx = 0;
int namelen = 0; int namelen = 0;
if (i->owner->cid.cid_name) if (name)
namelen = strlen(i->owner->cid.cid_name); namelen = strlen(name);
if (namelen < 1) { /* There's no name available, try to take Interface-Name */ if (namelen < 1) { /* There's no name available, try to take Interface-Name */
if (i->name) { if (i->name) {
@ -138,15 +138,15 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
} else { } else {
if (namelen > 50) if (namelen > 50)
namelen = 50; namelen = 50;
memcpy(namebuf, i->owner->cid.cid_name, namelen); memcpy(namebuf, name, namelen);
} }
invoke->id = 1; invoke->id = 1;
invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */ invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */
invoke->type = 0; /* Invoke Operation Number, if OID it's the last byte*/ invoke->type = (nametype % 4); /* Invoke Operation Number, if OID it's the last byte*/
if (namelen>0) { if (namelen>0) {
data[dataidx++] = 0x80 | (nametype % 4); /* We send only simple Name, Namepresentation allowed */ data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
data[dataidx++] = namelen; data[dataidx++] = namelen;
memcpy(&data[dataidx], namebuf, namelen); memcpy(&data[dataidx], namebuf, namelen);
dataidx += namelen; dataidx += namelen;
@ -163,6 +163,76 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
return 0; return 0;
} }
/*
* Encode Operation: 1.3.12.9.22 ECMA/ISDN/LEG_INFO3
*
* This function encodes the namepresentation facility
* The name will be copied from the cid.cid_name field of the asterisk channel struct.
* We create an invoke struct with the complete encoded invoke.
*
* parameters
* buf is pointer to facility array, not used now
* idx current idx in facility array, not used now
* invoke struct, which contains encoded data for facility
* i is pointer to capi channel
* returns
* always 0
*/
int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *name)
{
unsigned char namebuf[51];
unsigned char data[255];
int dataidx = 0;
int namelen = 0;
if (name)
namelen = strlen(name);
if (namelen < 1) { /* There's no name available, try to take Interface-Name */
if (i->name) {
if (strlen(i->name) >= 1) {
if (namelen > 50)
namelen = 50;
namelen = strlen(i->name);
memcpy(namebuf, i->name, namelen);
}
}
} else {
if (namelen > 50)
namelen = 50;
memcpy(namebuf, name, namelen);
}
invoke->id = 1;
invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */
invoke->type = 22; /* Invoke Operation Number, if OID it's the last byte*/
data[dataidx++] = ASN1_TF_CONSTRUCTED | ASN1_SEQUENCE;
data[dataidx++] = 5 + namelen;
data[dataidx++] = ASN1_BOOLEAN; /* PresentationAllowedIndicator */
data[dataidx++] = 1;
data[dataidx++] = 1;
if (namelen>0) {
data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
data[dataidx++] = namelen;
memcpy(&data[dataidx], namebuf, namelen);
dataidx += namelen;
} else {
data[dataidx++] = 0x84; /* Name not available */
data[dataidx++] = 0;
}
invoke->datalen = dataidx;
memcpy(invoke->data, data, dataidx);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending QSIG_LEG_INFO3 \"%s\": (%i byte(s))\n", namebuf, namelen);
return 0;
}
/* /*
* Handle Operation: 1.3.12.9.21 ECMA/ISDN/LEG_INFORMATION2 * Handle Operation: 1.3.12.9.21 ECMA/ISDN/LEG_INFORMATION2

View File

@ -41,7 +41,9 @@ struct cc_qsig_ctcomplete {
*/ */
extern void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i); extern void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype); extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, char *name);
extern int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *name);
extern void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i); extern void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);