From 84550afacfdeb4392cf240a37f240e6b6c29bfe0 Mon Sep 17 00:00:00 2001 From: MelwareDE Date: Thu, 6 Dec 2007 19:07:28 +0000 Subject: [PATCH] QSIG: - code cleanup - some minor bugfixes - bugfix in LEG_INFO2 code - caused a asterisk crash - adapted some macros from libpri, to make code more readable - started code for outbound CCNR requests --- README.qsig | 8 +- chan_capi.c | 44 ++++++++++ chan_capi_qsig.h | 89 +++++++++++++++++++ chan_capi_qsig_asn197ade.c | 10 +-- chan_capi_qsig_asn197no.c | 6 +- chan_capi_qsig_core.c | 173 +++++++++++++++++++++++++------------ chan_capi_qsig_ecma.c | 126 ++++++++++++++++++++------- chan_capi_qsig_ecma.h | 12 +++ 8 files changed, 373 insertions(+), 95 deletions(-) diff --git a/README.qsig b/README.qsig index 1108dea..4ea1344 100644 --- a/README.qsig +++ b/README.qsig @@ -65,7 +65,7 @@ The QSIG support includes: - Call Transfer (outgoing) You can do an outbound call transfer. - First you need the PLCI (logical channel id) of your first channel. You'll get it with capicommand(getplci). This + First you need the PLCI (logical channel id) of your first channel. You'll get it with capicommand(qsig_getplci). This command returns the channel id in the variable QSIG_PLCI. Now you can enable the call transfer feature. Simply add "Ct" to QSIG_SETUP (i.e. QSIG_SETUP="X/Ct${QSIG_PLCI}" ). On the next dial command the call will be automatically transferred. The transfer occurs after the CONNECT. If you want an transfer early on ringing you @@ -104,6 +104,12 @@ Future Targets: How to use: =========== +You will find more documentation at the chan_capi wiki. + +Please visit: http://www.melware.org/ChanCapiConf + + + simply enable Q.SIG with following line in your capi.conf interface: Here we go with new configuration diff --git a/chan_capi.c b/chan_capi.c index a22c63c..1e0cc65 100644 --- a/chan_capi.c +++ b/chan_capi.c @@ -5529,6 +5529,34 @@ static int pbxcli_capi_no_debug(int fd, int argc, char *argv[]) return RESULT_SUCCESS; } +/* + * enable QSIG debugging + */ +static int pbxcli_capi_qsig_do_debug(int fd, int argc, char *argv[]) +{ + if (argc != 3) + return RESULT_SHOWUSAGE; + + capiqsigdebug = 1; + ast_cli(fd, "CAPI QSIG Debugging Enabled\n"); + + return RESULT_SUCCESS; +} + +/* + * disable QSIG debugging + */ +static int pbxcli_capi_qsig_no_debug(int fd, int argc, char *argv[]) +{ + if (argc != 4) + return RESULT_SHOWUSAGE; + + capiqsigdebug = 0; + ast_cli(fd, "CAPI QSIG Debugging Disabled\n"); + + return RESULT_SUCCESS; +} + /* * usages */ @@ -5548,6 +5576,14 @@ static char no_debug_usage[] = "Usage: capi no debug\n" " Disables dumping of CAPI packets for debugging purposes\n"; +static char qsig_debug_usage[] = +"Usage: capi qsig debug\n" +" Enables dumping of CAPI QSIG facilities for debugging purposes\n"; + +static char qsig_no_debug_usage[] = +"Usage: capi qsig no debug\n" +" Disables dumping of CAPI QSIG facilities for debugging purposes\n"; + static char chatinfo_usage[] = "Usage: capi chatinfo\n" " Show info about chat status.\n"; @@ -5563,6 +5599,10 @@ static struct ast_cli_entry cli_debug = { { "capi", "debug", NULL }, pbxcli_capi_do_debug, "Enable CAPI debugging", debug_usage }; static struct ast_cli_entry cli_no_debug = { { "capi", "no", "debug", NULL }, pbxcli_capi_no_debug, "Disable CAPI debugging", no_debug_usage }; +static struct ast_cli_entry cli_qsig_debug = + { { "capi", "qsig", "debug", NULL }, pbxcli_capi_qsig_do_debug, "Enable CAPI QSIG debugging", qsig_debug_usage }; +static struct ast_cli_entry cli_qsig_no_debug = + { { "capi", "qsig", "no", "debug", NULL }, pbxcli_capi_qsig_no_debug, "Disable CAPI QSIG debugging", qsig_no_debug_usage }; static struct ast_cli_entry cli_chatinfo = { { "capi", "chatinfo", NULL }, pbxcli_capi_chatinfo, "Show CAPI chat info", chatinfo_usage }; @@ -6091,6 +6131,8 @@ int unload_module(void) ast_cli_unregister(&cli_show_channels); ast_cli_unregister(&cli_debug); ast_cli_unregister(&cli_no_debug); + ast_cli_unregister(&cli_qsig_debug); + ast_cli_unregister(&cli_qsig_no_debug); ast_cli_unregister(&cli_chatinfo); #ifdef CC_AST_HAS_VERSION_1_4 @@ -6198,6 +6240,8 @@ int load_module(void) ast_cli_register(&cli_show_channels); ast_cli_register(&cli_debug); ast_cli_register(&cli_no_debug); + ast_cli_register(&cli_qsig_debug); + ast_cli_register(&cli_qsig_no_debug); ast_cli_register(&cli_chatinfo); ast_register_application(commandapp, pbx_capicommand_exec, commandsynopsis, commandtdesc); diff --git a/chan_capi_qsig.h b/chan_capi_qsig.h index 57c7f79..499cf84 100644 --- a/chan_capi_qsig.h +++ b/chan_capi_qsig.h @@ -14,6 +14,8 @@ #ifndef PBX_QSIG_H #define PBX_QSIG_H +int capiqsigdebug; + #define QSIG_DISABLED 0x00 #define QSIG_ENABLED 0x01 /* shouldn't be used anymore */ @@ -102,6 +104,91 @@ #define CCQSIG_TIMER_WAIT_PRPROPOSE 1 /* Wait x seconds */ +struct rose_component { + u_int8_t type; + u_int8_t len; + u_int8_t data[0]; +}; + +#define GET_COMPONENT(component, idx, ptr, length) \ + if ((idx)+2 > (length)) \ + break; \ + (component) = (struct rose_component*)&((ptr)[idx]); \ + if ((idx)+(component)->len+2 > (length)) { \ + if ((component)->len != ASN1_LEN_INDEF) \ + pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \ +} + +#define NEXT_COMPONENT(component, idx) \ + (idx) += (component)->len + 2 + +#define SUB_COMPONENT(component, idx) \ + (idx) += 2 + +#define CHECK_COMPONENT(component, comptype, message) \ + if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \ + pri_message(pri, (message), (component)->type); \ + asn1_dump(pri, (component), (component)->len+2); \ + break; \ +} + +#define ASN1_GET_INTEGER(component, variable) \ + do { \ + int comp_idx; \ + (variable) = 0; \ + for (comp_idx = 0; comp_idx < (component)->len; ++comp_idx) \ + (variable) = ((variable) << 8) | (component)->data[comp_idx]; \ +} while (0) + +#define ASN1_FIXUP_LEN(component, size) \ + do { \ + if ((component)->len == ASN1_LEN_INDEF) \ + size += 2; \ +} while (0) + +#define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \ + do { \ + (component) = (struct rose_component *)&((ptr)[(idx)]); \ + (component)->type = (comptype); \ + (component)->len = 0; \ + (idx) += 2; \ +} while (0) + +#define ASN1_ADD_BYTECOMP(component, comptype, ptr, idx, value) \ + do { \ + (component) = (struct rose_component *)&((ptr)[(idx)]); \ + (component)->type = (comptype); \ + (component)->len = 1; \ + (component)->data[0] = (value); \ + (idx) += 3; \ +} while (0) + +#define ASN1_ADD_WORDCOMP(component, comptype, ptr, idx, value) \ + do { \ + int __val = (value); \ + int __i = 0; \ + (component) = (struct rose_component *)&((ptr)[(idx)]); \ + (component)->type = (comptype); \ + if ((__val >> 24)) \ + (component)->data[__i++] = (__val >> 24) & 0xff; \ + if ((__val >> 16)) \ + (component)->data[__i++] = (__val >> 16) & 0xff; \ + if ((__val >> 8)) \ + (component)->data[__i++] = (__val >> 8) & 0xff; \ + (component)->data[__i++] = __val & 0xff; \ + (component)->len = __i; \ + (idx) += 2 + __i; \ +} while (0) + +#define ASN1_PUSH(stack, stackpointer, component) \ + (stack)[(stackpointer)++] = (component) + +#define ASN1_FIXUP(stack, stackpointer, data, idx) \ + do { \ + --(stackpointer); \ + (stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \ +} while (0) + #define free_null(x) { free(x); x = NULL; } @@ -150,6 +237,7 @@ struct cc_qsig_nfe { /* *** QSIG Core Functions */ +extern void cc_qsig_verbose(int c_d, char *text, ...); extern int cc_qsig_build_facility_struct(unsigned char * buf, unsigned int *idx, int protocolvar, int apdu_interpr, struct cc_qsig_nfe *nfe); extern int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i); @@ -157,6 +245,7 @@ extern int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_ extern unsigned int cc_qsig_asn1_get_string(unsigned char *buf, int buflen, unsigned char *data); extern unsigned int cc_qsig_asn1_get_integer(unsigned char *data, int *idx); extern unsigned char *cc_qsig_asn1_oid2str(unsigned char *data, int size); +extern int cc_qsig_asn1_add_string2(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len); extern unsigned int cc_qsig_asn1_add_string(unsigned char *buf, int *idx, char *data, int datalen); extern unsigned int cc_qsig_asn1_add_integer(unsigned char *buf, int *idx, int value); diff --git a/chan_capi_qsig_asn197ade.c b/chan_capi_qsig_asn197ade.c index 4db2cf8..a4c6202 100644 --- a/chan_capi_qsig_asn197ade.c +++ b/chan_capi_qsig_asn197ade.c @@ -50,7 +50,7 @@ unsigned int cc_qsig_asn197ade_get_partynumber(char *buf, int buflen, int *idx, numtype = (data[myidx++] & 0x0F); /* defines type of Number: numDigits, publicPartyNum, nsapEncNum, dataNumDigits */ - /* cc_verbose(1, 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */ + /* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */ switch (numtype){ case 0: if (data[myidx] > 0) { /* length of this context data */ @@ -79,7 +79,7 @@ unsigned int cc_qsig_asn197ade_get_partynumber(char *buf, int buflen, int *idx, } break; }; - /* cc_verbose(1, 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */ + /* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */ return myidx - *idx; } @@ -97,7 +97,7 @@ unsigned int cc_qsig_asn197ade_get_numdigits(char *buf, int buflen, int *idx, un memcpy(buf, &data[myidx], strsize); buf[strsize] = 0; - /* cc_verbose(1, 1, VERBOSE_PREFIX_4 " * string length %i,%i\n", strsize, *idx); */ + /* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * string length %i,%i\n", strsize, *idx); */ return strsize; } @@ -138,12 +138,12 @@ unsigned int cc_qsig_asn197ade_get_pns(unsigned char *data, int *idx, struct asn numtype = (data[myidx++] & 0x0F); /* defines type of Number */ - /* cc_verbose(1, 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */ + /* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */ switch (numtype){ case 0: /* myidx points now to length */ res = cc_qsig_asn197ade_get_partynumber(buf, buflen, &myidx, data); - /* cc_verbose(1, 1, VERBOSE_PREFIX_4 " * res %i\n", numtype); */ + /* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * res %i\n", numtype); */ if (!res) return 0; diff --git a/chan_capi_qsig_asn197no.c b/chan_capi_qsig_asn197no.c index 4bc989a..2dc324a 100644 --- a/chan_capi_qsig_asn197no.c +++ b/chan_capi_qsig_asn197no.c @@ -54,7 +54,7 @@ unsigned int cc_qsig_asn197no_get_name(char *buf, int buflen, unsigned int *bufd /* This facility is encoded as SEQUENCE */ seqlength = data[++myidx]; myidx++; - cc_verbose(1, 1, VERBOSE_PREFIX_4 " Got name sequence (Length= %i)\n", seqlength); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " Got name sequence (Length= %i)\n", seqlength); } if (nametag < 0x80) { /* Tag shows an simple String */ @@ -76,13 +76,13 @@ unsigned int cc_qsig_asn197no_get_name(char *buf, int buflen, unsigned int *bufd namelength = cc_qsig_asn1_get_string((unsigned char *)buf, buflen, &data[myidx]); myidx += namelength + 1; } else { - cc_verbose(1, 1, VERBOSE_PREFIX_4 " Namestruct not ECMA conform (String expected)\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " Namestruct not ECMA conform (String expected)\n"); break; } if (data[myidx++] == ASN1_INTEGER) { charset = cc_qsig_asn1_get_integer(data, &myidx); } else { - cc_verbose(1, 1, VERBOSE_PREFIX_4 " Namestruct not ECMA conform (Integer expected)\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " Namestruct not ECMA conform (Integer expected)\n"); } break; case 4: /* Name not available */ diff --git a/chan_capi_qsig_core.c b/chan_capi_qsig_core.c index 841a009..ac5a94c 100644 --- a/chan_capi_qsig_core.c +++ b/chan_capi_qsig_core.c @@ -28,6 +28,69 @@ #include "chan_capi_qsig_asn197ade.h" #include "chan_capi_qsig_asn197no.h" +AST_MUTEX_DEFINE_STATIC(qsig_verbose_lock); + +/* + * helper for _verbose with different verbose settings + */ +void cc_qsig_verbose(int c_d, char *text, ...) +{ + char line[4096]; + va_list ap; + + va_start(ap, text); + vsnprintf(line, sizeof(line), text, ap); + va_end(ap); + +#if 0 + { + FILE *fp; + if ((fp = fopen("/tmp/cclog", "a")) != NULL) { + fprintf(fp, "%s", line); + fclose(fp); + } + } +#endif + + if (option_verbose > 4) { + if ((!c_d) || ((c_d) && (capiqsigdebug))) { + cc_mutex_lock(&qsig_verbose_lock); + cc_pbx_verbose(line); + cc_mutex_unlock(&qsig_verbose_lock); + } + } +} + + +/*! + * \brief Encodes an ASN.1 string with type of string + * + * \param asn1_type type of string like ASN1_OCTETSTRING + * \param data pointer to target buffer + * \param len size of target buffer + * \param max_len of the string data + * \param src source pointer for string + * \param src_len string length + * \return data length + */ +int cc_qsig_asn1_add_string2(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len) +{ + struct rose_component *comp = NULL; + + if (len < 2 + src_len) + return -1; + + if (max_len && (src_len > max_len)) + src_len = max_len; + + comp = (struct rose_component *)data; + comp->type = asn1_type; + comp->len = src_len; + memcpy(comp->data, src, src_len); + + return 2 + src_len; +} + /*! * \brief Encodes an ASN.1 string * @@ -110,7 +173,7 @@ unsigned int cc_qsig_asn1_get_integer(unsigned char *data, int *idx) intlen = data[myidx++]; if ((intlen < 1) || (intlen > 2)) { /* i don't know if there's a bigger Integer as 16bit -> read specs */ - cc_verbose(1, 1, VERBOSE_PREFIX_3 "ASN1Decode: Size of ASN.1 Integer not supported: %i\n", intlen); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "ASN1Decode: Size of ASN.1 Integer not supported: %i\n", intlen); *idx = myidx + intlen; return 0; } @@ -137,7 +200,7 @@ unsigned char *cc_qsig_asn1_oid2str(unsigned char *data, int size) s = buf; if (size < 3) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "OID2STR: Object identifier too small (%i).\n", size); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "OID2STR: Object identifier too small (%i).\n", size); return NULL; } @@ -279,7 +342,7 @@ int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_in myidx += invoke->oid_len; break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unknown Invoke Type, not encoded (%i)\n", invoke->descr_type); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unknown Invoke Type, not encoded (%i)\n", invoke->descr_type); return -1; break; } @@ -308,18 +371,18 @@ unsigned int cc_qsig_check_facility(unsigned char *data, int *idx, int *apduval, /* First byte after Facility Length */ if (data[myidx] != (unsigned char)(0x80 | protocol)) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: received protocol 0x%#x not configured!\n", (data[myidx] ^= 0x80)); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: received protocol 0x%#x not configured!\n", (data[myidx] ^= 0x80)); return 0; } myidx++; - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Supplementary Services\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Supplementary Services\n"); if (data[myidx] == (unsigned char)COMP_TYPE_NFE) { myidx++; /* TODO: Check Entities? */ myidx += data[myidx] + 1; *idx = myidx; - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Facility has NFE struct\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Facility has NFE struct\n"); } if ((data[myidx] == (unsigned char)COMP_TYPE_APDU_INTERP)) { myidx++; @@ -327,7 +390,7 @@ unsigned int cc_qsig_check_facility(unsigned char *data, int *idx, int *apduval, *apduval = data[myidx++]; /* TODO: implement real reject or clear call ? */ *idx = myidx; - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Facility has APDU - What to do if INVOKE is unknown: %s\n", APDU_STR[*apduval]); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Facility has APDU - What to do if INVOKE is unknown: %s\n", APDU_STR[*apduval]); } return 1; } @@ -375,7 +438,7 @@ signed int cc_qsig_get_invokeid(unsigned char *data, int *idx, struct cc_qsig_in invoke->offset = invoffset; /* offset in Facility Array, where the Invoke Data starts */ invidtype = data[myidx++]; /* Get INVOKE Id Type */ if (invidtype != ASN1_INTEGER) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unknown Invoke Identifier Type 0x%#x\n", invidtype); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unknown Invoke Identifier Type 0x%#x\n", invidtype); return -1; } temp = cc_qsig_asn1_get_integer(data, &myidx); @@ -408,7 +471,7 @@ signed int cc_qsig_fill_invokestruct(unsigned char *data, int *idx, struct cc_qs datalen = temp2 - myidx; if (datalen > 255) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation Size (max 255 Bytes): %i\n", datalen); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation Size (max 255 Bytes): %i\n", datalen); datalen = 255; } @@ -424,7 +487,7 @@ signed int cc_qsig_fill_invokestruct(unsigned char *data, int *idx, struct cc_qs invoke->descr_type = ASN1_OBJECTIDENTIFIER; temp = data[myidx++]; /* Length of OID */ if (temp > 20) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation OID Size (max 20 Bytes): %i\n", temp); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation OID Size (max 20 Bytes): %i\n", temp); temp = 20; } @@ -444,7 +507,7 @@ signed int cc_qsig_fill_invokestruct(unsigned char *data, int *idx, struct cc_qs datalen = temp2 - myidx; if (datalen > 255) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation Size (max 255 Bytes): %i\n", datalen); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation Size (max 255 Bytes): %i\n", datalen); datalen = 255; } @@ -456,13 +519,13 @@ signed int cc_qsig_fill_invokestruct(unsigned char *data, int *idx, struct cc_qs break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unknown INVOKE Operation Type: %i\n", invoptyp); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unknown INVOKE Operation Type: %i\n", invoptyp); temp2 = (invoke->len) + (invoke->offset) + 1; /* Array End = Invoke Length + Invoke Offset +1 */ datalen = temp2 - myidx; if (datalen > 255) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation Size (max 255 Bytes): %i\n", datalen); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unsupported INVOKE Operation Size (max 255 Bytes): %i\n", datalen); datalen = 255; } @@ -489,7 +552,7 @@ static int ident_qsig_invoke(int invoketype) case 21: return CCQSIG__ECMA__LEGINFO2; default: - cc_verbose(1, 1, VERBOSE_PREFIX_4 "QSIG: Unhandled QSIG INVOKE (%i)\n", invoketype); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "QSIG: Unhandled QSIG INVOKE (%i)\n", invoketype); return -1; } } @@ -502,14 +565,14 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco int invokedescrtype = 0; int datalen; -/* cc_verbose(1, 1, VERBOSE_PREFIX_4 "CONNECT_IND (Ident Invoke %i)\n", invoke->descr_type); */ +/* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "CONNECT_IND (Ident Invoke %i)\n", invoke->descr_type); */ switch (protocol) { case QSIG_TYPE_ALCATEL_ECMA: switch (invoke->descr_type) { case ASN1_INTEGER: invokedescrtype = 1; - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%i)\n", invoke->type); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%i)\n", invoke->type); return ident_qsig_invoke(invoke->type); break; case ASN1_OBJECTIDENTIFIER: @@ -519,10 +582,10 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco unsigned char *oidstr = NULL; oidstr = cc_qsig_asn1_oid2str(invoke->oid_bin, invoke->oid_len); if (oidstr) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%s)\n", oidstr); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%s)\n", oidstr); free(oidstr); } else { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (unknown - OID not displayable)\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (unknown - OID not displayable)\n"); } if ((datalen) == 4) { @@ -533,7 +596,7 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco return -1; break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unidentified INVOKE OP\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unidentified INVOKE OP\n"); break; } break; @@ -541,7 +604,7 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco switch (invoke->descr_type) { case ASN1_INTEGER: invokedescrtype = 1; - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%i)\n", invoke->type); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%i)\n", invoke->type); return ident_qsig_invoke(invoke->type); break; case ASN1_OBJECTIDENTIFIER: @@ -551,10 +614,10 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco unsigned char *oidstr = NULL; oidstr = cc_qsig_asn1_oid2str(invoke->oid_bin, invoke->oid_len); if (oidstr) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%s)\n", oidstr); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%s)\n", oidstr); free(oidstr); } else { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (unknown - OID not displayable)\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (unknown - OID not displayable)\n"); } if ((datalen) == 4) { @@ -564,7 +627,7 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco } break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Unidentified INVOKE OP\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Unidentified INVOKE OP\n"); break; } break; @@ -623,18 +686,18 @@ static void pbx_capi_qsig_handle_ctc(struct cc_qsig_invokedata *invoke, struct c ii = capi_find_interface_bynumber(ctc.redirectionNumber.partyNumber); if (ii) { char *prpn = i->qsig_data.if_pr_propose_pn; - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Call Transfer partner channel for %s found at channel %s, bridging possible.\n", ctc.redirectionNumber.partyNumber, ii->vname); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Call Transfer partner channel for %s found at channel %s, bridging possible.\n", ctc.redirectionNumber.partyNumber, ii->vname); if (!(strlen(prpn))) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Path Replacement not configured, bridging not available!\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Path Replacement not configured, bridging not available!\n"); } else { unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE]; - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: Trying to bridge with Path Replacement number %s...\n", prpn); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: Trying to bridge with Path Replacement number %s...\n", prpn); switch (ii->state) { case CAPI_STATE_ALERTING: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: peer is in state ALERTING, PATH REPLACE follows after CONNECT...\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: peer is in state ALERTING, PATH REPLACE follows after CONNECT...\n"); ii->qsig_data.pr_propose_cid = strdup("123"); /* HACK: need an dynamic ID */ ii->qsig_data.pr_propose_pn = strdup(i->qsig_data.if_pr_propose_pn); ii->qsig_data.pr_propose_doinboundbridge = 1; @@ -642,7 +705,7 @@ static void pbx_capi_qsig_handle_ctc(struct cc_qsig_invokedata *invoke, struct c i->qsig_data.partner_plci = ii->PLCI; break; case CAPI_STATE_CONNECTED: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: peer is CONNECTED...\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: peer is CONNECTED...\n"); i->qsig_data.pr_propose_cid = strdup("123"); /* HACK: need an dynamic ID */ i->qsig_data.pr_propose_pn = strdup(i->qsig_data.if_pr_propose_pn); ii->qsig_data.pr_propose_doinboundbridge = 1; @@ -657,7 +720,7 @@ static void pbx_capi_qsig_handle_ctc(struct cc_qsig_invokedata *invoke, struct c i->qsig_data.pr_propose_pn = NULL; break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "QSIG: peer's state is %i, which is not handled yet...\n", ii->state); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: peer's state is %i, which is not handled yet...\n", ii->state); break; } @@ -719,14 +782,14 @@ static int qsig_handle_q932facility(unsigned char *data, struct capi_pvt *i, int if (cc_qsig_check_facility(data, &facidx, &action_unkn_apdu, protocoltype)) { while ((facidx) < faclen) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Checking INVOKE at index %i (of %i)\n", facidx, faclen); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Checking INVOKE at index %i (of %i)\n", facidx, faclen); invoke_len = cc_qsig_check_invoke(data, &facidx); if (invoke_len > 0) { if (cc_qsig_get_invokeid(data, &facidx, &invoke) == 0) { invoketmp1 = cc_qsig_fill_invokestruct(data, &facidx, &invoke, action_unkn_apdu); invoke_op = cc_qsig_identifyinvoke(&invoke, i->qsigfeat); if (invoke_op < 0) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Invoke not identified!\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Invoke not identified!\n"); } cc_qsig_handle_invokeoperation(invoke_op, &invoke, i); } @@ -761,7 +824,7 @@ unsigned int cc_qsig_handle_capiind(unsigned char *data, struct capi_pvt *i) faclen = data[facidx++]; faclen += facidx; while (facidx < faclen0) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Checking Facility at index %i\n", facidx); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Checking Facility at index %i\n", facidx); switch (i->qsigfeat) { case QSIG_TYPE_ALCATEL_ECMA: qsig_handle_q932facility(data, i, &facidx, faclen, Q932_PROTOCOL_ROSE); @@ -770,23 +833,23 @@ unsigned int cc_qsig_handle_capiind(unsigned char *data, struct capi_pvt *i) qsig_handle_q932facility(data, i, &facidx, faclen, Q932_PROTOCOL_EXTENSIONS); break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Unknown QSIG protocol configured (%i)\n", i->qsigfeat); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Unknown QSIG protocol configured (%i)\n", i->qsigfeat); break; } if (facidx < faclen0) { /* there may follow a new facility */ if (data[facidx] == 0x1c) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Found another facility at index %i\n", facidx); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Found another facility at index %i\n", facidx); facidx++; faclen = data[facidx++]; faclen += facidx; } else { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "More data found in facility at index %i, but this is not an facility (%#x)\n", facidx, data[facidx]); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "More data found in facility at index %i, but this is not an facility (%#x)\n", facidx, data[facidx]); facidx++; /* don't start an endlessloop */ } } } - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Facility done at index %i from %i\n", facidx, faclen); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Facility done at index %i from %i\n", facidx, faclen); return 1; } @@ -802,9 +865,9 @@ unsigned int cc_qsig_handle_capi_facilityind(unsigned char *data, struct capi_pv return 0; } faclen = data[facidx++]; - /* cc_verbose(1, 1, VERBOSE_PREFIX_3 "CONNECT_IND (Got Facility IE, Length=%#x)\n", faclen); */ + /* cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "CONNECT_IND (Got Facility IE, Length=%#x)\n", faclen); */ while (facidx < faclen) { - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Checking Facility at index %i\n", facidx); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Checking Facility at index %i\n", facidx); switch (i->qsigfeat) { case QSIG_TYPE_ALCATEL_ECMA: qsig_handle_q932facility(data, i, &facidx, faclen, Q932_PROTOCOL_ROSE); @@ -813,13 +876,13 @@ unsigned int cc_qsig_handle_capi_facilityind(unsigned char *data, struct capi_pv qsig_handle_q932facility(data, i, &facidx, faclen, Q932_PROTOCOL_EXTENSIONS); break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Unknown QSIG protocol configured (%i)\n", i->qsigfeat); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Unknown QSIG protocol configured (%i)\n", i->qsigfeat); /* kill endlessloop */ facidx += faclen; break; } } - cc_verbose(1, 1, VERBOSE_PREFIX_3 "Facility done at index %i from %i\n", facidx, faclen); + cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "Facility done at index %i from %i\n", facidx, faclen); return 1; } @@ -828,16 +891,16 @@ static int identify_qsig_setup_callfeature(char *param) char *p = param; switch (*p) { case 't': - cc_verbose(1, 1, "Call Transfer"); + cc_qsig_verbose( 1, "Call Transfer"); p++; if (*p == 'r') { - cc_verbose(1, 1, " on ALERT"); + cc_qsig_verbose( 1, " on ALERT"); return 2; } else { return 1; } default: - cc_verbose(1, 1, "unknown (%c)\n", *p); + cc_qsig_verbose( 1, "unknown (%c)\n", *p); break; } @@ -868,13 +931,13 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i while ((p) && (*p)) { switch (*p) { case 'X': /* add PROGRESS INDICATOR for external calls*/ - cc_verbose(1, 1, VERBOSE_PREFIX_4 "Sending QSIG external PROGRESS IE.\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "Sending QSIG external PROGRESS IE.\n"); add_externalinfo = 1; pp = strsep (&p, "/"); pp = NULL; break; case 'C': - cc_verbose(1, 1, VERBOSE_PREFIX_4 "QSIG Call Feature requested: "); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "QSIG Call Feature requested: "); p++; switch(identify_qsig_setup_callfeature(p)) { case 1: /* Call transfer */ @@ -890,7 +953,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i if (ii) ii->qsig_data.partner_plci = i->PLCI; - cc_verbose(1, 1, " for plci %#x\n", i->qsig_data.partner_plci); + cc_qsig_verbose( 1, " for plci %#x\n", i->qsig_data.partner_plci); } break; case 2: /* Call transfer on ring */ @@ -906,7 +969,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i if (ii) ii->qsig_data.partner_plci = i->PLCI; - cc_verbose(1, 1, " for plci %#x\n", i->qsig_data.partner_plci); + cc_qsig_verbose( 1, " for plci %#x\n", i->qsig_data.partner_plci); } break; default: @@ -1091,7 +1154,7 @@ int pbx_capi_qsig_getplci(struct ast_channel *c, char *param) char buffer[10]; snprintf(buffer, sizeof(buffer)-1, "%d", i->PLCI); - cc_verbose(4, 1, VERBOSE_PREFIX_4 "QSIG_GETPLCI: %s\n", buffer); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "QSIG_GETPLCI: %s\n", buffer); pbx_builtin_setvar_helper(c, "QSIG_PLCI", buffer); return 0; @@ -1139,7 +1202,7 @@ int pbx_capi_qsig_ct(struct ast_channel *c, char *param) marker = strsep(¶m, "|"); callmark = atoi(marker); - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_CT: using call marker %i(%s)\n", callmark, marker); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * QSIG_CT: using call marker %i(%s)\n", callmark, marker); for (ii = capi_iflist; ii; ii = ii->next) { if (ii->qsig_data.callmark == callmark) @@ -1304,7 +1367,7 @@ static void qsig_cleanup_channel(struct capi_pvt *i) void interface_cleanup_qsig(struct capi_pvt *i) { if (i->qsigfeat) { - cc_verbose(1, 1, VERBOSE_PREFIX_4 "QSIG: cleanup channel\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "QSIG: cleanup channel\n"); qsig_cleanup_channel(i); } } @@ -1332,14 +1395,14 @@ int pbx_capi_qsig_wait_for_prpropose(struct capi_pvt *i) i->qsig_data.waitevent = CAPI_QSIG_WAITEVENT_PRPROPOSE; abstime.tv_sec = time(NULL) + CCQSIG_TIMER_WAIT_PRPROPOSE; /* PR PROPOSE TIMER */ abstime.tv_nsec = 0; - cc_verbose(4, 1, "%s: wait for PATH REPLACEMENT.\n", + cc_qsig_verbose( 1, "%s: wait for PATH REPLACEMENT.\n", i->vname); if (ast_cond_timedwait(&i->qsig_data.event_trigger, &i->lock, &abstime) != 0) { cc_log(LOG_WARNING, "%s: timed out waiting for PATH REPLACEMENT.\n", i->vname); ret = 0; } else { - cc_verbose(4, 1, "%s: cond signal received for PATH REPLACEMENT.\n", + cc_qsig_verbose( 1, "%s: cond signal received for PATH REPLACEMENT.\n", i->vname); } } @@ -1358,7 +1421,7 @@ static void pbx_capi_qsig_post_handling(struct capi_pvt *i) (i->qsig_data.pr_propose_sentback == 1)) { i->qsig_data.waitevent = 0; ast_cond_signal(&i->qsig_data.event_trigger); - cc_verbose(4, 1, "%s: found and signal for PATH REPLACEMENT state.\n", + cc_qsig_verbose( 1, "%s: found and signal for PATH REPLACEMENT state.\n", i->vname); return; } @@ -1466,7 +1529,7 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign ii->qsig_data.pr_propose_active = 1; } } else - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_PATHREPLACEMENT_PROPOSE: no partner channel found (%#x)\n", i->qsig_data.partner_plci); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * QSIG_PATHREPLACEMENT_PROPOSE: no partner channel found (%#x)\n", i->qsig_data.partner_plci); @@ -1481,7 +1544,7 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci); if (ii) { - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_PATHREPLACEMENT_PROPOSE: trying to complete bridge...\n"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * QSIG_PATHREPLACEMENT_PROPOSE: trying to complete bridge...\n"); chanx = ast_bridged_channel(i->owner); ast_channel_masquerade(ii->owner, chanx); } diff --git a/chan_capi_qsig_ecma.c b/chan_capi_qsig_ecma.c index da53ec7..54d8060 100644 --- a/chan_capi_qsig_ecma.c +++ b/chan_capi_qsig_ecma.c @@ -49,7 +49,7 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap int myidx = 0; char *nametype = NULL; - cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling Name Operation (id# %#x)\n", invoke->id); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "Handling Name Operation (id# %#x)\n", invoke->id); callername[0] = 0; datalength = invoke->datalen; @@ -85,7 +85,7 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap 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); + cc_qsig_verbose( 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 */ @@ -95,7 +95,7 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap break; } - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Got %s: \"%s\" (%i byte(s))\n", nametype, callername, namelength); + cc_qsig_verbose( 0, 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 */ @@ -140,6 +140,7 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru namelen = 50; memcpy(namebuf, name, namelen); } + namebuf[namelen] = 0; invoke->id = 1; invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */ @@ -158,7 +159,7 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru invoke->datalen = dataidx; memcpy(invoke->data, data, dataidx); - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending \"%s\": (%i byte(s))\n", namebuf, namelen); + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending \"%s\": (%i byte(s))\n", namebuf, namelen); return 0; } @@ -228,7 +229,7 @@ int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int * 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); + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_LEG_INFO3 \"%s\": (%i byte(s))\n", namebuf, namelen); return 0; } @@ -272,11 +273,14 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap divertName[0] = 0; origCalledName[0] = 0; - cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling QSIG LEG INFO2 (id# %#x)\n", invoke->id); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "Handling QSIG LEG INFO2 (id# %#x)\n", invoke->id); + origPNS.partyNumber = NULL; + divertPNS.partyNumber = NULL; + 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"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - not a sequence\n"); return; } @@ -284,7 +288,7 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap 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"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - buffer error\n"); return; } @@ -296,7 +300,7 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap while (myidx < datalength) { parameter = (invoke->data[myidx++] & 0x0f); - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Found parameter %i\n", parameter); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * Found parameter %i\n", parameter); switch (parameter) { case 0: myidx++; /* Ignore Length of enumeration tag*/ @@ -316,17 +320,17 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap case 3: /* Redirecting Name */ temp = invoke->data[myidx++]; /* keep the length of this info - maybe we don't get all data now */ - cc_qsig_asn197no_get_name(divertName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data); - myidx += temp; + cc_qsig_asn197no_get_name(divertName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data); + myidx += temp + 1; break; case 4: /* origCalled Name */ temp = invoke->data[myidx++]; /* keep the length of this info - maybe we don't get all data now */ cc_qsig_asn197no_get_name(origCalledName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data); - myidx += temp; + myidx += temp + 1; break; default: - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * unknown parameter %i\n", parameter); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * unknown parameter %i\n", parameter); break; } } @@ -338,12 +342,14 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap snprintf(tempstr, 5, "%i", divCount); pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVCOUNT", tempstr); - pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVNUM", divertPNS.partyNumber); - pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVNUM", origPNS.partyNumber); + if (divertPNS.partyNumber) + pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVNUM", divertPNS.partyNumber); + if (origPNS.partyNumber) + pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVNUM", origPNS.partyNumber); 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, origPNS.partyNumber, divertPNS.partyNumber, origCalledName, divertName); + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got QSIG_LEG_INFO2: %i(%i), %ix %s->%s, %s->%s\n", divReason, orgDivReason, divCount, origPNS.partyNumber, divertPNS.partyNumber, origCalledName, divertName); return; @@ -474,7 +480,7 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st invoke->datalen = ix; memcpy(invoke->data, c, ix); - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending QSIG_CT: %i->%s\n", info, cid); + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_CT: %i->%s\n", info, cid); if (cid) free(cid); @@ -517,9 +523,9 @@ unsigned int cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke, ctc->callStatus = answered; ctc->argumentExtension = NULL; /* unhandled yet */ -#define ct_err(x...) { cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG CALL TRANSFER - "x); return 0; } +#define ct_err(x...) { cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG CALL TRANSFER - "x); return 0; } - cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling QSIG CALL TRANSFER (id# %#x)\n", invoke->id); + cc_qsig_verbose( 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 */ @@ -554,7 +560,7 @@ unsigned int cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke, if (ctc->basicCallInfoElements) { memcpy(ctc->basicCallInfoElements, &data[myidx+1], data[myidx] ); } else { - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG CALL TRANSFER - couldn't allocate memory for basicCallInfoElements.\n", (int)data[myidx]); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * QSIG CALL TRANSFER - couldn't allocate memory for basicCallInfoElements.\n", (int)data[myidx]); } myidx += data[myidx] + 1; } @@ -574,7 +580,7 @@ unsigned int cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke, } } - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Got QSIG CALL TRANSFER endDesignation: %i partyNumber: %s (ScreeningInd: %i), partyName: \"%s\", Call state: %s\n", + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got QSIG CALL TRANSFER endDesignation: %i partyNumber: %s (ScreeningInd: %i), partyName: \"%s\", Call state: %s\n", ctc->endDesignation, ctc->redirectionNumber.partyNumber, ctc->redirectionNumber.screeningInd, ctc->redirectionName, ct_status_txt[ctc->callStatus]); return 1; @@ -649,7 +655,7 @@ void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx, invoke->datalen = ix; memcpy(invoke->data, c, ix); - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * Sending QSIG_SSCT: %s->%s\n", cidsrc, ciddst); + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_SSCT: %s->%s\n", cidsrc, ciddst); } @@ -680,11 +686,11 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca callid[0] = 0; reroutingnr[0] = 0; - cc_verbose(1, 1, VERBOSE_PREFIX_4 "Handling QSIG PATH REPLACEMENT PROPOSE (id# %#x)\n", invoke->id); + cc_qsig_verbose( 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"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - not a sequence\n"); return; } @@ -692,7 +698,7 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca 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"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - buffer error\n"); return; } @@ -701,7 +707,7 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca 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"); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - NUMERICSTRING expected\n"); return; } @@ -711,7 +717,7 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca if (temp) { myidx += temp; } else { - cc_verbose(1, 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - partyNumber expected (%i)\n", myidx); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - partyNumber expected (%i)\n", myidx); return; } @@ -719,7 +725,7 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca 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); + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got QSIG_PATHREPLACEMENT_PROPOSE Call identity: %s, Party number: %s (%i)\n", callid, reroutingnr, temp); return; } @@ -742,7 +748,6 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca */ 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; @@ -751,6 +756,11 @@ void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struc char c[255]; int ix = 0; + int res = 0; + int ii = 0; + struct rose_component *comp = NULL, *compstk[10]; + int compsp = 0; + if (!i->qsig_data.pr_propose_cid) return ; @@ -764,7 +774,8 @@ void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struc rrnlen = strlen(reroutingnr); seqlen += cidlen + rrnlen; - + +#if 0 c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */ c[ix++] = seqlen; @@ -777,6 +788,23 @@ void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struc c[ix++] = rrnlen; memcpy(&c[ix], reroutingnr, rrnlen); ix += rrnlen; +#else + ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED), c, ii); + ASN1_PUSH(compstk, compsp, comp); + + res = cc_qsig_asn1_add_string2(ASN1_NUMERICSTRING, &c[ii], sizeof(c) - ii, 20, callid, cidlen); + if (res < 0) + return; + ii += res; + + res = cc_qsig_asn1_add_string2(ASN1_TC_CONTEXTSPEC, &c[ii], sizeof(c) - ii, 20, reroutingnr, rrnlen); + if (res < 0) + return; + ii += res; + + ASN1_FIXUP(compstk, compsp, c, ii); + ix = ii; +#endif /* end of SEQUENCE */ /* there are optional data possible here */ @@ -787,8 +815,44 @@ void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struc 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); + cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_PATHREPLACEMENT_PROPOSE: Call identity: %s, Party number: %s\n", callid, reroutingnr); return; } + +void cc_qsig_encode_ecma_ccnr_req(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param) +{ + int invokeop = 27; + + int ii = 0; + unsigned char c[256]; + struct rose_component *comp = NULL, *compstk[10]; + int compsp = 0; + int ix = 0; + + ASN1_ADD_SIMPLE(comp, (ASN1_TF_CONSTRUCTED | ASN1_SEQUENCE), c, ii); + ASN1_PUSH(compstk, compsp, comp); + + + +#if 0 /* Constructed data - ECMAv1 HICOM/HIPATH */ + ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i); + ASN1_PUSH(compstk, compsp, comp); + res = asn1_string_encode(ASN1_OCTETSTRING, &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen); + if (res < 0) + return -1; + i += res; + ASN1_FIXUP(compstk, compsp, buffer, i); +#endif + + invoke->id = invokeop; + invoke->descr_type = -1; + invoke->type = invokeop; + + invoke->datalen = ix; + memcpy(invoke->data, c, ix); + cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * Sending QSIG_CCNR_REQ\n"); + + return ; +} diff --git a/chan_capi_qsig_ecma.h b/chan_capi_qsig_ecma.h index bc246d0..835c696 100644 --- a/chan_capi_qsig_ecma.h +++ b/chan_capi_qsig_ecma.h @@ -18,6 +18,7 @@ /* ECMA Features structs */ + /* Call Transfer Complete struct */ struct cc_qsig_ctcomplete { enum { @@ -35,6 +36,17 @@ struct cc_qsig_ctcomplete { char *argumentExtension; /* OPTIONAL: ASN1_SEQUENCE - manufacturer specific extension */ }; +/* CCBS struct */ +struct cc_qsig_ccbsreq { + char *numberA; /* Simplified numbers*/ + char *numberB; + char *PSS1InfoElement; /* Bearer caps, LLC, HLC */ + char *subaddrA; + char *subaddrB; + int can_retain_service; + int retain_sig_connection; + char *extension; +}; /* *** ECMA QSIG Functions