Fixed bugs with VoiceQuality and TCA
[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 #include <string.h>
23 #include <assert.h>
24 #include <stdlib.h>
25
26 #include "evel.h"
27 #include "evel_internal.h"
28 #include "evel_throttle.h"
29
30 /**************************************************************************//**
31  * Create a new voice quality event.
32  *
33  * @note    The mandatory fields on the Voice Quality must be supplied to this 
34  *          factory function and are immutable once set.  Optional fields have 
35  *          explicit setter functions, but again values may only be set once 
36  *          so that the Voice Quality has immutable properties.
37  * @param   calleeSideCodec         Callee codec for the call.
38  * @param   callerSideCodec         Caller codec for the call.
39  * @param   correlator              Constant across all events on this call.
40  * @param   midCallRtcp             Base64 encoding of the binary RTCP data
41  *                                  (excluding Eth/IP/UDP headers).
42  * @param   vendorVnfNameFields     Vendor, VNF and VfModule names.
43  * @returns pointer to the newly manufactured ::EVENT_VOICE_QUALITY.  If the 
44  *          event is not used (i.e. posted) it must be released using
45             ::evel_free_voice_quality.
46  * @retval  NULL  Failed to create the event.
47  *****************************************************************************/
48 EVENT_VOICE_QUALITY * evel_new_voice_quality(const char * const calleeSideCodec,
49     const char * const callerSideCodec, const char * const correlator,
50     const char * const midCallRtcp, const char * const vendorName) {
51     
52     bool inError = false;
53     EVENT_VOICE_QUALITY *voiceQuality = NULL;
54     EVEL_ENTER();
55
56     /***************************************************************************/
57     /* Check preconditions.                                                    */
58     /***************************************************************************/
59     assert(calleeSideCodec != NULL);
60     assert(callerSideCodec != NULL);
61     assert(correlator != NULL);
62     assert(midCallRtcp != NULL);
63     assert(vendorName != NULL);
64
65     /***************************************************************************/
66     /* Allocate the Voice Quality.                                                     */
67     /***************************************************************************/
68     voiceQuality = malloc(sizeof(EVENT_VOICE_QUALITY));
69     
70     if (voiceQuality == NULL)
71     {
72         log_error_state("Out of memory");
73         inError = true;
74     }
75
76     //Only in case of successful allocation initialize data.
77     if (inError == false) {
78         memset(voiceQuality, 0, sizeof(EVENT_VOICE_QUALITY));
79         EVEL_DEBUG("New Voice Quality is at %lp", voiceQuality);
80
81         /***************************************************************************/
82         /* Initialize the header & the fault fields.  Optional integer values are   */
83         /* initialized as 0.                                                        */
84         /***************************************************************************/
85         evel_init_header(&voiceQuality->header,"voiceQuality");
86         voiceQuality->header.event_domain = EVEL_DOMAIN_VOICE_QUALITY;
87         voiceQuality->major_version = EVEL_VOICEQ_MAJOR_VERSION;
88         voiceQuality->minor_version = EVEL_VOICEQ_MINOR_VERSION;
89
90         voiceQuality->calleeSideCodec = strdup(calleeSideCodec);
91         voiceQuality->callerSideCodec = strdup(callerSideCodec);
92         voiceQuality->correlator = strdup(correlator);
93         voiceQuality->midCallRtcp = strdup(midCallRtcp);
94         evel_init_vendor_field(&voiceQuality->vendorVnfNameFields, vendorName);
95         dlist_initialize(&voiceQuality->additionalInformation);
96         voiceQuality->endOfCallVqmSummaries = NULL;
97         evel_init_option_string(&voiceQuality->phoneNumber);
98     }
99
100     EVEL_EXIT();
101     return voiceQuality;
102
103 }
104
105 /**************************************************************************//**
106  * Add an additional value name/value pair to the Voice Quality.
107  *
108  * The name and value are null delimited ASCII strings.  The library takes
109  * a copy so the caller does not have to preserve values after the function
110  * returns.
111  *
112  * @param fault     Pointer to the fault.
113  * @param name      ASCIIZ string with the attribute's name.  The caller
114  *                  does not need to preserve the value once the function
115  *                  returns.
116  * @param value     ASCIIZ string with the attribute's value.  The caller
117  *                  does not need to preserve the value once the function
118  *                  returns.
119  *****************************************************************************/
120 void evel_voice_quality_addl_info_add(EVENT_VOICE_QUALITY * voiceQ, char * name, char * value) {
121     VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
122     EVEL_ENTER();
123
124     /***************************************************************************/
125     /* Check preconditions.                                                    */
126     /***************************************************************************/
127     assert(voiceQ != NULL);
128     assert(voiceQ->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
129     assert(name != NULL);
130     assert(value != NULL);
131
132     EVEL_DEBUG("Adding name=%s value=%s", name, value);
133     addlInfo = malloc(sizeof(VOICE_QUALITY_ADDL_INFO));
134     assert(addlInfo != NULL);
135     memset(addlInfo, 0, sizeof(VOICE_QUALITY_ADDL_INFO));
136     addlInfo->name = strdup(name);
137     addlInfo->value = strdup(value);
138     assert(addlInfo->name != NULL);
139     assert(addlInfo->value != NULL);
140
141     dlist_push_last(&voiceQ->additionalInformation, addlInfo);
142
143     EVEL_EXIT();
144 }
145
146 /**************************************************************************//**
147  * Set the Callee side codec for Call for domain Voice Quality
148  *
149  * @note  The property is treated as immutable: it is only valid to call
150  *        the setter once.  However, we don't assert if the caller tries to
151  *        overwrite, just ignoring the update instead.
152  *
153  * @param voiceQuality              Pointer to the Voice Quality Event.
154  * @param calleeCodecForCall        The Callee Side Codec to be set.  ASCIIZ 
155  *                                  string. The caller does not need to 
156  *                                  preserve the value once the function
157  *                                  returns.
158  *****************************************************************************/
159 void evel_voice_quality_callee_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
160     const char * const calleeCodecForCall) {
161     EVEL_ENTER();
162
163     /***************************************************************************/
164     /* Check preconditions.                                                    */
165     /***************************************************************************/
166     assert(voiceQuality != NULL);
167     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
168     assert(calleeCodecForCall != NULL);
169
170     voiceQuality->calleeSideCodec = strdup(calleeCodecForCall);
171
172     EVEL_EXIT();
173 }
174
175 /**************************************************************************//**
176  * Set the Caller side codec for Call for domain Voice Quality
177  *
178  * @note  The property is treated as immutable: it is only valid to call
179  *        the setter once.  However, we don't assert if the caller tries to
180  *        overwrite, just ignoring the update instead.
181  *
182  * @param voiceQuality              Pointer to the Voice Quality Event.
183  * @param callerCodecForCall        The Caller Side Codec to be set.  ASCIIZ 
184  *                                  string. The caller does not need to 
185  *                                  preserve the value once the function
186  *                                  returns.
187  *****************************************************************************/
188 void evel_voice_quality_caller_codec_set(EVENT_VOICE_QUALITY * voiceQuality,
189     const char * const callerCodecForCall) {
190     EVEL_ENTER();
191
192     /***************************************************************************/
193     /* Check preconditions.                                                    */
194     /***************************************************************************/
195     assert(voiceQuality != NULL);
196     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
197     assert(callerCodecForCall != NULL);
198
199     voiceQuality->calleeSideCodec = strdup(callerCodecForCall);
200
201     EVEL_EXIT();
202 }
203
204 /**************************************************************************//**
205  * Set the correlator for domain Voice Quality
206  *
207  * @note  The property is treated as immutable: it is only valid to call
208  *        the setter once.  However, we don't assert if the caller tries to
209  *        overwrite, just ignoring the update instead.
210  *
211  * @param voiceQuality              Pointer to the Voice Quality Event.
212  * @param correlator                The correlator value to be set.  ASCIIZ 
213  *                                  string. The caller does not need to 
214  *                                  preserve the value once the function
215  *                                  returns.
216  *****************************************************************************/
217 void evel_voice_quality_correlator_set(EVENT_VOICE_QUALITY * voiceQuality,
218     const char * const vCorrelator) {
219     EVEL_ENTER();
220
221     /***************************************************************************/
222     /* Check preconditions.                                                    */
223     /***************************************************************************/
224     assert(voiceQuality != NULL);
225     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
226     assert(vCorrelator != NULL);
227
228     voiceQuality->correlator = strdup(vCorrelator);
229
230     EVEL_EXIT();
231 }
232
233 /**************************************************************************//**
234  * Set the RTCP Call Data for domain Voice Quality
235  *
236  * @note  The property is treated as immutable: it is only valid to call
237  *        the setter once.  However, we don't assert if the caller tries to
238  *        overwrite, just ignoring the update instead.
239  *
240  * @param voiceQuality              Pointer to the Voice Quality Event.
241  * @param rtcpCallData              The RTCP Call Data to be set.  ASCIIZ 
242  *                                  string. The caller does not need to 
243  *                                  preserve the value once the function
244  *                                  returns.
245  *****************************************************************************/
246 void evel_voice_quality_rtcp_data_set(EVENT_VOICE_QUALITY * voiceQuality,
247     const char * const rtcpCallData) {
248     EVEL_ENTER();
249
250     /***************************************************************************/
251     /* Check preconditions.                                                    */
252     /***************************************************************************/
253     assert(voiceQuality != NULL);
254     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
255     assert(rtcpCallData != NULL);
256
257     voiceQuality->midCallRtcp = strdup(rtcpCallData);
258
259     EVEL_EXIT();
260 }
261
262 /**************************************************************************//**
263  * Set the Vendor VNF Name fields for domain Voice Quality
264  *
265  * @note  The property is treated as immutable: it is only valid to call
266  *        the setter once.  However, we don't assert if the caller tries to
267  *        overwrite, just ignoring the update instead.
268  *
269  * @param voiceQuality              Pointer to the Voice Quality Event.
270  * @param modulename                The Vendor, VNF and VfModule names to be set.   
271  *                                  ASCIIZ string. The caller does not need to 
272  *                                  preserve the value once the function
273  *                                  returns.
274  *****************************************************************************/
275 void evel_voice_quality_vnfmodule_name_set(EVENT_VOICE_QUALITY * voiceQuality,
276     const char * const module_name) {
277     EVEL_ENTER();
278
279     /***************************************************************************/
280     /* Check preconditions.                                                    */
281     /***************************************************************************/
282     assert(voiceQuality != NULL);
283     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
284     assert(module_name != NULL);
285
286     evel_vendor_field_module_set(&voiceQuality->vendorVnfNameFields, module_name);
287
288     EVEL_EXIT();
289 }
290
291 /**************************************************************************//**
292  * Set the Vendor VNF Name fields for domain Voice Quality
293  *
294  * @note  The property is treated as immutable: it is only valid to call
295  *        the setter once.  However, we don't assert if the caller tries to
296  *        overwrite, just ignoring the update instead.
297  *
298  * @param voiceQuality              Pointer to the Voice Quality Event.
299  * @param modulename                The Vendor, VNF and VfModule names to be set.   
300  *                                  ASCIIZ string. The caller does not need to 
301  *                                  preserve the value once the function
302  *                                  returns.
303  *****************************************************************************/
304 void evel_voice_quality_vnfname_set(EVENT_VOICE_QUALITY * voiceQuality,
305     const char * const vnfname) {
306     EVEL_ENTER();
307
308     /***************************************************************************/
309     /* Check preconditions.                                                    */
310     /***************************************************************************/
311     assert(voiceQuality != NULL);
312     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
313     assert(vnfname != NULL);
314
315     evel_vendor_field_vnfname_set(&voiceQuality->vendorVnfNameFields, vnfname);
316
317     EVEL_EXIT();
318 }
319
320 /**************************************************************************//**
321  * Set the Phone Number associated with the Correlator for domain Voice Quality
322  *
323  * @note  The property is treated as immutable: it is only valid to call
324  *        the setter once.  However, we don't assert if the caller tries to
325  *        overwrite, just ignoring the update instead.
326  *
327  * @param voiceQuality              Pointer to the Voice Quality Event.
328  * @param calleeCodecForCall        The Phone Number to be set.  ASCIIZ 
329  *                                  string. The caller does not need to 
330  *                                  preserve the value once the function
331  *                                  returns.
332  *****************************************************************************/
333 void evel_voice_quality_phone_number_set(EVENT_VOICE_QUALITY * voiceQuality,
334     const char * const phoneNumber) {
335     EVEL_ENTER();
336
337     /***************************************************************************/
338     /* Check preconditions.                                                    */
339     /***************************************************************************/
340     assert(voiceQuality != NULL);
341     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
342     assert(phoneNumber != NULL);
343
344     evel_set_option_string(&voiceQuality->phoneNumber, phoneNumber, "Phone_Number");
345
346     EVEL_EXIT();
347 }
348
349 /**************************************************************************//**
350  * Add an End of Call Voice Quality Metrices
351
352  * The adjacencyName and endpointDescription is null delimited ASCII string.  
353  * The library takes a copy so the caller does not have to preserve values
354  * after the function returns.
355  *
356  * @param voiceQuality     Pointer to the measurement.
357  * @param adjacencyName                     Adjacency name
358  * @param endpointDescription               Enumeration: ‘Caller’, ‘Callee’.
359  * @param endpointJitter                    Endpoint jitter
360  * @param endpointRtpOctetsDiscarded        Endpoint RTP octets discarded.
361  * @param endpointRtpOctetsReceived         Endpoint RTP octets received.
362  * @param endpointRtpOctetsSent             Endpoint RTP octets sent
363  * @param endpointRtpPacketsDiscarded       Endpoint RTP packets discarded.
364  * @param endpointRtpPacketsReceived        Endpoint RTP packets received.
365  * @param endpointRtpPacketsSent            Endpoint RTP packets sent.
366  * @param localJitter                       Local jitter.
367  * @param localRtpOctetsDiscarded           Local RTP octets discarded.
368  * @param localRtpOctetsReceived            Local RTP octets received.
369  * @param localRtpOctetsSent                Local RTP octets sent.
370  * @param localRtpPacketsDiscarded          Local RTP packets discarded.
371  * @param localRtpPacketsReceived           Local RTP packets received.
372  * @param localRtpPacketsSent               Local RTP packets sent.
373  * @param mosCqe                            Decimal range from 1 to 5
374  *                                          (1 decimal place)
375  * @param packetsLost                       No  Packets lost
376  * @param packetLossPercent                 Calculated percentage packet loss 
377  * @param rFactor                           rFactor from 0 to 100
378  * @param roundTripDelay                    Round trip delay in milliseconds
379  *****************************************************************************/
380 void evel_voice_quality_end_metrics_add(EVENT_VOICE_QUALITY * voiceQuality,
381     const char * adjacencyName, EVEL_SERVICE_ENDPOINT_DESC endpointDescription,
382     int endpointJitter,
383     int endpointRtpOctetsDiscarded,
384     int endpointRtpOctetsReceived,
385     int endpointRtpOctetsSent,
386     int endpointRtpPacketsDiscarded,
387     int endpointRtpPacketsReceived,
388     int endpointRtpPacketsSent,
389     int localJitter,
390     int localRtpOctetsDiscarded,
391     int localRtpOctetsReceived,
392     int localRtpOctetsSent,
393     int localRtpPacketsDiscarded,
394     int localRtpPacketsReceived,
395     int localRtpPacketsSent,
396     int mosCqe,
397     int packetsLost,
398     int packetLossPercent,
399     int rFactor,
400     int roundTripDelay) {
401     
402     END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL;
403     EVEL_ENTER();
404
405     /***************************************************************************/
406     /* Check assumptions.                                                      */
407     /***************************************************************************/
408     assert(voiceQuality != NULL);
409     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
410     assert(adjacencyName != NULL);
411     assert(endpointDescription >= 0);
412     assert(mosCqe >= 1 && mosCqe <= 5);
413     assert(rFactor >= 0 && rFactor <= 100);
414     assert(voiceQuality->endOfCallVqmSummaries == NULL);
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     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     /* If we've not written anything, rewind to before we opened the list.   */
525     /*************************************************************************/
526     if (!item_added)
527     {
528       evel_json_rewind(jbuf);
529     }
530   }
531
532     //endOfCallVqmSummaries
533   if( event->endOfCallVqmSummaries != NULL )
534   {
535      evel_json_open_named_object(jbuf, "endOfCallVqmSummaries");
536      vQMetrics = event->endOfCallVqmSummaries;
537      assert(vQMetrics != NULL);
538
539             if (!evel_throttle_suppress_nv_pair(jbuf->throttle_spec,
540                 "endOfCallVqmSummaries", vQMetrics->adjacencyName))
541             {
542                 evel_enc_kv_string(jbuf, "adjacencyName", vQMetrics->adjacencyName);
543                 evel_enc_kv_string(jbuf, "endpointDescription", vQMetrics->endpointDescription);
544                 evel_enc_kv_opt_int(jbuf, "endpointJitter", &vQMetrics->endpointJitter);
545                 evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsDiscarded", &vQMetrics->endpointRtpOctetsDiscarded);
546                 evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsReceived", &vQMetrics->endpointRtpOctetsReceived);
547                 evel_enc_kv_opt_int(jbuf, "endpointRtpOctetsSent", &vQMetrics->endpointRtpOctetsSent);
548                 evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsDiscarded", &vQMetrics->endpointRtpPacketsDiscarded);
549                 evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsReceived", &vQMetrics->endpointRtpPacketsReceived);
550                 evel_enc_kv_opt_int(jbuf, "endpointRtpPacketsSent", &vQMetrics->endpointRtpPacketsSent);
551                 evel_enc_kv_opt_int(jbuf, "localJitter", &vQMetrics->localJitter);
552                 evel_enc_kv_opt_int(jbuf, "localRtpOctetsDiscarded", &vQMetrics->localRtpOctetsDiscarded);
553                 evel_enc_kv_opt_int(jbuf, "localRtpOctetsReceived", &vQMetrics->localRtpOctetsReceived);
554                 evel_enc_kv_opt_int(jbuf, "localRtpOctetsSent", &vQMetrics->localRtpOctetsSent);
555                 evel_enc_kv_opt_int(jbuf, "localRtpPacketsDiscarded", &vQMetrics->localRtpPacketsDiscarded);
556                 evel_enc_kv_opt_int(jbuf, "localRtpPacketsReceived", &vQMetrics->localRtpPacketsReceived);
557                 evel_enc_kv_opt_int(jbuf, "localRtpPacketsSent", &vQMetrics->localRtpPacketsSent);
558                 evel_enc_kv_opt_int(jbuf, "mosCqe", &vQMetrics->mosCqe);
559                 evel_enc_kv_opt_int(jbuf, "packetsLost", &vQMetrics->packetsLost);
560                 evel_enc_kv_opt_int(jbuf, "packetLossPercent", &vQMetrics->packetLossPercent);
561                 evel_enc_kv_opt_int(jbuf, "rFactor", &vQMetrics->rFactor);
562                 evel_enc_kv_opt_int(jbuf, "roundTripDelay", &vQMetrics->roundTripDelay);
563
564             }
565
566     evel_json_close_object(jbuf);
567   }
568
569   evel_json_close_object(jbuf);
570
571   EVEL_EXIT();
572 }
573
574 /**************************************************************************//**
575  * Free a Voice Quality.
576  *
577  * Free off the Voce Quality supplied.  Will free all the contained allocated
578  * memory.
579  *
580  * @note It does not free the Voice Quality itself, since that may be part of a
581  * larger structure.
582  *****************************************************************************/
583 void evel_free_voice_quality(EVENT_VOICE_QUALITY * voiceQuality) {
584     END_OF_CALL_VOICE_QUALITY_METRICS * vQMetrices = NULL;
585     VOICE_QUALITY_ADDL_INFO * addlInfo = NULL;
586
587     EVEL_ENTER();
588
589     /***************************************************************************/
590     /* Check preconditions.  As an internal API we don't allow freeing NULL    */
591     /* events as we do on the public API.                                      */
592     /***************************************************************************/
593     assert(voiceQuality != NULL);
594     assert(voiceQuality->header.event_domain == EVEL_DOMAIN_VOICE_QUALITY);
595
596     /***************************************************************************/
597     /* Free all internal strings then the header itself.                       */
598     /***************************************************************************/
599     
600     //Additional Information
601     addlInfo = dlist_pop_last(&voiceQuality->additionalInformation);
602     while (addlInfo != NULL)
603     {
604         EVEL_DEBUG("Freeing Additional Info (%s, %s)",
605             addlInfo->name,
606             addlInfo->value);
607         free(addlInfo->name);
608         free(addlInfo->value);
609         free(addlInfo);
610         addlInfo = dlist_pop_last(&voiceQuality->additionalInformation);
611     }
612
613     //Summary Information
614     if(voiceQuality->endOfCallVqmSummaries != NULL)
615     {
616         vQMetrices = voiceQuality->endOfCallVqmSummaries;
617         EVEL_DEBUG("Freeing End of Call Voice Measurements Info (%s, %s)",
618             vQMetrices->adjacencyName,
619             vQMetrices->endpointDescription);
620         free(vQMetrices->adjacencyName);
621         free(vQMetrices);
622     }
623
624     //Members
625     free(voiceQuality->calleeSideCodec);
626     free(voiceQuality->callerSideCodec);
627     free(voiceQuality->correlator);
628     free(voiceQuality->midCallRtcp);
629     evel_free_option_string(&voiceQuality->phoneNumber);
630     evel_free_event_vendor_field(&voiceQuality->vendorVnfNameFields);
631
632     //header
633     evel_free_header(&voiceQuality->header);
634
635     EVEL_EXIT();
636 }
637