From 092b67b76c3158d6bfc0f4b8645dea87f2a210ac Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 30 Nov 2017 11:08:09 -0500 Subject: [PATCH] TT#24226 parse MOS JSON values and store in CDR sub-tables Change-Id: I02b91b03530ff29ccde70517b55475df874a8ba3 --- Makefile | 2 ++ cdr.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++--- cdr.h | 9 ++++++ debian/control | 1 + medmysql.c | 38 +++++++++++----------- 5 files changed, 114 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 2a81ee3..6d713ae 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,11 @@ CPPFLAGS := -DMEDIATOR_VERSION="\"$(VERSION)\"" GLIB_CFLAGS := $(shell pkg-config glib-2.0 --cflags) CFLAGS := -I/usr/include/mysql $(GLIB_CFLAGS) -g -Wall -O2 -D_GNU_SOURCE #CFLAGS += -DWITH_TIME_CALC +CFLAGS += $(shell pkg-config json-c --cflags) GLIB_LDFLAGS := $(shell pkg-config glib-2.0 --libs) LDFLAGS := $(GLIB_LDFLAGS) -lmysqlclient +LDFLAGS += $(shell pkg-config json-c --libs) CFILES := $(wildcard *.c) OFILES := $(CFILES:.c=.o) diff --git a/cdr.c b/cdr.c index b9dac10..ccfd220 100644 --- a/cdr.c +++ b/cdr.c @@ -1,4 +1,5 @@ #include +#include #include "cdr.h" #include "medmysql.h" @@ -580,6 +581,72 @@ static int cdr_parse_dstleg(char *dstleg, cdr_entry_t *cdr) } +static int cdr_parse_json_get_int(json_object *obj, const char *key, int *outp) { + json_object *int_obj; + if (!json_object_object_get_ex(obj, key, &int_obj)) + return 0; + if (!json_object_is_type(int_obj, json_type_int)) + return 0; + *outp = json_object_get_int64(int_obj); + return 1; +} + +static int cdr_parse_json_get_double(json_object *obj, const char *key, double *outp) { + json_object *int_obj; + if (!json_object_object_get_ex(obj, key, &int_obj)) + return 0; + if (!json_object_is_type(int_obj, json_type_double)) + return 0; + *outp = json_object_get_double(int_obj); + return 1; +} + +static int cdr_parse_bye_dstleg(char *dstleg, mos_data_t *mos_data) { + syslog(LOG_DEBUG, "Parsing JSON: '%s'", dstleg); + + json_object *json = json_tokener_parse(dstleg); + if (!json) { + syslog(LOG_ERR, "Could not parse JSON dst_leg string: '%s'", dstleg); + return -1; + } + if (!json_object_is_type(json, json_type_object)) { + syslog(LOG_ERR, "JSON type is not object: '%s'", dstleg); + goto err; + } + json_object *mos; + if (!json_object_object_get_ex(json, "mos", &mos) + || !json_object_is_type(mos, json_type_object)) + { + syslog(LOG_ERR, "JSON object does not contain 'mos' key: '%s'", dstleg); + goto err; + } + if (!cdr_parse_json_get_double(mos, "avg_score", &mos_data->avg_score)) { + syslog(LOG_ERR, "JSON object does not contain 'mos.avg_score' key: '%s'", dstleg); + goto err; + } + if (!cdr_parse_json_get_int(mos, "avg_packetloss", &mos_data->avg_packetloss)) { + syslog(LOG_ERR, "JSON object does not contain 'mos.avg_packetloss' key: '%s'", dstleg); + goto err; + } + if (!cdr_parse_json_get_int(mos, "avg_jitter", &mos_data->avg_jitter)) { + syslog(LOG_ERR, "JSON object does not contain 'mos.avg_jitter' key: '%s'", dstleg); + goto err; + } + if (!cdr_parse_json_get_int(mos, "avg_rtt", &mos_data->avg_rtt)) { + syslog(LOG_ERR, "JSON object does not contain 'mos.avg_rtt' key: '%s'", dstleg); + goto err; + } + + mos_data->filled = 1; + json_object_put(json); + return 0; + +err: + json_object_put(json); + return -1; +} + + static int cdr_create_cdrs(med_entry_t *records, uint64_t count, cdr_entry_t **cdrs, uint64_t *cdr_count, uint8_t *trash) { @@ -590,8 +657,10 @@ static int cdr_create_cdrs(med_entry_t *records, uint64_t count, char *endtime = NULL; double unix_endtime = 0, tmp_unix_endtime = 0; const char *call_status; + mos_data_t mos_data; *cdr_count = 0; + memset(&mos_data, 0, sizeof(mos_data)); /* get end time from BYE's timestamp */ @@ -602,10 +671,14 @@ static int cdr_create_cdrs(med_entry_t *records, uint64_t count, { ++invites; } - else if(e->method == MED_BYE && endtime == NULL) + else if(e->method == MED_BYE) { - endtime = e->timestamp; - unix_endtime = e->unix_timestamp; + if (endtime == NULL) { + endtime = e->timestamp; + unix_endtime = e->unix_timestamp; + } + if (!mos_data.filled) + cdr_parse_bye_dstleg(e->dst_leg, &mos_data); } if (check_shutdown()) @@ -638,8 +711,11 @@ static int cdr_create_cdrs(med_entry_t *records, uint64_t count, cdr = &(*cdrs)[cdr_index]; e = &(records[i]); + if (!e->valid) + continue; + call_status = cdr_map_status(e->sip_code); - if(e->valid && e->method == MED_INVITE && call_status != NULL) + if(e->method == MED_INVITE && call_status != NULL) { ++cdr_index; @@ -684,6 +760,8 @@ static int cdr_create_cdrs(med_entry_t *records, uint64_t count, { // TODO: error handling } + + cdr->mos = mos_data; } if (check_shutdown()) diff --git a/cdr.h b/cdr.h index 5ece8e0..02428ec 100644 --- a/cdr.h +++ b/cdr.h @@ -16,6 +16,14 @@ struct medmysql_batches; +typedef struct { + int filled; + double avg_score; + int avg_packetloss; + int avg_jitter; + int avg_rtt; +} mos_data_t; + typedef struct { char call_id[128]; @@ -70,6 +78,7 @@ typedef struct { uint8_t split; + mos_data_t mos; } cdr_entry_t; int cdr_process_records(med_entry_t *records, uint64_t count, uint64_t *cdr_count, struct medmysql_batches *); diff --git a/debian/control b/debian/control index feecaea..963ebec 100644 --- a/debian/control +++ b/debian/control @@ -6,6 +6,7 @@ Build-Depends: debhelper (>= 10), default-libmysqlclient-dev | libmysqlclient15-dev, libglib2.0-dev, + libjson-c-dev, Standards-Version: 3.9.8 Homepage: https://www.sipwise.com/ diff --git a/medmysql.c b/medmysql.c index 54b20e9..ebaa341 100644 --- a/medmysql.c +++ b/medmysql.c @@ -639,20 +639,20 @@ int medmysql_delete_entries(const char *callid, struct medmysql_batches *batches #define CDRESCAPE(x) batches->cdrs.len += mysql_real_escape_string(med_handler->m, batches->cdrs.str + batches->cdrs.len, x, strlen(x)) /**********************************************************************/ -static int medmysql_tag_record(GQueue *q, unsigned long cdr_id, unsigned long provider_id, - unsigned long direction_id, const char *value, double start_time, unsigned long tag_id) -{ - cdr_tag_record *record = malloc(sizeof(*record)); - record->cdr_id = cdr_id; - if (asprintf(&record->sql_record, "%lu, %lu, %lu, '%s', %f", - provider_id, direction_id, tag_id, value, start_time) <= 0) - { - free(record); - return -1; - } - g_queue_push_tail(q, record); - return 0; -} +// static int medmysql_tag_record(GQueue *q, unsigned long cdr_id, unsigned long provider_id, +// unsigned long direction_id, const char *value, double start_time, unsigned long tag_id) +// { +// cdr_tag_record *record = malloc(sizeof(*record)); +// record->cdr_id = cdr_id; +// if (asprintf(&record->sql_record, "%lu, %lu, %lu, '%s', %f", +// provider_id, direction_id, tag_id, value, start_time) <= 0) +// { +// free(record); +// return -1; +// } +// g_queue_push_tail(q, record); +// return 0; +// } static int medmysql_mos_record(GQueue *q, unsigned long cdr_id, double avg_score, int avg_packetloss, int avg_jitter, int avg_rtt, double start_time) { @@ -853,10 +853,12 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, uint64_t count, struct medmysql_b // if (medmysql_tag_record(&batches->cdr_tags, batches->num_cdrs, medmysql_tag_provider_reseller, // medmysql_tag_direction_destination, "fdfhgs", e->start_time, 1)) // return -1; -// if (medmysql_mos_record(&batches->cdr_mos, batches->num_cdrs, e->mos.avg_score, -// e->mos.avg_packetloss, e->mos.avg_jitter, e->mos.avg_rtt, -// e->start_time)) -// return -1; + if (e->mos.filled) { + if (medmysql_mos_record(&batches->cdr_mos, batches->num_cdrs, e->mos.avg_score, + e->mos.avg_packetloss, e->mos.avg_jitter, e->mos.avg_rtt, + e->start_time)) + return -1; + } batches->num_cdrs++;