summaryrefslogtreecommitdiff
path: root/util_pkt_logger
diff options
context:
space:
mode:
Diffstat (limited to 'util_pkt_logger')
-rw-r--r--util_pkt_logger/Makefile82
-rw-r--r--util_pkt_logger/cfg/global_conf.cn470.json51
-rw-r--r--util_pkt_logger/cfg/global_conf.empty.json66
-rw-r--r--util_pkt_logger/cfg/global_conf.eu433.json35
-rw-r--r--util_pkt_logger/cfg/global_conf.eu868.json45
-rw-r--r--util_pkt_logger/cfg/global_conf.us915.json46
-rw-r--r--util_pkt_logger/inc/parson.h111
-rw-r--r--util_pkt_logger/local_conf.json5
-rw-r--r--util_pkt_logger/obj/.gitkeep0
-rw-r--r--util_pkt_logger/readme.md143
-rw-r--r--util_pkt_logger/src/parson.c782
-rw-r--r--util_pkt_logger/src/util_pkt_logger.c570
12 files changed, 1936 insertions, 0 deletions
diff --git a/util_pkt_logger/Makefile b/util_pkt_logger/Makefile
new file mode 100644
index 0000000..2c99dde
--- /dev/null
+++ b/util_pkt_logger/Makefile
@@ -0,0 +1,82 @@
+### Application-specific constants
+
+APP_NAME := util_pkt_logger
+
+### Environment constants
+
+LGW_PATH := ../libloragw
+CROSS_COMPILE :=
+
+### External constant definitions
+# must get library build option to know if mpsse must be linked or not
+
+include $(LGW_PATH)/library.cfg
+
+### Constant symbols
+
+CC := $(CROSS_COMPILE)gcc
+AR := $(CROSS_COMPILE)ar
+
+CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I.
+
+### Constants for LoRa concentrator HAL library
+# List the library sub-modules that are used by the application
+
+LGW_INC = $(LGW_PATH)/inc/config.h
+LGW_INC += $(LGW_PATH)/inc/loragw_hal.h
+
+### Linking options
+
+ifeq ($(CFG_SPI),native)
+ LIBS := -lloragw -lrt
+else ifeq ($(CFG_SPI),ftdi)
+ LIBS := -lloragw -lrt -lmpsse
+endif
+
+### General build targets
+
+all: $(APP_NAME) global_conf.json
+
+clean:
+ rm -f obj/*.o
+ rm -f $(APP_NAME)
+ find . -name global_conf.json -exec rm -i {} \;
+
+### HAL library
+
+$(LGW_PATH)/libloragw.a: $(LGW_INC)
+ $(MAKE) all -C $(LGW_PATH)
+
+### Sub-modules compilation
+
+obj/parson.o: src/parson.c inc/parson.h
+ $(CC) -c $(CFLAGS) $< -o $@
+
+### Select the proper configuration JSON for the program
+
+ifeq ($(CFG_BAND),eu868)
+global_conf.json: cfg/global_conf.eu868.json
+ cp $< $@
+else ifeq ($(CFG_BAND),us915)
+global_conf.json: cfg/global_conf.us915.json
+ cp $< $@
+else ifeq ($(CFG_BAND),cn470)
+global_conf.json: cfg/global_conf.cn470.json
+ cp $< $@
+else ifeq ($(CFG_BAND),eu433)
+global_conf.json: cfg/global_conf.eu433.json
+ cp $< $@
+else
+global_conf.json: cfg/global_conf.empty.json
+ cp $< $@
+endif
+
+### Main program compilation and assembly
+
+obj/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) inc/parson.h
+ $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@
+
+$(APP_NAME): obj/$(APP_NAME).o $(LGW_PATH)/libloragw.a obj/parson.o
+ $(CC) -L$(LGW_PATH) $< obj/parson.o -o $@ $(LIBS)
+
+### EOF \ No newline at end of file
diff --git a/util_pkt_logger/cfg/global_conf.cn470.json b/util_pkt_logger/cfg/global_conf.cn470.json
new file mode 100644
index 0000000..26c7e63
--- /dev/null
+++ b/util_pkt_logger/cfg/global_conf.cn470.json
@@ -0,0 +1,51 @@
+{
+ "SX1301_conf": {
+ "radio_0": {
+ "enable": true,
+ "freq": 471500000
+ },
+ "chan_multiSF_0": {
+ /* LoRa MAC channel, 125kHz, all SF, 471.1 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": -400000
+ },
+ "chan_multiSF_1": {
+ /* LoRa MAC channel, 125kHz, all SF, 471.3 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": -200000
+ },
+ "chan_multiSF_2": {
+ /* LoRa MAC channel, 125kHz, all SF, 471.5 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_3": {
+ /* LoRa MAC channel, 125kHz, all SF, 471.7 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 200000
+ },
+ "chan_Lora_std": {
+ /* LoRa MAC channel, 125kHz, SF7, 471.9 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 400000,
+ "bandwidth": 125000,
+ "spread_factor": 7
+ },
+ "chan_FSK": {
+ /* FSK 64kbps channel, 471.9 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 400000,
+ "bandwidth": 200000,
+ "datarate": 64000
+ }
+ },
+ "gateway_conf": {
+ "gateway_ID": "AA555A0000000000"
+ }
+}
diff --git a/util_pkt_logger/cfg/global_conf.empty.json b/util_pkt_logger/cfg/global_conf.empty.json
new file mode 100644
index 0000000..697e161
--- /dev/null
+++ b/util_pkt_logger/cfg/global_conf.empty.json
@@ -0,0 +1,66 @@
+{
+ "SX1301_conf": {
+ "radio_0": {
+ "enable": false,
+ "freq": 0
+ },
+ "chan_multiSF_0": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_1": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_2": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_3": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_4": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_5": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_6": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_multiSF_7": {
+ "enable": false,
+ "radio": 0,
+ "if": 0
+ },
+ "chan_Lora_std": {
+ "enable": false,
+ "radio": 0,
+ "if": 0,
+ "bandwidth": 250000,
+ "spread_factor": 7
+ },
+
+ "chan_FSK": {
+ "enable": false,
+ "radio": 0,
+ "if": 100000,
+ "bandwidth": 250000,
+ "datarate": 100000
+ }
+ },
+ "gateway_conf": {
+ "gateway_ID": "AA555A0000000000"
+ }
+}
diff --git a/util_pkt_logger/cfg/global_conf.eu433.json b/util_pkt_logger/cfg/global_conf.eu433.json
new file mode 100644
index 0000000..9988809
--- /dev/null
+++ b/util_pkt_logger/cfg/global_conf.eu433.json
@@ -0,0 +1,35 @@
+{
+ "SX1301_conf": {
+ "radio_0": {
+ "enable": true,
+ "freq": 433500000
+ },
+ "chan_multiSF_0": {
+ /* LoRa MAC channel, 125kHz, all SF, 433.2 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": -300000
+ },
+ "chan_multiSF_1": {
+ /* LoRa MAC channel, 125kHz, all SF, 433.4 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": -100000
+ },
+ "chan_multiSF_2": {
+ /* LoRa MAC channel, 125kHz, all SF, 433.6 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 100000
+ },
+ "chan_multiSF_3": {
+ /* LoRa MAC channel, 125kHz, all SF, 433.8 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 300000
+ }
+ },
+ "gateway_conf": {
+ "gateway_ID": "AA555A0000000000"
+ }
+}
diff --git a/util_pkt_logger/cfg/global_conf.eu868.json b/util_pkt_logger/cfg/global_conf.eu868.json
new file mode 100644
index 0000000..2d7ae96
--- /dev/null
+++ b/util_pkt_logger/cfg/global_conf.eu868.json
@@ -0,0 +1,45 @@
+{
+ "SX1301_conf": {
+ "radio_0": {
+ "enable": true,
+ "freq": 868200000
+ },
+ "chan_multiSF_0": {
+ /* LoRa MAC channel, 125kHz, all SF, 868.1 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": -100000
+ },
+ "chan_multiSF_1": {
+ /* LoRa MAC channel, 125kHz, all SF, 868.3 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 100000
+ },
+ "chan_multiSF_2": {
+ /* LoRa MAC channel, 125kHz, all SF, 868.5 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 300000
+ },
+ "chan_Lora_std": {
+ /* LoRa MAC channel, 250kHz, SF7, 868.3 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 100000,
+ "bandwidth": 250000,
+ "spread_factor": 7
+ },
+ "chan_FSK": {
+ /* FSK 100kbps channel, 868.3 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 100000,
+ "bandwidth": 250000,
+ "datarate": 100000
+ }
+ },
+ "gateway_conf": {
+ "gateway_ID": "AA555A0000000000"
+ }
+}
diff --git a/util_pkt_logger/cfg/global_conf.us915.json b/util_pkt_logger/cfg/global_conf.us915.json
new file mode 100644
index 0000000..c57c536
--- /dev/null
+++ b/util_pkt_logger/cfg/global_conf.us915.json
@@ -0,0 +1,46 @@
+{
+ "SX1301_conf": {
+ "radio_0": {
+ "enable": true,
+ "freq": 927000000
+ },
+ "chan_multiSF_0": {
+ /* LoRa MAC channel, 125kHz, all SF, 926.7 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": -300000
+ },
+ "chan_multiSF_1": {
+ /* LoRa MAC channel, 125kHz, all SF, 926.9 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": -100000
+ },
+ "chan_multiSF_2": {
+ /* LoRa MAC channel, 125kHz, all SF, 927.1 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 100000
+ },
+ "chan_Lora_std": {
+ /* LoRa MAC channel, 250kHz, SF7, 927.3 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 300000,
+ "bandwidth": 250000,
+ "spread_factor": 7
+ },
+
+ "chan_FSK": {
+ /* FSK 100kbps channel, 927.3 MHz */
+ "enable": true,
+ "radio": 0,
+ "if": 300000,
+ "bandwidth": 250000,
+ "datarate": 100000
+ }
+ },
+ "gateway_conf": {
+ "gateway_ID": "AA555A0000000000"
+ }
+}
diff --git a/util_pkt_logger/inc/parson.h b/util_pkt_logger/inc/parson.h
new file mode 100644
index 0000000..ef21890
--- /dev/null
+++ b/util_pkt_logger/inc/parson.h
@@ -0,0 +1,111 @@
+/*
+ Parson ( http://kgabis.github.com/parson/ )
+ Copyright (c) 2013 Krzysztof Gabis
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef parson_parson_h
+#define parson_parson_h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stddef.h> /* size_t */
+
+#define PARSON_VERSION 20131130
+
+/* Types and enums */
+typedef struct json_object_t JSON_Object;
+typedef struct json_array_t JSON_Array;
+typedef struct json_value_t JSON_Value;
+
+typedef enum json_value_type {
+ JSONError = 0,
+ JSONNull = 1,
+ JSONString = 2,
+ JSONNumber = 3,
+ JSONObject = 4,
+ JSONArray = 5,
+ JSONBoolean = 6
+} JSON_Value_Type;
+
+
+/* Parses first JSON value in a file, returns NULL in case of error */
+JSON_Value * json_parse_file(const char *filename);
+
+/* Parses first JSON value in a file and ignores comments (/ * * / and //),
+ returns NULL in case of error */
+JSON_Value * json_parse_file_with_comments(const char *filename);
+
+/* Parses first JSON value in a string, returns NULL in case of error */
+JSON_Value * json_parse_string(const char *string);
+
+/* Parses first JSON value in a string and ignores comments (/ * * / and //),
+ returns NULL in case of error */
+JSON_Value * json_parse_string_with_comments(const char *string);
+
+/* JSON Object */
+JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
+const char * json_object_get_string (const JSON_Object *object, const char *name);
+JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
+JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
+double json_object_get_number (const JSON_Object *object, const char *name);
+int json_object_get_boolean(const JSON_Object *object, const char *name);
+
+/* dotget functions enable addressing values with dot notation in nested objects,
+ just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
+ Because valid names in JSON can contain dots, some values may be inaccessible
+ this way. */
+JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
+const char * json_object_dotget_string (const JSON_Object *object, const char *name);
+JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
+JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
+double json_object_dotget_number (const JSON_Object *object, const char *name);
+int json_object_dotget_boolean(const JSON_Object *object, const char *name);
+
+/* Functions to get available names */
+size_t json_object_get_count(const JSON_Object *object);
+const char * json_object_get_name (const JSON_Object *object, size_t index);
+
+/* JSON Array */
+JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
+const char * json_array_get_string (const JSON_Array *array, size_t index);
+JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
+JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
+double json_array_get_number (const JSON_Array *array, size_t index);
+int json_array_get_boolean(const JSON_Array *array, size_t index);
+size_t json_array_get_count (const JSON_Array *array);
+
+/* JSON Value */
+JSON_Value_Type json_value_get_type (const JSON_Value *value);
+JSON_Object * json_value_get_object (const JSON_Value *value);
+JSON_Array * json_value_get_array (const JSON_Value *value);
+const char * json_value_get_string (const JSON_Value *value);
+double json_value_get_number (const JSON_Value *value);
+int json_value_get_boolean(const JSON_Value *value);
+void json_value_free (JSON_Value *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/util_pkt_logger/local_conf.json b/util_pkt_logger/local_conf.json
new file mode 100644
index 0000000..624893d
--- /dev/null
+++ b/util_pkt_logger/local_conf.json
@@ -0,0 +1,5 @@
+{
+ "gateway_conf": {
+ "gateway_ID": "AA555A0000000101"
+ }
+}
diff --git a/util_pkt_logger/obj/.gitkeep b/util_pkt_logger/obj/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/util_pkt_logger/obj/.gitkeep
diff --git a/util_pkt_logger/readme.md b/util_pkt_logger/readme.md
new file mode 100644
index 0000000..a980bd4
--- /dev/null
+++ b/util_pkt_logger/readme.md
@@ -0,0 +1,143 @@
+ / _____) _ | |
+ ( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+ (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech-Cycleo
+
+LoRa packet logger
+===================
+
+1. Introduction
+----------------
+
+This software is used to set up a LoRa concentrator using a JSON configuration
+file and then record all the packets received in a log file, indefinitely, until
+the user stops the application.
+No filtering is done and all packets that are LoRa packets with the correct RF
+parameters (frequency, datarate, bandwidth) should appear in the log.
+
+2. Dependencies
+----------------
+
+This program uses the Parson library (http://kgabis.github.com/parson/) by
+Krzysztof Gabis for JSON parsing.
+Many thanks to him for that very practical and well written library.
+
+This program is a typical example of LoRa concentrator HAL usage for receiving
+packets.
+
+Only high-level functions are used (the ones contained in loragw_hal) so there
+is no hardware dependencies assuming the HAL is matched with the proper version
+of the hardware.
+Data structures of the received packets are accessed by name (ie. not at a
+binary level) so new functionalities can be added to the API without affecting
+that program at all.
+
+It was tested with v1.3.0 of the libloragw library, and should be compatible
+with any later version of the library assuming the API is downward-compatible.
+
+3. Usage
+---------
+
+To stop the application, press Ctrl+C.
+
+The only optional parameter when launching the application is the log rotation
+time (in seconds).
+
+The way the program takes configuration files into account is the following:
+ * if there is a debug_conf.json parse it, others are ignored
+ * if there is a global_conf.json parse it and look for the next file
+ * if there is a local_conf.json parse it
+If some parameters are defined in both global and local configuration files, the
+local definition overwrites the global definition.
+
+The global configuration file should be exactly the same throughout your
+network, contain all global parameters (parameters for "sensor" radio channels)
+and preferably default "safe" values for parameters that are specific for each
+gateway (eg. specify a default MAC address).
+
+If you have build the libloragw library for a specific radio band (eg. ETSI
+868 MHz band) a ready-to-use global_conf.json file is generated by the Makefile
+with a set of channels typical for a 'LoRa MAC' network application.
+If you don't specify a radio band, an empty global_conf.json is generated and
+must be filled with the settings you need.
+
+The local configuration file should contain parameters that are specific to each
+gateway (eg. MAC address, frequency for backhaul radio channels).
+
+In each configuration file, the program looks for a JSON object named
+"SX1301_conf" that should contain the parameters for the LoRa concentrator board
+(RF channels definition, modem parameters, etc) and another JSON object called
+"gateway_conf" that should contain the gateway parameters (gateway MAC address,
+IP address of the LoRa MAC controller, network authentication parameters, etc).
+
+To learn more about the JSON configuration format, read the provided JSON files
+and the API documentation. A dedicated document will be available later on.
+
+The received packets are put in a CSV file whose name include the MAC address of
+the gateway in hexadecimal format and a UTC timestamp of log starting time in
+ISO 8601 recommended compact format:
+yyyymmddThhmmssZ (eg. 20131009T172345Z for October 9th, 2013 at 5:23:45PM UTC)
+
+To able continuous monitoring, the current log file is closed is closed and a
+new one is opened every hour (by default, rotation interval is settable by the
+user using -r command line option).
+No packet is lost during that rotation of log file.
+Every log file but the current one can then be modified, uploaded and/or deleted
+without any consequence for the program execution.
+
+4. License
+-----------
+
+Copyright (c) 2013, SEMTECH S.A.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of the Semtech corporation nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+5. License for Parson library
+------------------------------
+
+Parson ( http://kgabis.github.com/parson/ )
+Copyright (c) 2012 Krzysztof Gabis
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*EOF* \ No newline at end of file
diff --git a/util_pkt_logger/src/parson.c b/util_pkt_logger/src/parson.c
new file mode 100644
index 0000000..ecf733f
--- /dev/null
+++ b/util_pkt_logger/src/parson.c
@@ -0,0 +1,782 @@
+/*
+ Parson ( http://kgabis.github.com/parson/ )
+ Copyright (c) 2013 Krzysztof Gabis
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "parson.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define ERROR 0
+#define SUCCESS 1
+#define STARTING_CAPACITY 15
+#define ARRAY_MAX_CAPACITY 122880 /* 15*(2^13) */
+#define OBJECT_MAX_CAPACITY 960 /* 15*(2^6) */
+#define MAX_NESTING 19
+#define sizeof_token(a) (sizeof(a) - 1)
+#define skip_char(str) ((*str)++)
+#define skip_whitespaces(str) while (isspace(**str)) { skip_char(str); }
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define parson_malloc(a) malloc(a)
+#define parson_free(a) free((void*)a)
+#define parson_realloc(a, b) realloc(a, b)
+
+/* Type definitions */
+typedef union json_value_value {
+ const char *string;
+ double number;
+ JSON_Object *object;
+ JSON_Array *array;
+ int boolean;
+ int null;
+} JSON_Value_Value;
+
+struct json_value_t {
+ JSON_Value_Type type;
+ JSON_Value_Value value;
+};
+
+struct json_object_t {
+ const char **names;
+ JSON_Value **values;
+ size_t count;
+ size_t capacity;
+};
+
+struct json_array_t {
+ JSON_Value **items;
+ size_t count;
+ size_t capacity;
+};
+
+/* Various */
+static char * read_file(const char *filename);
+static void remove_comments(char *string, const char *start_token, const char *end_token);
+static int try_realloc(void **ptr, size_t new_size);
+static char * parson_strndup(const char *string, size_t n);
+static int is_utf(const unsigned char *string);
+static int is_decimal(const char *string, size_t length);
+
+/* JSON Object */
+static JSON_Object * json_object_init(void);
+static int json_object_add(JSON_Object *object, const char *name, JSON_Value *value);
+static int json_object_resize(JSON_Object *object, size_t capacity);
+static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n);
+static void json_object_free(JSON_Object *object);
+
+/* JSON Array */
+static JSON_Array * json_array_init(void);
+static int json_array_add(JSON_Array *array, JSON_Value *value);
+static int json_array_resize(JSON_Array *array, size_t capacity);
+static void json_array_free(JSON_Array *array);
+
+/* JSON Value */
+static JSON_Value * json_value_init_object(void);
+static JSON_Value * json_value_init_array(void);
+static JSON_Value * json_value_init_string(const char *string);
+static JSON_Value * json_value_init_number(double number);
+static JSON_Value * json_value_init_boolean(int boolean);
+static JSON_Value * json_value_init_null(void);
+
+/* Parser */
+static void skip_quotes(const char **string);
+static const char * get_processed_string(const char **string);
+static JSON_Value * parse_object_value(const char **string, size_t nesting);
+static JSON_Value * parse_array_value(const char **string, size_t nesting);
+static JSON_Value * parse_string_value(const char **string);
+static JSON_Value * parse_boolean_value(const char **string);
+static JSON_Value * parse_number_value(const char **string);
+static JSON_Value * parse_null_value(const char **string);
+static JSON_Value * parse_value(const char **string, size_t nesting);
+
+/* Various */
+static int try_realloc(void **ptr, size_t new_size) {
+ void *reallocated_ptr = parson_realloc(*ptr, new_size);
+ if (!reallocated_ptr)
+ return ERROR;
+ *ptr = reallocated_ptr;
+ return SUCCESS;
+}
+
+static char * parson_strndup(const char *string, size_t n) {
+ char *output_string = (char*)parson_malloc(n + 1);
+ if (!output_string)
+ return NULL;
+ output_string[n] = '\0';
+ strncpy(output_string, string, n);
+ return output_string;
+}
+
+static int is_utf(const unsigned char *s) {
+ return isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]);
+}
+
+static int is_decimal(const char *string, size_t length) {
+ if (length > 1 && string[0] == '0' && string[1] != '.')
+ return 0;
+ if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.')
+ return 0;
+ while (length--)
+ if (strchr("xX", string[length]))
+ return 0;
+ return 1;
+}
+
+static char * read_file(const char * filename) {
+ FILE *fp = fopen(filename, "r");
+ size_t file_size;
+ char *file_contents;
+ if (!fp)
+ return NULL;
+ fseek(fp, 0L, SEEK_END);
+ file_size = ftell(fp);
+ rewind(fp);
+ file_contents = (char*)parson_malloc(sizeof(char) * (file_size + 1));
+ if (!file_contents) {
+ fclose(fp);
+ return NULL;
+ }
+ if (fread(file_contents, file_size, 1, fp) < 1) {
+ if (ferror(fp)) {
+ fclose(fp);
+ parson_free(file_contents);
+ return NULL;
+ }
+ }
+ fclose(fp);
+ file_contents[file_size] = '\0';
+ return file_contents;
+}
+
+static void remove_comments(char *string, const char *start_token, const char *end_token) {
+ int in_string = 0, escaped = 0;
+ size_t i;
+ char *ptr = NULL, current_char;
+ size_t start_token_len = strlen(start_token);
+ size_t end_token_len = strlen(end_token);
+ if (start_token_len == 0 || end_token_len == 0)
+ return;
+ while ((current_char = *string) != '\0') {
+ if (current_char == '\\' && !escaped) {
+ escaped = 1;
+ string++;
+ continue;
+ } else if (current_char == '\"' && !escaped) {
+ in_string = !in_string;
+ } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
+ for(i = 0; i < start_token_len; i++)
+ string[i] = ' ';
+ string = string + start_token_len;
+ ptr = strstr(string, end_token);
+ if (!ptr)
+ return;
+ for (i = 0; i < (ptr - string) + end_token_len; i++)
+ string[i] = ' ';
+ string = ptr + end_token_len - 1;
+ }
+ escaped = 0;
+ string++;
+ }
+}
+
+/* JSON Object */
+static JSON_Object * json_object_init(void) {
+ JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object));
+ if (!new_obj)
+ return NULL;
+ new_obj->names = (const char**)NULL;
+ new_obj->values = (JSON_Value**)NULL;
+ new_obj->capacity = 0;
+ new_obj->count = 0;
+ return new_obj;
+}
+
+static int json_object_add(JSON_Object *object, const char *name, JSON_Value *value) {
+ size_t index;
+ if (object->count >= object->capacity) {
+ size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY);
+ if (new_capacity > OBJECT_MAX_CAPACITY)
+ return ERROR;
+ if (json_object_resize(object, new_capacity) == ERROR)
+ return ERROR;
+ }
+ if (json_object_get_value(object, name) != NULL)
+ return ERROR;
+ index = object->count;
+ object->names[index] = parson_strndup(name, strlen(name));
+ if (!object->names[index])
+ return ERROR;
+ object->values[index] = value;
+ object->count++;
+ return SUCCESS;
+}
+
+static int json_object_resize(JSON_Object *object, size_t capacity) {
+ if (try_realloc((void**)&object->names, capacity * sizeof(char*)) == ERROR)
+ return ERROR;
+ if (try_realloc((void**)&object->values, capacity * sizeof(JSON_Value*)) == ERROR)
+ return ERROR;
+ object->capacity = capacity;
+ return SUCCESS;
+}
+
+static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n) {
+ size_t i, name_length;
+ for (i = 0; i < json_object_get_count(object); i++) {
+ name_length = strlen(object->names[i]);
+ if (name_length != n)
+ continue;
+ if (strncmp(object->names[i], name, n) == 0)
+ return object->values[i];
+ }
+ return NULL;
+}
+
+static void json_object_free(JSON_Object *object) {
+ while(object->count--) {
+ parson_free(object->names[object->count]);
+ json_value_free(object->values[object->count]);
+ }
+ parson_free(object->names);
+ parson_free(object->values);
+ parson_free(object);
+}
+
+/* JSON Array */
+static JSON_Array * json_array_init(void) {
+ JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array));
+ if (!new_array)
+ return NULL;
+ new_array->items = (JSON_Value**)NULL;
+ new_array->capacity = 0;
+ new_array->count = 0;
+ return new_array;
+}
+
+static int json_array_add(JSON_Array *array, JSON_Value *value) {
+ if (array->count >= array->capacity) {
+ size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
+ if (new_capacity > ARRAY_MAX_CAPACITY)
+ return ERROR;
+ if (!json_array_resize(array, new_capacity))
+ return ERROR;
+ }
+ array->items[array->count] = value;
+ array->count++;
+ return SUCCESS;
+}
+
+static int json_array_resize(JSON_Array *array, size_t capacity) {
+ if (try_realloc((void**)&array->items, capacity * sizeof(JSON_Value*)) == ERROR)
+ return ERROR;
+ array->capacity = capacity;
+ return SUCCESS;
+}
+
+static void json_array_free(JSON_Array *array) {
+ while (array->count--)
+ json_value_free(array->items[array->count]);
+ parson_free(array->items);
+ parson_free(array);
+}
+
+/* JSON Value */
+static JSON_Value * json_value_init_object(void) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value)
+ return NULL;
+ new_value->type = JSONObject;
+ new_value->value.object = json_object_init();
+ if (!new_value->value.object) {
+ parson_free(new_value);
+ return NULL;
+ }
+ return new_value;
+}
+
+static JSON_Value * json_value_init_array(void) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value)
+ return NULL;
+ new_value->type = JSONArray;
+ new_value->value.array = json_array_init();
+ if (!new_value->value.array) {
+ parson_free(new_value);
+ return NULL;
+ }
+ return new_value;
+}
+
+static JSON_Value * json_value_init_string(const char *string) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value)
+ return NULL;
+ new_value->type = JSONString;
+ new_value->value.string = string;
+ return new_value;
+}
+
+static JSON_Value * json_value_init_number(double number) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value)
+ return NULL;
+ new_value->type = JSONNumber;
+ new_value->value.number = number;
+ return new_value;
+}
+
+static JSON_Value * json_value_init_boolean(int boolean) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value)
+ return NULL;
+ new_value->type = JSONBoolean;
+ new_value->value.boolean = boolean;
+ return new_value;
+}
+
+static JSON_Value * json_value_init_null(void) {
+ JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
+ if (!new_value)
+ return NULL;
+ new_value->type = JSONNull;
+ return new_value;
+}
+
+/* Parser */
+static void skip_quotes(const char **string) {
+ skip_char(string);
+ while (**string != '\"') {
+ if (**string == '\0')