Update of /usr/cvsroot/libpri
In directory mongoose.digium.com:/tmp/cvs-serv4245

Modified Files:
        libpri.h pri.c pri_facility.c pri_facility.h pri_internal.h 
        q931.c 
Log Message:
Merging Advice of Charge code into libpri (bug #3843)


Index: libpri.h
===================================================================
RCS file: /usr/cvsroot/libpri/libpri.h,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- libpri.h    3 Apr 2005 23:07:55 -0000       1.45
+++ libpri.h    5 Apr 2005 03:55:58 -0000       1.46
@@ -37,7 +37,8 @@
 #define PRI_DEBUG_Q931_DUMP            (1 << 5)        /* Show interpreted 
Q.931 frames */
 #define PRI_DEBUG_Q931_STATE   (1 << 6)        /* Debug Q.931 state machine 
changes */
 #define        PRI_DEBUG_Q931_ANOMALY  (1 << 7)        /* Show unexpected 
events */
-#define PRI_DEBUG_APDU         (1 << 8)        /* Debug of APDU components 
such as ROSE */
+#define PRI_DEBUG_APDU                 (1 << 8)        /* Debug of APDU 
components such as ROSE */
+#define PRI_DEBUG_AOC                  (1 << 9)        /* Debug of Advice of 
Charge ROSE Messages */
 
 #define PRI_DEBUG_ALL                  (0xffff)        /* Everything */
 
@@ -53,7 +54,7 @@
 #define PRI_SWITCH_GR303_EOC           8       /* GR-303 Embedded Operations 
Channel */
 #define PRI_SWITCH_GR303_TMC           9       /* GR-303 Timeslot Management 
Channel */
 #define PRI_SWITCH_QSIG                        10      /* QSIG Switch */
-/* Switchtypes 10 - 20 are reserved for internal use */
+/* Switchtypes 11 - 20 are reserved for internal use */
 
 
 /* PRI D-Channel Events */
@@ -322,6 +323,7 @@
        int cause;
        int cref;
        q931_call *call;                        /* Opaque call pointer */
+       long aoc_units;                         /* Advise of Charge number of 
charged units */
 } pri_event_hangup;    
 
 typedef struct pri_event_restart_ack {

Index: pri.c
===================================================================
RCS file: /usr/cvsroot/libpri/pri.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- pri.c       17 Mar 2005 15:46:23 -0000      1.33
+++ pri.c       5 Apr 2005 03:55:58 -0000       1.34
@@ -474,6 +474,9 @@
                        call2->pri->switchtype != PRI_SWITCH_LUCENT5E)
                return -1;
 
+       /* Check for bearer capability */
+       if (call1->transcapability != call2->transcapability)
+               return -1;
        /* Check to see if calls are on the same PRI dchannel
         * Currently only support calls on the same dchannel
         */

Index: pri_facility.c
===================================================================
RCS file: /usr/cvsroot/libpri/pri_facility.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- pri_facility.c      16 Mar 2005 15:10:41 -0000      1.7
+++ pri_facility.c      5 Apr 2005 03:55:58 -0000       1.8
@@ -16,6 +16,7 @@
 #include "pri_q931.h"
 #include "pri_facility.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -32,128 +33,151 @@
        int  pres;
 };
 
