b99cfbb6584e0e1d71a37984e1d265d3716e6c33
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / evel_library / evel_voicequality.c
1 /**************************************************************************//**
2  * @file
3  * Implementation of EVEL functions relating to the Voice Quality.
4  *
5  * License
6  * -------
7  *
8  * Copyright(c) <2016>, AT&T Intellectual Property.  All other rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  *    this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:  This product includes
20  *    software developed by the AT&T.
21  * 4. Neither the name of AT&T nor the names of its contributors may be used to
22  *    endorse or promote products derived from this software without specific
23  *    prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
26  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28  * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
29  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *****************************************************************************/
36
37 #include <string.h>
38 #include <assert.h>
39 #include <stdlib.h>
40
41 #include "evel.h"
42 #include "evel_internal.h"
43 #include "evel_throttle.h"
44
45 /**************************************************************************//**
46  * Create a new voice quality event.
47  *
48  * @note    The mandatory fields on the Voice Quality must be supplied to this 
49  *          factory function and are immutable once set.  Optional fields have 
50  *          explicit setter functions, but again values may only be set once 
51  *          so that the Voice Quality has immutable properties.
52  * @param   calleeSideCodec         Callee codec for the call.
53  * @param   callerSideCodec         Caller codec for the call.
54  * @param   correlator              Constant across all events on this call.
55  * @param   midCallRtcp             Base64 encoding of the binary RTCP data
56  *                                  (excluding Eth/IP/UDP headers).
57  * @param   vendorVnfNameFields     Vendor, VNF and VfModule names.
58  * @returns pointer to the newly manufactured ::EVENT_VOICE_QUALITY.  If the 
59  *          event is not used (i.e. posted) it must be released using
60             ::evel_free_voice_quality.
61  * @retval  NULL  Failed to create the event.
62  *****************************************************************************/
63 EVENT_VOICE_QUALITY * evel_new_voice_quality(const char * const calleeSideCodec,
64     const char * const callerSideCodec, const char * const correlator,
65     const char * const midCallRtcp, const char * const vendorName) {
66     
67     bool inError = false;
68     EVENT_VOICE_QUALITY *voiceQuality = NULL;
69     EVEL_ENTER();
70
71     /***************************************************************************/
72     /* Check preconditions.                                                    */
73     /***************************************************************************/
74     assert(calleeSideCodec != NULL);
75     assert(callerSideCodec != NULL);
76     assert(correlator != NULL);
77     assert(midCallRtcp != NULL);
78     assert(vendorName != NULL);
79
80     /***************************************************************************/
81     /* Allocate the Voice Quality.                                                     */
82     /***************************************************************************/
83     voiceQuality = malloc(sizeof(EVENT_VOICE_QUALITY));
84     
85     if (voiceQuality == NULL)
86     {
87         log_error_state("Out of memory");
88         inError = true;
89     }
90
91     //Only in case of successful allocation initialize data.
92     if (inError == false) {
93         memset(voiceQuality, 0, sizeof(EVENT_VOICE_QUALITY));
94         EVEL_DEBUG("New Voice Quality is at %lp", voiceQuality);
95
96         /***************************************************************************/
97         /* Initialize the header & the fault fields.  Optional integer values are   */
98         /* initialized as 0.                                                        */
99         /***************************************************************************/
100         evel_init_header(&voiceQuality->header,"voiceQuality");
101         voiceQuality->header.event_domain = EVEL_DOMAIN_VOICE_QUALITY;
102         voiceQuality->major_version = EVEL_VOICEQ_MAJOR_VERSION;
103         voiceQuality->minor_version = EVEL_VOICEQ_MINOR_VERSION;
104
105         voiceQuality->calleeSideCodec = strdup(calleeSideCodec);
106         voiceQuality->callerSideCodec = strdup(callerSideCodec);
107         voiceQuality->correlator = strdup(correlator);
108         voiceQuality->midCallRtcp = strdup(midCallRtcp);
109         evel_init_vendor_field(&voiceQuality->vendorVnfNameFields, vendorName);
110         dlist_initialize(&voiceQuality->additionalInformation);
111         dlist_initialize(&voiceQuality->endOfCallVqmSummaries);
112         evel_init_option_string(&voiceQuality->phoneNumber);
113     }
114
115     EVEL_EXIT();
116     return voiceQuality;
117
118 }
119
120 /**************************************************************************//**
121  * Add an additional value name/value pair to the Voice Quality.
122  *
123  * The name and value are null delimited ASCII strings.  The library takes
124  * a copy so the caller does not have to preserve values after the function
125  * returns.
126  *
127  * @param fault     Pointer to the fault.
128  * @param name      ASCIIZ string with the attribute's name.  The caller
129  *                  does not need to preserve the value once the function
130  *                  returns.
131  * @param value     ASCIIZ string with the attribute's value.  The caller
132  *                  does not need to preserve the value once the function
133  *                  returns.
134  *****************************************************************************/
135 void evel_voice_quality_addl_info_add(EVENT_VOICE_QUALITY * voiceQ, char * name, char * value) {
136     VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
137     EVEL_ENTER();
138
139     /***************************************************************************/
140     /* Check preconditions.                                                    */
141     /***************************************************************************/
142     assert(voiceQ != NULL);
143     assert(voiceQ->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
144     assert(name != NULL);
145     assert(value != NULL);
146
147     EVEL_DEBUG("Adding name=%s value=%s", name, value);
148     addlInfo = malloc(sizeof(VOICE_QUALITY_ADDL_INFO));
149     assert(addlInfo != NULL);
150     memset(addlInfo, 0, sizeof(VOICE_QUALITY_ADDL_INFO));
151     addlInfo->name = strdup(name);
152     addlInfo->value = strdup(value);
153     assert(addlInfo->name != NULL);
154     assert(addlInfo->value != NULL);
155
156     dlist_push_last(&voiceQ->additionalInformation, addlInfo);
157
158     EVEL_EXIT();
159 }
160
161 /**************************************************************************//**
162  * Set the Callee side codec for Call for domain Voice Quality
163  *
164  * @note  The property is treated as immutable: it is only valid to call
165  *        the setter once.  However, we don't assert if the caller tries to
166  *        overwrite, just ignoring the update instead.
167  *
168  * @param voiceQuality              Pointer to the Voice Quality Event.
169  * @param calleeCodecForCall        The Callee Side Codec to be set.  ASCIIZ 
170  *                                  string. The caller does not need to 
171  *                                  preserve the value once the function
172  *                                  returns.
173  *****************************************************************************/
174 void evel_voice_quality_callee_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
175     const char * const calleeCodecForCall) {
176     EVEL_ENTER();
177
178     /***************************************************************************/
179     /* Check preconditions.                                                    */
180     /***************************************************************************/
181     assert(voiceQuality != NULL);
182     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
183     assert(calleeCodecForCall != NULL);
184
185     voiceQuality->calleeSideCodec = strdup(calleeCodecForCall);
186
187     EVEL_EXIT();
188 }
189
190 /**************************************************************************//**
191  * Set the Caller side codec for Call for domain Voice Quality
192  *
193  * @note  The property is treated as immutable: it is only valid to call
194  *        the setter once.  However, we don't assert if the caller tries to
195  *        overwrite, just ignoring the update instead.
196  *
197  * @param voiceQuality              Pointer to the Voice Quality Event.
198  * @param callerCodecForCall        The Caller Side Codec to be set.  ASCIIZ 
199  *                                  string. The caller does not need to 
200  *                                  preserve the value once the function
201  *                                  returns.
202  *****************************************************************************/
203 void evel_voice_quality_caller_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
204     const char * const callerCodecForCall) {
205     EVEL_ENTER();
206
207     /***************************************************************************/
208     /* Check preconditions.                                                    */
209     /***************************************************************************/
210     assert(voiceQuality != NULL);
211     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
212     assert(callerCodecForCall != NULL);
213
214     voiceQuality->calleeSideCodec = strdup(callerCodecForCall);
215
216     EVEL_EXIT();
217 }
218
219 /**************************************************************************//**
220  * Set the correlator for domain Voice Quality
221  *
222  * @note  The property is treated as immutable: it is only valid to call
223  *        the setter once.  However, we don't assert if the caller tries to
224  *        overwrite, just ignoring the update instead.
225  *
226  * @param voiceQuality              Pointer to the Voice Quality Event.
227  * @param correlator                The correlator value to be set.  ASCIIZ 
228  *                                  string. The caller does not need to 
229  *                                  preserve the value once the function
230  *                                  returns.
231  *****************************************************************************/
232 void evel_voice_quality_correlator_set(EVENT_VOICE_QUALITY * voiceQuality,
233     const char * const vCorrelator) {
234     EVEL_ENTER();
235
236     /***************************************************************************/
237     /* Check preconditions.                                                    */
238     /***************************************************************************/
239     assert(voiceQuality != NULL);
240     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
241     assert(vCorrelator != NULL);
242
243     voiceQuality->correlator = strdup(vCorrelator);
244
245     EVEL_EXIT();
246 }
247
248 /**************************************************************************//**
249  * Set the RTCP Call Data for domain Voice Quality
250  *
251  * @note  The property is treated as immutable: it is only valid to call
252  *        the setter once.  However, we don't assert if the caller tries to
253  *        overwrite, just ignoring the update instead.
254  *
255  * @param voiceQuality              Pointer to the Voice Quality Event.
256  * @param rtcpCallData              The RTCP Call Data to be set.  ASCIIZ 
257  *                                  string. The caller does not need to 
258  *                                  preserve the value once the function
259  *                                  returns.
260  *****************************************************************************/
261 void evel_voice_quality_rtcp_data_set(EVENT_VOICE_QUALITY * voiceQuality,
262     const char * const rtcpCallData) {
263     EVEL_ENTER();
264
265     /***************************************************************************/
266     /* Check preconditions.                                                    */
267     /***************************************************************************/
268     assert(voiceQuality != NULL);
269     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
270     assert(rtcpCallData != NULL);
271
272     voiceQuality->midCallRtcp = strdup(rtcpCallData);
273
274     EVEL_EXIT();
275 }
276
277 /**************************************************************************//**
278  * Set the Vendor VNF Name fields for domain Voice Quality
279  *
280  * @note  The property is treated as immutable: it is only valid to call
281  *        the setter once.  However, we don't assert if the caller tries to
282  *        overwrite, just ignoring the update instead.
283  *
284  * @param voiceQuality              Pointer to the Voice Quality Event.
285  * @param modulename                The Vendor, VNF and VfModule names to be set.   
286  *                                  ASCIIZ string. The caller does not need to 
287  *                                  preserve the value once the function
288  *                                  returns.
289  *****************************************************************************/
290 void evel_voice_quality_vnfmodule_name_set(EVENT_VOICE_QUALITY * voiceQuality,
291     const char * const module_name) {
292     EVEL_ENTER();
293
294     /***************************************************************************/
295     /* Check preconditions.                                                    */
296     /***************************************************************************/
297     assert(voiceQuality != NULL);
298     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
299     assert(module_name != NULL);
300
301     evel_vendor_field_module_set(&voiceQuality->vendorVnfNameFields, module_name);
302
303     EVEL_EXIT();
304 }
305
306 /**************************************************************************//**
307  * Set the Vendor VNF Name fields for domain Voice Quality
308  *
309  * @note  The property is treated as immutable: it is only valid to call
310  *        the setter once.  However, we don't assert if the caller tries to
311  *        overwrite, just ignoring the update instead.
312  *
313  * @param voiceQuality              Pointer to the Voice Quality Event.
314  * @param modulename                The Vendor, VNF and VfModule names to be set.   
315  *                                  ASCIIZ string. The caller does not need to 
316  *                                  preserve the value once the function
317  *                                  returns.
318  *****************************************************************************/
319 void evel_voice_quality_vnfname_set(EVENT_VOICE_QUALITY * voiceQuality,
320     const char * const vnfname) {
321     EVEL_ENTER();
322
323     /***************************************************************************/
324     /* Check preconditions.                                                    */
325     /***************************************************************************/
326     assert(voiceQuality != NULL);
327     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
328     assert(vnfname != NULL);
329
330     evel_vendor_field_vnfname_set(&voiceQuality->vendorVnfNameFields, vnfname);
331
332     EVEL_EXIT();
333 }
334
335 /**************************************************************************//**
336  * Set the Phone Number associated with the Correlator for domain Voice Quality
337  *
338  * @note  The property is treated as immutable: it is only valid to call
339  *        the setter once.  However, we don't assert if the caller tries to
340  *        overwrite, just ignoring the update instead.
341  *
342  * @param voiceQuality              Pointer to the Voice Quality Event.
343  * @param calleeCodecForCall        The Phone Number to be set.  ASCIIZ 
344  *                                  string. The caller does not need to 
345  *                                  preserve the value once the function
346  *                                  returns.
347  *****************************************************************************/
348 void evel_voice_quality_phone_number_set(EVENT_VOICE_QUALITY * voiceQuality,
349     const char * const phoneNumber) {
350     EVEL_ENTER();
351
352     /***************************************************************************/
353     /* Check preconditions.                                                    */
354     /***************************************************************************/
355     assert(voiceQuality != NULL);
356     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
357     assert(phoneNumber != NULL);
358
359     evel_set_option_string(&voiceQuality->phoneNumber, phoneNumber, "Phone_Number");
360
361     EVEL_EXIT();
362 }
363
364 /**************************************************************************//**
365  * Add an End of Call Voice Quality Metrices
366
367  * The adjacencyName and endpointDescription is null delimited ASCII string.  
368  * The library takes a copy so the caller does not have to preserve values
369  * after the function returns.
370  *
371  * @param voiceQuality     Pointer to the measurement.
372  * @param adjacencyName                     Adjacency name
373  * @param endpointDescription               Enumeration: â€˜Caller’, â€˜Callee’.
374  * @param endpointJitter                    Endpoint jitter
375  * @param endpointRtpOctetsDiscarded        Endpoint RTP octets discarded.
376  * @param endpointRtpOctetsReceived         Endpoint RTP octets received.
377  * @param endpointRtpOctetsSent             Endpoint RTP octets sent
378  * @param endpointRtpPacketsDiscarded       Endpoint RTP packets discarded.
379  * @param endpointRtpPacketsReceived        Endpoint RTP packets received.
380  * @param endpointRtpPacketsSent            Endpoint RTP packets sent.
381  * @param localJitter                       Local jitter.
382  * @param localRtpOctetsDiscarded           Local RTP octets discarded.
383  * @param localRtpOctetsReceived            Local RTP octets received.
384  * @param localRtpOctetsSent                Local RTP octets sent.
385  * @param localRtpPacketsDiscarded          Local RTP packets discarded.
386  * @param localRtpPacketsReceived           Local RTP packets received.
387  * @param localRtpPacketsSent               Local RTP packets sent.
388  * @param mosCqe                            Decimal range from 1 to 5
389  *                                          (1 decimal place)
390  * @param packetsLost                       No  Packets lost
391  * @param packetLossPercent                 Calculated percentage packet loss 
392  * @param rFactor                           rFactor from 0 to 100
393  * @param roundTripDelay                    Round trip delay in milliseconds
394  *****************************************************************************/
395 void evel_voice_quality_end_metrics_add(EVENT_VOICE_QUALITY * voiceQuality,
396     const char * adjacencyName, EVEL_SERVICE_ENDPOINT_DESC endpointDescription,
397     int endpointJitter,
398     int endpointRtpOctetsDiscarded,
399     int endpointRtpOctetsReceived,
400     int endpointRtpOctetsSent,
401     int endpointRtpPacketsDiscarded,
402     int endpointRtpPacketsReceived,
403     int endpointRtpPacketsSent,
404     int localJitter,
405     int localRtpOctetsDiscarded,
406     int localRtpOctetsReceived,
407     int localRtpOctetsSent,
408     int localRtpPacketsDiscarded,
409     int localRtpPacketsReceived,
410     int localRtpPacketsSent,
411     int mosCqe,
412     int packetsLost,
413     int packetLossPercent,
414     int rFactor,
415     int roundTripDelay) {
416     
417     END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL;
418     EVEL_ENTER();
419
420     /***************************************************************************/
421     /* Check assumptions.                                                      */
422     /***************************************************************************/
423     assert(voiceQuality != NULL);
424     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
425     assert(adjacencyName != NULL);
426     assert(endpointDescription >= 0);
427     assert(mosCqe >= 1 && mosCqe <= 5);
428     assert(rFactor >= 0 && rFactor <= 100);
429     
430     /***************************************************************************/
431     /* Allocate a container for the value and push onto the list.              */
432     /***************************************************************************/
433     EVEL_DEBUG("Adding adjacencyName=%s endpointDescription=%d", adjacencyName, endpointDescription);
434     vQMetrices = malloc(sizeof(END_OF_CALL_VOICE_QUALITY_METRICS));
435     assert(vQMetrices != NULL);
436     memset(vQMetrices, 0, sizeof(END_OF_CALL_VOICE_QUALITY_METRICS));
437
438     vQMetrices->adjacencyName = strdup(adjacencyName);
439     vQMetrices->endpointDescription = evel_service_endpoint_desc(endpointDescription);
440
441     evel_set_option_int(&vQMetrices->endpointJitter, endpointJitter, "Endpoint jitter");
442     evel_set_option_int(&vQMetrices->endpointRtpOctetsDiscarded, endpointRtpOctetsDiscarded, "Endpoint RTP octets discarded");
443     evel_set_option_int(&vQMetrices->endpointRtpOctetsReceived, endpointRtpOctetsReceived, "Endpoint RTP octets received");
444     evel_set_option_int(&vQMetrices->endpointRtpOctetsSent, endpointRtpOctetsSent, "Endpoint RTP octets sent");
445     evel_set_option_int(&vQMetrices->endpointRtpPacketsDiscarded, endpointRtpPacketsDiscarded, "Endpoint RTP packets discarded");
446     evel_set_option_int(&vQMetrices->endpointRtpPacketsReceived, endpointRtpPacketsReceived, "Endpoint RTP packets received");
447     evel_set_option_int(&vQMetrices->endpointRtpPacketsSent, endpointRtpPacketsSent, "Endpoint RTP packets sent");
448     evel_set_option_int(&vQMetrices->localJitter, localJitter, "Local jitter");
449     evel_set_option_int(&vQMetrices->localRtpOctetsDiscarded, localRtpOctetsDiscarded, "Local RTP octets discarded");
450     evel_set_option_int(&vQMetrices->localRtpOctetsReceived, localRtpOctetsReceived, "Local RTP octets received");
451     evel_set_option_int(&vQMetrices->localRtpOctetsSent, localRtpOctetsSent, "Local RTP octets sent");
452     evel_set_option_int(&vQMetrices->localRtpPacketsDiscarded, localRtpPacketsDiscarded, "Local RTP packets discarded");
453     evel_set_option_int(&vQMetrices->localRtpPacketsReceived, localRtpPacketsReceived, "Local RTP packets received");
454     evel_set_option_int(&vQMetrices->localRtpPacketsSent, localRtpPacketsSent, "Local RTP packets sent");
455     evel_set_option_int(&vQMetrices->mosCqe, mosCqe, "Decimal range from 1 to 5 (1 decimal place)");
456     evel_set_option_int(&vQMetrices->packetsLost, packetsLost, "Packets lost");
457     evel_set_option_int(&vQMetrices->packetLossPercent, packetLossPercent, "Calculated percentage packet loss");
458     evel_set_option_int(&vQMetrices->rFactor, rFactor, "rFactor ");
459     evel_set_option_int(&vQMetrices->roundTripDelay, roundTripDelay, "Round trip delay in milliseconds ");
460
461     dlist_push_last(&voiceQuality->endOfCallVqmSummaries, vQMetrices);
462
463     EVEL_EXIT();
464 }
465
466 /**************************************************************************//**
467  * Encode the Voce Quality in JSON according to AT&T's schema for the voice
468  * quality type.
469  *
470  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
471  * @param event         Pointer to the ::EVENT_HEADER to encode.
472  *****************************************************************************/
473 void evel_json_encode_voice_quality(EVEL_JSON_BUFFER * jbuf,
474                             EVENT_VOICE_QUALITY * event)
475 {
476   VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
477   DLIST_ITEM * addlInfoItem = NULL;
478
479   END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrics = NULL;
480   DLIST_ITEM * vQMetricsItem = NULL;
481
482   EVEL_ENTER();
483
484   /***************************************************************************/
485   /* Check preconditions.                                                    */
486   /***************************************************************************/
487   assert(event != NULL);
488   assert(event->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
489
490   evel_json_encode_header(jbuf, &event->header);
491   evel_json_open_named_object(jbuf, "voiceQualityFields");
492
493   /***************************************************************************/
494   /* Mandatory fields.                                                       */
495   /***************************************************************************/
496   evel_enc_kv_string(jbuf, "calleeSideCodec", event->calleeSideCodec);
497   evel_enc_kv_string(jbuf, "callerSideCodec", event->callerSideCodec);
498   evel_enc_kv_string(jbuf, "correlator", event->correlator);
499   evel_enc_kv_string(jbuf, "midCallRtcp", event->midCallRtcp);
500   evel_json_encode_vendor_field(jbuf, &event->vendorVnfNameFields);
501   evel_enc_version(
502     jbuf, "voiceQualityFieldsVersion", event->major_version, event->minor_version);
503
504   /***************************************************************************/
505   /* Optional fields.                                                        */
506   /***************************************************************************/
507   evel_enc_kv_opt_string(jbuf, "phoneNumber", &event->phoneNumber);
508   /***************************************************************************/
509   /* Checkpoint, so that we can wind back if all fields are suppressed.      */
510   /***************************************************************************/
511   //additionalInformation for Voice Quality
512   bool item_added = false;
513  
514   evel_json_checkpoint(jbuf);
515   if (evel_json_open_opt_named_list(jbuf, "additionalInformation"))
516   {
517
518     addlInfoItem = dlist_get_first(&event->additionalInformation);
519     while (addlInfoItem != NULL)
520     {
521       addlInfo = (VOICE_QUALITY_ADDL_INFO*)addlInfoItem->item;
522       assert(addlInfo != NULL);
523
524       if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
525                                           "additionalInformation",
526                                           addlInfo->name))
527       {
528         evel_json_open_object(jbuf);
529         evel_enc_kv_string(jbuf, "name", addlInfo->name);
530         evel_enc_kv_string(jbuf, "value", addlInfo->value);
531         evel_json_close_object(jbuf);
532         item_added = true;
533       }
534       addlInfoItem = dlist_get_next(addlInfoItem);
535     }
536     evel_json_close_list(jbuf);
537     }
538
539     //endOfCallVqmSummaries
540     evel_json_checkpoint(jbuf);
541     if (evel_json_open_opt_named_list(jbuf, "endOfCallVqmSummaries"))
542     {
543         vQMetricsItem = dlist_get_first(&event->endOfCallVqmSummaries);
544         while (vQMetricsItem != NULL)
545         {
546             vQMetrics = (END_OF_CALL_VOICE_QUALITY_METRICS *)vQMetricsItem->item;
547             assert(vQMetrics != NULL);
548
549             if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
550                 "endOfCallVqmSummaries",
551                 vQMetrics->adjacencyName))
552             {
553                 evel_json_open_object(jbuf);
554                 evel_enc_kv_string(jbuf, "adjacencyName", vQMetrics->adjacencyName);
555                 evel_enc_kv_string(jbuf, "endpointDescription", vQMetrics->endpointDescription);
556                 evel_enc_kv_opt_int(jbuf, "endpointJitter", &vQMetrics->endpointJitter);
557                 evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsDiscarded", &vQMetrics->endpointRtpOctetsDiscarded);
558                 evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsReceived", &vQMetrics->endpointRtpOctetsReceived);
559                 evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsSent", &vQMetrics->endpointRtpOctetsSent);
560                 evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsDiscarded", &vQMetrics->endpointRtpPacketsDiscarded);
561                 evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsReceived", &vQMetrics->endpointRtpPacketsReceived);
562                 evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsSent", &vQMetrics->endpointRtpPacketsSent);
563                 evel_enc_kv_opt_int(jbuf, "localJitter", &vQMetrics->localJitter);
564                 evel_enc_kv_opt_int(jbuf, "localRtpOctetsDiscarded", &vQMetrics->localRtpOctetsDiscarded);
565                 evel_enc_kv_opt_int(jbuf, "localRtpOctetsReceived", &vQMetrics->localRtpOctetsReceived);
566                 evel_enc_kv_opt_int(jbuf, "localRtpOctetsSent", &vQMetrics->localRtpOctetsSent);
567                 evel_enc_kv_opt_int(jbuf, "localRtpPacketsDiscarded", &vQMetrics->localRtpPacketsDiscarded);
568                 evel_enc_kv_opt_int(jbuf, "localRtpPacketsReceived", &vQMetrics->localRtpPacketsReceived);
569                 evel_enc_kv_opt_int(jbuf, "localRtpPacketsSent", &vQMetrics->localRtpPacketsSent);
570                 evel_enc_kv_opt_int(jbuf, "mosCqe", &vQMetrics->mosCqe);
571                 evel_enc_kv_opt_int(jbuf, "packetsLost", &vQMetrics->packetsLost);
572                 evel_enc_kv_opt_int(jbuf, "packetLossPercent", &vQMetrics->packetLossPercent);
573                 evel_enc_kv_opt_int(jbuf, "rFactor", &vQMetrics->rFactor);
574                 evel_enc_kv_opt_int(jbuf, "roundTripDelay", &vQMetrics->roundTripDelay);
575
576                 evel_json_close_object(jbuf);
577                 item_added = true;
578             }
579             vQMetricsItem = dlist_get_next(vQMetricsItem);
580         }
581         evel_json_close_list(jbuf);
582         }
583
584     /*************************************************************************/
585     /* If we've not written anything, rewind to before we opened the list.   */
586     /*************************************************************************/
587     if (!item_added)
588     {
589       evel_json_rewind(jbuf);
590     }
591
592   evel_json_close_object(jbuf);
593
594   EVEL_EXIT();
595 }
596
597 /**************************************************************************//**
598  * Free a Voice Quality.
599  *
600  * Free off the Voce Quality supplied.  Will free all the contained allocated
601  * memory.
602  *
603  * @note It does not free the Voice Quality itself, since that may be part of a
604  * larger structure.
605  *****************************************************************************/
606 void evel_free_voice_quality(EVENT_VOICE_QUALITY * voiceQuality) {
607     END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL;
608     VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
609
610     EVEL_ENTER();
611
612     /***************************************************************************/
613     /* Check preconditions.  As an internal API we don't allow freeing NULL    */
614     /* events as we do on the public API.                                      */
615     /***************************************************************************/
616     assert(voiceQuality != NULL);
617     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
618
619     /***************************************************************************/
620     /* Free all internal strings then the header itself.                       */
621     /***************************************************************************/
622     
623     //Additional Information
624     addlInfo = dlist_pop_last(&voiceQuality->additionalInformation);
625     while (addlInfo != NULL)
626     {
627         EVEL_DEBUG("Freeing Additional Info (%s, %s)",
628             addlInfo->name,
629             addlInfo->value);
630         free(addlInfo->name);
631         free(addlInfo->value);
632         free(addlInfo);
633         addlInfo = dlist_pop_last(&voiceQuality->additionalInformation);
634     }
635
636     //Summary Information
637     vQMetrices = dlist_pop_last(&voiceQuality->endOfCallVqmSummaries);
638     while (vQMetrices != NULL)
639     {
640         EVEL_DEBUG("Freeing End of Call Voice Measurements Info (%s, %s)",
641             vQMetrices->adjacencyName,
642             vQMetrices->endpointDescription);
643         free(vQMetrices->adjacencyName);
644         free(vQMetrices);
645         vQMetrices = dlist_pop_last(&voiceQuality->endOfCallVqmSummaries);
646     }
647
648     //Members
649     free(voiceQuality->calleeSideCodec);
650     free(voiceQuality->callerSideCodec);
651     free(voiceQuality->correlator);
652     free(voiceQuality->midCallRtcp);
653     evel_free_option_string(&voiceQuality->phoneNumber);
654     evel_free_event_vendor_field(&voiceQuality->vendorVnfNameFields);
655
656     //header
657     evel_free_header(&voiceQuality->header);
658
659     EVEL_EXIT();
660 }
661