Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
aoc.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2010, Digium, Inc.
5 *
6 * David Vossel <dvossel@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \brief generic AOC payload generation encoding and decoding
22 *
23 * \author David Vossel <dvossel@digium.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/aoc.h"
33#include "asterisk/utils.h"
34#include "asterisk/strings.h"
35#include "asterisk/_private.h"
36#include "asterisk/cli.h"
37#include "asterisk/manager.h"
40
41/*** DOCUMENTATION
42 <managerEvent language="en_US" name="AOC-S">
43 <managerEventInstance class="EVENT_FLAG_AOC">
44 <since>
45 <version>12.0.0</version>
46 </since>
47 <synopsis>Raised when an Advice of Charge message is sent at the beginning of a call.</synopsis>
48 <syntax>
49 <channel_snapshot/>
50 <parameter name="Chargeable" />
51 <parameter name="RateType">
52 <enumlist>
53 <enum name="NotAvailable" />
54 <enum name="Free" />
55 <enum name="FreeFromBeginning" />
56 <enum name="Duration" />
57 <enum name="Flag" />
58 <enum name="Volume" />
59 <enum name="SpecialCode" />
60 </enumlist>
61 </parameter>
62 <parameter name="Currency" />
63 <parameter name="Name" />
64 <parameter name="Cost" />
65 <parameter name="Multiplier">
66 <enumlist>
67 <enum name="1/1000" />
68 <enum name="1/100" />
69 <enum name="1/10" />
70 <enum name="1" />
71 <enum name="10" />
72 <enum name="100" />
73 <enum name="1000" />
74 </enumlist>
75 </parameter>
76 <parameter name="ChargingType" />
77 <parameter name="StepFunction" />
78 <parameter name="Granularity" />
79 <parameter name="Length" />
80 <parameter name="Scale" />
81 <parameter name="Unit">
82 <enumlist>
83 <enum name="Octet" />
84 <enum name="Segment" />
85 <enum name="Message" />
86 </enumlist>
87 </parameter>
88 <parameter name="SpecialCode" />
89 </syntax>
90 <see-also>
91 <ref type="managerEvent">AOC-D</ref>
92 <ref type="managerEvent">AOC-E</ref>
93 </see-also>
94 </managerEventInstance>
95 </managerEvent>
96 <managerEvent language="en_US" name="AOC-D">
97 <managerEventInstance class="EVENT_FLAG_AOC">
98 <since>
99 <version>12.0.0</version>
100 </since>
101 <synopsis>Raised when an Advice of Charge message is sent during a call.</synopsis>
102 <syntax>
103 <channel_snapshot/>
104 <parameter name="Charge" />
105 <parameter name="Type">
106 <enumlist>
107 <enum name="NotAvailable" />
108 <enum name="Free" />
109 <enum name="Currency" />
110 <enum name="Units" />
111 </enumlist>
112 </parameter>
113 <parameter name="BillingID">
114 <enumlist>
115 <enum name="Normal" />
116 <enum name="Reverse" />
117 <enum name="CreditCard" />
118 <enum name="CallForwardingUnconditional" />
119 <enum name="CallForwardingBusy" />
120 <enum name="CallForwardingNoReply" />
121 <enum name="CallDeflection" />
122 <enum name="CallTransfer" />
123 <enum name="NotAvailable" />
124 </enumlist>
125 </parameter>
126 <parameter name="TotalType">
127 <enumlist>
128 <enum name="SubTotal" />
129 <enum name="Total" />
130 </enumlist>
131 </parameter>
132 <parameter name="Currency" />
133 <parameter name="Name" />
134 <parameter name="Cost" />
135 <parameter name="Multiplier">
136 <enumlist>
137 <enum name="1/1000" />
138 <enum name="1/100" />
139 <enum name="1/10" />
140 <enum name="1" />
141 <enum name="10" />
142 <enum name="100" />
143 <enum name="1000" />
144 </enumlist>
145 </parameter>
146 <parameter name="Units" />
147 <parameter name="NumberOf" />
148 <parameter name="TypeOf" />
149 </syntax>
150 <see-also>
151 <ref type="manager">AOCMessage</ref>
152 <ref type="managerEvent">AOC-S</ref>
153 <ref type="managerEvent">AOC-E</ref>
154 </see-also>
155 </managerEventInstance>
156 </managerEvent>
157 <managerEvent language="en_US" name="AOC-E">
158 <managerEventInstance class="EVENT_FLAG_AOC">
159 <since>
160 <version>12.0.0</version>
161 </since>
162 <synopsis>Raised when an Advice of Charge message is sent at the end of a call.</synopsis>
163 <syntax>
164 <channel_snapshot/>
165 <parameter name="ChargingAssociation" />
166 <parameter name="Number" />
167 <parameter name="Plan" />
168 <parameter name="ID" />
169 <xi:include xpointer="xpointer(/docs/managerEvent[@name='AOC-D']/managerEventInstance/syntax/parameter)" />
170 </syntax>
171 <see-also>
172 <ref type="manager">AOCMessage</ref>
173 <ref type="managerEvent">AOC-S</ref>
174 <ref type="managerEvent">AOC-D</ref>
175 </see-also>
176 </managerEventInstance>
177 </managerEvent>
178***/
179
180/* Encoded Payload Flags */
181#define AST_AOC_ENCODED_TYPE_REQUEST (0 << 0)
182#define AST_AOC_ENCODED_TYPE_D (1 << 0)
183#define AST_AOC_ENCODED_TYPE_E (2 << 0)
184#define AST_AOC_ENCODED_TYPE_S (3 << 0)
185
186#define AST_AOC_ENCODED_REQUEST_S (1 << 2)
187#define AST_AOC_ENCODED_REQUEST_D (1 << 3)
188#define AST_AOC_ENCODED_REQUEST_E (1 << 4)
189
190#define AST_AOC_ENCODED_CHARGE_NA (0 << 5)
191#define AST_AOC_ENCODED_CHARGE_FREE (1 << 5)
192#define AST_AOC_ENCODED_CHARGE_CURRENCY (2 << 5)
193#define AST_AOC_ENCODED_CHARGE_UNIT (3 << 5)
194
195#define AST_AOC_ENCODED_CHARGE_SUBTOTAL (1 << 7)
196#define AST_AOC_ENCODED_CHARGE_TOTAL (0 << 7)
197
198#define AST_AOC_ENCODE_VERSION 1
199
200
201static char aoc_debug_enabled = 0;
202static void aoc_display_decoded_debug(const struct ast_aoc_decoded *decoded, int decoding, struct ast_channel *chan);
203static int aoc_s_add_entry(struct ast_aoc_decoded *decoded, struct ast_aoc_s_entry *entry);
204
205/* AOC Payload Header. Holds all the encoded AOC data to pass on the wire */
207 uint8_t version;
208 uint8_t flags;
209 uint16_t datalen;
210 unsigned char data[0];
211};
212
213/* Decoded AOC data */
219
220 /* currency information */
222 unsigned int currency_amount;
224
225 /* unit information */
228
229 /* Billing Id */
231
232 /* Charging Association information */
234
235 /* AOC-S charge information */
238
239 /* Is this an AOC Termination Request */
241};
242
243/*! \brief AOC Payload Information Elements */
244enum AOC_IE {
251};
252
253/*! \brief AOC IE payload header */
255 uint8_t ie_id;
256 uint8_t datalen;
257 char data[0];
258} __attribute__((packed));
259
261 uint32_t amount;
262 uint8_t multiplier;
264} __attribute__((packed));
265
267 uint32_t amount;
268 uint8_t valid_type;
270 uint8_t type;
271} __attribute__((packed));
272
274 uint8_t id;
275} __attribute__((packed));
276
279} __attribute__((packed));
280
283} __attribute__((packed));
284
287 const enum ast_aoc_request requests)
288{
289 struct ast_aoc_decoded *decoded = NULL;
290
291 /* verify input */
292 if (((unsigned int) charge_type > AST_AOC_CHARGE_UNIT) ||
293 ((unsigned int) msg_type > AST_AOC_E) ||
294 ((msg_type == AST_AOC_REQUEST) && !requests)) {
295
296 ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object, invalid input\n");
297 return NULL;
298 }
299
300 if (!(decoded = ast_calloc(1, sizeof(struct ast_aoc_decoded)))) {
301 ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object \n");
302 return NULL;
303 }
304
305 decoded->msg_type = msg_type;
306
307 if (msg_type == AST_AOC_REQUEST) {
308 decoded->request_flag = requests;
309 } else if ((msg_type == AST_AOC_D) || (msg_type == AST_AOC_E)) {
310 decoded->charge_type = charge_type;
311 }
312
313 return decoded;
314}
315
317{
318 ast_free(decoded);
319 return NULL;
320}
321
323{
324 ast_free(encoded);
325 return NULL;
326}
327
328static void aoc_parse_ie_charging_rate(struct ast_aoc_decoded *decoded, const struct aoc_ie_charging_rate *ie)
329{
330 struct ast_aoc_s_entry entry = { 0, };
331
332 entry.charged_item = ntohs(ie->entry.charged_item);
333 entry.rate_type = ntohs(ie->entry.rate_type);
334
335 switch (entry.rate_type) {
338 entry.rate.duration.amount = ntohl(ie->entry.rate.duration.amount);
339 entry.rate.duration.time = ntohl(ie->entry.rate.duration.time);
343 entry.rate.duration.charging_type = ie->entry.rate.duration.charging_type; /* only one byte */
344
348 sizeof(entry.rate.duration.currency_name));
349 }
350 break;
352 entry.rate.flat.multiplier = ntohs(ie->entry.rate.flat.multiplier);
353 entry.rate.flat.amount = ntohl(ie->entry.rate.flat.amount);
357 sizeof(entry.rate.flat.currency_name));
358 }
359 break;
361 entry.rate.volume.multiplier = ntohs(ie->entry.rate.volume.multiplier);
362 entry.rate.volume.amount = ntohl(ie->entry.rate.volume.amount);
367 sizeof(entry.rate.volume.currency_name));
368 }
369 break;
371 entry.rate.special_code = ntohs(ie->entry.rate.special_code);
372 break;
373 }
374
375 aoc_s_add_entry(decoded, &entry);
376}
377
378static int aoc_parse_ie(struct ast_aoc_decoded *decoded, unsigned char *data, unsigned int datalen)
379{
380 enum AOC_IE ie_id;
381 unsigned int len;
382
383 while (datalen >= 2) {
384 ie_id = data[0];
385 len = data[1];
386 if (len > datalen -2) {
387 ast_log(LOG_ERROR, "AOC information element length exceeds the total message size\n");
388 return -1;
389 }
390
391 switch(ie_id) {
392 case AOC_IE_CURRENCY:
393 if (len == sizeof(struct aoc_ie_currency)) {
394 struct aoc_ie_currency ie;
395 memcpy(&ie, data + 2, len);
396 decoded->currency_amount = ntohl(ie.amount);
397 decoded->multiplier = ie.multiplier; /* only one byte */
398 memcpy(decoded->currency_name, ie.name, sizeof(decoded->currency_name));
399 } else {
400 ast_log(LOG_WARNING, "Received invalid currency ie\n");
401 }
402 break;
403 case AOC_IE_UNIT:
404 if (len == sizeof(struct aoc_ie_unit)) {
405 struct aoc_ie_unit ie;
406 memcpy(&ie, data + 2, len);
407 ast_aoc_add_unit_entry(decoded, ie.valid_amount, ntohl(ie.amount), ie.valid_type, ie.type);
408 } else {
409 ast_log(LOG_WARNING, "Received invalid unit ie\n");
410 }
411 break;
412 case AOC_IE_BILLING:
413 if (len == sizeof(struct aoc_ie_billing)) {
414 struct aoc_ie_billing ie;
415 memcpy(&ie, data + 2, len);
416 decoded->billing_id = ie.id; /* only one byte */
417 } else {
418 ast_log(LOG_WARNING, "Received invalid billing ie\n");
419 }
420 break;
422 if (len == sizeof(struct aoc_ie_charging_association)) {
423 memcpy(&decoded->charging_association, data + 2, sizeof(decoded->charging_association));
424 /* everything in the charging_association struct is a single byte except for the id */
426 decoded->charging_association.charge.id = ntohl(decoded->charging_association.charge.id);
427 }
428 } else {
429 ast_log(LOG_WARNING, "Received invalid charging association ie\n");
430 }
431 break;
432 case AOC_IE_RATE:
433 if (len == sizeof(struct aoc_ie_charging_rate)) {
434 struct aoc_ie_charging_rate ie;
435 memcpy(&ie, data + 2, len);
436 aoc_parse_ie_charging_rate(decoded, &ie);
437 } else {
438 ast_log(LOG_WARNING, "Received invalid charging rate ie\n");
439 }
440 break;
442 if (len == 0) {
443 decoded->termination_request = 1;
444 } else {
445 ast_log(LOG_WARNING, "Received invalid termination request ie\n");
446 }
447 break;
448 default:
449 ast_log(LOG_WARNING, "Unknown AOC Information Element, ignoring.\n");
450 }
451
452 datalen -= (len + 2);
453 data += (len + 2);
454 }
455 return 0;
456}
457
458struct ast_aoc_decoded *ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan)
459{
460 struct ast_aoc_decoded *decoded;
461
462 /* verify our encoded payload is actually large enough to hold all the ies */
463 if ((size - (sizeof(struct ast_aoc_encoded)) != ntohs(encoded->datalen))) {
464 ast_log(LOG_WARNING, "Corrupted aoc encoded object, can not decode\n");
465 return NULL;
466 }
467
468 if (!(decoded = ast_calloc(1, sizeof(struct ast_aoc_decoded)))) {
469 ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object \n");
470 return NULL;
471 }
472
473 /* decode flags */
474
476 decoded->msg_type = AST_AOC_S;
477 } else if (encoded->flags & AST_AOC_ENCODED_TYPE_E) {
478 decoded->msg_type = AST_AOC_E;
479 } else if (encoded->flags & AST_AOC_ENCODED_TYPE_D) {
480 decoded->msg_type = AST_AOC_D;
481 } else {
482 decoded->msg_type = AST_AOC_REQUEST;
483 }
484
485 if (decoded->msg_type == AST_AOC_REQUEST) {
486 if (encoded->flags & AST_AOC_ENCODED_REQUEST_S) {
488 }
489 if (encoded->flags & AST_AOC_ENCODED_REQUEST_D) {
491 }
492 if (encoded->flags & AST_AOC_ENCODED_REQUEST_E) {
494 }
495 } else if ((decoded->msg_type == AST_AOC_D) || (decoded->msg_type == AST_AOC_E)) {
502 } else {
504 }
505
506 if (encoded->flags & AST_AOC_ENCODED_CHARGE_SUBTOTAL) {
507 decoded->total_type = AST_AOC_SUBTOTAL;
508 }
509 }
510
511 /* decode information elements */
512 aoc_parse_ie(decoded, encoded->data, ntohs(encoded->datalen));
513
514 if (aoc_debug_enabled) {
515 aoc_display_decoded_debug(decoded, 1, chan);
516 }
517
518 return decoded;
519}
520
522 unsigned char buf[1024];
523 int pos;
524};
525
526/*!
527 * \internal
528 * \brief append an AOC information element
529 * \note data is expected to already be in network byte order at this point
530 */
531static int aoc_append_ie(struct aoc_ie_data *ied, unsigned short ie_id, const void *data, unsigned short datalen)
532{
533 if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
534 ast_log(LOG_WARNING, "Failure to append AOC information element, out of space \n");
535 return -1;
536 }
537 ied->buf[ied->pos++] = ie_id;
538 ied->buf[ied->pos++] = datalen;
539 if (datalen) {
540 memcpy(ied->buf + ied->pos, data, datalen);
541 ied->pos += datalen;
542 }
543 return 0;
544}
545
547{
548 ie->entry.charged_item = htons(entry->charged_item);
549 ie->entry.rate_type = htons(entry->rate_type);
550
551 switch (entry->rate_type) {
554 ie->entry.rate.duration.amount = htonl(entry->rate.duration.amount);
555 ie->entry.rate.duration.time = htonl(entry->rate.duration.time);
559 ie->entry.rate.duration.charging_type = entry->rate.duration.charging_type; /* only one byte */
560
564 sizeof(ie->entry.rate.duration.currency_name));
565 }
566 break;
568 ie->entry.rate.flat.multiplier = htons(entry->rate.flat.multiplier);
569 ie->entry.rate.flat.amount = htonl(entry->rate.flat.amount);
570 if (!ast_strlen_zero(entry->rate.flat.currency_name)) {
572 entry->rate.flat.currency_name,
573 sizeof(ie->entry.rate.flat.currency_name));
574 }
575 break;
577 ie->entry.rate.volume.multiplier = htons(entry->rate.volume.multiplier);
578 ie->entry.rate.volume.amount = htonl(entry->rate.volume.amount);
579 ie->entry.rate.volume.volume_unit = htons(entry->rate.volume.volume_unit);
583 sizeof(ie->entry.rate.volume.currency_name));
584 }
585 break;
587 ie->entry.rate.special_code = htons(entry->rate.special_code);
588 break;
589 }
590
591}
592static void aoc_create_ie_data(struct ast_aoc_decoded *decoded, struct aoc_ie_data *ied)
593{
594 ied->pos = 0;
595
596 if (decoded->currency_amount) {
597 struct aoc_ie_currency ie = {
598 .amount = htonl(decoded->currency_amount),
599 .multiplier = decoded->multiplier, /* only one byte */
600 .name = { 0, },
601 };
602
603 if (!ast_strlen_zero(decoded->currency_name)) {
604 ast_copy_string(ie.name, decoded->currency_name, sizeof(ie.name));
605 }
606
607 aoc_append_ie(ied, AOC_IE_CURRENCY, (const void *) &ie, sizeof(ie));
608 }
609
610 if (decoded->unit_count) {
611 struct aoc_ie_unit ie = { 0 };
612 int i;
613
614 for (i = 0; i < decoded->unit_count; i++) {
615 ie.valid_amount = decoded->unit_list[i].valid_amount; /* only one byte */
616 ie.amount = htonl(decoded->unit_list[i].amount);
617 ie.valid_type = decoded->unit_list[i].valid_type; /* only one byte */
618 ie.type = decoded->unit_list[i].type; /* only one byte */
619 aoc_append_ie(ied, AOC_IE_UNIT, (const void *) &ie, sizeof(ie));
620 }
621 }
622
623 if (decoded->billing_id) {
624 struct aoc_ie_billing ie;
625 ie.id = decoded->billing_id; /* only one byte */
626 aoc_append_ie(ied, AOC_IE_BILLING, (const void *) &ie, sizeof(ie));
627 }
628
631 memset(&ie, 0, sizeof(ie));
632 ie.ca.charging_type = decoded->charging_association.charging_type; /* only one byte */
634 ie.ca.charge.number.plan = decoded->charging_association.charge.number.plan; /* only one byte */
637 sizeof(ie.ca.charge.number.number));
639 ie.ca.charge.id = htonl(decoded->charging_association.charge.id);
640 }
641 aoc_append_ie(ied, AOC_IE_CHARGING_ASSOCIATION, (const void *) &ie, sizeof(ie));
642 }
643
644 if (decoded->aoc_s_count) {
645 struct aoc_ie_charging_rate ie;
646 int i;
647 for (i = 0; i < decoded->aoc_s_count; i++) {
648 memset(&ie, 0, sizeof(ie));
650 aoc_append_ie(ied, AOC_IE_RATE, (const void *) &ie, sizeof(ie));
651 }
652 }
653
654 if (decoded->termination_request) {
656 }
657}
658
659struct ast_aoc_encoded *ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
660{
661 struct aoc_ie_data ied;
662 struct ast_aoc_encoded *encoded = NULL;
663 size_t size = 0;
664
665 if (!decoded || !out_size) {
666 return NULL;
667 }
668
669 *out_size = 0;
670
671 /* create information element buffer before allocating the payload,
672 * by doing this the exact size of the payload + the id data can be
673 * allocated all at once. */
674 aoc_create_ie_data(decoded, &ied);
675
676 size = sizeof(struct ast_aoc_encoded) + ied.pos;
677
678 if (!(encoded = ast_calloc(1, size))) {
679 ast_log(LOG_WARNING, "Failed to create ast_aoc_encoded object during decode routine. \n");
680 return NULL;
681 }
682
683 /* -- Set ie data buffer */
684 if (ied.pos) {
685 /* this is safe because encoded was allocated to fit this perfectly */
686 memcpy(encoded->data, ied.buf, ied.pos);
687 encoded->datalen = htons(ied.pos);
688 }
689
690 /* --- Set Flags --- */
691 switch (decoded->msg_type) {
692 case AST_AOC_S:
693 encoded->flags = AST_AOC_ENCODED_TYPE_S;
694 break;
695 case AST_AOC_D:
696 encoded->flags = AST_AOC_ENCODED_TYPE_D;
697 break;
698 case AST_AOC_E:
699 encoded->flags = AST_AOC_ENCODED_TYPE_E;
700 break;
701 case AST_AOC_REQUEST:
703 default:
704 break;
705 }
706
707 /* if it is type request, set the types requested, else set charge type */
708 if (decoded->msg_type == AST_AOC_REQUEST) {
709 if (decoded->request_flag & AST_AOC_REQUEST_S) {
711 }
712 if (decoded->request_flag & AST_AOC_REQUEST_D) {
714 }
715 if (decoded->request_flag & AST_AOC_REQUEST_E) {
717 }
718 } else if ((decoded->msg_type == AST_AOC_D) || (decoded->msg_type == AST_AOC_E)) {
719 switch (decoded->charge_type) {
722 break;
725 break;
729 default:
731 break;
732 }
733
734 if (decoded->total_type == AST_AOC_SUBTOTAL) {
736 }
737 }
738
739 /* --- Set Version Number --- */
741
742 /* set the output size */
743 *out_size = size;
744
745 if (aoc_debug_enabled) {
746 aoc_display_decoded_debug(decoded, 0, chan);
747 }
748
749 return encoded;
750}
751
752static int aoc_s_add_entry(struct ast_aoc_decoded *decoded, struct ast_aoc_s_entry *entry)
753{
754 if (decoded->aoc_s_count >= ARRAY_LEN(decoded->aoc_s_entries)) {
755 return -1;
756 }
757
758 decoded->aoc_s_entries[decoded->aoc_s_count] = *entry;
759 decoded->aoc_s_count++;
760
761 return 0;
762}
763
764
765unsigned int ast_aoc_s_get_count(struct ast_aoc_decoded *decoded)
766{
767 return decoded->aoc_s_count;
768}
769
770const struct ast_aoc_s_entry *ast_aoc_s_get_rate_info(struct ast_aoc_decoded *decoded, unsigned int entry_number)
771{
772 if (entry_number >= decoded->aoc_s_count) {
773 return NULL;
774 }
775
776 return (const struct ast_aoc_s_entry *) &decoded->aoc_s_entries[entry_number];
777}
778
781 unsigned int amount,
782 enum ast_aoc_currency_multiplier multiplier,
783 const char *currency_name,
784 unsigned long time,
785 enum ast_aoc_time_scale time_scale,
786 unsigned long granularity_time,
787 enum ast_aoc_time_scale granularity_time_scale,
788 int step_function)
789{
790
791 struct ast_aoc_s_entry entry = { 0, };
792
795 entry.rate.duration.amount = amount;
796 entry.rate.duration.multiplier = multiplier;
797 entry.rate.duration.time = time;
798 entry.rate.duration.time_scale = time_scale;
799 entry.rate.duration.granularity_time = granularity_time;
800 entry.rate.duration.granularity_time_scale = granularity_time_scale;
801 entry.rate.duration.charging_type = step_function ? 1 : 0;
802
803 if (!ast_strlen_zero(currency_name)) {
804 ast_copy_string(entry.rate.duration.currency_name, currency_name, sizeof(entry.rate.duration.currency_name));
805 }
806
807 return aoc_s_add_entry(decoded, &entry);
808}
809
812 unsigned int amount,
813 enum ast_aoc_currency_multiplier multiplier,
814 const char *currency_name)
815{
816 struct ast_aoc_s_entry entry = { 0, };
817
820 entry.rate.flat.amount = amount;
821 entry.rate.flat.multiplier = multiplier;
822
823 if (!ast_strlen_zero(currency_name)) {
824 ast_copy_string(entry.rate.flat.currency_name, currency_name, sizeof(entry.rate.flat.currency_name));
825 }
826
827 return aoc_s_add_entry(decoded, &entry);
828}
829
830
833 enum ast_aoc_volume_unit volume_unit,
834 unsigned int amount,
835 enum ast_aoc_currency_multiplier multiplier,
836 const char *currency_name)
837{
838 struct ast_aoc_s_entry entry = { 0, };
839
842 entry.rate.volume.multiplier = multiplier;
843 entry.rate.volume.amount = amount;
844 entry.rate.volume.volume_unit = volume_unit;
845
846 if (!ast_strlen_zero(currency_name)) {
847 ast_copy_string(entry.rate.volume.currency_name, currency_name, sizeof(entry.rate.volume.currency_name));
848 }
849
850 return aoc_s_add_entry(decoded, &entry);
851}
852
855 unsigned int code)
856{
857 struct ast_aoc_s_entry entry = { 0, };
858
861 entry.rate.special_code = code;
862
863 return aoc_s_add_entry(decoded, &entry);
864}
865
868 int from_beginning)
869{
870 struct ast_aoc_s_entry entry = { 0, };
871
874
875 return aoc_s_add_entry(decoded, &entry);
876}
877
880{
881 struct ast_aoc_s_entry entry = { 0, };
882
885
886 return aoc_s_add_entry(decoded, &entry);
887}
888
890 unsigned int code)
891{
892 struct ast_aoc_s_entry entry = { 0, };
893
896 entry.rate.special_code = code;
897
898 return aoc_s_add_entry(decoded, &entry);
899}
900
902{
903 return decoded->msg_type;
904}
905
907{
908 return decoded->charge_type;
909}
910
912{
913 return decoded->request_flag;
914}
915
917 const enum ast_aoc_total_type type)
918{
919 decoded->total_type = type;
920 return 0;
921}
922
924{
925 return decoded->total_type;
926}
927
929 const unsigned int amount,
930 const enum ast_aoc_currency_multiplier multiplier,
931 const char *name)
932{
933
934 if (!ast_strlen_zero(name)) {
935 ast_copy_string(decoded->currency_name, name, sizeof(decoded->currency_name));
936 }
937
938 decoded->currency_amount = amount;
939
940 if (multiplier && (multiplier < AST_AOC_MULT_NUM_ENTRIES)) {
941 decoded->multiplier = multiplier;
942 } else {
943 decoded->multiplier = AST_AOC_MULT_ONE;
944 }
945
946 return 0;
947}
948
949unsigned int ast_aoc_get_currency_amount(struct ast_aoc_decoded *decoded)
950{
951 return decoded->currency_amount;
952}
953
955{
956 return decoded->multiplier;
957}
958
960{
961 switch (decoded->multiplier) {
963 return "0.001";
965 return "0.01";
967 return "0.1";
968 case AST_AOC_MULT_ONE:
969 return "1.0";
970 case AST_AOC_MULT_TEN:
971 return "10.0";
973 return "100.0";
975 return "1000.0";
976 default:
977 return "1.0";
978 }
979}
980
981const char *ast_aoc_get_currency_name(struct ast_aoc_decoded *decoded)
982{
983 return decoded->currency_name;
984}
985
987 const unsigned int amount_is_present,
988 const unsigned int amount,
989 const unsigned int type_is_present,
990 const unsigned int type)
991{
992 if ((decoded->msg_type == AST_AOC_REQUEST) ||
993 (decoded->unit_count >= ARRAY_LEN(decoded->unit_list))) {
994 return -1;
995 }
996
997 if (!amount_is_present && !type_is_present) {
998 return -1;
999 }
1000
1001 decoded->unit_list[decoded->unit_count].valid_amount = amount_is_present;
1002 if (amount_is_present) {
1003 decoded->unit_list[decoded->unit_count].amount = amount;
1004 } else {
1005 decoded->unit_list[decoded->unit_count].amount = 0;
1006 }
1007
1008 decoded->unit_list[decoded->unit_count].valid_type = type_is_present;
1009 if (type_is_present) {
1010 decoded->unit_list[decoded->unit_count].type = type;
1011 } else {
1012 decoded->unit_list[decoded->unit_count].type = 0;
1013 }
1014 decoded->unit_count++;
1015
1016 return 0;
1017}
1018
1019const struct ast_aoc_unit_entry *ast_aoc_get_unit_info(struct ast_aoc_decoded *decoded, unsigned int entry_number)
1020{
1021 if (entry_number >= decoded->unit_count) {
1022 return NULL;
1023 }
1024
1025 return (const struct ast_aoc_unit_entry *) &decoded->unit_list[entry_number];
1026}
1027
1028unsigned int ast_aoc_get_unit_count(struct ast_aoc_decoded *decoded)
1029{
1030 return decoded->unit_count;
1031}
1032
1034{
1035 if ((id >= AST_AOC_BILLING_NUM_ENTRIES) || (id < AST_AOC_BILLING_NA)) {
1036 return -1;
1037 }
1038
1039 decoded->billing_id = id;
1040
1041 return 0;
1042}
1043
1045{
1046 return decoded->billing_id;
1047}
1048
1049int ast_aoc_set_association_id(struct ast_aoc_decoded *decoded, const int id)
1050{
1051 if (decoded->msg_type != AST_AOC_E) {
1052 return -1;
1053 }
1054 memset(&decoded->charging_association, 0, sizeof(decoded->charging_association));
1056 decoded->charging_association.charge.id = id;
1057 return 0;
1058}
1059
1061{
1062 return &decoded->charging_association;
1063}
1064
1065int ast_aoc_set_association_number(struct ast_aoc_decoded *decoded, const char *num, uint8_t plan)
1066{
1067 if ((decoded->msg_type != AST_AOC_E) || ast_strlen_zero(num)) {
1068 return -1;
1069 }
1070 memset(&decoded->charging_association, 0, sizeof(decoded->charging_association));
1072 decoded->charging_association.charge.number.plan = plan;
1074
1075 return 0;
1076}
1077
1079{
1080 if (decoded->msg_type != AST_AOC_REQUEST) {
1081 return -1;
1082 }
1083 decoded->termination_request = 1;
1084
1085 return 0;
1086}
1087
1089{
1090 return decoded->termination_request;
1091}
1092
1093/*!
1094 * \internal
1095 * \brief Convert AST_AOC_VOLUME_UNIT to string.
1096 * \since 1.8
1097 *
1098 * \param value Value to convert to string.
1099 *
1100 * \return String equivalent.
1101 */
1103{
1104 const char *str;
1105
1106 switch (value) {
1107 default:
1109 str = "Octet";
1110 break;
1112 str = "Segment";
1113 break;
1115 str = "Message";
1116 break;
1117 }
1118 return str;
1119}
1120
1121/*!
1122 * \internal
1123 * \brief Convert ast_aoc_charged_item to string.
1124 * \since 1.8
1125 *
1126 * \param value Value to convert to string.
1127 *
1128 * \return String equivalent.
1129 */
1131{
1132 const char *str;
1133
1134 switch (value) {
1135 default:
1137 str = "NotAvailable";
1138 break;
1140 str = "SpecialArrangement";
1141 break;
1143 str = "BasicCommunication";
1144 break;
1146 str = "CallAttempt";
1147 break;
1149 str = "CallSetup";
1150 break;
1152 str = "UserUserInfo";
1153 break;
1155 str = "SupplementaryService";
1156 break;
1157 }
1158 return str;
1159}
1160
1161/*!
1162 * \internal
1163 * \brief Convert ast_aoc_total_type to string.
1164 * \since 1.8
1165 *
1166 * \param value Value to convert to string.
1167 *
1168 * \return String equivalent.
1169 */
1171{
1172 const char *str;
1173
1174 switch (value) {
1175 default:
1176 case AST_AOC_SUBTOTAL:
1177 str = "SubTotal";
1178 break;
1179 case AST_AOC_TOTAL:
1180 str = "Total";
1181 break;
1182 }
1183 return str;
1184}
1185
1186/*!
1187 * \internal
1188 * \brief Convert ast_aoc_rate_type to string.
1189 * \since 1.8
1190 *
1191 * \param value Value to convert to string.
1192 *
1193 * \return String equivalent.
1194 */
1196{
1197 const char *str;
1198
1199 switch (value) {
1200 default:
1202 str = "NotAvailable";
1203 break;
1205 str = "Free";
1206 break;
1208 str = "FreeFromBeginning";
1209 break;
1211 str = "Duration";
1212 break;
1214 str = "Flat";
1215 break;
1217 str = "Volume";
1218 break;
1220 str = "SpecialCode";
1221 break;
1222 }
1223 return str;
1224}
1225
1226/*!
1227 * \internal
1228 * \brief Convert AST_AOC_TIME_SCALE to string.
1229 * \since 1.8
1230 *
1231 * \param value Value to convert to string.
1232 *
1233 * \return String equivalent.
1234 */
1236{
1237 const char *str;
1238
1239 switch (value) {
1240 default:
1242 str = "OneHundredthSecond";
1243 break;
1245 str = "OneTenthSecond";
1246 break;
1248 str = "Second";
1249 break;
1251 str = "TenSeconds";
1252 break;
1254 str = "Minute";
1255 break;
1257 str = "Hour";
1258 break;
1260 str = "Day";
1261 break;
1262 }
1263 return str;
1264}
1265
1267{
1268 const char *str;
1269
1270 switch (value) {
1271 default:
1272 case AST_AOC_CHARGE_NA:
1273 str = "NotAvailable";
1274 break;
1276 str = "Free";
1277 break;
1279 str = "Currency";
1280 break;
1282 str = "Units";
1283 break;
1284 }
1285
1286 return str;
1287}
1288
1290{
1291 switch (mult) {
1293 return "1/1000";
1295 return "1/100";
1297 return "1/10";
1298 case AST_AOC_MULT_ONE:
1299 return "1";
1300 case AST_AOC_MULT_TEN:
1301 return "10";
1303 return "100";
1305 return "1000";
1307 break;
1308 }
1309 return "1";
1310}
1311
1312static const char *aoc_billingid_str(enum ast_aoc_billing_id billing_id)
1313{
1314 switch (billing_id) {
1316 return "Normal";
1318 return "Reverse";
1320 return "CreditCard";
1322 return "CallForwardingUnconditional";
1324 return "CallForwardingBusy";
1326 return "CallForwardingNoReply";
1328 return "CallDeflection";
1330 return "CallTransfer";
1331 case AST_AOC_BILLING_NA:
1332 return "NotAvailable";
1334 break;
1335 }
1336 return "NotAvailable";
1337}
1338
1340{
1341 struct ast_aoc_decoded *new_decoded = NULL;
1342 struct ast_aoc_encoded *encoded = NULL;
1343 size_t size;
1344 int res = 0;
1345
1346 if (!(encoded = ast_aoc_encode(decoded, &size, NULL))) {
1347 return -1;
1348 }
1349
1350 if (!(new_decoded = ast_aoc_decode(encoded, size, NULL))) {
1351 ast_free(encoded);
1352 return -1;
1353 }
1354
1355 if (memcmp(new_decoded, decoded, sizeof(struct ast_aoc_decoded))) {
1356 res = -1;
1357 }
1358
1359 ast_aoc_destroy_decoded(new_decoded);
1360 ast_aoc_destroy_encoded(encoded);
1361 return res;
1362}
1363
1364static char *aoc_cli_debug_enable(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1365{
1366 switch (cmd) {
1367 case CLI_INIT:
1368 e->command = "aoc set debug";
1369 e->usage =
1370 "Usage: 'aoc set debug on' to enable aoc debug, 'aoc set debug off' to disable debug.\n";
1371 return NULL;
1372 case CLI_GENERATE:
1373 return NULL;
1374 case CLI_HANDLER:
1375 if (a->argc != 4) {
1376 return CLI_SHOWUSAGE;
1377 } else if(ast_true(a->argv[3])) {
1378 ast_cli(a->fd, "aoc debug enabled\n");
1380 } else if (ast_false(a->argv[3])) {
1381 ast_cli(a->fd, "aoc debug disabled\n");
1383 } else {
1384 return CLI_SHOWUSAGE;
1385 }
1386 }
1387
1388 return CLI_SUCCESS;
1389}
1390
1391/*!
1392 * \internal
1393 * \brief Append the time structure to the event message string.
1394 * \since 1.8
1395 *
1396 * \param msg Event message string being built.
1397 * \param prefix Prefix to add to the amount lines.
1398 * \param name Name of the time structure to convert.
1399 * \param time Data to convert.
1400 * \param scale Data to convert.
1401 */
1402static void aoc_time_str(struct ast_str **msg, const char *prefix, const char *name, unsigned long time, enum ast_aoc_time_scale scale)
1403{
1404 ast_str_append(msg, 0, "%s/%s/Length: %lu\r\n", prefix, name, time);
1405 ast_str_append(msg, 0, "%s/%s/Scale: %s\r\n", prefix, name,
1406 aoc_scale_str(scale));
1407}
1408
1409/*!
1410 * \internal
1411 * \brief Append the amount structure to the event message string.
1412 * \since 1.8
1413 *
1414 * \param msg Event message string being built.
1415 * \param prefix Prefix to add to the amount lines.
1416 * \param amount Data to convert.
1417 * \param mult to convert
1418 */
1419static void aoc_amount_str(struct ast_str **msg, const char *prefix, unsigned int amount, enum ast_aoc_currency_multiplier mult)
1420{
1421 static const char name[] = "Amount";
1422
1423 ast_str_append(msg, 0, "%s/%s/Cost: %u\r\n", prefix, name, amount);
1424 ast_str_append(msg, 0, "%s/%s/Multiplier: %s\r\n", prefix, name,
1425 aoc_multiplier_str(mult));
1426}
1427
1428static void aoc_request_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1429{
1430 if (decoded->request_flag) {
1431 ast_str_append(msg, 0, "AOCRequest:");
1432 if (decoded->request_flag & AST_AOC_REQUEST_S) {
1433 ast_str_append(msg, 0, "S");
1434 }
1435 if (decoded->request_flag & AST_AOC_REQUEST_D) {
1436 ast_str_append(msg, 0, "D");
1437 }
1438 if (decoded->request_flag & AST_AOC_REQUEST_E) {
1439 ast_str_append(msg, 0, "E");
1440 }
1441 ast_str_append(msg, 0, "\r\n");
1442
1443 } else {
1444 ast_str_append(msg, 0, "AOCRequest: NONE\r\n");
1445 }
1446}
1447
1448static void aoc_s_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1449{
1450 const char *rate_str;
1451 char prefix[32];
1452 int idx;
1453
1454 ast_str_append(msg, 0, "NumberRates: %d\r\n", decoded->aoc_s_count);
1455 for (idx = 0; idx < decoded->aoc_s_count; ++idx) {
1456 snprintf(prefix, sizeof(prefix), "Rate(%d)", idx);
1457
1458 ast_str_append(msg, 0, "%s/Chargeable: %s\r\n", prefix,
1460 if (decoded->aoc_s_entries[idx].charged_item == AST_AOC_CHARGED_ITEM_NA) {
1461 continue;
1462 }
1463 rate_str = aoc_rate_type_str(decoded->aoc_s_entries[idx].rate_type);
1464 ast_str_append(msg, 0, "%s/Type: %s\r\n", prefix, rate_str);
1465 switch (decoded->aoc_s_entries[idx].rate_type) {
1467 strcat(prefix, "/");
1468 strcat(prefix, rate_str);
1469 ast_str_append(msg, 0, "%s/Currency: %s\r\n", prefix,
1472 decoded->aoc_s_entries[idx].rate.duration.amount,
1473 decoded->aoc_s_entries[idx].rate.duration.multiplier);
1474 ast_str_append(msg, 0, "%s/ChargingType: %s\r\n", prefix,
1476 "StepFunction" : "ContinuousCharging");
1477 aoc_time_str(msg, prefix, "Time",
1478 decoded->aoc_s_entries[idx].rate.duration.time,
1479 decoded->aoc_s_entries[idx].rate.duration.time_scale);
1480 if (decoded->aoc_s_entries[idx].rate.duration.granularity_time) {
1481 aoc_time_str(msg, prefix, "Granularity",
1484 }
1485 break;
1487 strcat(prefix, "/");
1488 strcat(prefix, rate_str);
1489 ast_str_append(msg, 0, "%s/Currency: %s\r\n", prefix,
1490 decoded->aoc_s_entries[idx].rate.flat.currency_name);
1492 decoded->aoc_s_entries[idx].rate.flat.amount,
1493 decoded->aoc_s_entries[idx].rate.flat.multiplier);
1494 break;
1496 strcat(prefix, "/");
1497 strcat(prefix, rate_str);
1498 ast_str_append(msg, 0, "%s/Currency: %s\r\n", prefix,
1499 decoded->aoc_s_entries[idx].rate.volume.currency_name);
1501 decoded->aoc_s_entries[idx].rate.volume.amount,
1502 decoded->aoc_s_entries[idx].rate.volume.multiplier);
1503 ast_str_append(msg, 0, "%s/Unit: %s\r\n", prefix,
1505 break;
1507 ast_str_append(msg, 0, "%s/%s: %d\r\n", prefix, rate_str,
1508 decoded->aoc_s_entries[idx].rate.special_code);
1509 break;
1510 default:
1511 break;
1512 }
1513 }
1514}
1515
1516static void aoc_d_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1517{
1518 const char *charge_str;
1519 int idx;
1520 char prefix[32];
1521
1522 charge_str = aoc_charge_type_str(decoded->charge_type);
1523 ast_str_append(msg, 0, "Type: %s\r\n", charge_str);
1524
1525 switch (decoded->charge_type) {
1528 ast_str_append(msg, 0, "BillingID: %s\r\n",
1529 aoc_billingid_str(decoded->billing_id));
1530 ast_str_append(msg, 0, "TypeOfCharging: %s\r\n",
1532 break;
1533 default:
1534 break;
1535 }
1536
1537 switch (decoded->charge_type) {
1539 ast_str_append(msg, 0, "%s: %s\r\n", charge_str,
1540 decoded->currency_name);
1541 aoc_amount_str(msg, charge_str,
1542 decoded->currency_amount,
1543 decoded->multiplier);
1544 break;
1546 ast_str_append(msg, 0, "%s/NumberItems: %d\r\n", charge_str,
1547 decoded->unit_count);
1548 for (idx = 0; idx < decoded->unit_count; ++idx) {
1549 snprintf(prefix, sizeof(prefix), "%s/Item(%d)", charge_str, idx);
1550 if (decoded->unit_list[idx].valid_amount) {
1551 ast_str_append(msg, 0, "%s/NumberOf: %u\r\n", prefix,
1552 decoded->unit_list[idx].amount);
1553 }
1554 if (decoded->unit_list[idx].valid_type) {
1555 ast_str_append(msg, 0, "%s/TypeOf: %u\r\n", prefix,
1556 decoded->unit_list[idx].type);
1557 }
1558 }
1559 break;
1560 default:
1561 break;
1562 }
1563}
1564
1565static void aoc_e_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1566{
1567 const char *charge_str;
1568 int idx;
1569 char prefix[32];
1570
1571 charge_str = "ChargingAssociation";
1572
1573 switch (decoded->charging_association.charging_type) {
1575 snprintf(prefix, sizeof(prefix), "%s/Number", charge_str);
1576 ast_str_append(msg, 0, "%s: %s\r\n", prefix,
1578 ast_str_append(msg, 0, "%s/Plan: %d\r\n", prefix,
1580 break;
1582 ast_str_append(msg, 0, "%s/ID: %d\r\n", charge_str, decoded->charging_association.charge.id);
1583 break;
1585 default:
1586 break;
1587 }
1588
1589 charge_str = aoc_charge_type_str(decoded->charge_type);
1590 ast_str_append(msg, 0, "Type: %s\r\n", charge_str);
1591 switch (decoded->charge_type) {
1594 ast_str_append(msg, 0, "BillingID: %s\r\n",
1595 aoc_billingid_str(decoded->billing_id));
1596 break;
1597 default:
1598 break;
1599 }
1600 switch (decoded->charge_type) {
1602 ast_str_append(msg, 0, "%s: %s\r\n", charge_str,
1603 decoded->currency_name);
1604 aoc_amount_str(msg, charge_str,
1605 decoded->currency_amount,
1606 decoded->multiplier);
1607 break;
1609 ast_str_append(msg, 0, "%s/NumberItems: %d\r\n", charge_str,
1610 decoded->unit_count);
1611 for (idx = 0; idx < decoded->unit_count; ++idx) {
1612 snprintf(prefix, sizeof(prefix), "%s/Item(%d)", charge_str, idx);
1613 if (decoded->unit_list[idx].valid_amount) {
1614 ast_str_append(msg, 0, "%s/NumberOf: %u\r\n", prefix,
1615 decoded->unit_list[idx].amount);
1616 }
1617 if (decoded->unit_list[idx].valid_type) {
1618 ast_str_append(msg, 0, "%s/TypeOf: %u\r\n", prefix,
1619 decoded->unit_list[idx].type);
1620 }
1621 }
1622 break;
1623 default:
1624 break;
1625 }
1626}
1627
1628static struct ast_json *units_to_json(const struct ast_aoc_decoded *decoded)
1629{
1630 int i;
1631 struct ast_json *units = ast_json_array_create();
1632
1633 if (!units) {
1634 return ast_json_null();
1635 }
1636
1637 for (i = 0; i < decoded->unit_count; ++i) {
1638 struct ast_json *unit = ast_json_object_create();
1639
1640 if (decoded->unit_list[i].valid_amount) {
1642 unit, "NumberOf", ast_json_stringf(
1643 "%u", decoded->unit_list[i].amount));
1644 }
1645
1646 if (decoded->unit_list[i].valid_type) {
1648 unit, "TypeOf", ast_json_stringf(
1649 "%u", decoded->unit_list[i].type));
1650 }
1651
1652 if (ast_json_array_append(units, unit)) {
1653 break;
1654 }
1655 }
1656
1657 return units;
1658}
1659
1660static struct ast_json *currency_to_json(const char *name, int cost,
1662{
1663 return ast_json_pack("{s:s, s:i, s:s}",
1665 "Cost", cost,
1666 "Multiplier", aoc_multiplier_str(mult));
1667}
1668
1669static struct ast_json *charge_to_json(const struct ast_aoc_decoded *decoded)
1670{
1671 struct ast_json *obj;
1672 const char *obj_type;
1673
1674 if (decoded->charge_type != AST_AOC_CHARGE_CURRENCY &&
1675 decoded->charge_type != AST_AOC_CHARGE_UNIT) {
1676 return ast_json_pack("{s:s}",
1677 "Type", aoc_charge_type_str(decoded->charge_type));
1678 }
1679
1680 if (decoded->charge_type == AST_AOC_CHARGE_CURRENCY) {
1681 obj_type = "Currency";
1682 obj = currency_to_json(decoded->currency_name, decoded->currency_amount,
1683 decoded->multiplier);
1684 } else { /* decoded->charge_type == AST_AOC_CHARGE_UNIT */
1685 obj_type = "Units";
1686 obj = units_to_json(decoded);
1687 }
1688
1689 return ast_json_pack("{s:s, s:s, s:s, s:o}",
1690 "Type", aoc_charge_type_str(decoded->charge_type),
1691 "BillingID", aoc_billingid_str(decoded->billing_id),
1692 "TotalType", aoc_type_of_totaling_str(decoded->total_type),
1693 obj_type, obj);
1694}
1695
1696static struct ast_json *association_to_json(const struct ast_aoc_decoded *decoded)
1697{
1698 switch (decoded->charging_association.charging_type) {
1700 return ast_json_pack("{s:s, s:i}",
1702 "Plan", decoded->charging_association.charge.number.plan);
1704 return ast_json_pack("{s:i}", "ID", decoded->charging_association.charge.id);
1706 default:
1707 return ast_json_null();
1708 }
1709}
1710
1711static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
1712{
1713 int i;
1714 struct ast_json *rates = ast_json_array_create();
1715
1716 if (!rates) {
1717 return ast_json_null();
1718 }
1719
1720 for (i = 0; i < decoded->aoc_s_count; ++i) {
1721 struct ast_json *rate;
1722 struct ast_json *type = NULL;
1723 struct ast_json *currency;
1724 const char *charge_item = aoc_charged_item_str(
1725 decoded->aoc_s_entries[i].charged_item);
1726
1728 rate = ast_json_pack("{s:s}", "Chargeable", charge_item);
1729 if (ast_json_array_append(rates, rate)) {
1730 break;
1731 }
1732 continue;
1733 }
1734
1735 switch (decoded->aoc_s_entries[i].rate_type) {
1737 {
1738 struct ast_json *time;
1739 struct ast_json *granularity = NULL;
1740
1741 currency = currency_to_json(
1743 decoded->aoc_s_entries[i].rate.duration.amount,
1745
1746 time = ast_json_pack("{s:I, s:i}",
1747 "Length", (ast_json_int_t)decoded->aoc_s_entries[i].rate.duration.time,
1748 "Scale", decoded->aoc_s_entries[i].rate.duration.time_scale);
1749
1750 if (decoded->aoc_s_entries[i].rate.duration.granularity_time) {
1751 granularity = ast_json_pack("{s:I, s:i}",
1753 "Scale", decoded->aoc_s_entries[i].rate.duration.granularity_time_scale);
1754 }
1755
1756 type = ast_json_pack("{s:o, s:s, s:o, s:o}",
1757 "Currency", currency,
1758 "ChargingType", decoded->aoc_s_entries[i].rate.duration.charging_type
1759 ? "StepFunction" : "ContinuousCharging",
1760 "Time", time,
1761 "Granularity", granularity ?: ast_json_null());
1762
1763 break;
1764 }
1766 currency = currency_to_json(
1768 decoded->aoc_s_entries[i].rate.flat.amount,
1769 decoded->aoc_s_entries[i].rate.flat.multiplier);
1770
1771 type = ast_json_pack("{s:o}", "Currency", currency);
1772 break;
1774 currency = currency_to_json(
1776 decoded->aoc_s_entries[i].rate.volume.amount,
1777 decoded->aoc_s_entries[i].rate.volume.multiplier);
1778
1779 type = ast_json_pack("{s:s, s:o}",
1780 "Unit", aoc_volume_unit_str(
1781 decoded->aoc_s_entries[i].rate.volume.volume_unit),
1782 "Currency", currency);
1783 break;
1785 type = ast_json_pack("{s:i}",
1786 "SpecialCode", decoded->aoc_s_entries[i].rate.special_code);
1787 break;
1788 default:
1789 break;
1790 }
1791
1792 rate = ast_json_pack("{s:s, s:o}",
1793 "Chargeable", charge_item,
1795 if (ast_json_array_append(rates, rate)) {
1796 break;
1797 }
1798 }
1799 return rates;
1800}
1801
1802static struct ast_json *d_to_json(const struct ast_aoc_decoded *decoded)
1803{
1804 return ast_json_pack("{s:o}", "Charge", charge_to_json(decoded));
1805}
1806
1807static struct ast_json *e_to_json(const struct ast_aoc_decoded *decoded)
1808{
1809 return ast_json_pack("{s:o, s:o}",
1810 "ChargingAssociation", association_to_json(decoded),
1811 "Charge", charge_to_json(decoded));
1812}
1813
1815 /*! Channel AOC event is associated with (NULL for unassociated) */
1817 /*! AOC JSON blob of data */
1819};
1820
1821static void aoc_event_blob_dtor(void *obj)
1822{
1823 struct aoc_event_blob *aoc_event = obj;
1824
1825 ao2_cleanup(aoc_event->snapshot);
1826 ast_json_unref(aoc_event->blob);
1827}
1828
1829/*!
1830 * \internal
1831 * \brief Publish an AOC event.
1832 * \since 13.3.0
1833 *
1834 * \param chan Channel associated with the AOC event. (May be NULL if no channel)
1835 * \param msg_type What kind of AOC event.
1836 * \param blob AOC data blob to publish.
1837 */
1838static void aoc_publish_blob(struct ast_channel *chan, struct stasis_message_type *msg_type, struct ast_json *blob)
1839{
1840 struct stasis_message *msg;
1841 struct aoc_event_blob *aoc_event;
1842
1843 if (!blob || ast_json_is_null(blob)) {
1844 /* No AOC blob information? Nothing to send an event about. */
1845 return;
1846 }
1847
1848 aoc_event = ao2_alloc_options(sizeof(*aoc_event), aoc_event_blob_dtor,
1850 if (!aoc_event) {
1851 return;
1852 }
1853
1854 if (chan) {
1855 ast_channel_lock(chan);
1856 aoc_event->snapshot = ao2_bump(ast_channel_snapshot(chan));
1857 ast_channel_unlock(chan);
1858 if (!aoc_event->snapshot) {
1859 ao2_ref(aoc_event, -1);
1860 return;
1861 }
1862 }
1863 aoc_event->blob = ast_json_ref(blob);
1864
1865 msg = stasis_message_create(msg_type, aoc_event);
1866 ao2_ref(aoc_event, -1);
1867
1868 if (msg) {
1870 ao2_ref(msg, -1);
1871 }
1872}
1873
1875 const char *event_name)
1876{
1877 struct aoc_event_blob *aoc_event = stasis_message_data(message);
1878 struct ast_str *channel = NULL;
1879 struct ast_str *aoc;
1880 struct ast_manager_event_blob *ev = NULL;
1881
1882 if (aoc_event->snapshot) {
1884 if (!channel) {
1885 return NULL;
1886 }
1887 }
1888
1889 aoc = ast_manager_str_from_json_object(aoc_event->blob, NULL);
1890 if (aoc && !ast_strlen_zero(ast_str_buffer(aoc))) {
1891 ev = ast_manager_event_blob_create(EVENT_FLAG_AOC, event_name, "%s%s",
1892 AS_OR(channel, ""), ast_str_buffer(aoc));
1893 }
1894
1895 ast_free(aoc);
1896 ast_free(channel);
1897 return ev;
1898}
1899
1901{
1902 return aoc_to_ami(message, "AOC-S");
1903}
1904
1906{
1907 return aoc_to_ami(message, "AOC-D");
1908}
1909
1911{
1912 return aoc_to_ami(message, "AOC-E");
1913}
1914
1918
1920 aoc_s_type,
1921 .to_ami = aoc_s_to_ami);
1922
1924 aoc_d_type,
1925 .to_ami = aoc_d_to_ami);
1926
1928 aoc_e_type,
1929 .to_ami = aoc_e_to_ami);
1930
1931int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan)
1932{
1933 struct ast_json *blob;
1934 struct stasis_message_type *msg_type;
1935
1936 if (!decoded) {
1937 return -1;
1938 }
1939
1940 switch (decoded->msg_type) {
1941 case AST_AOC_S:
1942 blob = s_to_json(decoded);
1943 msg_type = aoc_s_type();
1944 break;
1945 case AST_AOC_D:
1946 blob = d_to_json(decoded);
1947 msg_type = aoc_d_type();
1948 break;
1949 case AST_AOC_E:
1950 blob = e_to_json(decoded);
1951 msg_type = aoc_e_type();
1952 break;
1953 default:
1954 /* events for AST_AOC_REQUEST are not generated here */
1955 return 0;
1956 }
1957
1958 aoc_publish_blob(chan, msg_type, blob);
1959 ast_json_unref(blob);
1960 return 0;
1961}
1962
1963int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1964{
1965 if (!decoded || !msg) {
1966 return -1;
1967 }
1968
1969 switch (decoded->msg_type) {
1970 case AST_AOC_S:
1971 ast_str_append(msg, 0, "AOC-S\r\n");
1972 aoc_s_event(decoded, msg);
1973 break;
1974 case AST_AOC_D:
1975 ast_str_append(msg, 0, "AOC-D\r\n");
1976 aoc_d_event(decoded, msg);
1977 break;
1978 case AST_AOC_E:
1979 ast_str_append(msg, 0, "AOC-E\r\n");
1980 aoc_e_event(decoded, msg);
1981 break;
1982 case AST_AOC_REQUEST:
1983 ast_str_append(msg, 0, "AOC-Request\r\n");
1984 aoc_request_event(decoded, msg);
1985 break;
1986 }
1987
1988 return 0;
1989}
1990
1991static void aoc_display_decoded_debug(const struct ast_aoc_decoded *decoded, int decoding, struct ast_channel *chan)
1992{
1993 struct ast_str *msg;
1994
1995 if (!decoded || !(msg = ast_str_create(1024))) {
1996 return;
1997 }
1998
1999 if (decoding) {
2000 ast_str_append(&msg, 0, "---- DECODED AOC MSG ----\r\n");
2001 } else {
2002 ast_str_append(&msg, 0, "---- ENCODED AOC MSG ----\r\n");
2003 }
2004 if (chan) {
2005 ast_str_append(&msg, 0, "CHANNEL: %s\r\n", ast_channel_name(chan));
2006 }
2007
2008 if (ast_aoc_decoded2str(decoded, &msg)) {
2009 ast_free(msg);
2010 return;
2011 }
2012
2013 ast_verb(1, "%s\r\n", ast_str_buffer(msg));
2014 ast_free(msg);
2015}
2016
2017static struct ast_cli_entry aoc_cli[] = {
2018 AST_CLI_DEFINE(aoc_cli_debug_enable, "enable cli debugging of AOC messages"),
2019};
2020
2021static void aoc_shutdown(void)
2022{
2026
2028}
2030{
2034
2037}
Prototypes for public functions only of internal interest,.
#define AST_AOC_ENCODED_CHARGE_UNIT
Definition: aoc.c:193
int ast_aoc_cli_init(void)
enable aoc cli options
Definition: aoc.c:2029
static int aoc_parse_ie(struct ast_aoc_decoded *decoded, unsigned char *data, unsigned int datalen)
Definition: aoc.c:378
#define AST_AOC_ENCODED_TYPE_D
Definition: aoc.c:182
AOC_IE
AOC Payload Information Elements.
Definition: aoc.c:244
@ AOC_IE_UNIT
Definition: aoc.c:246
@ AOC_IE_RATE
Definition: aoc.c:249
@ AOC_IE_TERMINATION_REQUEST
Definition: aoc.c:250
@ AOC_IE_CHARGING_ASSOCIATION
Definition: aoc.c:248
@ AOC_IE_BILLING
Definition: aoc.c:247
@ AOC_IE_CURRENCY
Definition: aoc.c:245
int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Convert decoded aoc msg to string representation.
Definition: aoc.c:1963
void * ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
free an ast_aoc_encoded object
Definition: aoc.c:322
unsigned int ast_aoc_get_unit_count(struct ast_aoc_decoded *decoded)
get the number of unit entries for AOC-D and AOC-E messages
Definition: aoc.c:1028
int ast_aoc_s_add_rate_duration(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name, unsigned long time, enum ast_aoc_time_scale time_scale, unsigned long granularity_time, enum ast_aoc_time_scale granularity_time_scale, int step_function)
Add AOC-S duration rate entry.
Definition: aoc.c:779
#define AST_AOC_ENCODED_CHARGE_NA
Definition: aoc.c:190
static struct ast_manager_event_blob * aoc_e_to_ami(struct stasis_message *message)
Definition: aoc.c:1910
enum ast_aoc_total_type ast_aoc_get_total_type(struct ast_aoc_decoded *decoded)
get the type of total for a AOC-D message
Definition: aoc.c:923
const char * ast_aoc_get_currency_name(struct ast_aoc_decoded *decoded)
get the currency name for AOC-D and AOC-E messages
Definition: aoc.c:981
struct stasis_message_type * aoc_s_type(void)
static const char * aoc_charged_item_str(enum ast_aoc_s_charged_item value)
Definition: aoc.c:1130
static void aoc_create_ie_data_charging_rate(const struct ast_aoc_s_entry *entry, struct aoc_ie_charging_rate *ie)
Definition: aoc.c:546
enum ast_aoc_type ast_aoc_get_msg_type(struct ast_aoc_decoded *decoded)
get the message type, AOC-D, AOC-E, or AOC Request
Definition: aoc.c:901
static struct ast_json * s_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1711
int ast_aoc_test_encode_decode_match(struct ast_aoc_decoded *decoded)
test aoc encode decode routines.
Definition: aoc.c:1339
int ast_aoc_s_add_rate_special_charge_code(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int code)
Add AOC-S special rate entry.
Definition: aoc.c:853
static void aoc_shutdown(void)
Definition: aoc.c:2021
int ast_aoc_get_termination_request(struct ast_aoc_decoded *decoded)
get whether or not the AST_AOC_REQUEST message as a termination request.
Definition: aoc.c:1088
static struct ast_json * association_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1696
static void aoc_event_blob_dtor(void *obj)
Definition: aoc.c:1821
static void aoc_e_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1565
static const char * aoc_charge_type_str(enum ast_aoc_charge_type value)
Definition: aoc.c:1266
struct ast_aoc_decoded * ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan)
decodes an encoded aoc payload.
Definition: aoc.c:458
struct ast_aoc_decoded * ast_aoc_create(const enum ast_aoc_type msg_type, const enum ast_aoc_charge_type charge_type, const enum ast_aoc_request requests)
creates a ast_aoc_decode object of a specific message type
Definition: aoc.c:285
static const char * aoc_scale_str(enum ast_aoc_time_scale value)
Definition: aoc.c:1235
static struct ast_json * charge_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1669
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
Definition: aoc.c:316
static struct ast_json * units_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1628
static struct ast_manager_event_blob * aoc_d_to_ami(struct stasis_message *message)
Definition: aoc.c:1905
static struct ast_json * d_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1802
int ast_aoc_set_association_number(struct ast_aoc_decoded *decoded, const char *num, uint8_t plan)
set the charging association number for an AOC-E message
Definition: aoc.c:1065
#define AST_AOC_ENCODE_VERSION
Definition: aoc.c:198
#define AST_AOC_ENCODED_TYPE_REQUEST
Definition: aoc.c:181
static struct ast_cli_entry aoc_cli[]
Definition: aoc.c:2017
int ast_aoc_add_unit_entry(struct ast_aoc_decoded *decoded, const unsigned int amount_is_present, const unsigned int amount, const unsigned int type_is_present, const unsigned int type)
Adds a unit entry into the list of units.
Definition: aoc.c:986
const char * ast_aoc_get_currency_multiplier_decimal(struct ast_aoc_decoded *decoded)
get the currency multiplier for AOC-D and AOC-E messages in decimal format
Definition: aoc.c:959
int ast_aoc_s_add_rate_free(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, int from_beginning)
Add AOC-S indicating charge item is free.
Definition: aoc.c:866
const struct ast_aoc_unit_entry * ast_aoc_get_unit_info(struct ast_aoc_decoded *decoded, unsigned int entry_number)
get a specific unit entry.
Definition: aoc.c:1019
STASIS_MESSAGE_TYPE_DEFN(aoc_s_type,.to_ami=aoc_s_to_ami)
static struct ast_manager_event_blob * aoc_to_ami(struct stasis_message *message, const char *event_name)
Definition: aoc.c:1874
enum ast_aoc_request ast_aoc_get_request(struct ast_aoc_decoded *decoded)
get the types of AOC requested for when message type is AOC Request
Definition: aoc.c:911
int ast_aoc_set_billing_id(struct ast_aoc_decoded *decoded, const enum ast_aoc_billing_id id)
set the billing id for a AOC-D or AST_AOC_E message
Definition: aoc.c:1033
int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded, unsigned int code)
Add AOC-S special arrangement entry.
Definition: aoc.c:889
int ast_aoc_set_currency_info(struct ast_aoc_decoded *decoded, const unsigned int amount, const enum ast_aoc_currency_multiplier multiplier, const char *name)
Sets the currency values for a AOC-D or AOC-E message.
Definition: aoc.c:928
#define AST_AOC_ENCODED_CHARGE_CURRENCY
Definition: aoc.c:192
static void aoc_request_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1428
int ast_aoc_set_association_id(struct ast_aoc_decoded *decoded, const int id)
set the charging association id for an AST_AOC_E message
Definition: aoc.c:1049
int ast_aoc_s_add_rate_flat(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name)
Add AOC-S flat rate entry.
Definition: aoc.c:810
struct ast_aoc_encoded * ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
encodes a decoded aoc structure so it can be passed on the wire
Definition: aoc.c:659
static void aoc_s_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1448
static int aoc_s_add_entry(struct ast_aoc_decoded *decoded, struct ast_aoc_s_entry *entry)
Definition: aoc.c:752
#define AST_AOC_ENCODED_REQUEST_E
Definition: aoc.c:188
static const char * aoc_multiplier_str(enum ast_aoc_currency_multiplier mult)
Definition: aoc.c:1289
static struct ast_json * currency_to_json(const char *name, int cost, enum ast_aoc_currency_multiplier mult)
Definition: aoc.c:1660
static void aoc_publish_blob(struct ast_channel *chan, struct stasis_message_type *msg_type, struct ast_json *blob)
Definition: aoc.c:1838
int ast_aoc_set_total_type(struct ast_aoc_decoded *decoded, const enum ast_aoc_total_type type)
Sets the type of total for a AOC-D message.
Definition: aoc.c:916
int ast_aoc_s_add_rate_volume(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, enum ast_aoc_volume_unit volume_unit, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name)
Add AOC-S volume rate entry.
Definition: aoc.c:831
#define AST_AOC_ENCODED_REQUEST_D
Definition: aoc.c:187
static char * aoc_cli_debug_enable(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: aoc.c:1364
static void aoc_d_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1516
enum ast_aoc_billing_id ast_aoc_get_billing_id(struct ast_aoc_decoded *decoded)
get the billing id for AOC-D and AOC-E messages
Definition: aoc.c:1044
struct stasis_message_type * aoc_d_type(void)
const struct ast_aoc_charging_association * ast_aoc_get_association_info(struct ast_aoc_decoded *decoded)
get the charging association info for AOC-E messages
Definition: aoc.c:1060
unsigned int ast_aoc_s_get_count(struct ast_aoc_decoded *decoded)
get the number rates associated with an AOC-S message
Definition: aoc.c:765
static const char * aoc_type_of_totaling_str(enum ast_aoc_total_type value)
Definition: aoc.c:1170
enum ast_aoc_currency_multiplier ast_aoc_get_currency_multiplier(struct ast_aoc_decoded *decoded)
get the currency multiplier for AOC-D and AOC-E messages
Definition: aoc.c:954
static const char * aoc_volume_unit_str(enum ast_aoc_volume_unit value)
Definition: aoc.c:1102
static char aoc_debug_enabled
Definition: aoc.c:201
static void aoc_time_str(struct ast_str **msg, const char *prefix, const char *name, unsigned long time, enum ast_aoc_time_scale scale)
Definition: aoc.c:1402
const struct ast_aoc_s_entry * ast_aoc_s_get_rate_info(struct ast_aoc_decoded *decoded, unsigned int entry_number)
get a specific AOC-S rate entry.
Definition: aoc.c:770
static void aoc_display_decoded_debug(const struct ast_aoc_decoded *decoded, int decoding, struct ast_channel *chan)
Definition: aoc.c:1991
static const char * aoc_billingid_str(enum ast_aoc_billing_id billing_id)
Definition: aoc.c:1312
static const char * aoc_rate_type_str(enum ast_aoc_s_rate_type value)
Definition: aoc.c:1195
int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan)
generate AOC manager event for an AOC-S, AOC-D, or AOC-E msg
Definition: aoc.c:1931
struct stasis_message_type * aoc_e_type(void)
#define AST_AOC_ENCODED_TYPE_S
Definition: aoc.c:184
static void aoc_create_ie_data(struct ast_aoc_decoded *decoded, struct aoc_ie_data *ied)
Definition: aoc.c:592
int ast_aoc_set_termination_request(struct ast_aoc_decoded *decoded)
Mark the AST_AOC_REQUEST message as a termination request.
Definition: aoc.c:1078
enum ast_aoc_charge_type ast_aoc_get_charge_type(struct ast_aoc_decoded *decoded)
get the charging type for an AOC-D or AOC-E message
Definition: aoc.c:906
int ast_aoc_s_add_rate_na(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item)
Add AOC-S entry indicating charge item is not available.
Definition: aoc.c:878
unsigned int ast_aoc_get_currency_amount(struct ast_aoc_decoded *decoded)
get the currency amount for AOC-D and AOC-E messages
Definition: aoc.c:949
static void aoc_amount_str(struct ast_str **msg, const char *prefix, unsigned int amount, enum ast_aoc_currency_multiplier mult)
Definition: aoc.c:1419
#define AST_AOC_ENCODED_CHARGE_SUBTOTAL
Definition: aoc.c:195
#define AST_AOC_ENCODED_CHARGE_FREE
Definition: aoc.c:191
#define AST_AOC_ENCODED_REQUEST_S
Definition: aoc.c:186
#define AST_AOC_ENCODED_TYPE_E
Definition: aoc.c:183
static struct ast_json * e_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1807
static struct ast_manager_event_blob * aoc_s_to_ami(struct stasis_message *message)
Definition: aoc.c:1900
static void aoc_parse_ie_charging_rate(struct ast_aoc_decoded *decoded, const struct aoc_ie_charging_rate *ie)
Definition: aoc.c:328
static int aoc_append_ie(struct aoc_ie_data *ied, unsigned short ie_id, const void *data, unsigned short datalen)
Definition: aoc.c:531
Generic Advice of Charge encode and decode routines.
ast_aoc_s_charged_item
Definition: aoc.h:145
@ AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION
Definition: aoc.h:148
@ AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT
Definition: aoc.h:147
@ AST_AOC_CHARGED_ITEM_NA
Definition: aoc.h:146
@ AST_AOC_CHARGED_ITEM_USER_USER_INFO
Definition: aoc.h:151
@ AST_AOC_CHARGED_ITEM_CALL_SETUP
Definition: aoc.h:150
@ AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE
Definition: aoc.h:152
@ AST_AOC_CHARGED_ITEM_CALL_ATTEMPT
Definition: aoc.h:149
ast_aoc_charge_type
Definition: aoc.h:69
@ AST_AOC_CHARGE_CURRENCY
Definition: aoc.h:72
@ AST_AOC_CHARGE_FREE
Definition: aoc.h:71
@ AST_AOC_CHARGE_UNIT
Definition: aoc.h:73
@ AST_AOC_CHARGE_NA
Definition: aoc.h:70
ast_aoc_time_scale
Definition: aoc.h:87
@ AST_AOC_TIME_SCALE_TEN_SECOND
Definition: aoc.h:91
@ AST_AOC_TIME_SCALE_DAY
Definition: aoc.h:94
@ AST_AOC_TIME_SCALE_TENTH_SECOND
Definition: aoc.h:89
@ AST_AOC_TIME_SCALE_MINUTE
Definition: aoc.h:92
@ AST_AOC_TIME_SCALE_SECOND
Definition: aoc.h:90
@ AST_AOC_TIME_SCALE_HOUR
Definition: aoc.h:93
@ AST_AOC_TIME_SCALE_HUNDREDTH_SECOND
Definition: aoc.h:88
ast_aoc_volume_unit
Definition: aoc.h:125
@ AST_AOC_VOLUME_UNIT_OCTET
Definition: aoc.h:126
@ AST_AOC_VOLUME_UNIT_SEGMENT
Definition: aoc.h:127
@ AST_AOC_VOLUME_UNIT_MESSAGE
Definition: aoc.h:128
#define AOC_CURRENCY_NAME_SIZE
Definition: aoc.h:31
ast_aoc_currency_multiplier
Defines the currency multiplier for an aoc message.
Definition: aoc.h:34
@ AST_AOC_MULT_TEN
Definition: aoc.h:39
@ AST_AOC_MULT_ONEHUNDREDTH
Definition: aoc.h:36
@ AST_AOC_MULT_HUNDRED
Definition: aoc.h:40
@ AST_AOC_MULT_NUM_ENTRIES
Definition: aoc.h:42
@ AST_AOC_MULT_ONETENTH
Definition: aoc.h:37
@ AST_AOC_MULT_ONETHOUSANDTH
Definition: aoc.h:35
@ AST_AOC_MULT_THOUSAND
Definition: aoc.h:41
@ AST_AOC_MULT_ONE
Definition: aoc.h:38
@ AST_AOC_CHARGING_ASSOCIATION_NA
Definition: aoc.h:186
@ AST_AOC_CHARGING_ASSOCIATION_ID
Definition: aoc.h:188
@ AST_AOC_CHARGING_ASSOCIATION_NUMBER
Definition: aoc.h:187
ast_aoc_billing_id
Defines the billing id options for an aoc message.
Definition: aoc.h:49
@ AST_AOC_BILLING_NUM_ENTRIES
Definition: aoc.h:59
@ AST_AOC_BILLING_CALL_FWD_BUSY
Definition: aoc.h:55
@ AST_AOC_BILLING_CALL_FWD_NO_REPLY
Definition: aoc.h:56
@ AST_AOC_BILLING_NORMAL
Definition: aoc.h:51
@ AST_AOC_BILLING_CALL_DEFLECTION
Definition: aoc.h:57
@ AST_AOC_BILLING_CREDIT_CARD
Definition: aoc.h:53
@ AST_AOC_BILLING_CALL_TRANSFER
Definition: aoc.h:58
@ AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL
Definition: aoc.h:54
@ AST_AOC_BILLING_REVERSE_CHARGE
Definition: aoc.h:52
@ AST_AOC_BILLING_NA
Definition: aoc.h:50
ast_aoc_type
Definition: aoc.h:62
@ AST_AOC_S
Definition: aoc.h:64
@ AST_AOC_D
Definition: aoc.h:65
@ AST_AOC_E
Definition: aoc.h:66
@ AST_AOC_REQUEST
Definition: aoc.h:63
ast_aoc_request
Definition: aoc.h:76
@ AST_AOC_REQUEST_E
Definition: aoc.h:79
@ AST_AOC_REQUEST_D
Definition: aoc.h:78
@ AST_AOC_REQUEST_S
Definition: aoc.h:77
ast_aoc_total_type
Definition: aoc.h:82
@ AST_AOC_TOTAL
Definition: aoc.h:83
@ AST_AOC_SUBTOTAL
Definition: aoc.h:84
ast_aoc_s_rate_type
Definition: aoc.h:155
@ AST_AOC_RATE_TYPE_VOLUME
Definition: aoc.h:161
@ AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING
Definition: aoc.h:158
@ AST_AOC_RATE_TYPE_SPECIAL_CODE
Definition: aoc.h:162
@ AST_AOC_RATE_TYPE_NA
Definition: aoc.h:156
@ AST_AOC_RATE_TYPE_DURATION
Definition: aoc.h:159
@ AST_AOC_RATE_TYPE_FLAT
Definition: aoc.h:160
@ AST_AOC_RATE_TYPE_FREE
Definition: aoc.h:157
const char * str
Definition: app_jack.c:150
enum queue_result id
Definition: app_queue.c:1808
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static const char type[]
Definition: chan_ooh323.c:109
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2970
struct ast_channel_snapshot * ast_channel_snapshot(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2971
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_HANDLER
Definition: cli.h:154
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition: manager.c:454
struct ast_str * ast_manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
Convert a JSON object into an AMI compatible string.
Definition: manager.c:555
static char prefix[MAX_PREFIX]
Definition: http.c:144
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
struct ast_json * ast_json_object_create(void)
Create a new JSON object.
Definition: json.c:399
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_stringf(const char *format,...)
Create a JSON string, printf style.
Definition: json.c:293
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition: json.h:224
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
int ast_json_is_null(const struct ast_json *value)
Check if value is JSON null.
Definition: json.c:273
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10237
#define EVENT_FLAG_AOC
Definition: manager.h:91
static struct requests requests
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
#define NULL
Definition: resample.c:96
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1538
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
#define AS_OR(a, b)
Definition: strings.h:49
struct ast_channel_snapshot * snapshot
Definition: aoc.c:1816
struct ast_json * blob
Definition: aoc.c:1818
uint8_t id
Definition: aoc.c:274
struct ast_aoc_charging_association ca
Definition: aoc.c:278
struct ast_aoc_s_entry entry
Definition: aoc.c:282
uint32_t amount
Definition: aoc.c:261
uint8_t multiplier
Definition: aoc.c:262
char name[AOC_CURRENCY_NAME_SIZE]
Definition: aoc.c:263
int pos
Definition: aoc.c:523
unsigned char buf[1024]
Definition: aoc.c:522
uint32_t amount
Definition: aoc.c:267
uint8_t type
Definition: aoc.c:270
uint8_t valid_amount
Definition: aoc.c:269
uint8_t valid_type
Definition: aoc.c:268
AOC IE payload header.
Definition: aoc.c:254
char data[0]
Definition: aoc.c:257
uint8_t ie_id
Definition: aoc.c:255
uint8_t datalen
Definition: aoc.c:256
union ast_aoc_charging_association::@183 charge
struct ast_aoc_charging_association_number number
Definition: aoc.h:197
enum ast_aoc_currency_multiplier multiplier
Definition: aoc.c:221
unsigned int currency_amount
Definition: aoc.c:222
struct ast_aoc_unit_entry unit_list[32]
Definition: aoc.c:227
char currency_name[AOC_CURRENCY_NAME_SIZE]
Definition: aoc.c:223
enum ast_aoc_billing_id billing_id
Definition: aoc.c:230
int unit_count
Definition: aoc.c:226
struct ast_aoc_s_entry aoc_s_entries[10]
Definition: aoc.c:237
struct ast_aoc_charging_association charging_association
Definition: aoc.c:233
enum ast_aoc_request request_flag
Definition: aoc.c:217
char termination_request
Definition: aoc.c:240
enum ast_aoc_total_type total_type
Definition: aoc.c:218
int aoc_s_count
Definition: aoc.c:236
enum ast_aoc_charge_type charge_type
Definition: aoc.c:216
enum ast_aoc_type msg_type
Definition: aoc.c:215
uint32_t amount
Definition: aoc.h:104
char currency_name[AOC_CURRENCY_NAME_SIZE]
Definition: aoc.h:114
uint16_t multiplier
Definition: aoc.h:109
uint16_t granularity_time_scale
Definition: aoc.h:111
uint8_t charging_type
Charging interval type.
Definition: aoc.h:122
uint16_t time_scale
Definition: aoc.h:110
uint32_t granularity_time
Definition: aoc.h:107
uint32_t time
Definition: aoc.h:105
uint16_t datalen
Definition: aoc.c:209
uint8_t flags
Definition: aoc.c:208
uint8_t version
Definition: aoc.c:207
unsigned char data[0]
Definition: aoc.c:210
uint32_t amount
Definition: aoc.h:139
char currency_name[AOC_CURRENCY_NAME_SIZE]
Definition: aoc.h:142
uint16_t multiplier
Definition: aoc.h:140
Definition: aoc.h:165
struct ast_aoc_flat_rate flat
Definition: aoc.h:172
uint16_t special_code
Definition: aoc.h:174
uint16_t charged_item
Definition: aoc.h:166
union ast_aoc_s_entry::@182 rate
Charge rate being applied.
struct ast_aoc_volume_rate volume
Definition: aoc.h:173
struct ast_aoc_duration_rate duration
Definition: aoc.h:171
uint16_t rate_type
Definition: aoc.h:167
Definition: aoc.h:178
unsigned int amount
Definition: aoc.h:180
unsigned int type
Definition: aoc.h:182
char valid_type
Definition: aoc.h:181
char valid_amount
Definition: aoc.h:179
uint32_t amount
Definition: aoc.h:132
char currency_name[AOC_CURRENCY_NAME_SIZE]
Definition: aoc.h:135
uint16_t multiplier
Definition: aoc.h:133
uint16_t volume_unit
Definition: aoc.h:134
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Abstract JSON element (object, array, string, int, ...).
Struct containing info for an AMI event to send out.
Definition: manager.h:503
Support for dynamic strings.
Definition: strings.h:623
int value
Definition: syslog.c:37
static struct test_val a
Utility functions.
#define ARRAY_LEN(a)
Definition: utils.h:666