+static void dump_apdu(unsigned char *c, int len) 
+{
+       #define MAX_APDU_LENGTH 255
+       int i;
+       char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; 
/* please adjust here, if you make changes below! */
+       
+       if (len > MAX_APDU_LENGTH)
+               return;
+       
+       snprintf(message, sizeof(message)-1, " [");     
+       for (i=0; i<len; i++)
+               snprintf((char *)(message+strlen(message)), 
sizeof(message)-strlen(message)-1, " %02x", c[i]);
+       snprintf((char *)(message+strlen(message)), 
sizeof(message)-strlen(message)-1, " ] - [");
+       for (i=0; i<len; i++) {
+               if (c[i] < 20 || c[i] >= 128)
+                       snprintf((char *)(message+strlen(message)), 
sizeof(message)-strlen(message)-1, "�");
+               else
+                       snprintf((char *)(message+strlen(message)), 
sizeof(message)-strlen(message)-1, "%c", c[i]);
+       }
+       snprintf((char *)(message+strlen(message)), 
sizeof(message)-strlen(message)-1, "]\n");
+       pri_message(message);
+}
+
 int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
 {
        switch(pri->switchtype) {
-       case PRI_SWITCH_QSIG:
-               switch(redirectingreason) {
-               case PRI_REDIR_UNKNOWN:
-                       return QSIG_DIVERT_REASON_UNKNOWN;
-               case PRI_REDIR_FORWARD_ON_BUSY:
-                       return QSIG_DIVERT_REASON_CFB;
-               case PRI_REDIR_FORWARD_ON_NO_REPLY:
-                       return QSIG_DIVERT_REASON_CFNR;
-               case PRI_REDIR_UNCONDITIONAL:
-                       return QSIG_DIVERT_REASON_CFU;
-               case PRI_REDIR_DEFLECTION:
-               case PRI_REDIR_DTE_OUT_OF_ORDER:
-               case PRI_REDIR_FORWARDED_BY_DTE:
-                       pri_message("!! Don't know how to convert Q.931 
redirection reason %d to Q.SIG\n", redirectingreason);
-                       /* Fall through */
-               default:
-                       return QSIG_DIVERT_REASON_UNKNOWN;
-               }
-       default:
-               switch(redirectingreason) {
-               case PRI_REDIR_UNKNOWN:
-                       return Q952_DIVERT_REASON_UNKNOWN;
-               case PRI_REDIR_FORWARD_ON_BUSY:
-                       return Q952_DIVERT_REASON_CFB;
-               case PRI_REDIR_FORWARD_ON_NO_REPLY:
-                       return Q952_DIVERT_REASON_CFNR;
-               case PRI_REDIR_DEFLECTION:
-                       return Q952_DIVERT_REASON_CD;
-               case PRI_REDIR_UNCONDITIONAL:
-                       return Q952_DIVERT_REASON_CFU;
-               case PRI_REDIR_DTE_OUT_OF_ORDER:
-               case PRI_REDIR_FORWARDED_BY_DTE:
-                       pri_message("!! Don't know how to convert Q.931 
redirection reason %d to Q.952\n", redirectingreason);
-                       /* Fall through */
+               case PRI_SWITCH_QSIG:
+                       switch(redirectingreason) {
+                               case PRI_REDIR_UNKNOWN:
+                                       return QSIG_DIVERT_REASON_UNKNOWN;
+                               case PRI_REDIR_FORWARD_ON_BUSY:
+                                       return QSIG_DIVERT_REASON_CFB;
+                               case PRI_REDIR_FORWARD_ON_NO_REPLY:
+                                       return QSIG_DIVERT_REASON_CFNR;
+                               case PRI_REDIR_UNCONDITIONAL:
+                                       return QSIG_DIVERT_REASON_CFU;
+                               case PRI_REDIR_DEFLECTION:
+                               case PRI_REDIR_DTE_OUT_OF_ORDER:
+                               case PRI_REDIR_FORWARDED_BY_DTE:
+                                       pri_message("!! Don't know how to 
convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason);
+                                       /* Fall through */
+                               default:
+                                       return QSIG_DIVERT_REASON_UNKNOWN;
+                       }
                default:
-                       return Q952_DIVERT_REASON_UNKNOWN;
-               }
+                       switch(redirectingreason) {
+                               case PRI_REDIR_UNKNOWN:
+                                       return Q952_DIVERT_REASON_UNKNOWN;
+                               case PRI_REDIR_FORWARD_ON_BUSY:
+                                       return Q952_DIVERT_REASON_CFB;
+                               case PRI_REDIR_FORWARD_ON_NO_REPLY:
+                                       return Q952_DIVERT_REASON_CFNR;
+                               case PRI_REDIR_DEFLECTION:
+                                       return Q952_DIVERT_REASON_CD;
+                               case PRI_REDIR_UNCONDITIONAL:
+                                       return Q952_DIVERT_REASON_CFU;
+                               case PRI_REDIR_DTE_OUT_OF_ORDER:
+                               case PRI_REDIR_FORWARDED_BY_DTE:
+                                       pri_message("!! Don't know how to 
convert Q.931 redirection reason %d to Q.952\n", redirectingreason);
+                                       /* Fall through */
+                               default:
+                                       return Q952_DIVERT_REASON_UNKNOWN;
+                       }
        }
 }
 
 static int redirectingreason_for_q931(struct pri *pri, int redirectingreason)
 {
        switch(pri->switchtype) {
-       case PRI_SWITCH_QSIG:
-               switch(redirectingreason) {
-               case QSIG_DIVERT_REASON_UNKNOWN:
-                       return PRI_REDIR_UNKNOWN;
-               case QSIG_DIVERT_REASON_CFU:
-                       return PRI_REDIR_UNCONDITIONAL;
-               case QSIG_DIVERT_REASON_CFB:
-                       return PRI_REDIR_FORWARD_ON_BUSY;
-               case QSIG_DIVERT_REASON_CFNR:
-                       return PRI_REDIR_FORWARD_ON_NO_REPLY;
-               default:
-                       pri_message("!! Unknown Q.SIG diversion reason %d\n", 
redirectingreason);
-                       return PRI_REDIR_UNKNOWN;
-               }
-       default:
-               switch(redirectingreason) {
-               case Q952_DIVERT_REASON_UNKNOWN:
-                       return PRI_REDIR_UNKNOWN;
-               case Q952_DIVERT_REASON_CFU:
-                       return PRI_REDIR_UNCONDITIONAL;
-               case Q952_DIVERT_REASON_CFB:
-                       return PRI_REDIR_FORWARD_ON_BUSY;
-               case Q952_DIVERT_REASON_CFNR:
-                       return PRI_REDIR_FORWARD_ON_NO_REPLY;
-               case Q952_DIVERT_REASON_CD:
-                       return PRI_REDIR_DEFLECTION;
-               case Q952_DIVERT_REASON_IMMEDIATE:
-                       pri_message("!! Dont' know how to convert Q.952 
diversion reason IMMEDIATE to PRI analog\n");
-                       return PRI_REDIR_UNKNOWN;       /* ??? */
+               case PRI_SWITCH_QSIG:
+                       switch(redirectingreason) {
+                               case QSIG_DIVERT_REASON_UNKNOWN:
+                                       return PRI_REDIR_UNKNOWN;
+                               case QSIG_DIVERT_REASON_CFU:
+                                       return PRI_REDIR_UNCONDITIONAL;
+                               case QSIG_DIVERT_REASON_CFB:
+                                       return PRI_REDIR_FORWARD_ON_BUSY;
+                               case QSIG_DIVERT_REASON_CFNR:
+                                       return PRI_REDIR_FORWARD_ON_NO_REPLY;
+                               default:
+                                       pri_message("!! Unknown Q.SIG diversion 
reason %d\n", redirectingreason);
+                                       return PRI_REDIR_UNKNOWN;
+                       }
                default:
-                       pri_message("!! Unknown Q.952 diversion reason %d\n", 
redirectingreason);
-                       return PRI_REDIR_UNKNOWN;
-               }
+                       switch(redirectingreason) {
+                               case Q952_DIVERT_REASON_UNKNOWN:
+                                       return PRI_REDIR_UNKNOWN;
+                               case Q952_DIVERT_REASON_CFU:
+                                       return PRI_REDIR_UNCONDITIONAL;
+                               case Q952_DIVERT_REASON_CFB:
+                                       return PRI_REDIR_FORWARD_ON_BUSY;
+                               case Q952_DIVERT_REASON_CFNR:
+                                       return PRI_REDIR_FORWARD_ON_NO_REPLY;
+                               case Q952_DIVERT_REASON_CD:
+                                       return PRI_REDIR_DEFLECTION;
+                               case Q952_DIVERT_REASON_IMMEDIATE:
+                                       pri_message("!! Dont' know how to 
convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
+                                       return PRI_REDIR_UNKNOWN;       /* ??? 
*/
+                               default:
+                                       pri_message("!! Unknown Q.952 diversion 
reason %d\n", redirectingreason);
+                                       return PRI_REDIR_UNKNOWN;
+                       }
        }
 }
 
 int typeofnumber_from_q931(struct pri *pri, int ton)
 {
        switch(ton) {
-       case PRI_TON_INTERNATIONAL:
-               return Q932_TON_INTERNATIONAL;
-       case PRI_TON_NATIONAL:
-               return Q932_TON_NATIONAL;
-       case PRI_TON_NET_SPECIFIC:
-               return Q932_TON_NET_SPECIFIC;
-       case PRI_TON_SUBSCRIBER:
-               return Q932_TON_SUBSCRIBER;
-       case PRI_TON_ABBREVIATED:
-               return Q932_TON_ABBREVIATED;
-       case PRI_TON_RESERVED:
-       default:
-               pri_message("!! Unsupported Q.931 TypeOfNumber value (%d)\n", 
ton);
-               /* fall through */
-       case PRI_TON_UNKNOWN:
-               return Q932_TON_UNKNOWN;
+               case PRI_TON_INTERNATIONAL:
+                       return Q932_TON_INTERNATIONAL;
+               case PRI_TON_NATIONAL:
+                       return Q932_TON_NATIONAL;
+               case PRI_TON_NET_SPECIFIC:
+                       return Q932_TON_NET_SPECIFIC;
+               case PRI_TON_SUBSCRIBER:
+                       return Q932_TON_SUBSCRIBER;
+               case PRI_TON_ABBREVIATED:
+                       return Q932_TON_ABBREVIATED;
+               case PRI_TON_RESERVED:
+               default:
+                       pri_message("!! Unsupported Q.931 TypeOfNumber value 
(%d)\n", ton);
+                       /* fall through */
+               case PRI_TON_UNKNOWN:
+                       return Q932_TON_UNKNOWN;
        }
 }
 
 static int typeofnumber_for_q931(struct pri *pri, int ton)
 {
        switch (ton) {
-       case Q932_TON_UNKNOWN:
-               return PRI_TON_UNKNOWN;
-       case Q932_TON_INTERNATIONAL:
-               return PRI_TON_INTERNATIONAL;
-       case Q932_TON_NATIONAL:
-               return PRI_TON_NATIONAL;
-       case Q932_TON_NET_SPECIFIC:
-               return PRI_TON_NET_SPECIFIC;
-       case Q932_TON_SUBSCRIBER:
-               return PRI_TON_SUBSCRIBER;
-       case Q932_TON_ABBREVIATED:
-               return PRI_TON_ABBREVIATED;
-       default:
-               pri_message("!! Invalid Q.932 TypeOfNumber %d\n", ton);
-               return PRI_TON_UNKNOWN;
+               case Q932_TON_UNKNOWN:
+                       return PRI_TON_UNKNOWN;
+               case Q932_TON_INTERNATIONAL:
+                       return PRI_TON_INTERNATIONAL;
+               case Q932_TON_NATIONAL:
+                       return PRI_TON_NATIONAL;
+               case Q932_TON_NET_SPECIFIC:
+                       return PRI_TON_NET_SPECIFIC;
+               case Q932_TON_SUBSCRIBER:
+                       return PRI_TON_SUBSCRIBER;
+               case Q932_TON_ABBREVIATED:
+                       return PRI_TON_ABBREVIATED;
+               default:
+                       pri_message("!! Invalid Q.932 TypeOfNumber %d\n", ton);
+                       return PRI_TON_UNKNOWN;
        }
 }
 
@@ -235,39 +259,39 @@
                GET_COMPONENT(comp, i, vdata, len);
 
                switch(comp->type) {
-               case 0xA0:      /* unknownPartyNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0):   
/* [0] unknownPartyNumber */
                        if(rose_number_digits_decode(pri, call, comp->data, 
comp->len, value))
                                return -1;
                        value->npi = PRI_NPI_UNKNOWN;
                        value->ton = PRI_TON_UNKNOWN;
                        break;
-               case 0xA1:      /* publicPartyNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1):   
/* [1] publicPartyNumber */
                        if(rose_public_party_number_decode(pri, call, 
comp->data, comp->len, value) != 0)
                                return -1;
                        value->npi = PRI_NPI_E163_E164;
                        break;
-               case 0xA2:      /* nsapEncodedNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2):   
/* [2] nsapEncodedNumber */
                        pri_message("!! NsapEncodedNumber isn't handled\n");
                        return -1;
-               case 0xA3:      /* dataPartyNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3):   
/* [3] dataPartyNumber */
                        if(rose_number_digits_decode(pri, call, comp->data, 
comp->len, value))
                                return -1;
                        value->npi = PRI_NPI_X121 /* ??? */;
                        value->ton = PRI_TON_UNKNOWN /* ??? */;
                        pri_message("!! dataPartyNumber isn't handled\n");
                        return -1;
-               case 0xA4:      /* telexPartyNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4):   
/* [4] telexPartyNumber */
                        if (rose_number_digits_decode(pri, call, comp->data, 
comp->len, value))
                                return -1;
                        value->npi = PRI_NPI_F69 /* ??? */;
                        value->ton = PRI_TON_UNKNOWN /* ??? */;
                        pri_message("!! telexPartyNumber isn't handled\n");
                        return -1;
-               case 0xA5:      /* priavePartyNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5):   
/* [5] priavePartyNumber */
                        pri_message("!! privatePartyNumber isn't handled\n");
                        value->npi = PRI_NPI_PRIVATE;
                        return -1;
-               case 0xA8:      /* nationalStandardPartyNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8):   
/* [8] nationalStandardPartyNumber */
                        if (rose_number_digits_decode(pri, call, comp->data, 
comp->len, value))
                                return -1;
                        value->npi = PRI_NPI_NATIONAL;
@@ -302,24 +326,24 @@
                GET_COMPONENT(comp, i, vdata, len);
 
                switch(comp->type) {
-               case 0xA0:              /* [0] presentationAllowedNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0):   
        /* [0] presentationAllowedNumber */
                        value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
                        return rose_address_decode(pri, call, comp->data, 
comp->len, value);
-               case 0x81:              /* [1] IMPLICIT presentationRestricted 
*/
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1):              /* [1] 
IMPLICIT presentationRestricted */
                        if (comp->len != 0) { /* must be NULL */
                                pri_error("!! Invalid PresentationRestricted 
component received (len != 0)\n");
                                return -1;
                        }
                        value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
                        return 0;
-               case 0x82:              /* [2] IMPLICIT 
numberNotAvailableDueToInterworking */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2):              /* [2] 
IMPLICIT numberNotAvailableDueToInterworking */
                        if (comp->len != 0) { /* must be NULL */
                                pri_error("!! Invalid 
NumberNotAvailableDueToInterworking component received (len != 0)\n");
                                return -1;
                        }
                        value->pres = PRES_NUMBER_NOT_AVAILABLE;
                        return 0;
-               case 0xA3:              /* [3] presentationRestrictedNumber */
+               case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3):   
        /* [3] presentationRestrictedNumber */
                        value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
                        return rose_address_decode(pri, call, comp->data, 
comp->len, value);
                default:
@@ -419,7 +443,7 @@
                return -1;
        }
 
-       buffer[i] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+       buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
        i++;
        /* Interpretation component */
        ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* 
Discard unrecognized invokes */);
@@ -436,7 +460,7 @@
        ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 
ROSE_DIVERTING_LEG_INFORMATION2);
 
        /* ROSE ARGUMENT component */
-       ASN1_ADD_SIMPLE(comp, 0x30, buffer, i);
+       ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
        /* ROSE DivertingLegInformation2.diversionCounter component */
        /* Always is 1 because other isn't available in the current design */
@@ -446,7 +470,7 @@
        ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 
redirectingreason_from_q931(pri, call->redirectingreason));
                
        /* ROSE DivertingLegInformation2.divertingNr component */
-       ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | 
ASN1_TAG_1), buffer, i);
        
        ASN1_PUSH(compstk, compsp, comp);
                /* Redirecting information always not screened */
@@ -455,10 +479,10 @@
                case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
                case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
                        if (call->redirectingnum && 
strlen(call->redirectingnum)) {
-                               ASN1_ADD_SIMPLE(comp, 0xA0, buffer, i);
+                               ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
                                ASN1_PUSH(compstk, compsp, comp);
                                        /* NPI of redirected number is not 
supported in the current design */
-                               ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+                               ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
                                ASN1_PUSH(compstk, compsp, comp);
                                        ASN1_ADD_BYTECOMP(comp, 
ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan 
>> 4));
                                        j = 
asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, 
call->redirectingnum, strlen(call->redirectingnum));
@@ -473,35 +497,35 @@
                        /* fall through */
                case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
                case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-                       ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+                       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_TAG_1), buffer, i);
                        break;
                /* Don't know how to handle this */
                case PRES_ALLOWED_NETWORK_NUMBER:
                case PRES_PROHIB_NETWORK_NUMBER:
                case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
                case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-                       ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+                       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_TAG_1), buffer, i);
                        break;
                default:
                        pri_message("!! Undefined presentation value for 
redirecting number: %d\n", call->redirectingpres);
                case PRES_NUMBER_NOT_AVAILABLE:
-                       ASN1_ADD_SIMPLE(comp, 0x82, buffer, i);
+                       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_TAG_2), buffer, i);
                        break;
        }
        ASN1_FIXUP(compstk, compsp, buffer, i);
 
        /* ROSE DivertingLegInformation2.originalCalledNr component */
        /* This information isn't supported by current design - duplicate 
divertingNr */
-       ASN1_ADD_SIMPLE(comp, 0xA2, buffer, i);
+       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | 
ASN1_TAG_2), buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
                /* Redirecting information always not screened */
        switch(call->redirectingpres) {
                case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
                case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
                        if (call->redirectingnum && 
strlen(call->redirectingnum)) {
-                               ASN1_ADD_SIMPLE(comp, 0xA0, buffer, i);
+                               ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
                                ASN1_PUSH(compstk, compsp, comp);
-                               ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+                               ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
                                ASN1_PUSH(compstk, compsp, comp);
                                ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, 
buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
        
@@ -517,19 +541,19 @@
                                /* fall through */
                case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
                case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-                       ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+                       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_TAG_1), buffer, i);
                        break;
                /* Don't know how to handle this */
                case PRES_ALLOWED_NETWORK_NUMBER:
                case PRES_PROHIB_NETWORK_NUMBER:
                case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
                case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-                       ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+                       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_TAG_1), buffer, i);
                        break;
                default:
                        pri_message("!! Undefined presentation value for 
redirecting number: %d\n", call->redirectingpres);
                case PRES_NUMBER_NOT_AVAILABLE:
-                       ASN1_ADD_SIMPLE(comp, 0x82, buffer, i);
+                       ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | 
ASN1_TAG_2), buffer, i);
                        break;
        }
        ASN1_FIXUP(compstk, compsp, buffer, i);
