Send AOC-E facility on call termination; fixed AOC-E encoding function
- Some ISDN terminals require AOC-E information to increment their internal unit counter. Tested with Siemens Profiset 51 - Fixed encodeAOCEChargingUnitOperation() producing incorrect AOC-E IE. Tested with K1297 protocol analyser, protocol ETSI-SupplementalServices
This commit is contained in:
parent
b79127209c
commit
bd72569a0e
|
@ -184,7 +184,7 @@ static void split_3pty(call_t *call)
|
|||
}
|
||||
}
|
||||
|
||||
/* Generate AOC-S facility IE from metering information */
|
||||
/* Generate AOC-S facility msg from metering information */
|
||||
#define AOCS_CURRENCY_AMOUNT_PER_UNIT 5
|
||||
static void generate_aocs_fac(call_t *call)
|
||||
{
|
||||
|
@ -216,7 +216,7 @@ static void generate_aocs_fac(call_t *call)
|
|||
fac.u.inv.o.AOCcuril.currencyInfoCount = 2;
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // BasicComm
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA2; // FlatRate
|
||||
strncpy(fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currency, "EUR", 10); // Currency value
|
||||
strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currency, "EUR", 10); // Currency value
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call->metering_connect_units;
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].FlatRateCurrency.multiplier = 1; // 1/100 EUR
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[1].chargedItem = 0x02; // CallSetup
|
||||
|
@ -227,7 +227,7 @@ static void generate_aocs_fac(call_t *call)
|
|||
fac.u.inv.o.AOCcuril.currencyInfoCount = 2;
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].chargedItem = 0x00; // BasicComm
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].currencyType = 0xA1; // DurationCurrency
|
||||
strncpy(fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currency, "EUR", 10); // Currency value
|
||||
strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currency, "EUR", 10); // Currency value
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT;
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.multiplier = 1; // 1/100 EUR
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[0].durationCurrency.typeOfCharging = 1; // StepFunction
|
||||
|
@ -240,7 +240,7 @@ static void generate_aocs_fac(call_t *call)
|
|||
/* Additional CallSetup charge */
|
||||
PDEBUG(DISDN, DEBUG_DEBUG, "AOC-S currencyInfoList: BasicComm DurationCurrency %d/100 EUR per %d/100 seconds; CallSetup FlatRate %d/100 EUR\n", AOCS_CURRENCY_AMOUNT_PER_UNIT, call->metering_unit_period_decisecs * 10, AOCS_CURRENCY_AMOUNT_PER_UNIT * (call->metering_connect_units - 1));
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[1].currencyType = 0xA2; // FlatRate
|
||||
strncpy(fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currency, "EUR", 10); // Currency value
|
||||
strncpy((char *)fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currency, "EUR", 10); // Currency value
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * (call->metering_connect_units - 1);
|
||||
fac.u.inv.o.AOCcuril.currencyInfo[1].FlatRateCurrency.multiplier = 1; // 1/100 EUR
|
||||
}
|
||||
|
@ -260,6 +260,32 @@ static void generate_aocs_fac(call_t *call)
|
|||
}
|
||||
}
|
||||
|
||||
/* Generate AOC-E facility msg */
|
||||
static void generate_aoce_fac(call_t *call)
|
||||
{
|
||||
uint8_t fac_ie[256];
|
||||
struct asn1_parm fac;
|
||||
struct l3_msg *l3m;
|
||||
|
||||
PDEBUG(DISDN, DEBUG_DEBUG, "Sending AOC-E facility, total_units=%d\n", call->metering_total_units);
|
||||
|
||||
timer_start(&call->aocd_unit_timer, (double)call->metering_unit_period_decisecs / (double)10);
|
||||
|
||||
memset(&fac, 0, sizeof(fac));
|
||||
fac.Valid = 1;
|
||||
fac.comp = CompInvoke;
|
||||
fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */
|
||||
fac.u.inv.operationValue = Fac_AOCEChargingUnit;
|
||||
fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units;
|
||||
|
||||
encodeFac(fac_ie, &fac);
|
||||
|
||||
// sending facility
|
||||
l3m = create_l3msg();
|
||||
enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
|
||||
call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m);
|
||||
}
|
||||
|
||||
/* AOC-D timer callback */
|
||||
static void aocd_timer_cb(void *data)
|
||||
{
|
||||
|
@ -876,12 +902,13 @@ void disconnect_ind(call_t *call, uint32_t pid, struct l3_msg *l3m)
|
|||
/* send message to osmo-cc */
|
||||
osmo_cc_ll_msg(&call->isdn_ep->cc_ep, call->cc_callref, msg);
|
||||
|
||||
/* stop AOC-D timer */
|
||||
/* stop AOC-D timer and send AOC-E facility */
|
||||
if(call->aocd_unit_timer_started)
|
||||
{
|
||||
timer_stop(&call->aocd_unit_timer);
|
||||
timer_exit(&call->aocd_unit_timer);
|
||||
call->aocd_unit_timer_started = 0;
|
||||
generate_aoce_fac(call);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2508,18 +2535,19 @@ void disc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
enc_ie_display(l3m, display);
|
||||
}
|
||||
|
||||
/* stop AOC-D timer */
|
||||
new_state(call, ISDN_STATE_OUT_DISCONNECT);
|
||||
|
||||
/* send message to ISDN */
|
||||
call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_DISCONNECT, call->l3_pid, l3m);
|
||||
|
||||
/* stop AOC-D timer and send AOC-E facility */
|
||||
if(call->aocd_unit_timer_started)
|
||||
{
|
||||
timer_stop(&call->aocd_unit_timer);
|
||||
timer_exit(&call->aocd_unit_timer);
|
||||
call->aocd_unit_timer_started = 0;
|
||||
generate_aoce_fac(call);
|
||||
}
|
||||
|
||||
new_state(call, ISDN_STATE_OUT_DISCONNECT);
|
||||
|
||||
/* send message to ISDN */
|
||||
call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_DISCONNECT, call->l3_pid, l3m);
|
||||
}
|
||||
|
||||
/* CC-RELEASE REQUEST */
|
||||
|
|
|
@ -239,7 +239,7 @@ static int encodeAOCSChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
ci_len++;
|
||||
p[i++] = 0x81; // CurrencySpec
|
||||
ci_len++; c_len++;
|
||||
cval_len = strlen(currinfolist->currencyInfo[ci].durationCurrency.currency);
|
||||
cval_len = strlen((char *)currinfolist->currencyInfo[ci].durationCurrency.currency);
|
||||
if(cval_len > 10)
|
||||
cval_len = 10;
|
||||
p[i++] = cval_len;
|
||||
|
@ -341,7 +341,7 @@ static int encodeAOCSChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
ci_len++;
|
||||
p[i++] = 0x81; // CurrencySpec
|
||||
ci_len++; c_len++;
|
||||
cval_len = strlen(currinfolist->currencyInfo[ci].FlatRateCurrency.currency);
|
||||
cval_len = strlen((char *)currinfolist->currencyInfo[ci].FlatRateCurrency.currency);
|
||||
if(cval_len > 10)
|
||||
cval_len = 10;
|
||||
p[i++] = cval_len;
|
||||
|
@ -481,15 +481,14 @@ static int encodeAOCEChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
p[i++] = 0x02; // Operation Tag
|
||||
p[i++] = 0x01; // Tag Length
|
||||
p[i++] = Fac_AOCEChargingUnit; // Operation Value
|
||||
p[i++] = 0xa1; // APDU
|
||||
p[i++] = 0x30;
|
||||
p[i++] = 0x30; // ChargingUnitInfo
|
||||
p[i++] = (0x0b + len); // Length
|
||||
p[i++] = 0x30; // specificChargingUnits
|
||||
p[i++] = (0x09 + len); // Length
|
||||
p[i++] = 0xa1; // APDU
|
||||
p[i++] = (0x04 + len); // Length
|
||||
p[i++] = 0x30;
|
||||
p[i++] = 0x30; // recordedUnits
|
||||
p[i++] = (0x02 + len);
|
||||
p[i++] = 0x02;
|
||||
p[i++] = 0x02; // AOC-E so Total
|
||||
p[i++] = 0x02; // recordedNumberOfUnits
|
||||
p[i++] = len;
|
||||
|
||||
// Recorded units could take up as much as 3 bytes (0xFFFFFF)
|
||||
p[i] = numberOfUnits & 0xFF;
|
||||
|
@ -499,7 +498,11 @@ static int encodeAOCEChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
p[i+2] = (numberOfUnits >> 16) & 0xFF;
|
||||
i += len;
|
||||
|
||||
p[1] = (AOCE_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length
|
||||
p[i++] = 0x82; // AOCEBillingId
|
||||
p[i++] = 0x01; // Length
|
||||
p[i++] = 0x00; // normalCharging
|
||||
|
||||
p[1] = i - 2; // IE Payload Length
|
||||
p[4] = p[1] - 3; // Invoke Component Length
|
||||
|
||||
result = p[1] + 2; // Total Length of IE
|
||||
|
|
Loading…
Reference in New Issue