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