@@ -568,13 +592,13 @@
                return -1;
        }
 
-       buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+       buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
        /* Interpretation component */
 
        ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
-       ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
-       ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, 
i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, 
i, 0);
        ASN1_FIXUP(compstk, compsp, buffer, i);
 
        ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -607,13 +631,13 @@
                namelen = 50; /* truncate the name */
        }
 
-       buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+       buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
        /* Interpretation component */
 
        ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
-       ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
-       ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, 
i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, 
i, 0);
        ASN1_FIXUP(compstk, compsp, buffer, i);
 
        ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -627,7 +651,7 @@
        /* Operation ID: Calling name */
        ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNID_CALLINGNAME);
 
-       res = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i,  50, 
c->callername, namelen);
+       res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), 
&buffer[i], sizeof(buffer)-i,  50, c->callername, namelen);
        if (res < 0)
          return -1;
        i += res;
@@ -638,7 +662,6 @@
        
        return 0;
 }
-
 /* End Callername */
 
 /* MWI related encode and decode functions */
@@ -661,13 +684,13 @@
        } else if (destlen > 20)
                destlen = 20;  /* Destination number cannot be greater then 20 
digits */
 
-       buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+       buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
        /* Interpretation component */
 
        ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
-       ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
-       ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, 
i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, 
i, 0);
        ASN1_FIXUP(compstk, compsp, buffer, i);
 
        ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -678,10 +701,10 @@
        ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
 
        ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, (activate) ? 
