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