Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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 <synopsis>Raised when an Advice of Charge message is sent at the beginning of a call.</synopsis>
45 <syntax>
46 <channel_snapshot/>
47 <parameter name="Chargeable" />
48 <parameter name="RateType">
49 <enumlist>
50 <enum name="NotAvailable" />
51 <enum name="Free" />
52 <enum name="FreeFromBeginning" />
53 <enum name="Duration" />
54 <enum name="Flag" />
55 <enum name="Volume" />
56 <enum name="SpecialCode" />
57 </enumlist>
58 </parameter>
59 <parameter name="Currency" />
60 <parameter name="Name" />
61 <parameter name="Cost" />
62 <parameter name="Multiplier">
63 <enumlist>
64 <enum name="1/1000" />
65 <enum name="1/100" />
66 <enum name="1/10" />
67 <enum name="1" />
68 <enum name="10" />
69 <enum name="100" />
70 <enum name="1000" />
71 </enumlist>
72 </parameter>
73 <parameter name="ChargingType" />
74 <parameter name="StepFunction" />
75 <parameter name="Granularity" />
76 <parameter name="Length" />
77 <parameter name="Scale" />
78 <parameter name="Unit">
79 <enumlist>
80 <enum name="Octect" />
81 <enum name="Segment" />
82 <enum name="Message" />
83 </enumlist>
84 </parameter>
85 <parameter name="SpecialCode" />
86 </syntax>
87 <see-also>
88 <ref type="managerEvent">AOC-D</ref>
89 <ref type="managerEvent">AOC-E</ref>
90 </see-also>
91 </managerEventInstance>
92 </managerEvent>
93 <managerEvent language="en_US" name="AOC-D">
94 <managerEventInstance class="EVENT_FLAG_AOC">
95 <synopsis>Raised when an Advice of Charge message is sent during a call.</synopsis>
96 <syntax>
97 <channel_snapshot/>
98 <parameter name="Charge" />
99 <parameter name="Type">
100 <enumlist>
101 <enum name="NotAvailable" />
102 <enum name="Free" />
103 <enum name="Currency" />
104 <enum name="Units" />
105 </enumlist>
106 </parameter>
107 <parameter name="BillingID">
108 <enumlist>
109 <enum name="Normal" />
110 <enum name="Reverse" />
111 <enum name="CreditCard" />
112 <enum name="CallForwardingUnconditional" />
113 <enum name="CallForwardingBusy" />
114 <enum name="CallForwardingNoReply" />
115 <enum name="CallDeflection" />
116 <enum name="CallTransfer" />
117 <enum name="NotAvailable" />
118 </enumlist>
119 </parameter>
120 <parameter name="TotalType">
121 <enumlist>
122 <enum name="SubTotal" />
123 <enum name="Total" />
124 </enumlist>
125 </parameter>
126 <parameter name="Currency" />
127 <parameter name="Name" />
128 <parameter name="Cost" />
129 <parameter name="Multiplier">
130 <enumlist>
131 <enum name="1/1000" />
132 <enum name="1/100" />
133 <enum name="1/10" />
134 <enum name="1" />
135 <enum name="10" />
136 <enum name="100" />
137 <enum name="1000" />
138 </enumlist>
139 </parameter>
140 <parameter name="Units" />
141 <parameter name="NumberOf" />
142 <parameter name="TypeOf" />
143 </syntax>
144 <see-also>
145 <ref type="manager">AOCMessage</ref>
146 <ref type="managerEvent">AOC-S</ref>
147 <ref type="managerEvent">AOC-E</ref>
148 </see-also>
149 </managerEventInstance>
150 </managerEvent>
151 <managerEvent language="en_US" name="AOC-E">
152 <managerEventInstance class="EVENT_FLAG_AOC">
153 <synopsis>Raised when an Advice of Charge message is sent at the end of a call.</synopsis>
154 <syntax>
155 <channel_snapshot/>
156 <parameter name="ChargingAssociation" />
157 <parameter name="Number" />
158 <parameter name="Plan" />
159 <parameter name="ID" />
160 <xi:include xpointer="xpointer(/docs/managerEvent[@name='AOC-D']/managerEventInstance/syntax/parameter)" />
161 </syntax>
162 <see-also>
163 <ref type="manager">AOCMessage</ref>
164 <ref type="managerEvent">AOC-S</ref>
165 <ref type="managerEvent">AOC-D</ref>
166 </see-also>
167 </managerEventInstance>
168 </managerEvent>
169***/
170
171/* Encoded Payload Flags */
172#define AST_AOC_ENCODED_TYPE_REQUEST (0 << 0)
173#define AST_AOC_ENCODED_TYPE_D (1 << 0)
174#define AST_AOC_ENCODED_TYPE_E (2 << 0)
175#define AST_AOC_ENCODED_TYPE_S (3 << 0)
176
177#define AST_AOC_ENCODED_REQUEST_S (1 << 2)
178#define AST_AOC_ENCODED_REQUEST_D (1 << 3)
179#define AST_AOC_ENCODED_REQUEST_E (1 << 4)
180
181#define AST_AOC_ENCODED_CHARGE_NA (0 << 5)
182#define AST_AOC_ENCODED_CHARGE_FREE (1 << 5)
183#define AST_AOC_ENCODED_CHARGE_CURRENCY (2 << 5)
184#define AST_AOC_ENCODED_CHARGE_UNIT (3 << 5)
185
186#define AST_AOC_ENCODED_CHARGE_SUBTOTAL (1 << 7)
187#define AST_AOC_ENCODED_CHARGE_TOTAL (0 << 7)
188
189#define AST_AOC_ENCODE_VERSION 1
190
191
192static char aoc_debug_enabled = 0;
193static void aoc_display_decoded_debug(const struct ast_aoc_decoded *decoded, int decoding, struct ast_channel *chan);
194static int aoc_s_add_entry(struct ast_aoc_decoded *decoded, struct ast_aoc_s_entry *entry);
195
196/* AOC Payload Header. Holds all the encoded AOC data to pass on the wire */
198 uint8_t version;
199 uint8_t flags;
200 uint16_t datalen;
201 unsigned char data[0];
202};
203
204/* Decoded AOC data */
210
211 /* currency information */
213 unsigned int currency_amount;
215
216 /* unit information */
219
220 /* Billing Id */
222
223 /* Charging Association information */
225
226 /* AOC-S charge information */
229
230 /* Is this an AOC Termination Request */
232};
233
234/*! \brief AOC Payload Information Elements */
235enum AOC_IE {
242};
243
244/*! \brief AOC IE payload header */
246 uint8_t ie_id;
247 uint8_t datalen;
248 char data[0];
249} __attribute__((packed));
250
252 uint32_t amount;
253 uint8_t multiplier;
255} __attribute__((packed));
256
258 uint32_t amount;
259 uint8_t valid_type;
261 uint8_t type;
262} __attribute__((packed));
263
265 uint8_t id;
266} __attribute__((packed));
267
270} __attribute__((packed));
271
274} __attribute__((packed));
275
278 const enum ast_aoc_request requests)
279{
280 struct ast_aoc_decoded *decoded = NULL;
281
282 /* verify input */
283 if (((unsigned int) charge_type > AST_AOC_CHARGE_UNIT) ||
284 ((unsigned int) msg_type > AST_AOC_E) ||
285 ((msg_type == AST_AOC_REQUEST) && !requests)) {
286
287 ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object, invalid input\n");
288 return NULL;
289 }
290
291 if (!(decoded = ast_calloc(1, sizeof(struct ast_aoc_decoded)))) {
292 ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object \n");
293 return NULL;
294 }
295
296 decoded->msg_type = msg_type;
297
298 if (msg_type == AST_AOC_REQUEST) {
299 decoded->request_flag = requests;
300 } else if ((msg_type == AST_AOC_D) || (msg_type == AST_AOC_E)) {
301 decoded->charge_type = charge_type;
302 }
303
304 return decoded;
305}
306
308{
309 ast_free(decoded);
310 return NULL;
311}
312
314{
315 ast_free(encoded);
316 return NULL;
317}
318
319static void aoc_parse_ie_charging_rate(struct ast_aoc_decoded *decoded, const struct aoc_ie_charging_rate *ie)
320{
321 struct ast_aoc_s_entry entry = { 0, };
322
323 entry.charged_item = ntohs(ie->entry.charged_item);
324 entry.rate_type = ntohs(ie->entry.rate_type);
325
326 switch (entry.rate_type) {
328 entry.rate.duration.multiplier = ntohs(ie->entry.rate.duration.multiplier);
329 entry.rate.duration.amount = ntohl(ie->entry.rate.duration.amount);
330 entry.rate.duration.time = ntohl(ie->entry.rate.duration.time);
331 entry.rate.duration.time_scale = ntohs(ie->entry.rate.duration.time_scale);
332 entry.rate.duration.granularity_time = ntohl(ie->entry.rate.duration.granularity_time);
333 entry.rate.duration.granularity_time_scale = ntohs(ie->entry.rate.duration.granularity_time_scale);
334 entry.rate.duration.charging_type = ie->entry.rate.duration.charging_type; /* only one byte */
335
337 ast_copy_string(entry.rate.duration.currency_name,
339 sizeof(entry.rate.duration.currency_name));
340 }
341 break;
343 entry.rate.flat.multiplier = ntohs(ie->entry.rate.flat.multiplier);
344 entry.rate.flat.amount = ntohl(ie->entry.rate.flat.amount);
346 ast_copy_string(entry.rate.flat.currency_name,
348 sizeof(entry.rate.flat.currency_name));
349 }
350 break;
352 entry.rate.volume.multiplier = ntohs(ie->entry.rate.volume.multiplier);
353 entry.rate.volume.amount = ntohl(ie->entry.rate.volume.amount);
354 entry.rate.volume.volume_unit = ntohs(ie->entry.rate.volume.volume_unit);
356 ast_copy_string(entry.rate.volume.currency_name,
358 sizeof(entry.rate.volume.currency_name));
359 }
360 break;
362 entry.rate.special_code = ntohs(ie->entry.rate.special_code);
363 break;
364 }
365
366 aoc_s_add_entry(decoded, &entry);
367}
368
369static int aoc_parse_ie(struct ast_aoc_decoded *decoded, unsigned char *data, unsigned int datalen)
370{
371 enum AOC_IE ie_id;
372 unsigned int len;
373
374 while (datalen >= 2) {
375 ie_id = data[0];
376 len = data[1];
377 if (len > datalen -2) {
378 ast_log(LOG_ERROR, "AOC information element length exceeds the total message size\n");
379 return -1;
380 }
381
382 switch(ie_id) {
383 case AOC_IE_CURRENCY:
384 if (len == sizeof(struct aoc_ie_currency)) {
385 struct aoc_ie_currency ie;
386 memcpy(&ie, data + 2, len);
387 decoded->currency_amount = ntohl(ie.amount);
388 decoded->multiplier = ie.multiplier; /* only one byte */
389 memcpy(decoded->currency_name, ie.name, sizeof(decoded->currency_name));
390 } else {
391 ast_log(LOG_WARNING, "Received invalid currency ie\n");
392 }
393 break;
394 case AOC_IE_UNIT:
395 if (len == sizeof(struct aoc_ie_unit)) {
396 struct aoc_ie_unit ie;
397 memcpy(&ie, data + 2, len);
398 ast_aoc_add_unit_entry(decoded, ie.valid_amount, ntohl(ie.amount), ie.valid_type, ie.type);
399 } else {
400 ast_log(LOG_WARNING, "Received invalid unit ie\n");
401 }
402 break;
403 case AOC_IE_BILLING:
404 if (len == sizeof(struct aoc_ie_billing)) {
405 struct aoc_ie_billing ie;
406 memcpy(&ie, data + 2, len);
407 decoded->billing_id = ie.id; /* only one byte */
408 } else {
409 ast_log(LOG_WARNING, "Received invalid billing ie\n");
410 }
411 break;
413 if (len == sizeof(struct aoc_ie_charging_association)) {
414 memcpy(&decoded->charging_association, data + 2, sizeof(decoded->charging_association));
415 /* everything in the charging_association struct is a single byte except for the id */
417 decoded->charging_association.charge.id = ntohl(decoded->charging_association.charge.id);
418 }
419 } else {
420 ast_log(LOG_WARNING, "Received invalid charging association ie\n");
421 }
422 break;
423 case AOC_IE_RATE:
424 if (len == sizeof(struct aoc_ie_charging_rate)) {
425 struct aoc_ie_charging_rate ie;
426 memcpy(&ie, data + 2, len);
427 aoc_parse_ie_charging_rate(decoded, &ie);
428 } else {
429 ast_log(LOG_WARNING, "Received invalid charging rate ie\n");
430 }
431 break;
433 if (len == 0) {
434 decoded->termination_request = 1;
435 } else {
436 ast_log(LOG_WARNING, "Received invalid termination request ie\n");
437 }
438 break;
439 default:
440 ast_log(LOG_WARNING, "Unknown AOC Information Element, ignoring.\n");
441 }
442
443 datalen -= (len + 2);
444 data += (len + 2);
445 }
446 return 0;
447}
448
449struct ast_aoc_decoded *ast_aoc_decode(struct ast_aoc_encoded *encoded, size_t size, struct ast_channel *chan)
450{
451 struct ast_aoc_decoded *decoded;
452
453 /* verify our encoded payload is actually large enough to hold all the ies */
454 if ((size - (sizeof(struct ast_aoc_encoded)) != ntohs(encoded->datalen))) {
455 ast_log(LOG_WARNING, "Corrupted aoc encoded object, can not decode\n");
456 return NULL;
457 }
458
459 if (!(decoded = ast_calloc(1, sizeof(struct ast_aoc_decoded)))) {
460 ast_log(LOG_WARNING, "Failed to create ast_aoc_decoded object \n");
461 return NULL;
462 }
463
464 /* decode flags */
465
467 decoded->msg_type = AST_AOC_S;
468 } else if (encoded->flags & AST_AOC_ENCODED_TYPE_E) {
469 decoded->msg_type = AST_AOC_E;
470 } else if (encoded->flags & AST_AOC_ENCODED_TYPE_D) {
471 decoded->msg_type = AST_AOC_D;
472 } else {
473 decoded->msg_type = AST_AOC_REQUEST;
474 }
475
476 if (decoded->msg_type == AST_AOC_REQUEST) {
477 if (encoded->flags & AST_AOC_ENCODED_REQUEST_S) {
479 }
480 if (encoded->flags & AST_AOC_ENCODED_REQUEST_D) {
482 }
483 if (encoded->flags & AST_AOC_ENCODED_REQUEST_E) {
485 }
486 } else if ((decoded->msg_type == AST_AOC_D) || (decoded->msg_type == AST_AOC_E)) {
493 } else {
495 }
496
497 if (encoded->flags & AST_AOC_ENCODED_CHARGE_SUBTOTAL) {
498 decoded->total_type = AST_AOC_SUBTOTAL;
499 }
500 }
501
502 /* decode information elements */
503 aoc_parse_ie(decoded, encoded->data, ntohs(encoded->datalen));
504
505 if (aoc_debug_enabled) {
506 aoc_display_decoded_debug(decoded, 1, chan);
507 }
508
509 return decoded;
510}
511
513 unsigned char buf[1024];
514 int pos;
515};
516
517/*!
518 * \internal
519 * \brief append an AOC information element
520 * \note data is expected to already be in network byte order at this point
521 */
522static int aoc_append_ie(struct aoc_ie_data *ied, unsigned short ie_id, const void *data, unsigned short datalen)
523{
524 if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
525 ast_log(LOG_WARNING, "Failure to append AOC information element, out of space \n");
526 return -1;
527 }
528 ied->buf[ied->pos++] = ie_id;
529 ied->buf[ied->pos++] = datalen;
530 if (datalen) {
531 memcpy(ied->buf + ied->pos, data, datalen);
532 ied->pos += datalen;
533 }
534 return 0;
535}
536
538{
539 ie->entry.charged_item = htons(entry->charged_item);
540 ie->entry.rate_type = htons(entry->rate_type);
541
542 switch (entry->rate_type) {
544 ie->entry.rate.duration.multiplier = htons(entry->rate.duration.multiplier);
545 ie->entry.rate.duration.amount = htonl(entry->rate.duration.amount);
546 ie->entry.rate.duration.time = htonl(entry->rate.duration.time);
547 ie->entry.rate.duration.time_scale = htons(entry->rate.duration.time_scale);
548 ie->entry.rate.duration.granularity_time = htonl(entry->rate.duration.granularity_time);
549 ie->entry.rate.duration.granularity_time_scale = htons(entry->rate.duration.granularity_time_scale);
550 ie->entry.rate.duration.charging_type = entry->rate.duration.charging_type; /* only one byte */
551
552 if (!ast_strlen_zero(entry->rate.duration.currency_name)) {
554 entry->rate.duration.currency_name,
555 sizeof(ie->entry.rate.duration.currency_name));
556 }
557 break;
559 ie->entry.rate.flat.multiplier = htons(entry->rate.flat.multiplier);
560 ie->entry.rate.flat.amount = htonl(entry->rate.flat.amount);
561 if (!ast_strlen_zero(entry->rate.flat.currency_name)) {
563 entry->rate.flat.currency_name,
564 sizeof(ie->entry.rate.flat.currency_name));
565 }
566 break;
568 ie->entry.rate.volume.multiplier = htons(entry->rate.volume.multiplier);
569 ie->entry.rate.volume.amount = htonl(entry->rate.volume.amount);
570 ie->entry.rate.volume.volume_unit = htons(entry->rate.volume.volume_unit);
571 if (!ast_strlen_zero(entry->rate.volume.currency_name)) {
573 entry->rate.volume.currency_name,
574 sizeof(ie->entry.rate.volume.currency_name));
575 }
576 break;
578 ie->entry.rate.special_code = htons(entry->rate.special_code);
579 break;
580 }
581
582}
583static void aoc_create_ie_data(struct ast_aoc_decoded *decoded, struct aoc_ie_data *ied)
584{
585 ied->pos = 0;
586
587 if (decoded->currency_amount) {
588 struct aoc_ie_currency ie = {
589 .amount = htonl(decoded->currency_amount),
590 .multiplier = decoded->multiplier, /* only one byte */
591 .name = { 0, },
592 };
593
594 if (!ast_strlen_zero(decoded->currency_name)) {
595 ast_copy_string(ie.name, decoded->currency_name, sizeof(ie.name));
596 }
597
598 aoc_append_ie(ied, AOC_IE_CURRENCY, (const void *) &ie, sizeof(ie));
599 }
600
601 if (decoded->unit_count) {
602 struct aoc_ie_unit ie = { 0 };
603 int i;
604
605 for (i = 0; i < decoded->unit_count; i++) {
606 ie.valid_amount = decoded->unit_list[i].valid_amount; /* only one byte */
607 ie.amount = htonl(decoded->unit_list[i].amount);
608 ie.valid_type = decoded->unit_list[i].valid_type; /* only one byte */
609 ie.type = decoded->unit_list[i].type; /* only one byte */
610 aoc_append_ie(ied, AOC_IE_UNIT, (const void *) &ie, sizeof(ie));
611 }
612 }
613
614 if (decoded->billing_id) {
615 struct aoc_ie_billing ie;
616 ie.id = decoded->billing_id; /* only one byte */
617 aoc_append_ie(ied, AOC_IE_BILLING, (const void *) &ie, sizeof(ie));
618 }
619
622 memset(&ie, 0, sizeof(ie));
623 ie.ca.charging_type = decoded->charging_association.charging_type; /* only one byte */
625 ie.ca.charge.number.plan = decoded->charging_association.charge.number.plan; /* only one byte */
628 sizeof(ie.ca.charge.number.number));
630 ie.ca.charge.id = htonl(decoded->charging_association.charge.id);
631 }
632 aoc_append_ie(ied, AOC_IE_CHARGING_ASSOCIATION, (const void *) &ie, sizeof(ie));
633 }
634
635 if (decoded->aoc_s_count) {
636 struct aoc_ie_charging_rate ie;
637 int i;
638 for (i = 0; i < decoded->aoc_s_count; i++) {
639 memset(&ie, 0, sizeof(ie));
641 aoc_append_ie(ied, AOC_IE_RATE, (const void *) &ie, sizeof(ie));
642 }
643 }
644
645 if (decoded->termination_request) {
647 }
648}
649
650struct ast_aoc_encoded *ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
651{
652 struct aoc_ie_data ied;
653 struct ast_aoc_encoded *encoded = NULL;
654 size_t size = 0;
655
656 if (!decoded || !out_size) {
657 return NULL;
658 }
659
660 *out_size = 0;
661
662 /* create information element buffer before allocating the payload,
663 * by doing this the exact size of the payload + the id data can be
664 * allocated all at once. */
665 aoc_create_ie_data(decoded, &ied);
666
667 size = sizeof(struct ast_aoc_encoded) + ied.pos;
668
669 if (!(encoded = ast_calloc(1, size))) {
670 ast_log(LOG_WARNING, "Failed to create ast_aoc_encoded object during decode routine. \n");
671 return NULL;
672 }
673
674 /* -- Set ie data buffer */
675 if (ied.pos) {
676 /* this is safe because encoded was allocated to fit this perfectly */
677 memcpy(encoded->data, ied.buf, ied.pos);
678 encoded->datalen = htons(ied.pos);
679 }
680
681 /* --- Set Flags --- */
682 switch (decoded->msg_type) {
683 case AST_AOC_S:
684 encoded->flags = AST_AOC_ENCODED_TYPE_S;
685 break;
686 case AST_AOC_D:
687 encoded->flags = AST_AOC_ENCODED_TYPE_D;
688 break;
689 case AST_AOC_E:
690 encoded->flags = AST_AOC_ENCODED_TYPE_E;
691 break;
692 case AST_AOC_REQUEST:
694 default:
695 break;
696 }
697
698 /* if it is type request, set the types requested, else set charge type */
699 if (decoded->msg_type == AST_AOC_REQUEST) {
700 if (decoded->request_flag & AST_AOC_REQUEST_S) {
702 }
703 if (decoded->request_flag & AST_AOC_REQUEST_D) {
705 }
706 if (decoded->request_flag & AST_AOC_REQUEST_E) {
708 }
709 } else if ((decoded->msg_type == AST_AOC_D) || (decoded->msg_type == AST_AOC_E)) {
710 switch (decoded->charge_type) {
713 break;
716 break;
720 default:
722 break;
723 }
724
725 if (decoded->total_type == AST_AOC_SUBTOTAL) {
727 }
728 }
729
730 /* --- Set Version Number --- */
732
733 /* set the output size */
734 *out_size = size;
735
736 if (aoc_debug_enabled) {
737 aoc_display_decoded_debug(decoded, 0, chan);
738 }
739
740 return encoded;
741}
742
743static int aoc_s_add_entry(struct ast_aoc_decoded *decoded, struct ast_aoc_s_entry *entry)
744{
745 if (decoded->aoc_s_count >= ARRAY_LEN(decoded->aoc_s_entries)) {
746 return -1;
747 }
748
749 decoded->aoc_s_entries[decoded->aoc_s_count] = *entry;
750 decoded->aoc_s_count++;
751
752 return 0;
753}
754
755
756unsigned int ast_aoc_s_get_count(struct ast_aoc_decoded *decoded)
757{
758 return decoded->aoc_s_count;
759}
760
761const struct ast_aoc_s_entry *ast_aoc_s_get_rate_info(struct ast_aoc_decoded *decoded, unsigned int entry_number)
762{
763 if (entry_number >= decoded->aoc_s_count) {
764 return NULL;
765 }
766
767 return (const struct ast_aoc_s_entry *) &decoded->aoc_s_entries[entry_number];
768}
769
772 unsigned int amount,
773 enum ast_aoc_currency_multiplier multiplier,
774 const char *currency_name,
775 unsigned long time,
776 enum ast_aoc_time_scale time_scale,
777 unsigned long granularity_time,
778 enum ast_aoc_time_scale granularity_time_scale,
779 int step_function)
780{
781
782 struct ast_aoc_s_entry entry = { 0, };
783
784 entry.charged_item = charged_item;
786 entry.rate.duration.amount = amount;
787 entry.rate.duration.multiplier = multiplier;
788 entry.rate.duration.time = time;
789 entry.rate.duration.time_scale = time_scale;
790 entry.rate.duration.granularity_time = granularity_time;
791 entry.rate.duration.granularity_time_scale = granularity_time_scale;
792 entry.rate.duration.charging_type = step_function ? 1 : 0;
793
794 if (!ast_strlen_zero(currency_name)) {
795 ast_copy_string(entry.rate.duration.currency_name, currency_name, sizeof(entry.rate.duration.currency_name));
796 }
797
798 return aoc_s_add_entry(decoded, &entry);
799}
800
803 unsigned int amount,
804 enum ast_aoc_currency_multiplier multiplier,
805 const char *currency_name)
806{
807 struct ast_aoc_s_entry entry = { 0, };
808
809 entry.charged_item = charged_item;
810 entry.rate_type = AST_AOC_RATE_TYPE_FLAT;
811 entry.rate.flat.amount = amount;
812 entry.rate.flat.multiplier = multiplier;
813
814 if (!ast_strlen_zero(currency_name)) {
815 ast_copy_string(entry.rate.flat.currency_name, currency_name, sizeof(entry.rate.flat.currency_name));
816 }
817
818 return aoc_s_add_entry(decoded, &entry);
819}
820
821
824 enum ast_aoc_volume_unit volume_unit,
825 unsigned int amount,
826 enum ast_aoc_currency_multiplier multiplier,
827 const char *currency_name)
828{
829 struct ast_aoc_s_entry entry = { 0, };
830
831 entry.charged_item = charged_item;
833 entry.rate.volume.multiplier = multiplier;
834 entry.rate.volume.amount = amount;
835 entry.rate.volume.volume_unit = volume_unit;
836
837 if (!ast_strlen_zero(currency_name)) {
838 ast_copy_string(entry.rate.volume.currency_name, currency_name, sizeof(entry.rate.volume.currency_name));
839 }
840
841 return aoc_s_add_entry(decoded, &entry);
842}
843
846 unsigned int code)
847{
848 struct ast_aoc_s_entry entry = { 0, };
849
850 entry.charged_item = charged_item;
852 entry.rate.special_code = code;
853
854 return aoc_s_add_entry(decoded, &entry);
855}
856
859 int from_beginning)
860{
861 struct ast_aoc_s_entry entry = { 0, };
862
863 entry.charged_item = charged_item;
865
866 return aoc_s_add_entry(decoded, &entry);
867}
868
871{
872 struct ast_aoc_s_entry entry = { 0, };
873
874 entry.charged_item = charged_item;
875 entry.rate_type = AST_AOC_RATE_TYPE_NA;
876
877 return aoc_s_add_entry(decoded, &entry);
878}
879
881 unsigned int code)
882{
883 struct ast_aoc_s_entry entry = { 0, };
884
887 entry.rate.special_code = code;
888
889 return aoc_s_add_entry(decoded, &entry);
890}
891
893{
894 return decoded->msg_type;
895}
896
898{
899 return decoded->charge_type;
900}
901
903{
904 return decoded->request_flag;
905}
906
908 const enum ast_aoc_total_type type)
909{
910 decoded->total_type = type;
911 return 0;
912}
913
915{
916 return decoded->total_type;
917}
918
920 const unsigned int amount,
921 const enum ast_aoc_currency_multiplier multiplier,
922 const char *name)
923{
924
925 if (!ast_strlen_zero(name)) {
926 ast_copy_string(decoded->currency_name, name, sizeof(decoded->currency_name));
927 }
928
929 decoded->currency_amount = amount;
930
931 if (multiplier && (multiplier < AST_AOC_MULT_NUM_ENTRIES)) {
932 decoded->multiplier = multiplier;
933 } else {
934 decoded->multiplier = AST_AOC_MULT_ONE;
935 }
936
937 return 0;
938}
939
940unsigned int ast_aoc_get_currency_amount(struct ast_aoc_decoded *decoded)
941{
942 return decoded->currency_amount;
943}
944
946{
947 return decoded->multiplier;
948}
949
951{
952 switch (decoded->multiplier) {
954 return "0.001";
956 return "0.01";
958 return "0.1";
959 case AST_AOC_MULT_ONE:
960 return "1.0";
961 case AST_AOC_MULT_TEN:
962 return "10.0";
964 return "100.0";
966 return "1000.0";
967 default:
968 return "1.0";
969 }
970}
971
972const char *ast_aoc_get_currency_name(struct ast_aoc_decoded *decoded)
973{
974 return decoded->currency_name;
975}
976
978 const unsigned int amount_is_present,
979 const unsigned int amount,
980 const unsigned int type_is_present,
981 const unsigned int type)
982{
983 if ((decoded->msg_type == AST_AOC_REQUEST) ||
984 (decoded->unit_count >= ARRAY_LEN(decoded->unit_list))) {
985 return -1;
986 }
987
988 if (!amount_is_present && !type_is_present) {
989 return -1;
990 }
991
992 decoded->unit_list[decoded->unit_count].valid_amount = amount_is_present;
993 if (amount_is_present) {
994 decoded->unit_list[decoded->unit_count].amount = amount;
995 } else {
996 decoded->unit_list[decoded->unit_count].amount = 0;
997 }
998
999 decoded->unit_list[decoded->unit_count].valid_type = type_is_present;
1000 if (type_is_present) {
1001 decoded->unit_list[decoded->unit_count].type = type;
1002 } else {
1003 decoded->unit_list[decoded->unit_count].type = 0;
1004 }
1005 decoded->unit_count++;
1006
1007 return 0;
1008}
1009
1010const struct ast_aoc_unit_entry *ast_aoc_get_unit_info(struct ast_aoc_decoded *decoded, unsigned int entry_number)
1011{
1012 if (entry_number >= decoded->unit_count) {
1013 return NULL;
1014 }
1015
1016 return (const struct ast_aoc_unit_entry *) &decoded->unit_list[entry_number];
1017}
1018
1019unsigned int ast_aoc_get_unit_count(struct ast_aoc_decoded *decoded)
1020{
1021 return decoded->unit_count;
1022}
1023
1025{
1026 if ((id >= AST_AOC_BILLING_NUM_ENTRIES) || (id < AST_AOC_BILLING_NA)) {
1027 return -1;
1028 }
1029
1030 decoded->billing_id = id;
1031
1032 return 0;
1033}
1034
1036{
1037 return decoded->billing_id;
1038}
1039
1040int ast_aoc_set_association_id(struct ast_aoc_decoded *decoded, const int id)
1041{
1042 if (decoded->msg_type != AST_AOC_E) {
1043 return -1;
1044 }
1045 memset(&decoded->charging_association, 0, sizeof(decoded->charging_association));
1047 decoded->charging_association.charge.id = id;
1048 return 0;
1049}
1050
1052{
1053 return &decoded->charging_association;
1054}
1055
1056int ast_aoc_set_association_number(struct ast_aoc_decoded *decoded, const char *num, uint8_t plan)
1057{
1058 if ((decoded->msg_type != AST_AOC_E) || ast_strlen_zero(num)) {
1059 return -1;
1060 }
1061 memset(&decoded->charging_association, 0, sizeof(decoded->charging_association));
1063 decoded->charging_association.charge.number.plan = plan;
1065
1066 return 0;
1067}
1068
1070{
1071 if (decoded->msg_type != AST_AOC_REQUEST) {
1072 return -1;
1073 }
1074 decoded->termination_request = 1;
1075
1076 return 0;
1077}
1078
1080{
1081 return decoded->termination_request;
1082}
1083
1084/*!
1085 * \internal
1086 * \brief Convert AST_AOC_VOLUME_UNIT to string.
1087 * \since 1.8
1088 *
1089 * \param value Value to convert to string.
1090 *
1091 * \return String equivalent.
1092 */
1094{
1095 const char *str;
1096
1097 switch (value) {
1098 default:
1100 str = "Octet";
1101 break;
1103 str = "Segment";
1104 break;
1106 str = "Message";
1107 break;
1108 }
1109 return str;
1110}
1111
1112/*!
1113 * \internal
1114 * \brief Convert ast_aoc_charged_item to string.
1115 * \since 1.8
1116 *
1117 * \param value Value to convert to string.
1118 *
1119 * \return String equivalent.
1120 */
1122{
1123 const char *str;
1124
1125 switch (value) {
1126 default:
1128 str = "NotAvailable";
1129 break;
1131 str = "SpecialArrangement";
1132 break;
1134 str = "BasicCommunication";
1135 break;
1137 str = "CallAttempt";
1138 break;
1140 str = "CallSetup";
1141 break;
1143 str = "UserUserInfo";
1144 break;
1146 str = "SupplementaryService";
1147 break;
1148 }
1149 return str;
1150}
1151
1152/*!
1153 * \internal
1154 * \brief Convert ast_aoc_total_type to string.
1155 * \since 1.8
1156 *
1157 * \param value Value to convert to string.
1158 *
1159 * \return String equivalent.
1160 */
1162{
1163 const char *str;
1164
1165 switch (value) {
1166 default:
1167 case AST_AOC_SUBTOTAL:
1168 str = "SubTotal";
1169 break;
1170 case AST_AOC_TOTAL:
1171 str = "Total";
1172 break;
1173 }
1174 return str;
1175}
1176
1177/*!
1178 * \internal
1179 * \brief Convert ast_aoc_rate_type to string.
1180 * \since 1.8
1181 *
1182 * \param value Value to convert to string.
1183 *
1184 * \return String equivalent.
1185 */
1187{
1188 const char *str;
1189
1190 switch (value) {
1191 default:
1193 str = "NotAvailable";
1194 break;
1196 str = "Free";
1197 break;
1199 str = "FreeFromBeginning";
1200 break;
1202 str = "Duration";
1203 break;
1205 str = "Flat";
1206 break;
1208 str = "Volume";
1209 break;
1211 str = "SpecialCode";
1212 break;
1213 }
1214 return str;
1215}
1216
1217/*!
1218 * \internal
1219 * \brief Convert AST_AOC_TIME_SCALE to string.
1220 * \since 1.8
1221 *
1222 * \param value Value to convert to string.
1223 *
1224 * \return String equivalent.
1225 */
1227{
1228 const char *str;
1229
1230 switch (value) {
1231 default:
1233 str = "OneHundredthSecond";
1234 break;
1236 str = "OneTenthSecond";
1237 break;
1239 str = "Second";
1240 break;
1242 str = "TenSeconds";
1243 break;
1245 str = "Minute";
1246 break;
1248 str = "Hour";
1249 break;
1251 str = "Day";
1252 break;
1253 }
1254 return str;
1255}
1256
1258{
1259 const char *str;
1260
1261 switch (value) {
1262 default:
1263 case AST_AOC_CHARGE_NA:
1264 str = "NotAvailable";
1265 break;
1267 str = "Free";
1268 break;
1270 str = "Currency";
1271 break;
1273 str = "Units";
1274 break;
1275 }
1276
1277 return str;
1278}
1279
1281{
1282 switch (mult) {
1284 return "1/1000";
1286 return "1/100";
1288 return "1/10";
1289 case AST_AOC_MULT_ONE:
1290 return "1";
1291 case AST_AOC_MULT_TEN:
1292 return "10";
1294 return "100";
1296 return "1000";
1298 break;
1299 }
1300 return "1";
1301}
1302
1303static const char *aoc_billingid_str(enum ast_aoc_billing_id billing_id)
1304{
1305 switch (billing_id) {
1307 return "Normal";
1309 return "Reverse";
1311 return "CreditCard";
1313 return "CallForwardingUnconditional";
1315 return "CallForwardingBusy";
1317 return "CallForwardingNoReply";
1319 return "CallDeflection";
1321 return "CallTransfer";
1322 case AST_AOC_BILLING_NA:
1323 return "NotAvailable";
1325 break;
1326 }
1327 return "NotAvailable";
1328}
1329
1331{
1332 struct ast_aoc_decoded *new_decoded = NULL;
1333 struct ast_aoc_encoded *encoded = NULL;
1334 size_t size;
1335 int res = 0;
1336
1337 if (!(encoded = ast_aoc_encode(decoded, &size, NULL))) {
1338 return -1;
1339 }
1340
1341 if (!(new_decoded = ast_aoc_decode(encoded, size, NULL))) {
1342 ast_free(encoded);
1343 return -1;
1344 }
1345
1346 if (memcmp(new_decoded, decoded, sizeof(struct ast_aoc_decoded))) {
1347 res = -1;
1348 }
1349
1350 ast_aoc_destroy_decoded(new_decoded);
1351 ast_aoc_destroy_encoded(encoded);
1352 return res;
1353}
1354
1355static char *aoc_cli_debug_enable(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1356{
1357 switch (cmd) {
1358 case CLI_INIT:
1359 e->command = "aoc set debug";
1360 e->usage =
1361 "Usage: 'aoc set debug on' to enable aoc debug, 'aoc set debug off' to disable debug.\n";
1362 return NULL;
1363 case CLI_GENERATE:
1364 return NULL;
1365 case CLI_HANDLER:
1366 if (a->argc != 4) {
1367 return CLI_SHOWUSAGE;
1368 } else if(ast_true(a->argv[3])) {
1369 ast_cli(a->fd, "aoc debug enabled\n");
1371 } else if (ast_false(a->argv[3])) {
1372 ast_cli(a->fd, "aoc debug disabled\n");
1374 } else {
1375 return CLI_SHOWUSAGE;
1376 }
1377 }
1378
1379 return CLI_SUCCESS;
1380}
1381
1382/*!
1383 * \internal
1384 * \brief Append the time structure to the event message string.
1385 * \since 1.8
1386 *
1387 * \param msg Event message string being built.
1388 * \param prefix Prefix to add to the amount lines.
1389 * \param name Name of the time structure to convert.
1390 * \param time Data to convert.
1391 * \param scale Data to convert.
1392 */
1393static void aoc_time_str(struct ast_str **msg, const char *prefix, const char *name, unsigned long time, enum ast_aoc_time_scale scale)
1394{
1395 ast_str_append(msg, 0, "%s/%s/Length: %lu\r\n", prefix, name, time);
1396 ast_str_append(msg, 0, "%s/%s/Scale: %s\r\n", prefix, name,
1397 aoc_scale_str(scale));
1398}
1399
1400/*!
1401 * \internal
1402 * \brief Append the amount structure to the event message string.
1403 * \since 1.8
1404 *
1405 * \param msg Event message string being built.
1406 * \param prefix Prefix to add to the amount lines.
1407 * \param amount Data to convert.
1408 * \param mult to convert
1409 */
1410static void aoc_amount_str(struct ast_str **msg, const char *prefix, unsigned int amount, enum ast_aoc_currency_multiplier mult)
1411{
1412 static const char name[] = "Amount";
1413
1414 ast_str_append(msg, 0, "%s/%s/Cost: %u\r\n", prefix, name, amount);
1415 ast_str_append(msg, 0, "%s/%s/Multiplier: %s\r\n", prefix, name,
1416 aoc_multiplier_str(mult));
1417}
1418
1419static void aoc_request_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1420{
1421 if (decoded->request_flag) {
1422 ast_str_append(msg, 0, "AOCRequest:");
1423 if (decoded->request_flag & AST_AOC_REQUEST_S) {
1424 ast_str_append(msg, 0, "S");
1425 }
1426 if (decoded->request_flag & AST_AOC_REQUEST_D) {
1427 ast_str_append(msg, 0, "D");
1428 }
1429 if (decoded->request_flag & AST_AOC_REQUEST_E) {
1430 ast_str_append(msg, 0, "E");
1431 }
1432 ast_str_append(msg, 0, "\r\n");
1433
1434 } else {
1435 ast_str_append(msg, 0, "AOCRequest: NONE\r\n");
1436 }
1437}
1438
1439static void aoc_s_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1440{
1441 const char *rate_str;
1442 char prefix[32];
1443 int idx;
1444
1445 ast_str_append(msg, 0, "NumberRates: %d\r\n", decoded->aoc_s_count);
1446 for (idx = 0; idx < decoded->aoc_s_count; ++idx) {
1447 snprintf(prefix, sizeof(prefix), "Rate(%d)", idx);
1448
1449 ast_str_append(msg, 0, "%s/Chargeable: %s\r\n", prefix,
1451 if (decoded->aoc_s_entries[idx].charged_item == AST_AOC_CHARGED_ITEM_NA) {
1452 continue;
1453 }
1454 rate_str = aoc_rate_type_str(decoded->aoc_s_entries[idx].rate_type);
1455 ast_str_append(msg, 0, "%s/Type: %s\r\n", prefix, rate_str);
1456 switch (decoded->aoc_s_entries[idx].rate_type) {
1458 strcat(prefix, "/");
1459 strcat(prefix, rate_str);
1460 ast_str_append(msg, 0, "%s/Currency: %s\r\n", prefix,
1463 decoded->aoc_s_entries[idx].rate.duration.amount,
1464 decoded->aoc_s_entries[idx].rate.duration.multiplier);
1465 ast_str_append(msg, 0, "%s/ChargingType: %s\r\n", prefix,
1467 "StepFunction" : "ContinuousCharging");
1468 aoc_time_str(msg, prefix, "Time",
1469 decoded->aoc_s_entries[idx].rate.duration.time,
1470 decoded->aoc_s_entries[idx].rate.duration.time_scale);
1471 if (decoded->aoc_s_entries[idx].rate.duration.granularity_time) {
1472 aoc_time_str(msg, prefix, "Granularity",
1475 }
1476 break;
1478 strcat(prefix, "/");
1479 strcat(prefix, rate_str);
1480 ast_str_append(msg, 0, "%s/Currency: %s\r\n", prefix,
1481 decoded->aoc_s_entries[idx].rate.flat.currency_name);
1483 decoded->aoc_s_entries[idx].rate.flat.amount,
1484 decoded->aoc_s_entries[idx].rate.flat.multiplier);
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.volume.currency_name);
1492 decoded->aoc_s_entries[idx].rate.volume.amount,
1493 decoded->aoc_s_entries[idx].rate.volume.multiplier);
1494 ast_str_append(msg, 0, "%s/Unit: %s\r\n", prefix,
1496 break;
1498 ast_str_append(msg, 0, "%s/%s: %d\r\n", prefix, rate_str,
1499 decoded->aoc_s_entries[idx].rate.special_code);
1500 break;
1501 default:
1502 break;
1503 }
1504 }
1505}
1506
1507static void aoc_d_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1508{
1509 const char *charge_str;
1510 int idx;
1511 char prefix[32];
1512
1513 charge_str = aoc_charge_type_str(decoded->charge_type);
1514 ast_str_append(msg, 0, "Type: %s\r\n", charge_str);
1515
1516 switch (decoded->charge_type) {
1519 ast_str_append(msg, 0, "BillingID: %s\r\n",
1520 aoc_billingid_str(decoded->billing_id));
1521 ast_str_append(msg, 0, "TypeOfCharging: %s\r\n",
1523 break;
1524 default:
1525 break;
1526 }
1527
1528 switch (decoded->charge_type) {
1530 ast_str_append(msg, 0, "%s: %s\r\n", charge_str,
1531 decoded->currency_name);
1532 aoc_amount_str(msg, charge_str,
1533 decoded->currency_amount,
1534 decoded->multiplier);
1535 break;
1537 ast_str_append(msg, 0, "%s/NumberItems: %d\r\n", charge_str,
1538 decoded->unit_count);
1539 for (idx = 0; idx < decoded->unit_count; ++idx) {
1540 snprintf(prefix, sizeof(prefix), "%s/Item(%d)", charge_str, idx);
1541 if (decoded->unit_list[idx].valid_amount) {
1542 ast_str_append(msg, 0, "%s/NumberOf: %u\r\n", prefix,
1543 decoded->unit_list[idx].amount);
1544 }
1545 if (decoded->unit_list[idx].valid_type) {
1546 ast_str_append(msg, 0, "%s/TypeOf: %u\r\n", prefix,
1547 decoded->unit_list[idx].type);
1548 }
1549 }
1550 break;
1551 default:
1552 break;
1553 }
1554}
1555
1556static void aoc_e_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1557{
1558 const char *charge_str;
1559 int idx;
1560 char prefix[32];
1561
1562 charge_str = "ChargingAssociation";
1563
1564 switch (decoded->charging_association.charging_type) {
1566 snprintf(prefix, sizeof(prefix), "%s/Number", charge_str);
1567 ast_str_append(msg, 0, "%s: %s\r\n", prefix,
1569 ast_str_append(msg, 0, "%s/Plan: %d\r\n", prefix,
1571 break;
1573 ast_str_append(msg, 0, "%s/ID: %d\r\n", charge_str, decoded->charging_association.charge.id);
1574 break;
1576 default:
1577 break;
1578 }
1579
1580 charge_str = aoc_charge_type_str(decoded->charge_type);
1581 ast_str_append(msg, 0, "Type: %s\r\n", charge_str);
1582 switch (decoded->charge_type) {
1585 ast_str_append(msg, 0, "BillingID: %s\r\n",
1586 aoc_billingid_str(decoded->billing_id));
1587 break;
1588 default:
1589 break;
1590 }
1591 switch (decoded->charge_type) {
1593 ast_str_append(msg, 0, "%s: %s\r\n", charge_str,
1594 decoded->currency_name);
1595 aoc_amount_str(msg, charge_str,
1596 decoded->currency_amount,
1597 decoded->multiplier);
1598 break;
1600 ast_str_append(msg, 0, "%s/NumberItems: %d\r\n", charge_str,
1601 decoded->unit_count);
1602 for (idx = 0; idx < decoded->unit_count; ++idx) {
1603 snprintf(prefix, sizeof(prefix), "%s/Item(%d)", charge_str, idx);
1604 if (decoded->unit_list[idx].valid_amount) {
1605 ast_str_append(msg, 0, "%s/NumberOf: %u\r\n", prefix,
1606 decoded->unit_list[idx].amount);
1607 }
1608 if (decoded->unit_list[idx].valid_type) {
1609 ast_str_append(msg, 0, "%s/TypeOf: %u\r\n", prefix,
1610 decoded->unit_list[idx].type);
1611 }
1612 }
1613 break;
1614 default:
1615 break;
1616 }
1617}
1618
1619static struct ast_json *units_to_json(const struct ast_aoc_decoded *decoded)
1620{
1621 int i;
1622 struct ast_json *units = ast_json_array_create();
1623
1624 if (!units) {
1625 return ast_json_null();
1626 }
1627
1628 for (i = 0; i < decoded->unit_count; ++i) {
1629 struct ast_json *unit = ast_json_object_create();
1630
1631 if (decoded->unit_list[i].valid_amount) {
1633 unit, "NumberOf", ast_json_stringf(
1634 "%u", decoded->unit_list[i].amount));
1635 }
1636
1637 if (decoded->unit_list[i].valid_type) {
1639 unit, "TypeOf", ast_json_stringf(
1640 "%u", decoded->unit_list[i].type));
1641 }
1642
1643 if (ast_json_array_append(units, unit)) {
1644 break;
1645 }
1646 }
1647
1648 return units;
1649}
1650
1651static struct ast_json *currency_to_json(const char *name, int cost,
1653{
1654 return ast_json_pack("{s:s, s:i, s:s}",
1656 "Cost", cost,
1657 "Multiplier", aoc_multiplier_str(mult));
1658}
1659
1660static struct ast_json *charge_to_json(const struct ast_aoc_decoded *decoded)
1661{
1662 struct ast_json *obj;
1663 const char *obj_type;
1664
1665 if (decoded->charge_type != AST_AOC_CHARGE_CURRENCY &&
1666 decoded->charge_type != AST_AOC_CHARGE_UNIT) {
1667 return ast_json_pack("{s:s}",
1668 "Type", aoc_charge_type_str(decoded->charge_type));
1669 }
1670
1671 if (decoded->charge_type == AST_AOC_CHARGE_CURRENCY) {
1672 obj_type = "Currency";
1673 obj = currency_to_json(decoded->currency_name, decoded->currency_amount,
1674 decoded->multiplier);
1675 } else { /* decoded->charge_type == AST_AOC_CHARGE_UNIT */
1676 obj_type = "Units";
1677 obj = units_to_json(decoded);
1678 }
1679
1680 return ast_json_pack("{s:s, s:s, s:s, s:o}",
1681 "Type", aoc_charge_type_str(decoded->charge_type),
1682 "BillingID", aoc_billingid_str(decoded->billing_id),
1683 "TotalType", aoc_type_of_totaling_str(decoded->total_type),
1684 obj_type, obj);
1685}
1686
1687static struct ast_json *association_to_json(const struct ast_aoc_decoded *decoded)
1688{
1689 switch (decoded->charging_association.charging_type) {
1691 return ast_json_pack("{s:s, s:i}",
1693 "Plan", decoded->charging_association.charge.number.plan);
1695 return ast_json_pack("{s:i}", "ID", decoded->charging_association.charge.id);
1697 default:
1698 return ast_json_null();
1699 }
1700}
1701
1702static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
1703{
1704 int i;
1705 struct ast_json *rates = ast_json_array_create();
1706
1707 if (!rates) {
1708 return ast_json_null();
1709 }
1710
1711 for (i = 0; i < decoded->aoc_s_count; ++i) {
1712 struct ast_json *rate;
1713 struct ast_json *type = NULL;
1714 struct ast_json *currency;
1715 const char *charge_item = aoc_charged_item_str(
1716 decoded->aoc_s_entries[i].charged_item);
1717
1719 rate = ast_json_pack("{s:s}", "Chargeable", charge_item);
1720 if (ast_json_array_append(rates, rate)) {
1721 break;
1722 }
1723 continue;
1724 }
1725
1726 switch (decoded->aoc_s_entries[i].rate_type) {
1728 {
1729 struct ast_json *time;
1730 struct ast_json *granularity = NULL;
1731
1732 currency = currency_to_json(
1734 decoded->aoc_s_entries[i].rate.duration.amount,
1736
1737 time = ast_json_pack("{s:I, s:i}",
1738 "Length", (ast_json_int_t)decoded->aoc_s_entries[i].rate.duration.time,
1739 "Scale", decoded->aoc_s_entries[i].rate.duration.time_scale);
1740
1741 if (decoded->aoc_s_entries[i].rate.duration.granularity_time) {
1742 granularity = ast_json_pack("{s:I, s:i}",
1744 "Scale", decoded->aoc_s_entries[i].rate.duration.granularity_time_scale);
1745 }
1746
1747 type = ast_json_pack("{s:o, s:s, s:o, s:o}",
1748 "Currency", currency,
1749 "ChargingType", decoded->aoc_s_entries[i].rate.duration.charging_type
1750 ? "StepFunction" : "ContinuousCharging",
1751 "Time", time,
1752 "Granularity", granularity ?: ast_json_null());
1753
1754 break;
1755 }
1757 currency = currency_to_json(
1759 decoded->aoc_s_entries[i].rate.flat.amount,
1760 decoded->aoc_s_entries[i].rate.flat.multiplier);
1761
1762 type = ast_json_pack("{s:o}", "Currency", currency);
1763 break;
1765 currency = currency_to_json(
1767 decoded->aoc_s_entries[i].rate.volume.amount,
1768 decoded->aoc_s_entries[i].rate.volume.multiplier);
1769
1770 type = ast_json_pack("{s:s, s:o}",
1771 "Unit", aoc_volume_unit_str(
1772 decoded->aoc_s_entries[i].rate.volume.volume_unit),
1773 "Currency", currency);
1774 break;
1776 type = ast_json_pack("{s:i}",
1777 "SpecialCode", decoded->aoc_s_entries[i].rate.special_code);
1778 break;
1779 default:
1780 break;
1781 }
1782
1783 rate = ast_json_pack("{s:s, s:o}",
1784 "Chargeable", charge_item,
1786 if (ast_json_array_append(rates, rate)) {
1787 break;
1788 }
1789 }
1790 return rates;
1791}
1792
1793static struct ast_json *d_to_json(const struct ast_aoc_decoded *decoded)
1794{
1795 return ast_json_pack("{s:o}", "Charge", charge_to_json(decoded));
1796}
1797
1798static struct ast_json *e_to_json(const struct ast_aoc_decoded *decoded)
1799{
1800 return ast_json_pack("{s:o, s:o}",
1801 "ChargingAssociation", association_to_json(decoded),
1802 "Charge", charge_to_json(decoded));
1803}
1804
1806 /*! Channel AOC event is associated with (NULL for unassociated) */
1808 /*! AOC JSON blob of data */
1810};
1811
1812static void aoc_event_blob_dtor(void *obj)
1813{
1814 struct aoc_event_blob *aoc_event = obj;
1815
1816 ao2_cleanup(aoc_event->snapshot);
1817 ast_json_unref(aoc_event->blob);
1818}
1819
1820/*!
1821 * \internal
1822 * \brief Publish an AOC event.
1823 * \since 13.3.0
1824 *
1825 * \param chan Channel associated with the AOC event. (May be NULL if no channel)
1826 * \param msg_type What kind of AOC event.
1827 * \param blob AOC data blob to publish.
1828 */
1829static void aoc_publish_blob(struct ast_channel *chan, struct stasis_message_type *msg_type, struct ast_json *blob)
1830{
1831 struct stasis_message *msg;
1832 struct aoc_event_blob *aoc_event;
1833
1834 if (!blob || ast_json_is_null(blob)) {
1835 /* No AOC blob information? Nothing to send an event about. */
1836 return;
1837 }
1838
1839 aoc_event = ao2_alloc_options(sizeof(*aoc_event), aoc_event_blob_dtor,
1841 if (!aoc_event) {
1842 return;
1843 }
1844
1845 if (chan) {
1846 ast_channel_lock(chan);
1847 aoc_event->snapshot = ao2_bump(ast_channel_snapshot(chan));
1848 ast_channel_unlock(chan);
1849 if (!aoc_event->snapshot) {
1850 ao2_ref(aoc_event, -1);
1851 return;
1852 }
1853 }
1854 aoc_event->blob = ast_json_ref(blob);
1855
1856 msg = stasis_message_create(msg_type, aoc_event);
1857 ao2_ref(aoc_event, -1);
1858
1859 if (msg) {
1861 ao2_ref(msg, -1);
1862 }
1863}
1864
1866 const char *event_name)
1867{
1868 struct aoc_event_blob *aoc_event = stasis_message_data(message);
1869 struct ast_str *channel = NULL;
1870 struct ast_str *aoc;
1871 struct ast_manager_event_blob *ev = NULL;
1872
1873 if (aoc_event->snapshot) {
1875 if (!channel) {
1876 return NULL;
1877 }
1878 }
1879
1880 aoc = ast_manager_str_from_json_object(aoc_event->blob, NULL);
1881 if (aoc && !ast_strlen_zero(ast_str_buffer(aoc))) {
1882 ev = ast_manager_event_blob_create(EVENT_FLAG_AOC, event_name, "%s%s",
1883 AS_OR(channel, ""), ast_str_buffer(aoc));
1884 }
1885
1886 ast_free(aoc);
1887 ast_free(channel);
1888 return ev;
1889}
1890
1892{
1893 return aoc_to_ami(message, "AOC-S");
1894}
1895
1897{
1898 return aoc_to_ami(message, "AOC-D");
1899}
1900
1902{
1903 return aoc_to_ami(message, "AOC-E");
1904}
1905
1909
1911 aoc_s_type,
1912 .to_ami = aoc_s_to_ami);
1913
1915 aoc_d_type,
1916 .to_ami = aoc_d_to_ami);
1917
1919 aoc_e_type,
1920 .to_ami = aoc_e_to_ami);
1921
1922int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan)
1923{
1924 struct ast_json *blob;
1925 struct stasis_message_type *msg_type;
1926
1927 if (!decoded) {
1928 return -1;
1929 }
1930
1931 switch (decoded->msg_type) {
1932 case AST_AOC_S:
1933 blob = s_to_json(decoded);
1934 msg_type = aoc_s_type();
1935 break;
1936 case AST_AOC_D:
1937 blob = d_to_json(decoded);
1938 msg_type = aoc_d_type();
1939 break;
1940 case AST_AOC_E:
1941 blob = e_to_json(decoded);
1942 msg_type = aoc_e_type();
1943 break;
1944 default:
1945 /* events for AST_AOC_REQUEST are not generated here */
1946 return 0;
1947 }
1948
1949 aoc_publish_blob(chan, msg_type, blob);
1950 ast_json_unref(blob);
1951 return 0;
1952}
1953
1954int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
1955{
1956 if (!decoded || !msg) {
1957 return -1;
1958 }
1959
1960 switch (decoded->msg_type) {
1961 case AST_AOC_S:
1962 ast_str_append(msg, 0, "AOC-S\r\n");
1963 aoc_s_event(decoded, msg);
1964 break;
1965 case AST_AOC_D:
1966 ast_str_append(msg, 0, "AOC-D\r\n");
1967 aoc_d_event(decoded, msg);
1968 break;
1969 case AST_AOC_E:
1970 ast_str_append(msg, 0, "AOC-E\r\n");
1971 aoc_e_event(decoded, msg);
1972 break;
1973 case AST_AOC_REQUEST:
1974 ast_str_append(msg, 0, "AOC-Request\r\n");
1975 aoc_request_event(decoded, msg);
1976 break;
1977 }
1978
1979 return 0;
1980}
1981
1982static void aoc_display_decoded_debug(const struct ast_aoc_decoded *decoded, int decoding, struct ast_channel *chan)
1983{
1984 struct ast_str *msg;
1985
1986 if (!decoded || !(msg = ast_str_create(1024))) {
1987 return;
1988 }
1989
1990 if (decoding) {
1991 ast_str_append(&msg, 0, "---- DECODED AOC MSG ----\r\n");
1992 } else {
1993 ast_str_append(&msg, 0, "---- ENCODED AOC MSG ----\r\n");
1994 }
1995 if (chan) {
1996 ast_str_append(&msg, 0, "CHANNEL: %s\r\n", ast_channel_name(chan));
1997 }
1998
1999 if (ast_aoc_decoded2str(decoded, &msg)) {
2000 ast_free(msg);
2001 return;
2002 }
2003
2004 ast_verb(1, "%s\r\n", ast_str_buffer(msg));
2005 ast_free(msg);
2006}
2007
2008static struct ast_cli_entry aoc_cli[] = {
2009 AST_CLI_DEFINE(aoc_cli_debug_enable, "enable cli debugging of AOC messages"),
2010};
2011
2012static void aoc_shutdown(void)
2013{
2017
2019}
2021{
2025
2028}
Prototypes for public functions only of internal interest,.
#define AST_AOC_ENCODED_CHARGE_UNIT
Definition: aoc.c:184
int ast_aoc_cli_init(void)
enable aoc cli options
Definition: aoc.c:2020
static int aoc_parse_ie(struct ast_aoc_decoded *decoded, unsigned char *data, unsigned int datalen)
Definition: aoc.c:369
#define AST_AOC_ENCODED_TYPE_D
Definition: aoc.c:173
AOC_IE
AOC Payload Information Elements.
Definition: aoc.c:235
@ AOC_IE_UNIT
Definition: aoc.c:237
@ AOC_IE_RATE
Definition: aoc.c:240
@ AOC_IE_TERMINATION_REQUEST
Definition: aoc.c:241
@ AOC_IE_CHARGING_ASSOCIATION
Definition: aoc.c:239
@ AOC_IE_BILLING
Definition: aoc.c:238
@ AOC_IE_CURRENCY
Definition: aoc.c:236
int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Convert decoded aoc msg to string representation.
Definition: aoc.c:1954
void * ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
free an ast_aoc_encoded object
Definition: aoc.c:313
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:1019
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:770
#define AST_AOC_ENCODED_CHARGE_NA
Definition: aoc.c:181
static struct ast_manager_event_blob * aoc_e_to_ami(struct stasis_message *message)
Definition: aoc.c:1901
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:914
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:972
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:1121
static void aoc_create_ie_data_charging_rate(const struct ast_aoc_s_entry *entry, struct aoc_ie_charging_rate *ie)
Definition: aoc.c:537
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:892
static struct ast_json * s_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1702
int ast_aoc_test_encode_decode_match(struct ast_aoc_decoded *decoded)
test aoc encode decode routines.
Definition: aoc.c:1330
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:844
static void aoc_shutdown(void)
Definition: aoc.c:2012
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:1079
static struct ast_json * association_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1687
static void aoc_event_blob_dtor(void *obj)
Definition: aoc.c:1812
static void aoc_e_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1556
static const char * aoc_charge_type_str(enum ast_aoc_charge_type value)
Definition: aoc.c:1257
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:449
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:276
static const char * aoc_scale_str(enum ast_aoc_time_scale value)
Definition: aoc.c:1226
static struct ast_json * charge_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1660
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
Definition: aoc.c:307
static struct ast_json * units_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1619
static struct ast_manager_event_blob * aoc_d_to_ami(struct stasis_message *message)
Definition: aoc.c:1896
static struct ast_json * d_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1793
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:1056
#define AST_AOC_ENCODE_VERSION
Definition: aoc.c:189
#define AST_AOC_ENCODED_TYPE_REQUEST
Definition: aoc.c:172
static struct ast_cli_entry aoc_cli[]
Definition: aoc.c:2008
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:977
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:950
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:857
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:1010
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:1865
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:902
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:1024
int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded, unsigned int code)
Add AOC-S special arrangement entry.
Definition: aoc.c:880
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:919
#define AST_AOC_ENCODED_CHARGE_CURRENCY
Definition: aoc.c:183
static void aoc_request_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1419
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:1040
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:801
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:650
static void aoc_s_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1439
static int aoc_s_add_entry(struct ast_aoc_decoded *decoded, struct ast_aoc_s_entry *entry)
Definition: aoc.c:743
#define AST_AOC_ENCODED_REQUEST_E
Definition: aoc.c:179
static const char * aoc_multiplier_str(enum ast_aoc_currency_multiplier mult)
Definition: aoc.c:1280
static struct ast_json * currency_to_json(const char *name, int cost, enum ast_aoc_currency_multiplier mult)
Definition: aoc.c:1651
static void aoc_publish_blob(struct ast_channel *chan, struct stasis_message_type *msg_type, struct ast_json *blob)
Definition: aoc.c:1829
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:907
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:822
#define AST_AOC_ENCODED_REQUEST_D
Definition: aoc.c:178
static char * aoc_cli_debug_enable(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: aoc.c:1355
static void aoc_d_event(const struct ast_aoc_decoded *decoded, struct ast_str **msg)
Definition: aoc.c:1507
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:1035
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:1051
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:756
static const char * aoc_type_of_totaling_str(enum ast_aoc_total_type value)
Definition: aoc.c:1161
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:945
static const char * aoc_volume_unit_str(enum ast_aoc_volume_unit value)
Definition: aoc.c:1093
static char aoc_debug_enabled
Definition: aoc.c:192
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:1393
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:761
static void aoc_display_decoded_debug(const struct ast_aoc_decoded *decoded, int decoding, struct ast_channel *chan)
Definition: aoc.c:1982
static const char * aoc_billingid_str(enum ast_aoc_billing_id billing_id)
Definition: aoc.c:1303
static const char * aoc_rate_type_str(enum ast_aoc_s_rate_type value)
Definition: aoc.c:1186
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:1922
struct stasis_message_type * aoc_e_type(void)
#define AST_AOC_ENCODED_TYPE_S
Definition: aoc.c:175
static void aoc_create_ie_data(struct ast_aoc_decoded *decoded, struct aoc_ie_data *ied)
Definition: aoc.c:583
int ast_aoc_set_termination_request(struct ast_aoc_decoded *decoded)
Mark the AST_AOC_REQUEST message as a termination request.
Definition: aoc.c:1069
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:897
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:869
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:940
static void aoc_amount_str(struct ast_str **msg, const char *prefix, unsigned int amount, enum ast_aoc_currency_multiplier mult)
Definition: aoc.c:1410
#define AST_AOC_ENCODED_CHARGE_SUBTOTAL
Definition: aoc.c:186
#define AST_AOC_ENCODED_CHARGE_FREE
Definition: aoc.c:182
#define AST_AOC_ENCODED_REQUEST_S
Definition: aoc.c:177
#define AST_AOC_ENCODED_TYPE_E
Definition: aoc.c:174
static struct ast_json * e_to_json(const struct ast_aoc_decoded *decoded)
Definition: aoc.c:1798
static struct ast_manager_event_blob * aoc_s_to_ami(struct stasis_message *message)
Definition: aoc.c:1891
static void aoc_parse_ie_charging_rate(struct ast_aoc_decoded *decoded, const struct aoc_ie_charging_rate *ie)
Definition: aoc.c:319
static int aoc_append_ie(struct aoc_ie_data *ied, unsigned short ie_id, const void *data, unsigned short datalen)
Definition: aoc.c:522
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:147
enum queue_result id
Definition: app_queue.c:1638
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:2922
struct ast_channel_snapshot * ast_channel_snapshot(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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:1872
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:1973
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:10548
#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:1511
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:1807
struct ast_json * blob
Definition: aoc.c:1809
uint8_t id
Definition: aoc.c:265
struct ast_aoc_charging_association ca
Definition: aoc.c:269
struct ast_aoc_s_entry entry
Definition: aoc.c:273
uint32_t amount
Definition: aoc.c:252
uint8_t multiplier
Definition: aoc.c:253
char name[AOC_CURRENCY_NAME_SIZE]
Definition: aoc.c:254
int pos
Definition: aoc.c:514
unsigned char buf[1024]
Definition: aoc.c:513
uint32_t amount
Definition: aoc.c:258
uint8_t type
Definition: aoc.c:261
uint8_t valid_amount
Definition: aoc.c:260
uint8_t valid_type
Definition: aoc.c:259
AOC IE payload header.
Definition: aoc.c:245
char data[0]
Definition: aoc.c:248
uint8_t ie_id
Definition: aoc.c:246
uint8_t datalen
Definition: aoc.c:247
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:212
unsigned int currency_amount
Definition: aoc.c:213
struct ast_aoc_unit_entry unit_list[32]
Definition: aoc.c:218
char currency_name[AOC_CURRENCY_NAME_SIZE]
Definition: aoc.c:214
enum ast_aoc_billing_id billing_id
Definition: aoc.c:221
int unit_count
Definition: aoc.c:217
struct ast_aoc_s_entry aoc_s_entries[10]
Definition: aoc.c:228
struct ast_aoc_charging_association charging_association
Definition: aoc.c:224
enum ast_aoc_request request_flag
Definition: aoc.c:208
char termination_request
Definition: aoc.c:231
enum ast_aoc_total_type total_type
Definition: aoc.c:209
int aoc_s_count
Definition: aoc.c:227
enum ast_aoc_charge_type charge_type
Definition: aoc.c:207
enum ast_aoc_type msg_type
Definition: aoc.c:206
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:200
uint8_t flags
Definition: aoc.c:199
uint8_t version
Definition: aoc.c:198
unsigned char data[0]
Definition: aoc.c:201
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:502
Support for dynamic strings.
Definition: strings.h:623
Definition: search.h:40
int value
Definition: syslog.c:37
static struct test_val a
Utility functions.
#define ARRAY_LEN(a)
Definition: utils.h:666