SS_MWI_ACTIVATE : SS_MWI_DEACTIVATE);
-       ASN1_ADD_SIMPLE(comp, 0x30 /* Sequence */, buffer, i);
+       ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
        /* PartyNumber */
-       res = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i, destlen, 
req->called, destlen);
+       res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), 
&buffer[i], sizeof(buffer)-i, destlen, req->called, destlen);
        
        if (res < 0)
                return -1;
@@ -718,13 +741,13 @@
                0x08,
        };
 
-       buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+       buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
        /* Interpretation component */
 
        ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
-       ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
-       ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, 
i, 0);
+       ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, 
i, 0);
        ASN1_FIXUP(compstk, compsp, buffer, i);
 
        ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -739,9 +762,9 @@
                return -1;
        i += res;
 
-       ASN1_ADD_SIMPLE(comp, ASN1_SEQUENCE | 0x20, buffer, i);
+       ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
        ASN1_PUSH(compstk, compsp, comp);
-       ASN1_ADD_WORDCOMP(comp, 0x02, buffer, i, call_reference);
+       ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
        ASN1_FIXUP(compstk, compsp, buffer, i);
        ASN1_FIXUP(compstk, compsp, buffer, i);
 
@@ -764,6 +787,211 @@
 }
 /* End EECT */
 
+/* AOC */
+static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, 
unsigned char *data, int len) 
+{
+       int chargingcase = -1;
+       unsigned char *vdata = data;
+       struct rose_component *comp = NULL;
+       int pos1 = 0;
+
+       if (pri->debug & PRI_DEBUG_AOC)
+               dump_apdu (data, len);
+
+       do {
+               GET_COMPONENT(comp, pos1, vdata, len);
+               CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging 
Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n");
+               ASN1_GET_INTEGER(comp, chargingcase);                           
+               if (chargingcase >= 0 && chargingcase <= 2) {
+                       if (pri->debug & PRI_DEBUG_APDU)
+                               pri_message("Channel %d/%d, Call %d  - received 
AOC charging request - charging case: %i\n", 
+                                       call->ds1no, call->channelno, call->cr, 
chargingcase);
+               } else {
+                       pri_message("!! unkown AOC ChargingCase: 0x%02X", 
chargingcase);
+                       chargingcase = -1;
+               }
+               NEXT_COMPONENT(comp, pos1);
+       } while (pos1 < len);
+       if (pos1 < len) {
+               pri_message("!! Only reached position %i in %i bytes long AOC-E 
structure:", pos1, len );
+               dump_apdu (data, len);
+               return -1;      /* Aborted before */
+       }
+       return 0;
+}
+       
+
+static int aoc_aoce_charging_unit_decode(struct pri *pri, q931_call *call, 
unsigned char *data, int len) 
+{
+       long chargingunits = 0, chargetype = -1, temp, chargeIdentifier = -1;
+       unsigned char *vdata = data;
+       struct rose_component *comp1 = NULL, *comp2 = NULL, *comp3 = NULL;
+       int pos1 = 0, pos2, pos3, sublen2, sublen3;
+       struct addressingdataelements_presentednumberunscreened chargednr;
+
+       if (pri->debug & PRI_DEBUG_AOC)
+               dump_apdu (data, len);
+
+       do {
+               GET_COMPONENT(comp1, pos1, vdata, len); /* AOCEChargingUnitInfo 
*/
+               CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid AOC-E 
Charging Unit argument. Expected Sequence (0x30) but Received 0x%02X\n");
+               SUB_COMPONENT(comp1, pos1);
+               GET_COMPONENT(comp1, pos1, vdata, len);
+               switch (comp1->type) {
+                       case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR):        /* 
specificChargingUnits */
+                               sublen2 = comp1->len; 
+                               pos2 = pos1;
+                               comp2 = comp1;
+                               SUB_COMPONENT(comp2, pos2);
+                               do {
+                                       GET_COMPONENT(comp2, pos2, vdata, len);
+                                       switch (comp2->type) {
+                                               case (ASN1_CONTEXT_SPECIFIC | 
ASN1_CONSTRUCTOR | ASN1_TAG_1):   /* RecordedUnitsList (0xA1) */
+                                                       SUB_COMPONENT(comp2, 
pos2);
+                                                       GET_COMPONENT(comp2, 
pos2, vdata, len);
+                                                       CHECK_COMPONENT(comp2, 
ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence 
(0x30) but received 0x02%X\n");       /* RecordedUnits */
+                                                       sublen3 = pos2 + 
comp2->len;
+                                                       pos3 = pos2;
+                                                       comp3 = comp2;
+                                                       SUB_COMPONENT(comp3, 
pos3);
+                                                       do {
+                                                               
GET_COMPONENT(comp3, pos3, vdata, len);
+                                                               switch 
(comp3->type) {
+                                                                       case 
ASN1_INTEGER:      /* numberOfUnits */
+                                                                               
ASN1_GET_INTEGER(comp3, temp);
+                                                                               
chargingunits += temp;
+                                                                       case 
ASN1_NULL:         /* notAvailable */
+                                                                               
break;
+                                                                       default:
+                                                                               
pri_message("!! Don't know how to handle 0x%02X in AOC-E RecordedUnits\n", 
comp3->type);
+                                                               }
+                                                               
NEXT_COMPONENT(comp3, pos3);
+                                                       } while (pos3 < 
sublen3);
+                                                       if (pri->debug & 
PRI_DEBUG_AOC)
+                                                               
pri_message("Channel %d/%d, Call %d - received AOC-E charging: %i unit%s\n", 
+                                                                       
call->ds1no, call->channelno, call->cr, chargingunits, (chargingunits == 1) ? 
"" : "s");
+                                                       break;
+                                               case (ASN1_CONTEXT_SPECIFIC | 
ASN1_CONSTRUCTOR | ASN1_TAG_2):   /* AOCEBillingID (0xA2) */
+                                                       SUB_COMPONENT(comp2, 
pos2);
+                                                       GET_COMPONENT(comp2, 
pos2, vdata, len);
+                                                       ASN1_GET_INTEGER(comp2, 
chargetype);
+                                                       pri_message("!! not 
handled: Channel %d/%d, Call %d - received AOC-E billing ID: %i\n", 
+                                                               call->ds1no, 
call->channelno, call->cr, chargetype);
+                                                       break;
+                                               default:
+                                                       pri_message("!! Don't 
know how to handle 0x%02X in AOC-E RecordedUnitsList\n", comp2->type);
+                                       }
+                                       NEXT_COMPONENT(comp2, pos2);
+                               } while (pos2 < sublen2);
+                               break;
+                       case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* 
freeOfCharge (0x81) */
+                               if (pri->debug & PRI_DEBUG_AOC)
+                                       pri_message("Channel %d/%d, Call %d - 
received AOC-E free of charge\n", call->ds1no, call->channelno, call->cr);
+                               chargingunits = 0;
+                               break;
+                       default:
+                               pri_message("!! Invalid AOC-E 
specificChargingUnits. Expected Sequence (0x30) or Object Identifier 
(0x81/0x01) but received 0x%02X\n", comp1->type);
+               }
+               NEXT_COMPONENT(comp1, pos1);
+               GET_COMPONENT(comp1, pos1, vdata, len); /* get optional 
chargingAssociation. will 'break' when reached end of structure */
+               switch (comp1->type) {
+                       /* TODO: charged number is untested - please report! */
+                       case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | 
ASN1_TAG_0): /* chargedNumber (0xA0) */
+                               if(rose_presented_number_unscreened_decode(pri, 
call, comp1->data, comp1->len, &chargednr) != 0)
+                                       return -1;
+                               pri_message("!! not handled: Received ChargedNr 
'%s' \n", chargednr.partyaddress);
+                               pri_message("  ton = %d, pres = %d, npi = 
%d\n", chargednr.ton, chargednr.pres, chargednr.npi);
+                               break;
+                       case ASN1_INTEGER:
+                               ASN1_GET_INTEGER(comp1, chargeIdentifier);
+                               break;
+                       default:
+                               pri_message("!! Invalid AOC-E 
chargingAssociation. Expected Object Identifier (0xA0) or Integer (0x02) but 
received 0x%02X\n", comp1->type);
+               }
+               NEXT_COMPONENT(comp1, pos1);
+       } while (pos1 < len);
+
+       if (pos1 < len) {
+               pri_message("!! Only reached position %i in %i bytes long AOC-E 
structure:", pos1, len );
+               dump_apdu (data, len);
+               return -1;      /* oops - aborted before */
+       }
+       call->aoc_units = chargingunits;
+       
+       return 0;
+}
+
+static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long 
chargedunits)
+{
+       /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 
02 01 01 ] */
+       int i = 0, res = 0, compsp = 0;
+       unsigned char buffer[255] = "";
+       struct rose_component *comp = NULL, *compstk[10];
+
+       /* ROSE protocol (0x91)*/
+       buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
+
+       /* ROSE Component (0xA1,len)*/
+       ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+       ASN1_PUSH(compstk, compsp, comp); 
+
+       /* ROSE invokeId component (0x02,len,id)*/
+       ASN1_ADD_WORDCOMP(comp, INVOKE_IDENTIFIER, buffer, i, 
++pri->last_invoke);
+
+       /* ROSE operationId component (0x02,0x01,0x24)*/
+       ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 
ROSE_AOC_AOCE_CHARGING_UNIT);
+
+       /* AOCEChargingUnitInfo (0x30,len) */
+       ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+       ASN1_PUSH(compstk, compsp, comp);
+
+       if (chargedunits > 0) {
+               /* SpecificChargingUnits (0x30,len) */
+               ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), 
buffer, i);
+               ASN1_PUSH(compstk, compsp, comp);
+
+               /* RecordedUnitsList (0xA1,len) */
+               ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR 
| ASN1_TAG_1), buffer, i);
+               ASN1_PUSH(compstk, compsp, comp);
+               
+               /* RecordedUnits (0x30,len) */
+               ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), 
buffer, i);
+               ASN1_PUSH(compstk, compsp, comp);
+               
+               /* NumberOfUnits (0x02,len,charge) */
+               ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, chargedunits);
+
+               ASN1_FIXUP(compstk, compsp, buffer, i);
+               ASN1_FIXUP(compstk, compsp, buffer, i);
+               ASN1_FIXUP(compstk, compsp, buffer, i);
+       } else {
+               /* freeOfCharge (0x81,0) */
+               ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), 
buffer, i);
+       }
+       ASN1_FIXUP(compstk, compsp, buffer, i);
+       ASN1_FIXUP(compstk, compsp, buffer, i); 
+       
+       if (pri->debug & PRI_DEBUG_AOC)
+               dump_apdu (buffer, i);
+               
+       /* code below is untested */
+       res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
+       if (res) {
+               pri_message("Could not queue ADPU in facility message\n");
+               return -1;
+       }
+
+       /* Remember that if we queue a facility IE for a facility message we
+        * have to explicitly send the facility message ourselves */
+       res = q931_facility(c->pri, c);
+       if (res) {
+               pri_message("Could not schedule facility message for call 
%d\n", c->cr);
+               return -1;
+       }
+
+       return 0;
+}
+/* End AOC */
 
 extern int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char 
