aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/ndpiReader.c6
-rw-r--r--src/include/ndpi_api.h.in32
-rw-r--r--src/include/ndpi_typedefs.h1
-rw-r--r--src/lib/Makefile.in2
-rw-r--r--src/lib/ndpi_serializer.c121
-rw-r--r--tests/unit/unit.c46
6 files changed, 191 insertions, 17 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index 0ef7cd9eb..68151c939 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -1678,9 +1678,9 @@ static void printFlowSerialized(u_int16_t thread_id,
float data_ratio = ndpi_data_ratio(flow->src2dst_bytes, flow->dst2src_bytes);
ndpi_serialize_string_uint32(serializer, "flow_id", flow->flow_id);
- ndpi_serialize_string_float(serializer, "first_seen_ms", f, "%.3f");
- ndpi_serialize_string_float(serializer, "last_seen_ms", l, "%.3f");
- ndpi_serialize_string_float(serializer, "duration_ms", (l-f)/1000.0, "%.3f");
+ ndpi_serialize_string_double(serializer, "first_seen", f / 1000., "%.3f");
+ ndpi_serialize_string_double(serializer, "last_seen", l / 1000., "%.3f");
+ ndpi_serialize_string_double(serializer, "duration", (l-f)/1000.0, "%.3f");
ndpi_serialize_string_uint32(serializer, "vlan_id", flow->vlan_id);
ndpi_serialize_string_uint32(serializer, "bidirectional", flow->bidirectional);
diff --git a/src/include/ndpi_api.h.in b/src/include/ndpi_api.h.in
index 2e8690203..3a81cceb3 100644
--- a/src/include/ndpi_api.h.in
+++ b/src/include/ndpi_api.h.in
@@ -1230,6 +1230,16 @@ extern "C" {
int ndpi_serialize_uint32_float(ndpi_serializer *serializer, u_int32_t key, float value, const char *format /* e.f. "%.2f" */);
/**
+ * Serialize a 32-bit unsigned int key and a double value
+ * @param serializer The serializer handle
+ * @param key The field name or ID
+ * @param value The field value
+ * @param format The double value format
+ * @return 0 on success, a negative number otherwise
+ */
+ int ndpi_serialize_uint32_double(ndpi_serializer *serializer, u_int32_t key, double value, const char *format /* e.f. "%.2f" */);
+
+ /**
* Serialize a 32-bit unsigned int key and a string value
* @param serializer The serializer handle
* @param key The field name or ID
@@ -1396,6 +1406,17 @@ extern "C" {
int ndpi_serialize_binary_float(ndpi_serializer *_serializer, const char *key, u_int16_t klen, float value, const char *format /* e.f. "%.2f" */);
/**
+ * Serialize an unterminated string key and a double value
+ * @param serializer The serializer handle
+ * @param key The field name or ID
+ * @param klen The key length
+ * @param value The field value
+ * @param format The double format
+ * @return 0 on success, a negative number otherwise
+ */
+ int ndpi_serialize_binary_double(ndpi_serializer *_serializer, const char *key, u_int16_t klen, double value, const char *format /* e.f. "%.2f" */);
+
+ /**
* Serialize a string key and a a float value
* @param serializer The serializer handle
* @param key The field name or ID
@@ -1406,6 +1427,16 @@ extern "C" {
int ndpi_serialize_string_float(ndpi_serializer *serializer, const char *key, float value, const char *format /* e.f. "%.2f" */);
/**
+ * Serialize a string key and a a double value
+ * @param serializer The serializer handle
+ * @param key The field name or ID
+ * @param value The field value
+ * @param format The double format
+ * @return 0 on success, a negative number otherwise
+ */
+ int ndpi_serialize_string_double(ndpi_serializer *serializer, const char *key, double value, const char *format /* e.f. "%.2f" */);
+
+ /**
* Serialize an unterminated string key and a boolean value (JSON/CSV only, not supported by TLV)
* @param serializer The serializer handle
* @param key The field name or ID
@@ -1586,6 +1617,7 @@ extern "C" {
int ndpi_deserialize_value_int32(ndpi_deserializer *deserializer, int32_t *value);
int ndpi_deserialize_value_int64(ndpi_deserializer *deserializer, int64_t *value);
int ndpi_deserialize_value_float(ndpi_deserializer *deserializer, float *value);
+ int ndpi_deserialize_value_double(ndpi_deserializer *deserializer, double *value);
int ndpi_deserialize_value_string(ndpi_deserializer *deserializer, ndpi_string *value);
int ndpi_deserialize_clone_item(ndpi_deserializer *deserializer, ndpi_serializer *serializer);
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 502c7fe12..377ed0e2e 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -1618,6 +1618,7 @@ typedef enum {
ndpi_serialization_int32,
ndpi_serialization_int64,
ndpi_serialization_float,
+ ndpi_serialization_double,
ndpi_serialization_string,
ndpi_serialization_start_of_block,
ndpi_serialization_end_of_block,
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
index 201c49420..b6db5330e 100644
--- a/src/lib/Makefile.in
+++ b/src/lib/Makefile.in
@@ -61,7 +61,7 @@ $(NDPI_LIB_STATIC): $(OBJECTS)
$(RANLIB) $@
$(NDPI_LIB_SHARED): $(OBJECTS)
- $(CC) -shared -fPIC $(SONAME_FLAG) -o $@ $(LDFLAGS) $(OBJECTS) $(LIBS)
+ $(CC) -shared -fPIC $(CFLAGS) $(SONAME_FLAG) -o $@ $(LDFLAGS) $(OBJECTS) $(LIBS)
ln -fs $(NDPI_LIB_SHARED) $(NDPI_LIB_SHARED_BASE)
ln -fs $(NDPI_LIB_SHARED) $(NDPI_LIB_SHARED_BASE).$(NDPI_VERSION_MAJOR)
diff --git a/src/lib/ndpi_serializer.c b/src/lib/ndpi_serializer.c
index 7843ace60..e51a168d0 100644
--- a/src/lib/ndpi_serializer.c
+++ b/src/lib/ndpi_serializer.c
@@ -492,6 +492,15 @@ static inline void ndpi_serialize_single_float(ndpi_private_serializer *serializ
/* ********************************** */
+/* TODO: fix portability across platforms */
+static inline void ndpi_serialize_single_double(ndpi_private_serializer *serializer,
+ double s) {
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &s, sizeof(s));
+ serializer->status.buffer.size_used += sizeof(double);
+}
+
+/* ********************************** */
+
static inline void ndpi_serialize_single_string(ndpi_private_serializer *serializer,
const char *s, u_int16_t slen) {
u_int16_t l = htons(slen);
@@ -571,6 +580,14 @@ static inline void ndpi_deserialize_single_float(ndpi_private_deserializer *dese
/* ********************************** */
+/* TODO: fix portability across platforms */
+static inline void ndpi_deserialize_single_double(ndpi_private_deserializer *deserializer,
+ u_int32_t offset, double *s) {
+ *s = *(double*)&deserializer->buffer.data[offset];
+}
+
+/* ********************************** */
+
static inline void ndpi_deserialize_single_string(ndpi_private_deserializer *deserializer,
u_int32_t offset, ndpi_string *v) {
v->str_len = ntohs(*((u_int16_t *) &deserializer->buffer.data[offset]));
@@ -1633,6 +1650,62 @@ int ndpi_serialize_binary_float(ndpi_serializer *_serializer,
/* ********************************** */
+int ndpi_serialize_binary_double(ndpi_serializer *_serializer,
+ const char *key,
+ u_int16_t klen,
+ double value,
+ const char *format /* e.f. "%.2f" */) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ u_int32_t needed;
+
+ needed =
+ sizeof(u_int8_t) /* type */ +
+ sizeof(u_int16_t) /* key len */ +
+ klen /* key */ +
+ sizeof(double);
+
+ if(serializer->fmt == ndpi_serialization_format_json)
+ needed += 32 + klen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ ndpi_serialize_json_pre(_serializer);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ serializer->buffer.data[serializer->status.buffer.size_used] = ':';
+ serializer->status.buffer.size_used++;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += ndpi_snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
+
+ ndpi_serialize_json_post(_serializer);
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
+ ndpi_serialize_csv_pre(serializer);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->status.buffer.size_used += ndpi_snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
+ } else {
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_double;
+
+ ndpi_serialize_single_string(serializer, key, klen);
+ ndpi_serialize_single_double(serializer, value);
+ }
+
+ serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
+ return(0);
+}
+
+/* ********************************** */
+
int ndpi_serialize_string_float(ndpi_serializer *_serializer,
const char *key,
float value,
@@ -1642,6 +1715,16 @@ int ndpi_serialize_string_float(ndpi_serializer *_serializer,
/* ********************************** */
+int ndpi_serialize_string_double(ndpi_serializer *_serializer,
+ const char *key,
+ double value,
+ const char *format /* e.f. "%.2f" */)
+{
+ return(ndpi_serialize_binary_double(_serializer, key, strlen(key), value, format));
+}
+
+/* ********************************** */
+
/* Key is a <string, len> pair, value is a raw value */
static int ndpi_serialize_binary_raw(ndpi_serializer *_serializer,
const char *key,
@@ -1684,7 +1767,6 @@ static int ndpi_serialize_binary_raw(ndpi_serializer *_serializer,
serializer->status.buffer.size_used += ndpi_json_string_escape(value, vlen,
(char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
else {
- //serializer->status.buffer.size_used += ndpi_snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, value, vlen);
memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], value, vlen);
serializer->status.buffer.size_used += vlen;
}
@@ -1694,9 +1776,6 @@ static int ndpi_serialize_binary_raw(ndpi_serializer *_serializer,
if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
ndpi_serialize_csv_pre(serializer);
buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
-
- //serializer->status.buffer.size_used += ndpi_snprintf((char *)
- // &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%s", value);
memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], value, vlen);
serializer->status.buffer.size_used += vlen;
@@ -2210,6 +2289,9 @@ static inline int ndpi_deserialize_get_single_size(ndpi_private_deserializer *de
case ndpi_serialization_float:
size = sizeof(float);
break;
+ case ndpi_serialization_double:
+ size = sizeof(double);
+ break;
case ndpi_serialization_string:
case ndpi_serialization_start_of_block:
case ndpi_serialization_start_of_list:
@@ -2528,6 +2610,37 @@ int ndpi_deserialize_value_float(ndpi_deserializer *_deserializer,
/* ********************************** */
+int ndpi_deserialize_value_double(ndpi_deserializer *_deserializer,
+ double *value) {
+ ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
+ ndpi_serialization_type kt, et;
+ u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
+ u_int16_t expected;
+ int size;
+
+ expected = sizeof(u_int8_t) /* type */;
+ if(buff_diff < expected) return(-2);
+
+ kt = ndpi_deserialize_get_key_subtype(deserializer);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
+ if(size < 0) return(-2);
+
+ expected += size;
+
+ et = ndpi_deserialize_get_value_subtype(deserializer);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
+ if(size < 0) return(-2);
+
+ if(et != ndpi_serialization_double)
+ return(-1);
+
+ ndpi_deserialize_single_double(deserializer, deserializer->status.buffer.size_used + expected, value);
+
+ return(0);
+}
+
+/* ********************************** */
+
/* Return the string value for the current element */
int ndpi_deserialize_value_string(ndpi_deserializer *_deserializer,
ndpi_string *value) {
diff --git a/tests/unit/unit.c b/tests/unit/unit.c
index 13de97a1f..1620daab3 100644
--- a/tests/unit/unit.c
+++ b/tests/unit/unit.c
@@ -62,6 +62,7 @@ static int verbose = 0;
/* *********************************************** */
+#define FLT_MAX 3.402823466e+38F
int serializerUnitTest() {
ndpi_serializer serializer, deserializer;
int i, loop_id;
@@ -99,6 +100,7 @@ int serializerUnitTest() {
assert(ndpi_serialize_string_string(&serializer, kbuf, vbuf) != -1);
assert(ndpi_serialize_string_uint32(&serializer, kbuf, i*i) != -1);
assert(ndpi_serialize_string_float(&serializer, kbuf, (float)(i*i), "%f") != -1);
+ assert(ndpi_serialize_string_double(&serializer, kbuf, ((double)(FLT_MAX))*2, "%lf") != -1);
assert(ndpi_serialize_string_int64(&serializer, kbuf, INT64_MAX) != -1);
if ((i&0x3) == 0x3) ndpi_serialize_end_of_record(&serializer);
}
@@ -126,7 +128,8 @@ int serializerUnitTest() {
jerr = json_tokener_success;
j = json_tokener_parse_verbose(buffer, &jerr);
if (j == NULL) {
- printf("%s: ERROR (json validation failed)\n", __FUNCTION__);
+ printf("%s: ERROR (json validation failed: `%s')\n",
+ __FUNCTION__, json_tokener_error_desc(jerr));
return -1;
} else {
/* Validation ok */
@@ -165,6 +168,7 @@ int serializerUnitTest() {
int64_t v64;
ndpi_string ks, vs;
float vf;
+ double vd;
switch(kt) {
case ndpi_serialization_uint32:
@@ -211,6 +215,11 @@ int serializerUnitTest() {
if(verbose) printf("%f\n", vf);
break;
+ case ndpi_serialization_double:
+ assert(ndpi_deserialize_value_double(&deserializer, &vd) != -1);
+ if(verbose) printf("%lf\n", vd);
+ break;
+
default:
if (verbose) printf("\n");
printf("%s: ERROR (unsupported type %u detected)\n", __FUNCTION__, et);
@@ -267,12 +276,15 @@ int serializeProtoUnitTest(void)
NDPI_SET_BIT(risks, NDPI_TLS_OBSOLETE_VERSION);
NDPI_SET_BIT(risks, NDPI_TLS_SELFSIGNED_CERTIFICATE);
ndpi_serialize_proto(ndpi_info_mod, &serializer, risks, NDPI_CONFIDENCE_DPI, ndpi_proto);
+ assert(ndpi_serialize_string_float(&serializer, "float", FLT_MAX, "%f") != -1);
+ assert(ndpi_serialize_string_double(&serializer, "double", ((double)(FLT_MAX))*2, "%lf") != -1);
if (fmt == ndpi_serialization_format_json)
{
buffer_len = 0;
buffer = ndpi_serializer_get_buffer(&serializer, &buffer_len);
- char const * const expected_json_str = "{\"ndpi\": {\"flow_risk\": {\"6\": {\"risk\":\"Self-signed Cert\",\"severity\":\"High\",\"risk_score\": {\"total\":500,\"client\":450,\"server\":50}},\"7\": {\"risk\":\"Obsolete TLS (v1.1 or older)\",\"severity\":\"High\",\"risk_score\": {\"total\":510,\"client\":455,\"server\":55}},\"8\": {\"risk\":\"Weak TLS Cipher\",\"severity\":\"High\",\"risk_score\": {\"total\":250,\"client\":225,\"server\":25}},\"17\": {\"risk\":\"Malformed Packet\",\"severity\":\"Low\",\"risk_score\": {\"total\":260,\"client\":130,\"server\":130}}},\"confidence\": {\"6\":\"DPI\"},\"proto\":\"TLS.Facebook\",\"proto_id\":\"91.119\",\"encrypted\":1,\"breed\":\"Fun\",\"category_id\":6,\"category\":\"SocialNetwork\"}}";
+#ifndef WIN32
+ char const * const expected_json_str = "{\"ndpi\": {\"flow_risk\": {\"6\": {\"risk\":\"Self-signed Cert\",\"severity\":\"High\",\"risk_score\": {\"total\":500,\"client\":450,\"server\":50}},\"7\": {\"risk\":\"Obsolete TLS (v1.1 or older)\",\"severity\":\"High\",\"risk_score\": {\"total\":510,\"client\":455,\"server\":55}},\"8\": {\"risk\":\"Weak TLS Cipher\",\"severity\":\"High\",\"risk_score\": {\"total\":250,\"client\":225,\"server\":25}},\"17\": {\"risk\":\"Malformed Packet\",\"severity\":\"Low\",\"risk_score\": {\"total\":260,\"client\":130,\"server\":130}}},\"confidence\": {\"6\":\"DPI\"},\"proto\":\"TLS.Facebook\",\"proto_id\":\"91.119\",\"encrypted\":1,\"breed\":\"Fun\",\"category_id\":6,\"category\":\"SocialNetwork\"},\"float\":340282346638528859811704183484516925440.000000,\"double\":680564693277057719623408366969033850880.000000}";
if (strncmp(buffer, expected_json_str, buffer_len) != 0)
{
@@ -280,6 +292,7 @@ int serializeProtoUnitTest(void)
printf("%s: ERROR: got JSON str: \"%.*s\"\n", __FUNCTION__, (int)buffer_len, buffer);
return -1;
}
+#endif
if(verbose)
printf("%s\n", buffer);
@@ -288,7 +301,8 @@ int serializeProtoUnitTest(void)
enum json_tokener_error jerr = json_tokener_success;
json_object * const j = json_tokener_parse_verbose(buffer, &jerr);
if (j == NULL) {
- printf("%s: ERROR (json validation failed)\n", __FUNCTION__);
+ printf("%s: ERROR (json validation failed: `%s')\n",
+ __FUNCTION__, json_tokener_error_desc(jerr));
return -1;
} else {
/* Validation ok */
@@ -296,14 +310,28 @@ int serializeProtoUnitTest(void)
}
} else if (fmt == ndpi_serialization_format_csv)
{
- if(verbose) {
- buffer_len = 0;
- buffer = ndpi_serializer_get_header(&serializer, &buffer_len);
+ char const * const expected_csv_hdr_str = "risk,severity,total,client,server,risk,severity,total,client,server,risk,severity,total,client,server,risk,severity,total,client,server,6,proto,proto_id,encrypted,breed,category_id,category,float,double";
+ buffer_len = 0;
+ buffer = ndpi_serializer_get_header(&serializer, &buffer_len);
+ assert(buffer != NULL && buffer_len != 0);
+ if (verbose)
printf("%s\n", buffer);
+ if (strncmp(buffer, expected_csv_hdr_str, buffer_len) != 0)
+ {
+ printf("%s: ERROR: expected CSV str: \"%s\"\n", __FUNCTION__, expected_csv_hdr_str);
+ printf("%s: ERROR: got CSV str: \"%.*s\"\n", __FUNCTION__, (int)buffer_len, buffer);
+ }
- buffer_len = 0;
- buffer = ndpi_serializer_get_buffer(&serializer, &buffer_len);
- printf("%s\n", buffer);
+ char const * const expected_csv_buf_str = "Self-signed Cert,High,500,450,50,Obsolete TLS (v1.1 or older),High,510,455,55,Weak TLS Cipher,High,250,225,25,Malformed Packet,Low,260,130,130,DPI,TLS.Facebook,91.119,1,Fun,6,SocialNetwork,340282346638528859811704183484516925440.000000,680564693277057719623408366969033850880.000000";
+ buffer_len = 0;
+ buffer = ndpi_serializer_get_buffer(&serializer, &buffer_len);
+ assert(buffer != NULL && buffer_len != 0);
+ if (verbose)
+ printf("%s\n", buffer);
+ if (strncmp(buffer, expected_csv_buf_str, buffer_len) != 0)
+ {
+ printf("%s: ERROR: expected CSV str: \"%s\"\n", __FUNCTION__, expected_csv_buf_str);
+ printf("%s: ERROR: got CSV str: \"%.*s\"\n", __FUNCTION__, (int)buffer_len, buffer);
}
}