chan-capi/chan_capi_qsig_ecma.c

752 lines
22 KiB
C

/*
* (CAPI*)
*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* Copyright (C) 2005-2007 Cytronics & Melware
* Copyright (C) 2007 Mario Goegel
*
* Armin Schindler <armin@melware.de>
* Mario Goegel <m.goegel@gmx.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <asterisk/channel.h>
#include <asterisk/options.h>
#include <asterisk/pbx.h>
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
#include "chan_capi_qsig.h"
#include "chan_capi_qsig_asn197ade.h"
#include "chan_capi_qsig_asn197no.h"
/*
* Handle Operation: 1.3.12.9.0-3 ECMA/ISDN/NAMEPRESENTATION
*
* This function decodes the namepresentation facility
* The name will be copied in the cid.cid_name field of the asterisk channel struct
*
* parameters
* invoke struct, which contains encoded data from facility
* i is pointer to capi channel
* returns
* nothing
*/
void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
{
char callername[51]; /* ECMA defines max length to 50 */
unsigned int namelength = 0;
unsigned int datalength;
int myidx = 0;
char *nametype = NULL;
cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling Name Operation (id# %#x)\n", invoke->id);
callername[0] = 0;
datalength = invoke->datalen;
myidx = cc_qsig_asn197no_get_name(callername, ASN197NO_NAME_STRSIZE, &namelength, &myidx, invoke->data );
if (namelength == 0) {
return;
}
/* TODO: Maybe we do some charset conversions */
switch (invoke->type) {
case 0: /* Calling Name */
nametype = "CALLING NAME";
break;
case 1: /* Called Name */
nametype = "CALLED NAME";
break;
case 2: /* Connected Name */
nametype = "CONNECTED NAME";
break;
case 3: /* Busy Name */
nametype = "BUSY NAME";
break;
}
switch (invoke->type) {
case 0: /* Calling Name */
i->owner->cid.cid_name = strdup(callername); /* Save name to callerid */
break;
case 1: /* Called Name */
case 2: /* Connected Name */
case 3: /* Busy Name */
if (i->qsig_data.dnameid) { /* this facility may come more than once - if so, then update this value */
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * deleting previously received name.\n", nametype, namelength, callername);
free(i->qsig_data.dnameid);
}
i->qsig_data.dnameid = strdup(callername); /* save name as destination in qsig specific fields */
/* there's no similarly field in asterisk */
break;
default:
break;
}
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Got %s: \"%s\" (%i byte(s))\n", nametype, callername, namelength);
/* if there was an sequence tag, we have more informations here, but we will ignore it at the moment */
}
/*
* Encode Operation: 1.3.12.9.0-3 ECMA/ISDN/NAMEPRESENTATION
*
* 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_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype)
{
unsigned char namebuf[51];
unsigned char data[255];
int dataidx = 0;
int namelen = 0;
if (i->owner->cid.cid_name)
namelen = strlen(i->owner->cid.cid_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, i->owner->cid.cid_name, namelen);
}
invoke->id = 1;
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*/
if (namelen>0) {
data[dataidx++] = 0x80 | (nametype % 4); /* 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 \"%s\": (%i byte(s))\n", namebuf, namelen);
return 0;
}
/*
* Handle Operation: 1.3.12.9.21 ECMA/ISDN/LEG_INFORMATION2
*
* This function decodes the LEG INFORMATION2 facility
* The datas will be copied in the some Asterisk channel variables -> see README.qsig
*
* parameters
* invoke struct, which contains encoded data from facility
* i is pointer to capi channel
* returns
* nothing
*/
void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
{
unsigned int datalength;
unsigned int seqlength = 0;
int myidx = 0;
unsigned int parameter = 0;
unsigned int divCount = 0;
unsigned int divReason = 0;
unsigned int orgDivReason = 0;
char tempstr[5];
char divertNum[ASN197ADE_NUMDIGITS_STRSIZE+1];
char origCalledNum[ASN197ADE_NUMDIGITS_STRSIZE+1];
char divertName[ASN197NO_NAME_STRSIZE+1];
char origCalledName[ASN197NO_NAME_STRSIZE+1];
unsigned int temp = 0;
unsigned int temp2 = 0;
divertNum[0] = 0;
origCalledNum[0] = 0;
divertNum[0] = 0;
divertName[0] = 0;
origCalledName[0] = 0;
cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling QSIG LEG INFO2 (id# %#x)\n", invoke->id);
if (invoke->data[myidx++] != (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */
/* We do not handle this, because it should start with an sequence tag */
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - not a sequence\n");
return;
}
/* This facility is encoded as SEQUENCE */
seqlength = invoke->data[myidx++];
datalength = invoke->datalen;
if (datalength < (seqlength+1)) {
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - buffer error\n");
return;
}
if (invoke->data[myidx++] == ASN1_INTEGER)
divCount = cc_qsig_asn1_get_integer(invoke->data, &myidx);
if (invoke->data[myidx++] == ASN1_ENUMERATED)
divReason = cc_qsig_asn1_get_integer(invoke->data, &myidx);
while (myidx < datalength) {
parameter = (invoke->data[myidx++] & 0x0f);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Found parameter %i\n", parameter);
switch (parameter) {
case 0:
myidx++; /* Ignore Length of enumeration tag*/
if (invoke->data[myidx++] == ASN1_ENUMERATED)
orgDivReason = cc_qsig_asn1_get_integer(invoke->data, &myidx);
break;
case 1:
temp = cc_qsig_asn197ade_get_partynumber(divertNum, ASN197ADE_NUMDIGITS_STRSIZE, &myidx, invoke->data);
if (temp) {
myidx += temp;
}
break;
case 2:
temp = cc_qsig_asn197ade_get_partynumber(origCalledNum, ASN197ADE_NUMDIGITS_STRSIZE, &myidx, invoke->data);
if (temp) {
myidx += temp;
}
break;
case 3:
/* Redirecting Name */
myidx++;
temp = cc_qsig_asn197no_get_name(divertName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data);
if (temp) {
myidx += temp;
}
break;
case 4:
/* origCalled Name */
myidx++;
temp = cc_qsig_asn197no_get_name(origCalledName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data);
if (temp) {
myidx += temp;
}
break;
}
}
snprintf(tempstr, 5, "%i", divReason);
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVREASON", tempstr);
snprintf(tempstr, 5, "%i", orgDivReason);
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVREASON", tempstr);
snprintf(tempstr, 5, "%i", divCount);
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVCOUNT", tempstr);
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVNUM", divertNum);
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVNUM", origCalledNum);
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVNAME", divertName);
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVNAME", origCalledName);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Got QSIG_LEG_INFO2: %i(%i), %ix %s->%s, %s->%s\n", divReason, orgDivReason, divCount, origCalledNum, divertNum, origCalledName, divertName);
return;
}
/*
* Encode Operation: 1.3.12.9.12 ECMA/ISDN/CALLTRANSFER
*
* This function encodes the call transfer facility
*
* 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
* param is parameter from capicommand
* info this facility is part of 2, 0 is facility 1, 1 is facility 2
* returns
* always 0
*/
void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param, int info)
{
char *cid, *ccanswer;
char *name = NULL;
int icanswer = 0;
int cidlen = 0;
int namelength = 0;
int seqlen = 13;
char c[255];
int ix = 0;
if (param) { /* got Call Transfer Parameters */
if (info) {
cid = strsep(&param, "|");
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
} else {
char *tmp = strsep(&param, "|");
tmp = NULL;
cid = strsep(&param, "|");
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
ccanswer = strsep(&param, "|");
if (ccanswer[0])
icanswer = ccanswer[0] - 0x30;
}
} else {
/* cid = strdup(i->owner->cid.cid_num);*/ /* Here we get the Asterisk extension */
if (info) { /* info is >0 on outbound channel (second facility) */
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
cid = strdup(i->cid);
cidlen = strlen(cid);
if (ii) {
/* send callers name to user B */
if (ii->owner->cid.cid_name) {
name = ast_strdupa(ii->owner->cid.cid_name);
namelength = strlen(name);
}
}
} else { /* have to build first facility - send destination number back to inbound channel */
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
cid = strdup(ii->dnid);
cidlen = strlen(cid);
if (ii) {
/* send destination name to user A */
if (ii->qsig_data.dnameid) {
name = ast_strdupa(ii->qsig_data.dnameid);
namelength = strlen(name);
}
}
}
if (!info)
icanswer = i->qsig_data.calltransfer_onring % 1;
}
seqlen += cidlen;
if (namelength)
seqlen += 4 + namelength;
c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */
c[ix++] = seqlen;
c[ix++] = ASN1_ENUMERATED; /* End Designation */
c[ix++] = 1; /* length */
c[ix++] = info;
c[ix++] = (ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED) + 0; /* val 0 - Source Caller ID struct */
c[ix++] = 5 + cidlen;
c[ix++] = ASN1_TC_CONTEXTSPEC; /* CallerID */
c[ix++] = cidlen;
memcpy(&c[ix], cid, cidlen);
ix += cidlen;
c[ix++] = ASN1_ENUMERATED; /* Screening Indicator */
c[ix++] = 1; /* length */
c[ix++] = 1; /* 01 = userProvidedVerifiedAndPassed ...we hope so */
{
if (namelength) {
c[ix++] = (ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED) + 1; /* val 1 - Source Caller ID struct */
c[ix++] = 2 + namelength;
c[ix++] = ASN1_OCTETSTRING; /* CallerID */
c[ix++] = namelength;
memcpy(&c[ix], name, namelength);
ix += namelength;
}
}
c[ix++] = ASN1_ENUMERATED; /* val 3 - wait for connect ? */
c[ix++] = 1;
c[ix++] = icanswer;
/* end of SEQUENCE */
/* there are optional data possible here */
invoke->id = 12;
invoke->descr_type = -1;
invoke->type = 12; /* Invoke Operation Code */
invoke->datalen = ix;
memcpy(invoke->data, c, ix);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending QSIG_CT: %i->%s\n", info, cid);
if (cid)
free(cid);
}
/*
* Decode Operation: 1.3.12.9.12 ECMA/ISDN/CALLTRANSFER
*
* This function decodes the call transfer facility
*
* 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 from facility
* i is pointer to capi channel
* returns
* transfer to destination number
*/
char *cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
{
unsigned int datalength;
unsigned int seqlength = 0;
unsigned char *data = invoke->data;
int myidx = 0;
/* TODO: write more code */
char *ct_status_txt[] = { "ANSWERED", "ALERTING" };
int ct_status = 0;
char ct_target[ASN197ADE_NUMDIGITS_STRSIZE+1] = { 0 };
char ct_name[ASN197NO_NAME_STRSIZE+1] = { "EMPTY" };
int ct_enddesignation = 0;
int ct_numberpresentation = 0;
unsigned int namelength = 0;
int temp = 0;
#define ct_err(x...) { cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG CALL TRANSFER - "x); return NULL; }
cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling QSIG CALL TRANSFER (id# %#x)\n", invoke->id);
if (data[myidx++] != (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */
/* We do not handle this, because it should start with an sequence tag */
ct_err("not a sequence\n");
}
/* This facility is encoded as SEQUENCE */
seqlength = data[myidx++];
datalength = invoke->datalen;
if (datalength < (seqlength+1)) {
ct_err("buffer error\n");
}
if (data[myidx++] == ASN1_ENUMERATED) {
ct_enddesignation = cc_qsig_asn1_get_integer(data, &myidx);
} else {
ct_err("no endDesignation information.\n");
}
if (data[myidx] == (ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED | 0)) { /* Parameter 0: partyNumber - transferee number */
myidx ++;
temp = cc_qsig_asn197ade_get_partynumber(ct_target, ASN197ADE_NUMDIGITS_STRSIZE+1, &myidx, data);
if (temp)
myidx += temp + 1;
/* HACK: this has to be moved to _get_presentednumberscreened */
if (data[myidx++] == ASN1_ENUMERATED) {
ct_numberpresentation = cc_qsig_asn1_get_integer(data, &myidx);
} else {
ct_err("screeningIndicator is missing.\n");
return NULL;
}
} else {
myidx += 2; /* HACK: I've seen an IMPLICIT ade "numberNotAvailableDueToInterworking NULL" */
}
/* TODO: remove this code snippet, when it's 100% working */
/*
if (data[myidx++] == (ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED | 0)) { */ /* Parameter 0: partyNumber - transferee number */
/* if (!data[myidx++]) /* length = 0 */
/* ct_err("No destination received.\n");
if (data[myidx++] != ASN1_TC_CONTEXTSPEC)
ct_err("No destination received.\n");
temp = cc_qsig_asn1_get_string((unsigned char*)&ct_target, sizeof(ct_target), &data[myidx]);
if (temp) {
myidx += temp + 1;
} else {
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG CALL TRANSFER - partyNumber expected (%i)\n", myidx);
return NULL;
}
if (data[myidx++] == ASN1_ENUMERATED) {
ct_numberpresentation = cc_qsig_asn1_get_integer(data, &myidx);
} else {
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG CALL TRANSFER - wrong encoded #2.\n");
return NULL;
}
}*/
if (myidx < datalength) {
if (data[myidx] == ASN1_TC_APPLICATION) {
/* ignore special Application Parameters - have no info about content */
myidx++;
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG CALL TRANSFER - ignoring application data (%i bytes).\n", (int)data[myidx]);
myidx += data[myidx] + 1;
}
}
if (myidx < datalength) {
if (data[myidx] != ASN1_ENUMERATED) { /* Maybe we get an name (OPTIONAL) */
myidx += cc_qsig_asn197no_get_name(ct_name, ASN197NO_NAME_STRSIZE+1, &namelength, &myidx, data );
}
}
if (myidx < datalength) {
if (data[myidx++] == ASN1_ENUMERATED) { /* Call Status */
ct_status = cc_qsig_asn1_get_integer(data, &myidx);
}
}
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Got QSIG CALL TRANSFER endDesignation: %i partyNumber: %s (ScreeningInd: %i), partyName: \"%s\", Call state: %s\n", ct_enddesignation, ct_target, ct_numberpresentation, ct_name, ct_status_txt[ct_status]);
return strdup(ct_target);
#undef ct_err
}
/*
* Encode Operation: 1.3.12.9.99 ECMA/ISDN/SINGLESTEPCALLTRANSFER
*
* This function encodes the single step call transfer facility
*
* 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
* param is parameter from capicommand
* returns
* always 0
*/
void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
{
char *cidsrc, *ciddst;
int srclen, dstlen;
int seqlen = 12;
char c[255];
int ix = 0;
cidsrc = strsep(&param, "|");
srclen = strlen(cidsrc);
if (srclen > 20) /* HACK: stop action here, maybe we have invalid data */
srclen = 20;
ciddst = strsep(&param, "|");
dstlen = strlen(ciddst);
if (dstlen > 20) /* HACK: stop action here, maybe we have invalid data */
dstlen = 20;
seqlen += srclen + dstlen;
c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */
c[ix++] = seqlen;
c[ix++] = ASN1_TC_CONTEXTSPEC; /* val 1 - Destination CallerID */
c[ix++] = dstlen;
memcpy(&c[ix], ciddst, dstlen);
ix += dstlen;
c[ix++] = ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED; /* val 2 - Source Caller ID struct */
c[ix++] = 5 + srclen;
c[ix++] = ASN1_TC_CONTEXTSPEC; /* CallerID */
c[ix++] = srclen;
memcpy(&c[ix], cidsrc, srclen);
ix += srclen;
c[ix++] = ASN1_ENUMERATED; /* Screening Indicator */
c[ix++] = 1; /* length */
c[ix++] = 1; /* 01 = userProvidedVerifiedAndPassed ...we hope so */
c[ix++] = ASN1_BOOLEAN; /* val 3 - wait for connect ? */
c[ix++] = 1;
c[ix++] = 0;
/* end of SEQUENCE */
/* there are optional data possible here */
invoke->id = 99;
invoke->descr_type = -1;
invoke->type = 99;
invoke->datalen = ix;
memcpy(invoke->data, c, ix);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending QSIG_SSCT: %s->%s\n", cidsrc, ciddst);
}
/*
* Handle Operation: 1.3.12.9.19 ECMA/ISDN/PATH REPLACEMENT PROPOSE
*
* This function decodes the PATH REPLACEMENT PROPOSE facility
* The datas will be copied in the some capi_pvt channel variables
*
* parameters
* invoke struct, which contains encoded data from facility
* i is pointer to capi channel
* returns
* nothing
*/
void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
{
unsigned int datalength;
unsigned int seqlength = 0;
int myidx = 0;
/* TODO: write more code */
char callid[4+1];
char reroutingnr[ASN197ADE_NUMDIGITS_STRSIZE+1];
int temp = 0;
callid[0] = 0;
reroutingnr[0] = 0;
cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling QSIG PATH REPLACEMENT PROPOSE (id# %#x)\n", invoke->id);
if (invoke->data[myidx++] != (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */
/* We do not handle this, because it should start with an sequence tag */
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - not a sequence\n");
return;
}
/* This facility is encoded as SEQUENCE */
seqlength = invoke->data[myidx++];
datalength = invoke->datalen;
if (datalength < (seqlength+1)) {
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - buffer error\n");
return;
}
if (invoke->data[myidx++] == ASN1_NUMERICSTRING) {
int strsize;
strsize = cc_qsig_asn1_get_string((unsigned char*)&callid, sizeof(callid), &invoke->data[myidx]);
myidx += strsize +1;
} else {
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - NUMERICSTRING expected\n");
return;
}
if (invoke->data[myidx++] == ASN1_TC_CONTEXTSPEC)
temp = cc_qsig_asn1_get_string((unsigned char*)&reroutingnr, sizeof(reroutingnr), &invoke->data[myidx]);
if (temp) {
myidx += temp;
} else {
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - partyNumber expected (%i)\n", myidx);
return;
}
i->qsig_data.pr_propose_cid = strdup(callid);
i->qsig_data.pr_propose_pn = strdup(reroutingnr);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Got QSIG_PATHREPLACEMENT_PROPOSE Call identity: %s, Party number: %s (%i)\n", callid, reroutingnr, temp);
return;
}
/*
* Encode Operation: 1.3.12.9.19 ECMA/ISDN/PATH REPLACEMENT PROPOSE
*
* This function encodes the path replacement propose
*
* 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
* param is parameter from capicommand
* returns
* always 0
*/
void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
{
/* TODO: write code */
int invokeop = 4;
char *callid, *reroutingnr;
int cidlen, rrnlen;
int seqlen = 4;
char c[255];
int ix = 0;
if (!i->qsig_data.pr_propose_cid)
return ;
if (!i->qsig_data.pr_propose_pn)
return ;
callid = i->qsig_data.pr_propose_cid;
reroutingnr = i->qsig_data.pr_propose_pn;
cidlen = strlen(callid);
rrnlen = strlen(reroutingnr);
seqlen += cidlen + rrnlen;
c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */
c[ix++] = seqlen;
c[ix++] = ASN1_NUMERICSTRING; /* val 1 - CallID */
c[ix++] = cidlen;
memcpy(&c[ix], callid, cidlen);
ix += cidlen;
c[ix++] = ASN1_TC_CONTEXTSPEC; /* val 2 - Rerouting number*/
c[ix++] = rrnlen;
memcpy(&c[ix], reroutingnr, rrnlen);
ix += rrnlen;
/* end of SEQUENCE */
/* there are optional data possible here */
invoke->id = invokeop;
invoke->descr_type = -1;
invoke->type = invokeop;
invoke->datalen = ix;
memcpy(invoke->data, c, ix);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending QSIG_PATHREPLACEMENT_PROPOSE: Call identity: %s, Party number: %s\n", callid, reroutingnr);
return;
}