*data, int len)
 {
@@ -771,11 +999,11 @@
        int operation_tag;
        unsigned char *vdata = data;
        struct rose_component *comp = NULL, *invokeid = NULL, *operationid = 
NULL;
-
+       
        do {
                /* Invoke ID stuff */
                GET_COMPONENT(comp, i, vdata, len);
-               CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if 
first ROSE component is of type 0x%x\n");
+               CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do 
if first ROSE component is of type 0x%x\n");
                invokeid = comp;
                NEXT_COMPONENT(comp, i);
 
@@ -806,23 +1034,77 @@
                                        memcpy(call->callername, comp->data, 
comp->len);
                                        call->callername[comp->len] = 0;
                                        if (pri->debug & PRI_DEBUG_APDU)
-                                         pri_message("    Received caller name 
'%s'\n", call->callername);
+                                               pri_message("    Received 
caller name '%s'\n", call->callername);
                                        return 0;
                                default:
-                                       pri_message("Do not handle argument of 
type 0x%X\n", comp->type);
+                                       if (pri->debug & PRI_DEBUG_APDU)
+                                               pri_message("Do not handle 
argument of type 0x%X\n", comp->type);
                                        return -1;
                        }
                        break;
                case ROSE_DIVERTING_LEG_INFORMATION2:
                        if (pri->debug & PRI_DEBUG_APDU)
                                pri_message("  Handle 
DivertingLegInformation2\n");
-                       if (comp->type != 0x30) { /* Sequence */
+                       if (comp->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { 
/* Constructed Sequence */
                                pri_message("Invalid 
DivertingLegInformation2Type argument\n");
                                return -1;
                        }
                        return rose_diverting_leg_information2_decode(pri, 
call, comp->data, comp->len);
+               case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("ROSE %i: AOC No Charging Info 
Available - not handled!", operation_tag);
+                               dump_apdu (comp->data, comp->len);
+                       }
+                       return -1;
+               case ROSE_AOC_CHARGING_REQUEST:
+                       return aoc_aoce_charging_request_decode(pri, call, 
(u_int8_t *)comp, comp->len + 2);
+               case ROSE_AOC_AOCS_CURRENCY:
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("ROSE %i: AOC-S Currency - not 
handled!", operation_tag);
+                               dump_apdu ((u_int8_t *)comp, comp->len + 2);
+                       }
+                       return -1;
+               case ROSE_AOC_AOCS_SPECIAL_ARR:
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("ROSE %i: AOC-S Special Array - not 
handled!", operation_tag);
+                               dump_apdu ((u_int8_t *)comp, comp->len + 2);
+                       }
+                       return -1;
+               case ROSE_AOC_AOCD_CURRENCY:
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("ROSE %i: AOC-D Currency - not 
handled!", operation_tag);
+                               dump_apdu ((u_int8_t *)comp, comp->len + 2);
+                       }
+                       return -1;
+               case ROSE_AOC_AOCD_CHARGING_UNIT:
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("ROSE %i: AOC-D Charging Unit - not 
handled!", operation_tag);
+                               dump_apdu ((u_int8_t *)comp, comp->len + 2);
+                       }
+                       return -1;
+               case ROSE_AOC_AOCE_CURRENCY:
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("ROSE %i: AOC-E Currency - not 
handled!", operation_tag);
+                               dump_apdu ((u_int8_t *)comp, comp->len + 2);
+                       }
+                       return -1;
+               case ROSE_AOC_AOCE_CHARGING_UNIT:
+                       return aoc_aoce_charging_unit_decode(pri, call, 
(u_int8_t *)comp, comp->len + 2);
+                       if (0) { /* the following function is currently not 
used - just to make the compiler happy */
+                               aoc_aoce_charging_unit_encode(pri, call, 
call->aoc_units); /* use this function to forward the aoc-e on a bridged 
channel */ 
+                               return 0;
+                       }
+               case ROSE_AOC_IDENTIFICATION_OF_CHARGE:
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("ROSE %i: AOC Identification Of 
Charge - not handled!", operation_tag);
+                               dump_apdu ((u_int8_t *)comp, comp->len + 2);
+                       }
+                       return -1;
                default:
-                       pri_message("!! Unable to handle ROSE operation %d\n", 
operation_tag);
+                       if (pri->debug & PRI_DEBUG_APDU) {
+                               pri_message("!! Unable to handle ROSE operation 
%d", operation_tag);
+                               dump_apdu ((u_int8_t *)comp, comp->len + 2);
+                       }
                        return -1;
                }
        } while(0);
@@ -848,7 +1130,7 @@
                memcpy(new_event->apdu, apdu, apdu_len);
                new_event->apdu_len = apdu_len;
        } else {
-               pri_error("malloc failed\n");
+               pri_error("!! Malloc failed!\n");
                return -1;
        }
        

Index: pri_facility.h
===================================================================
RCS file: /usr/cvsroot/libpri/pri_facility.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- pri_facility.h      2 Mar 2005 15:56:11 -0000       1.3
+++ pri_facility.h      5 Apr 2005 03:55:58 -0000       1.4
@@ -32,10 +32,20 @@
 #define COMP_TYPE_NFE                                          0xAA
 
 /* Operation ID values */
-/* Q.952 ROSE operations */
+/* Q.952 ROSE operations (Diverting) */
 #define ROSE_DIVERTING_LEG_INFORMATION1                18
 #define ROSE_DIVERTING_LEG_INFORMATION2                15
 #define ROSE_DIVERTING_LEG_INFORMATION3                19
+/* Q.956 ROSE operations (Advice Of Charge) */
+#define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE    26
+#define ROSE_AOC_CHARGING_REQUEST                      30
+#define ROSE_AOC_AOCS_CURRENCY                         31
+#define ROSE_AOC_AOCS_SPECIAL_ARR                      32
+#define ROSE_AOC_AOCD_CURRENCY                         33
+#define ROSE_AOC_AOCD_CHARGING_UNIT                    34
+#define ROSE_AOC_AOCE_CURRENCY                         35
+#define ROSE_AOC_AOCE_CHARGING_UNIT                    36
+#define ROSE_AOC_IDENTIFICATION_OF_CHARGE      37
 /* Q.SIG operations */
 #define SS_CNID_CALLINGNAME                                    0
 #define SS_DIVERTING_LEG_INFORMATION2          22
@@ -48,14 +58,15 @@
 #define INVOKE_LINKED_IDENTIFIER       0x80
 #define INVOKE_NULL_IDENTIFIER         __USE_ASN1_NULL
 
-/* ASN.1 Data types */
+/* ASN.1 Identifier Octet - Data types */
+#define ASN1_TYPE_MASK                 0x1f
 #define ASN1_BOOLEAN                   0x01
 #define ASN1_INTEGER                   0x02
 #define ASN1_BITSTRING                 0x03
 #define ASN1_OCTETSTRING               0x04
 #define ASN1_NULL                              0x05
 #define ASN1_OBJECTIDENTIFIER  0x06
-#define ASN1_OBJECTDESCRIPTER  0x07
+#define ASN1_OBJECTDESCRIPTOR  0x07
 #define ASN1_EXTERN                            0x08
 #define ASN1_REAL                              0x09
 #define ASN1_ENUMERATED                        0x0a
@@ -72,6 +83,31 @@
 #define ASN1_UTCTIME                   0x17
 #define ASN1_GENERALIZEDTIME   0x18
 
+/* ASN.1 Identifier Octet - Tags */
+#define ASN1_TAG_0                             0x00
+#define ASN1_TAG_1                             0x01
+#define ASN1_TAG_2                             0x02
+#define ASN1_TAG_3                             0x03
+#define ASN1_TAG_4                             0x04
+#define ASN1_TAG_5                             0x05
+#define ASN1_TAG_6                             0x06
+#define ASN1_TAG_7                             0x07
+#define ASN1_TAG_8                             0x08
+#define ASN1_TAG_9                             0x09
+
+/* ASN.1 Identifier Octet - Primitive/Constructor Bit */
+#define ASN1_PC_MASK                   0x20
+#define ASN1_PRIMITIVE                 0x00
+#define ASN1_CONSTRUCTOR               0x20
+
+/* ASN.1 Identifier Octet - Clan Bits */
+#define ASN1_CLAN_MASK                 0xc0
+#define ASN1_UNIVERSAL                 0x00
+#define ASN1_APPLICATION               0x40
+#define ASN1_CONTEXT_SPECIFIC  0x80
+#define ASN1_PRIVATE                   0xc0
+
+
 #define INVOKE_OPERATION_INT   __USE_ASN1_INTEGER
 #define INVOKE_OBJECT_ID               __USE_ASN1_OBJECTIDENTIFIER
 
@@ -103,7 +139,7 @@
 };
 
 #define GET_COMPONENT(component, idx, ptr, length) \
-       if ((idx)+2 >= (length)) \
+       if ((idx)+2 > (length)) \
                break; \
        (component) = (struct rose_component*)&((ptr)[idx]); \
        if ((idx)+(component)->len+2 > (length)) { \
@@ -128,7 +164,7 @@
        (idx) += 2
 
 #define CHECK_COMPONENT(component, comptype, message) \
-       if ((component)->type && ((component)->type&0x1f) != (comptype)) { \
+       if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != 
(comptype)) { \
                pri_message((message), (component)->type); \
                break; \
        }

Index: pri_internal.h
===================================================================
RCS file: /usr/cvsroot/libpri/pri_internal.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- pri_internal.h      17 Mar 2005 15:46:23 -0000      1.18
+++ pri_internal.h      5 Apr 2005 03:55:58 -0000       1.19
@@ -219,6 +219,8 @@
         int useruserprotocoldisc;
        char useruserinfo[256];
        char callingsubaddr[256];       /* Calling parties sub address */
+       
+       long aoc_units;                         /* Advice of Charge Units */
 
        struct apdu_event *apdus;       /* APDU queue for call */
 };

Index: q931.c
===================================================================
RCS file: /usr/cvsroot/libpri/q931.c,v
retrieving revision 1.121
retrieving revision 1.122
diff -u -d -r1.121 -r1.122
--- q931.c      3 Apr 2005 23:07:55 -0000       1.121
+++ q931.c      5 Apr 2005 03:55:58 -0000       1.122
@@ -3170,6 +3170,7 @@
                c->cause = -1;
                c->causecode = -1;
                c->causeloc = -1;
+               c->aoc_units = -1;
                if (c->retranstimer)
                        pri_schedule_del(pri, c->retranstimer);
                c->retranstimer = 0;
@@ -3183,6 +3184,7 @@
                c->causecode = -1;
                c->causeloc = -1;
                c->sugcallstate = -1;
+               c->aoc_units = -1;
                break;
        case Q931_RESTART_ACKNOWLEDGE:
                c->channelno = -1;
@@ -3538,6 +3540,7 @@
                pri->ev.hangup.cref = c->cr;
                pri->ev.hangup.cause = c->cause;
                pri->ev.hangup.call = c;
+               pri->ev.hangup.aoc_units = c->aoc_units;
                /* Don't send release complete if they send us release 
                   while we sent it, assume a NULL state */
                if (c->newcall)
@@ -3563,6 +3566,7 @@
                pri->ev.hangup.cref = c->cr;
                pri->ev.hangup.cause = c->cause;
                pri->ev.hangup.call = c;
+               pri->ev.hangup.aoc_units = c->aoc_units;
                if (c->alive)
                        return Q931_RES_HAVEEVENT;
                else

_______________________________________________
Asterisk-Cvs mailing list
[email protected]
http://lists.digium.com/mailman/listinfo/asterisk-cvs

Reply via email to