summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgit commit -m first <[email protected]>2019-06-12 15:06:20 +0800
committergit commit -m first <[email protected]>2019-06-12 15:06:20 +0800
commit10e810b629148dcc96159d96045edccb94af600a (patch)
treed8e4724d2f1ea208f05fa6d96be8ad6413b6df3b
add source code
-rw-r--r--Makefile47
-rw-r--r--comm_zip_py/interval_zip.py94
-rw-r--r--comm_zip_py/run2
-rw-r--r--comm_zip_py/run_comm_interval_zip12
-rw-r--r--conf/comm_audit.inf13
-rw-r--r--conf/net_log_upload_pz.txt1
-rw-r--r--djconf/comm_audit.conf19
-rw-r--r--inc/cJSON.h149
-rw-r--r--inc/comm_audit.h489
-rw-r--r--inc/identify.h35
-rw-r--r--inc/maxminddb.h241
-rw-r--r--inc/project_requirement.h112
-rwxr-xr-xlib/comm_audit.sobin0 -> 200288 bytes
-rw-r--r--libmaxminddb.abin0 -> 178110 bytes
-rw-r--r--src/.comm_audit.cpp.swpbin0 -> 16384 bytes
-rw-r--r--src/cJSON.c763
-rw-r--r--src/comm_audit.cpp968
17 files changed, 2945 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fffe8fe
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,47 @@
+CC = g++
+CCC = g++
+CFLAGS += -g -Wall -fPIC -std=c++11
+#CFLAGS += $(OPTFLAGS)
+SRCS += $(wildcard ./src/*.cpp) $(wildcard ./src/*.c)
+OBJECTS := $(patsubst %.cpp, %.o, $(SRCS))
+LDFLAGS = -L/usr/local/lib
+#OBJECTS := $(patsubst %.cpp, %.o)
+TARGET := comm_audit.so
+
+INCS := -I./inc -I./.
+LIBS = -lMESA_handle_logger -lMESA_prof_load
+STATICLIB = ./libmaxminddb.a
+
+# LIBPATH += -L./lib
+LIBPATH := ./lib
+vpath %.cpp src
+vpath %.c src
+vpath %.h inc:MESA
+
+%.o:%.cpp
+ $(CCC) $(CFLAGS) $(INCS) -o $@ -c $<
+%.o:%.c
+ $(CC) $(CFLAGS) $(INCS) -o $@ -c $<
+
+all:$(TARGET) $(SUPPORT)
+
+$(TARGET):$(OBJECTS)
+ $(CC) -o $(TARGET) $^ $(INCS) $(STATICLIB) $(LIBS) -shared -fPIC
+ rm -f src/*.o
+ mv $(TARGET) $(LIBPATH)
+
+.PHONY: clean
+
+clean:
+# rm -f $(OBJECTS) *.o ./lib/*
+ rm -f ./lib/*
+
+install:
+ cp -ru ./lib/$(TARGET) /home/jcq/bin/sapp_se/plug/business/comm_audit/
+ cp -ru ./djconf/* /home/jcq/bin/sapp_se/djconf/
+ cp -ru ./comm_zip_py /usr/local/bin/
+ chmod +x /usr/local/bin/comm_zip_py/interval_zip.py
+ chmod +x /usr/local/bin/comm_zip_py/run
+ chmod +x /usr/local/bin/comm_zip_py/run_comm_interval_zip
+# echo "cd /usr/local/bin/comm_zip_py;./run" >> /etc/rc.local
+
diff --git a/comm_zip_py/interval_zip.py b/comm_zip_py/interval_zip.py
new file mode 100644
index 0000000..4ea9578
--- /dev/null
+++ b/comm_zip_py/interval_zip.py
@@ -0,0 +1,94 @@
+#!/usr/bin/python
+# encoding: utf8
+
+# Author: zhangxi
+# Last modified: 2017/11/24
+
+import os
+import json
+import time
+import datetime
+import pprint
+import pdb
+from optparse import OptionParser
+
+
+def interval_zip(interval, conf_file):
+
+ dest_path = ""
+ tmp_path = ""
+ # interval = 1
+
+ with open(conf_file) as f:
+ for line in f.readlines():
+ if line.startswith("upload_log_path"):
+ dest_path = line[line.find("=")+1:].strip()
+ if not dest_path.endswith('/'):
+ dest_path+='/'
+ elif line.startswith("tmp_log_path"):
+ tmp_path = line[line.find("=")+1:].strip()
+ else:
+ pass
+
+ while True:
+ try:
+ '''
+ try:
+ with open(upload_pz) as f:
+ for line in f.readlines():
+ start = line.find('interval":')+10
+ end = line.find(',"num')
+ interval = int(line[start:end])
+ except Exception, e:
+ pass
+ #raise e
+ # print interval
+ '''
+
+ time_remaining = interval-time.time()%interval
+ # print time_remaining
+ time.sleep(time_remaining)
+
+ # today = time.strftime('%Y-%m-%d',time.localtime(time.time()))
+ # now_path = dest_path+today
+ # now_path+="/"
+ # cmd = 'mkdir -p %s; cd %s; gzip -q *; mv %s/* %s'%(now_path, tmp_path, tmp_path, now_path)
+ # # print cmd
+ # os.system(cmd)
+
+
+ # l = os.listdir(tmp_path)
+ l = tmp_path
+ if len(l)>1:
+ # st = l.sort(key=lambda fn: os.path.getmtime(tmp_path+"/"+fn) if not os.path.isdir(tmp_path+"/"+fn) else 0)
+ latest = sorted([(x, os.path.getmtime(os.path.join(l,x))) for x in os.listdir(l) if os.path.isfile(os.path.join(l,x))], \
+ key=lambda i: i[1])[-1]
+ # print ('last file is '+l[-1])
+
+ today = time.strftime('%Y-%m-%d',time.localtime(time.time()))
+ now_path = dest_path+today
+ now_path+="/"
+ now_time = time.strftime('%H%M%S',time.localtime(time.time()))
+ # print now_time
+ # cmd = 'mkdir -p %s; cd %s; tar zcf %s/%s.tar.gz * --exclude=%s; rm `ls *|egrep -v %s`'\
+ # %(now_path, tmp_path, now_path, now_time, l[-1], l[-1])
+ #pdb.set_trace()
+ cmd = 'mkdir -p %s; cd %s; count=`ls|grep .txt|wc -l`; if [[ $count -gt 1 ]]; then tar zcf %s/%s.tar.gz * --exclude=%s; rm `ls *|egrep -v %s`;fi;'\
+ %(now_path, tmp_path, now_path, now_time, latest[0], latest[0])
+ # print cmd
+ os.system(cmd)
+
+ except Exception, e:
+ pass
+ # print e
+
+
+if __name__ == '__main__':
+ usage_info ="python %prog [options arg] \n"
+ parser =OptionParser(usage=usage_info,version="version verifiy 1.0")
+ parser.add_option("-i","--interval",dest="interval",default=5,help="interval of scanning upload file. Default is 5 seconds.")
+ # parser.add_option("-u","--upload_pz",dest="upload_pz",default="/tmp/upload_pz/net_log_upload_pz.txt",help="upload_pz_path. Default file is /tmp/upload_pz/net_log_upload_pz.txt")
+ parser.add_option("-c","--conf_file",dest="conf_file",default="/home/jcq/bin/sapp_se/djconf/comm_audit.conf",help="conf_path. Default file is /home/jcq/bin/sapp_se/djconf/comm_audit.conf")
+ (options,args) =parser.parse_args()
+ interval_zip(options.interval, options.conf_file)
+
diff --git a/comm_zip_py/run b/comm_zip_py/run
new file mode 100644
index 0000000..8dd112c
--- /dev/null
+++ b/comm_zip_py/run
@@ -0,0 +1,2 @@
+killall interval_zip.py run_comm_interval_zip
+./run_comm_interval_zip & > /dev/null &
diff --git a/comm_zip_py/run_comm_interval_zip b/comm_zip_py/run_comm_interval_zip
new file mode 100644
index 0000000..4c005f4
--- /dev/null
+++ b/comm_zip_py/run_comm_interval_zip
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+while [ 1 ]; do
+ count=`ps aux | grep interval_zip.py | grep -v grep | wc -l`
+ if [ $count -lt 1 ]
+ then
+ ./interval_zip.py > /dev/null &
+ echo program crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log
+ sleep 10
+ fi
+ sleep 10
+done
diff --git a/conf/comm_audit.inf b/conf/comm_audit.inf
new file mode 100644
index 0000000..bf8707a
--- /dev/null
+++ b/conf/comm_audit.inf
@@ -0,0 +1,13 @@
+[PLUGINFO]
+PLUGNAME=COMM_AUDIT
+SO_PATH=./plug/business/comm_audit/comm_audit.so
+INIT_FUNC=COMM_AUDIT_INIT
+DESTROY_FUNC=COMM_AUDIT_DESTROY
+
+[UDP]
+FUNC_FLAG=ALL
+FUNC_NAME=COMM_AUDIT_ENTRY
+
+[TCP_ALL]
+FUNC_FLAG=ALL
+FUNC_NAME=COMM_AUDIT_ENTRY
diff --git a/conf/net_log_upload_pz.txt b/conf/net_log_upload_pz.txt
new file mode 100644
index 0000000..084b081
--- /dev/null
+++ b/conf/net_log_upload_pz.txt
@@ -0,0 +1 @@
+[{"interval":15,"num":100}] \ No newline at end of file
diff --git a/djconf/comm_audit.conf b/djconf/comm_audit.conf
new file mode 100644
index 0000000..71aa9ff
--- /dev/null
+++ b/djconf/comm_audit.conf
@@ -0,0 +1,19 @@
+[DEFAULT]
+htable_size = 100000
+sleep = 2
+log_level = 10
+log_path = ./log/comm_audit_log
+
+[UPLOAD_LOG]
+upload_log_path = /tmp/comm_upload_log
+tmp_log_path = /tmp/comm_log
+
+[UPLOAD_PZ]
+upload_pz_path = /tmp/upload_pz
+read_upload_pz_interval = 60
+default_upload_interval = 2
+defailt_upload_max_num = 100000
+
+[IPDB_PZ]
+flag = 0
+mmdb_path = ./db/all_ip_only_coun_v4.mmdb
diff --git a/inc/cJSON.h b/inc/cJSON.h
new file mode 100644
index 0000000..466d10d
--- /dev/null
+++ b/inc/cJSON.h
@@ -0,0 +1,149 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+
+ 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 cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* cJSON Types: */
+#define cJSON_False 0
+#define cJSON_True 1
+#define cJSON_NULL 2
+#define cJSON_Number 3
+#define cJSON_String 4
+#define cJSON_Array 5
+#define cJSON_Object 6
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON {
+ struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+
+ int type; /* The type of the item, as above. */
+
+ char *valuestring; /* The item's string, if type==cJSON_String */
+ int valueint; /* The item's number, if type==cJSON_Number */
+ double valuedouble; /* The item's number, if type==cJSON_Number */
+
+ char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+} cJSON;
+
+typedef struct cJSON_Hooks {
+ void *(*malloc_fn)(size_t sz);
+ void (*free_fn)(void *ptr);
+} cJSON_Hooks;
+
+/* Supply malloc, realloc and free functions to cJSON */
+extern void cJSON_InitHooks(cJSON_Hooks* hooks);
+
+
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
+extern cJSON *cJSON_Parse(const char *value);
+/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
+extern char *cJSON_Print(cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
+extern char *cJSON_PrintUnformatted(cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
+/* Delete a cJSON entity and all subentities. */
+extern void cJSON_Delete(cJSON *c);
+
+/* Returns the number of items in an array (or object). */
+extern int cJSON_GetArraySize(cJSON *array);
+/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
+/* Get item "string" from object. Case insensitive. */
+extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
+
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+extern const char *cJSON_GetErrorPtr(void);
+
+/* These calls create a cJSON item of the appropriate type. */
+extern cJSON *cJSON_CreateNull(void);
+extern cJSON *cJSON_CreateTrue(void);
+extern cJSON *cJSON_CreateFalse(void);
+extern cJSON *cJSON_CreateBool(int b);
+extern cJSON *cJSON_CreateNumber(double num);
+extern cJSON *cJSON_CreateString(const char *string);
+extern cJSON *cJSON_CreateArray(void);
+extern cJSON *cJSON_CreateObject(void);
+
+/* These utilities create an Array of count items. */
+extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
+extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
+extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
+extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
+
+/* Append item to the specified array/object. */
+extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
+extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
+
+/* Remove/Detatch items from Arrays/Objects. */
+extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
+extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
+extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
+extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
+
+/* Update array items. */
+extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */
+extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
+extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+need to be released. With recurse!=0, it will duplicate any children connected to the item.
+The item->next and ->prev pointers are always zero on return from Duplicate. */
+
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
+
+extern void cJSON_Minify(char *json);
+
+/* Macros for creating things quickly. */
+#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
+#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/inc/comm_audit.h b/inc/comm_audit.h
new file mode 100644
index 0000000..be9038d
--- /dev/null
+++ b/inc/comm_audit.h
@@ -0,0 +1,489 @@
+/*
+ * COMM_AUDIT.h
+ *
+ * Created on: 2017-8-14
+ * Last Modified: 2017-11-23
+ * Author: zhangxi
+ */
+
+#ifndef _COMM_AUDIT_H_
+#define _COMM_AUDIT_H_
+
+#include <sys/types.h>
+#include <time.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <dirent.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <MESA/stream.h>
+#include <MESA/MESA_handle_logger.h>
+#include <MESA/MESA_htable.h>
+#include <MESA/MESA_prof_load.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IPLEN (16)
+#define MACLEN (60)
+#define MB (1024 * 1024)
+#define MAX_LEN (1024)
+
+#define STREAM_TYPE(num)\
+({\
+ string type;\
+ switch(num)\
+ {\
+ case 0:\
+ type="NON";\
+ break;\
+ case 1:\
+ type="TCP";\
+ break;\
+ case 2:\
+ type="UDP";\
+ break;\
+ case 3:\
+ type="VLAN";\
+ break;\
+ case 4:\
+ type="SOCKS4";\
+ break;\
+ case 5:\
+ type="SOCKS5";\
+ break;\
+ case 6:\
+ type="HTTP_PROXY";\
+ break;\
+ case 7:\
+ type="PPPOE";\
+ break;\
+ case 8:\
+ type="L2TP";\
+ break;\
+ case 9:\
+ type="OPENVPN";\
+ break;\
+ case 10:\
+ type="PPTP";\
+ break;\
+ case 11:\
+ type="ISAKMP";\
+ break;\
+ }\
+ (type);\
+})
+
+
+#define APP_TYPE(num)\
+({\
+ string type;\
+ switch(num)\
+ {\
+ case 227:\
+ type="HTTP";\
+ break;\
+ case 256:\
+ type="DNS";\
+ break;\
+ case 314:\
+ type="SSL";\
+ break;\
+ case 229:\
+ type="FTP";\
+ break;\
+ case 243:\
+ type="SMTP";\
+ break;\
+ case 242:\
+ type="POP3";\
+ break;\
+ case 244:\
+ type="IMAP";\
+ break;\
+ case 1:\
+ type="BT";\
+ break;\
+ case 145:\
+ type="RTSP";\
+ break;\
+ case 1054:\
+ type="SSH";\
+ break;\
+ case 1058:\
+ type="telnet";\
+ break;\
+ case 312:\
+ type="socks4";\
+ break;\
+ case 313:\
+ type="socks5";\
+ break;\
+ case 15:\
+ type="fasttrack";\
+ break;\
+ case 17:\
+ type="filetopia";\
+ break;\
+ case 18:\
+ type="flashget";\
+ break;\
+ case 954:\
+ type="oracle";\
+ break;\
+ case 1002:\
+ type="skinny";\
+ break;\
+ case 1023:\
+ type="yyvoice";\
+ break;\
+ case 28:\
+ type="imesh";\
+ break;\
+ case 975:\
+ type="iax";\
+ break;\
+ case 986:\
+ type="mgcp";\
+ break;\
+ case 997:\
+ type="rtcp";\
+ break;\
+ case 998:\
+ type="rtp";\
+ break;\
+ case 1042:\
+ type="citrix";\
+ break;\
+ case 1043:\
+ type="corba";\
+ break;\
+ case 1044:\
+ type="dameware";\
+ break;\
+ case 1050:\
+ type="pcanywhere";\
+ break;\
+ case 1051:\
+ type="qq_rdp";\
+ break;\
+ case 1056:\
+ type="teamview";\
+ break;\
+ case 1060:\
+ type="vnc";\
+ break;\
+ case 1063:\
+ type="xdmcp";\
+ break;\
+ case 1068:\
+ type="rdp";\
+ break;\
+ case 4:\
+ type="aimini";\
+ break;\
+ case 41:\
+ type="poco";\
+ break;\
+ case 46:\
+ type="qqdownload";\
+ break;\
+ case 5:\
+ type="applejuice";\
+ break;\
+ case 55:\
+ type="stealthnet";\
+ break;\
+ case 59:\
+ type="winmx";\
+ break;\
+ case 66:\
+ type="emule";\
+ break;\
+ case 72:\
+ type="kuwo";\
+ break;\
+ case 80:\
+ type="thunder";\
+ break;\
+ case 138:\
+ type="qvod";\
+ break;\
+ case 953:\
+ type="mysql";\
+ break;\
+ case 101:\
+ type="icecast";\
+ break;\
+ case 113:\
+ type="mms";\
+ break;\
+ case 127:\
+ type="pplive";\
+ break;\
+ case 129:\
+ type="ppstream";\
+ break;\
+ case 151:\
+ type="sopcast";\
+ break;\
+ case 153:\
+ type="steam";\
+ break;\
+ case 157:\
+ type="tvants";\
+ break;\
+ case 199:\
+ type="iqiyi";\
+ break;\
+ case 208:\
+ type="sohutv";\
+ break;\
+ case 223:\
+ type="iku";\
+ break;\
+ case 228:\
+ type="cvs";\
+ break;\
+ case 232:\
+ type="ipp";\
+ break;\
+ case 235:\
+ type="nfs";\
+ break;\
+ case 236:\
+ type="rsync";\
+ break;\
+ case 237:\
+ type="smb";\
+ break;\
+ case 239:\
+ type="tftp";\
+ break;\
+ case 247:\
+ type="lotus_notes";\
+ break;\
+ case 251:\
+ type="bgp";\
+ break;\
+ case 254:\
+ type="dhcp";\
+ break;\
+ case 259:\
+ type="finger";\
+ break;\
+ case 264:\
+ type="kerberos";\
+ break;\
+ case 265:\
+ type="ldap";\
+ break;\
+ case 266:\
+ type="mdns";\
+ break;\
+ case 268:\
+ type="nntp";\
+ break;\
+ case 276:\
+ type="snmp";\
+ break;\
+ case 277:\
+ type="ssdp";\
+ break;\
+ case 278:\
+ type="syslog";\
+ break;\
+ case 281:\
+ type="whois";\
+ break;\
+ case 288:\
+ type="radius";\
+ break;\
+ case 1150:\
+ type="quic";\
+ break;\
+ case 295:\
+ type="ikev1";\
+ break;\
+ case 296:\
+ type="ikev2";\
+ break;\
+ case 304:\
+ type="l2tp";\
+ break;\
+ case 307:\
+ type="openvpn";\
+ break;\
+ case 309:\
+ type="pptp";\
+ break;\
+ case 315:\
+ type="stun";\
+ break;\
+ case 317:\
+ type="teredo";\
+ break;\
+ case 318:\
+ type="tor";\
+ break;\
+ case 328:\
+ type="xunyou_speedup";\
+ break;\
+ case 360:\
+ type="msn";\
+ break;\
+ case 368:\
+ type="popo";\
+ break;\
+ case 404:\
+ type="qq";\
+ break;\
+ case 410:\
+ type="sinauc";\
+ break;\
+ case 467:\
+ type="qqbattle";\
+ break;\
+ case 484:\
+ type="quake";\
+ break;\
+ case 507:\
+ type="xbox";\
+ break;\
+ case 690:\
+ type="wow";\
+ break;\
+ case 1074:\
+ type="gtp";\
+ break;\
+ default:\
+ type="unknown";\
+ break;\
+ }\
+ (type);\
+})
+
+#define TCP_FLAG(num)\
+({\
+ string flag;\
+ int n = num;\
+ if(n >= 32)\
+ {\
+ flag += "U";\
+ n -= 32;\
+ }\
+ if(n >= 16)\
+ {\
+ flag += "A";\
+ n -= 16;\
+ }\
+ if(n >= 8)\
+ {\
+ flag += "P";\
+ n -= 8;\
+ }\
+ if(n >= 4)\
+ {\
+ flag += "R";\
+ n -= 4;\
+ }\
+ if(n >= 2)\
+ {\
+ flag += "S";\
+ n -= 2;\
+ }\
+ if(n >= 1)\
+ {\
+ flag += "F";\
+ n -= 1;\
+ }\
+ (flag);\
+})
+
+
+typedef struct _htable_data_t
+{
+
+ unsigned int inner_ip;
+ unsigned int ext_ip;
+ unsigned short inner_port;
+ unsigned short ext_port;
+ char inner_mac[MACLEN];
+ char ext_mac[MACLEN];
+ unsigned char protocol;
+ unsigned short app;
+
+ unsigned short tcp_flag;
+ unsigned long long in_bytes;
+ unsigned long long out_bytes;
+ unsigned long long in_pkts;
+ unsigned long long out_pkts;
+ long long start_time;
+ long long end_time;
+
+}htable_data_t;
+
+
+typedef struct htable_search_arg
+{
+ struct streaminfo * stream;
+ void * packet;
+ int is_end;
+}htable_search_arg;
+
+
+typedef struct comm_prog_configure_t
+{
+ int htable_size;
+ int sleep;
+ int read_interval;
+ int write_interval;
+ int write_max_num;
+ int flag; //0:use mmd filter;1:no filter;2:no have any data
+ // char * log_path;
+ char * tmp_log_path;
+ char * upload_pz_path;
+ char * mmdb_path;
+}comm_prog_configure_t;
+
+typedef struct comm_prog_runtime_parameter_t
+{
+ int project_id_pro;
+ int thread_num;
+ void* log_handle;
+ long long last_send_time;
+ pthread_mutex_t mutex;
+ MESA_htable_handle **htable_handle;
+ // MESA_htable_handle htable_handle1;
+ // MESA_htable_handle htable_handle2;
+ // MESA_htable_handle wtable;
+ // MESA_htable_handle rtable;
+
+}comm_prog_runtime_parameter_t;
+
+typedef struct del_para_t
+{
+ char * writetime;
+ int thread_seq;
+}del_para_t;
+
+int COMM_AUDIT_INIT();
+char COMM_AUDIT_ENTRY(struct streaminfo *, void **, int , void *);
+void COMM_AUDIT_DESTROY();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/inc/identify.h b/inc/identify.h
new file mode 100644
index 0000000..2912b8d
--- /dev/null
+++ b/inc/identify.h
@@ -0,0 +1,35 @@
+#ifndef _IDENTIFY_PROC_H_
+#define _IDENTIFY_PROC_H_
+
+
+#define DNTY_PPROJECT_TYPE "struct"
+
+#define DNTY_PPROJECT_AREA "PPROJECT_AREA"
+#define DNTY_PPROJECT_PRO "PPROJECT_PRO"
+
+
+#define DNTY_AREA_OUTSIDE 700000
+#define DNTY_AREA_UNKONW 0
+
+
+typedef struct _dnty_area_info
+{
+ unsigned int client_area;
+ unsigned int server_area;
+}stDntyAreaInfo;
+
+
+typedef struct _dnty_protocol_info
+{
+ unsigned char trans_proto;
+ unsigned char communicate_mode:7;
+ unsigned char v6:1;
+ unsigned short protocol_type;
+ unsigned short application_class;
+ unsigned char cmd_type;
+ unsigned char reserved;
+}stDntyProInfo;
+
+
+#endif
+
diff --git a/inc/maxminddb.h b/inc/maxminddb.h
new file mode 100644
index 0000000..de1fdf8
--- /dev/null
+++ b/inc/maxminddb.h
@@ -0,0 +1,241 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MAXMINDDB_H
+#define MAXMINDDB_H
+
+/* Request POSIX.1-2008. However, we want to remain compatible with
+ * POSIX.1-2001 (since we have been historically and see no reason to drop
+ * compatibility). By requesting POSIX.1-2008, we can conditionally use
+ * features provided by that standard if the implementation provides it. We can
+ * check for what the implementation provides by checking the _POSIX_VERSION
+ * macro after including unistd.h. If a feature is in POSIX.1-2008 but not
+ * POSIX.1-2001, check that macro before using the feature (or check for the
+ * feature directly if possible). */
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include "maxminddb_config.h"
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+/* libmaxminddb package version from configure */
+#define PACKAGE_VERSION "1.3.2"
+
+typedef ADDRESS_FAMILY sa_family_t;
+
+#if defined(_MSC_VER)
+/* MSVC doesn't define signed size_t, copy it from configure */
+#define ssize_t SSIZE_T
+
+/* MSVC doesn't support restricted pointers */
+#define restrict
+#endif
+#else
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+
+#define MMDB_DATA_TYPE_EXTENDED (0)
+#define MMDB_DATA_TYPE_POINTER (1)
+#define MMDB_DATA_TYPE_UTF8_STRING (2)
+#define MMDB_DATA_TYPE_DOUBLE (3)
+#define MMDB_DATA_TYPE_BYTES (4)
+#define MMDB_DATA_TYPE_UINT16 (5)
+#define MMDB_DATA_TYPE_UINT32 (6)
+#define MMDB_DATA_TYPE_MAP (7)
+#define MMDB_DATA_TYPE_INT32 (8)
+#define MMDB_DATA_TYPE_UINT64 (9)
+#define MMDB_DATA_TYPE_UINT128 (10)
+#define MMDB_DATA_TYPE_ARRAY (11)
+#define MMDB_DATA_TYPE_CONTAINER (12)
+#define MMDB_DATA_TYPE_END_MARKER (13)
+#define MMDB_DATA_TYPE_BOOLEAN (14)
+#define MMDB_DATA_TYPE_FLOAT (15)
+
+#define MMDB_RECORD_TYPE_SEARCH_NODE (0)
+#define MMDB_RECORD_TYPE_EMPTY (1)
+#define MMDB_RECORD_TYPE_DATA (2)
+#define MMDB_RECORD_TYPE_INVALID (3)
+
+/* flags for open */
+#define MMDB_MODE_MMAP (1)
+#define MMDB_MODE_MASK (7)
+
+/* error codes */
+#define MMDB_SUCCESS (0)
+#define MMDB_FILE_OPEN_ERROR (1)
+#define MMDB_CORRUPT_SEARCH_TREE_ERROR (2)
+#define MMDB_INVALID_METADATA_ERROR (3)
+#define MMDB_IO_ERROR (4)
+#define MMDB_OUT_OF_MEMORY_ERROR (5)
+#define MMDB_UNKNOWN_DATABASE_FORMAT_ERROR (6)
+#define MMDB_INVALID_DATA_ERROR (7)
+#define MMDB_INVALID_LOOKUP_PATH_ERROR (8)
+#define MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR (9)
+#define MMDB_INVALID_NODE_NUMBER_ERROR (10)
+#define MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR (11)
+
+#if !(MMDB_UINT128_IS_BYTE_ARRAY)
+#if MMDB_UINT128_USING_MODE
+typedef unsigned int mmdb_uint128_t __attribute__ ((__mode__(TI)));
+#else
+typedef unsigned __int128 mmdb_uint128_t;
+#endif
+#endif
+
+/* This is a pointer into the data section for a given IP address lookup */
+typedef struct MMDB_entry_s {
+ struct MMDB_s *mmdb;
+ uint32_t offset;
+} MMDB_entry_s;
+
+typedef struct MMDB_lookup_result_s {
+ bool found_entry;
+ MMDB_entry_s entry;
+ uint16_t netmask;
+} MMDB_lookup_result_s;
+
+typedef struct MMDB_entry_data_s {
+ bool has_data;
+ union {
+ uint32_t pointer;
+ const char *utf8_string;
+ double double_value;
+ const uint8_t *bytes;
+ uint16_t uint16;
+ uint32_t uint32;
+ int32_t int32;
+ uint64_t uint64;
+#if MMDB_UINT128_IS_BYTE_ARRAY
+ uint8_t uint128[16];
+#else
+ mmdb_uint128_t uint128;
+#endif
+ bool boolean;
+ float float_value;
+ };
+ /* This is a 0 if a given entry cannot be found. This can only happen
+ * when a call to MMDB_(v)get_value() asks for hash keys or array
+ * indices that don't exist. */
+ uint32_t offset;
+ /* This is the next entry in the data section, but it's really only
+ * relevant for entries that part of a larger map or array
+ * struct. There's no good reason for an end user to look at this
+ * directly. */
+ uint32_t offset_to_next;
+ /* This is only valid for strings, utf8_strings or binary data */
+ uint32_t data_size;
+ /* This is an MMDB_DATA_TYPE_* constant */
+ uint32_t type;
+} MMDB_entry_data_s;
+
+/* This is the return type when someone asks for all the entry data in a map or array */
+typedef struct MMDB_entry_data_list_s {
+ MMDB_entry_data_s entry_data;
+ struct MMDB_entry_data_list_s *next;
+ void *pool;
+} MMDB_entry_data_list_s;
+
+typedef struct MMDB_description_s {
+ const char *language;
+ const char *description;
+} MMDB_description_s;
+
+typedef struct MMDB_metadata_s {
+ uint32_t node_count;
+ uint16_t record_size;
+ uint16_t ip_version;
+ const char *database_type;
+ struct {
+ size_t count;
+ const char **names;
+ } languages;
+ uint16_t binary_format_major_version;
+ uint16_t binary_format_minor_version;
+ uint64_t build_epoch;
+ struct {
+ size_t count;
+ MMDB_description_s **descriptions;
+ } description;
+} MMDB_metadata_s;
+
+typedef struct MMDB_ipv4_start_node_s {
+ uint16_t netmask;
+ uint32_t node_value;
+} MMDB_ipv4_start_node_s;
+
+typedef struct MMDB_s {
+ uint32_t flags;
+ const char *filename;
+ ssize_t file_size;
+ const uint8_t *file_content;
+ const uint8_t *data_section;
+ uint32_t data_section_size;
+ const uint8_t *metadata_section;
+ uint32_t metadata_section_size;
+ uint16_t full_record_byte_size;
+ uint16_t depth;
+ MMDB_ipv4_start_node_s ipv4_start_node;
+ MMDB_metadata_s metadata;
+} MMDB_s;
+
+typedef struct MMDB_search_node_s {
+ uint64_t left_record;
+ uint64_t right_record;
+ uint8_t left_record_type;
+ uint8_t right_record_type;
+ MMDB_entry_s left_record_entry;
+ MMDB_entry_s right_record_entry;
+} MMDB_search_node_s;
+
+ /* *INDENT-OFF* */
+ /* --prototypes automatically generated by dev-bin/regen-prototypes.pl - don't remove this comment */
+ extern int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb);
+ extern MMDB_lookup_result_s MMDB_lookup_string(MMDB_s *const mmdb,
+ const char *const ipstr,
+ int *const gai_error,
+ int *const mmdb_error);
+ extern MMDB_lookup_result_s MMDB_lookup_sockaddr(
+ MMDB_s *const mmdb,
+ const struct sockaddr *const sockaddr,
+ int *const mmdb_error);
+ extern int MMDB_read_node(MMDB_s *const mmdb, uint32_t node_number,
+ MMDB_search_node_s *const node);
+ extern int MMDB_get_value(MMDB_entry_s *const start,
+ MMDB_entry_data_s *const entry_data,
+ ...);
+ extern int MMDB_vget_value(MMDB_entry_s *const start,
+ MMDB_entry_data_s *const entry_data,
+ va_list va_path);
+ extern int MMDB_aget_value(MMDB_entry_s *const start,
+ MMDB_entry_data_s *const entry_data,
+ const char *const *const path);
+ extern int MMDB_get_metadata_as_entry_data_list(
+ MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list);
+ extern int MMDB_get_entry_data_list(
+ MMDB_entry_s *start, MMDB_entry_data_list_s **const entry_data_list);
+ extern void MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list);
+ extern void MMDB_close(MMDB_s *const mmdb);
+ extern const char *MMDB_lib_version(void);
+ extern int MMDB_dump_entry_data_list(FILE *const stream,
+ MMDB_entry_data_list_s *const entry_data_list,
+ int indent);
+ extern const char *MMDB_strerror(int error_code);
+ /* --prototypes end - don't remove this comment-- */
+ /* *INDENT-ON* */
+
+#endif /* MAXMINDDB_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/inc/project_requirement.h b/inc/project_requirement.h
new file mode 100644
index 0000000..3159b36
--- /dev/null
+++ b/inc/project_requirement.h
@@ -0,0 +1,112 @@
+#ifndef _PROJECT_REQUIREMENT_H_
+#define _PROJECT_REQUIREMENT_H_
+
+#include <MESA/stream.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define PROJECT_REQ_NAME_MAX_LEN (64)
+
+typedef void (project_req_free_t)(int thread_seq, void *project_req_value);
+
+#define PROJECT_VAL_TYPE_CHAR "char"
+#define PROJECT_VAL_TYPE_SHORT "short"
+#define PROJECT_VAL_TYPE_INT "int"
+#define PROJECT_VAL_TYPE_LONG "long"
+#define PROJECT_VAL_TYPE_STRUCT "struct"
+
+
+int project_requirement_global_init(void);
+
+/*
+ must call this function in initialization, only one times,
+ the 'free_cb' should be NULL if 'project_req_val_type' is simple type,
+ otherwise please implement it by youself.
+
+ args:
+ project_req_name: for example, "terminal_tag", "stream_id".
+ project_req_val_type: support "char","short","int","long","struct".
+ free_cb: used to free resource when 'project_req_val_type' is "struct".
+
+
+ return value: 'project_req_id' of this project_req_name, must use this id in following functions.
+ >= 0 : success;
+ -1 : error.
+*/
+int project_producer_register(const char *project_req_name, const char *project_req_val_type, project_req_free_t *free_cb);
+
+/* args and return value same with project_producer_register() */
+int project_customer_register(const char *project_req_name, const char *project_req_val_type);
+
+/*
+ Function project_req_add_struct: 'project_req_value' must be a pointer to heap memory(obtain by malloc).
+
+ return value:
+ 0 : success;
+ -1: error.
+*/
+int project_req_add_char(struct streaminfo *stream, int project_req_id, char project_req_value);
+int project_req_add_short(struct streaminfo *stream, int project_req_id, short project_req_value);
+int project_req_add_int(struct streaminfo *stream, int project_req_id, int project_req_value);
+int project_req_add_long(struct streaminfo *stream, int project_req_id, long project_req_value);
+
+int project_req_add_uchar(struct streaminfo *stream, int project_req_id, unsigned char project_req_value);
+int project_req_add_ushort(struct streaminfo *stream, int project_req_id, unsigned short project_req_value);
+int project_req_add_uint(struct streaminfo *stream, int project_req_id, unsigned int project_req_value);
+int project_req_add_ulong(struct streaminfo *stream, int project_req_id, unsigned long project_req_value);
+
+
+int project_req_add_struct(struct streaminfo *stream, int project_req_id, const void *project_req_value);
+
+
+/*
+ return value:
+ -1(or all bit is '1' in Hex mode, 0xFF, 0xFFFF):
+ maybe error, maybe the actual project_req_value is -1 indeed,
+ must check tht 'errno' in this case,
+ the 'errno' will be set to 'ERANGE' indicate an error.
+ others: success.
+
+ for example:
+ int value = project_req_get_int(stream, req_id);
+ if((-1 == value) && (ERANGE == errno)){
+ error_handle();
+ }else{
+ do_somgthing();
+ }
+
+ for example2:
+ unsigned short value = project_req_get_ushort(stream, req_id);
+ if((0xFF == value) && (ERANGE == errno)){
+ error_handle();
+ }else{
+ do_somgthing();
+ }
+
+*/
+char project_req_get_char(const struct streaminfo *stream, int project_req_id);
+short project_req_get_short(const struct streaminfo *stream, int project_req_id);
+int project_req_get_int(const struct streaminfo *stream, int project_req_id);
+long project_req_get_long(const struct streaminfo *stream, int project_req_id);
+
+unsigned char project_req_get_uchar(const struct streaminfo *stream, int project_req_id);
+unsigned short project_req_get_ushort(const struct streaminfo *stream, int project_req_id);
+unsigned int project_req_get_uint(const struct streaminfo *stream, int project_req_id);
+unsigned long project_req_get_ulong(const struct streaminfo *stream, int project_req_id);
+
+/*
+ return value:
+ NULL : error;
+ others: success.
+*/
+const void *project_req_get_struct(const struct streaminfo *stream, int project_req_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/lib/comm_audit.so b/lib/comm_audit.so
new file mode 100755
index 0000000..518b585
--- /dev/null
+++ b/lib/comm_audit.so
Binary files differ
diff --git a/libmaxminddb.a b/libmaxminddb.a
new file mode 100644
index 0000000..77a550b
--- /dev/null
+++ b/libmaxminddb.a
Binary files differ
diff --git a/src/.comm_audit.cpp.swp b/src/.comm_audit.cpp.swp
new file mode 100644
index 0000000..499ead6
--- /dev/null
+++ b/src/.comm_audit.cpp.swp
Binary files differ
diff --git a/src/cJSON.c b/src/cJSON.c
new file mode 100644
index 0000000..772f9af
--- /dev/null
+++ b/src/cJSON.c
@@ -0,0 +1,763 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+
+ 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.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cJSON.h"
+
+static const char *ep;
+
+const char *cJSON_GetErrorPtr(void) {return ep;}
+
+static int cJSON_strcasecmp(const char *s1,const char *s2)
+{
+ if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
+ for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
+ return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+}
+
+// static void *(*cJSON_malloc)(size_t sz) = rt_malloc;
+// static void (*cJSON_free)(void *ptr) = rt_free;
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static char* cJSON_strdup(const char* str)
+{
+ size_t len;
+ char* copy;
+
+ len = strlen(str) + 1;
+ if (!(copy = (char*)cJSON_malloc(len))) return 0;
+ memcpy(copy,str,len);
+ return copy;
+}
+
+// void cJSON_InitHooks(cJSON_Hooks* hooks)
+// {
+// if (!hooks) { /* Reset hooks */
+// cJSON_malloc = rt_malloc;
+// cJSON_free = rt_free;
+// return;
+// }
+
+// cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:rt_malloc;
+// cJSON_free = (hooks->free_fn)?hooks->free_fn:rt_free;
+// }
+void cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (!hooks) { /* Reset hooks */
+ cJSON_malloc = malloc;
+ cJSON_free = free;
+ return;
+ }
+
+ cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
+ cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(void)
+{
+ cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
+ if (node) memset(node,0,sizeof(cJSON));
+ return node;
+}
+
+/* Delete a cJSON structure. */
+void cJSON_Delete(cJSON *c)
+{
+ cJSON *next;
+ while (c)
+ {
+ next=c->next;
+ if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
+ if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
+ if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
+ cJSON_free(c);
+ c=next;
+ }
+}
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static const char *parse_number(cJSON *item,const char *num)
+{
+ double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
+
+ if (*num=='-') sign=-1,num++; /* Has sign? */
+ if (*num=='0') num++; /* is zero */
+ if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
+ if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
+ if (*num=='e' || *num=='E') /* Exponent? */
+ { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
+ while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
+ }
+
+ n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
+
+ item->valuedouble=n;
+ item->valueint=(int)n;
+ item->type=cJSON_Number;
+ return num;
+}
+
+static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; }
+
+typedef struct {char *buffer; int length; int offset; } printbuffer;
+
+static char* ensure(printbuffer *p,int needed)
+{
+ char *newbuffer;int newsize;
+ if (!p || !p->buffer) return 0;
+ needed+=p->offset;
+ if (needed<=p->length) return p->buffer+p->offset;
+
+ newsize=pow2gt(needed);
+ newbuffer=(char*)cJSON_malloc(newsize);
+ if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
+ if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
+ cJSON_free(p->buffer);
+ p->length=newsize;
+ p->buffer=newbuffer;
+ return newbuffer+p->offset;
+}
+
+static int update(printbuffer *p)
+{
+ char *str;
+ if (!p || !p->buffer) return 0;
+ str=p->buffer+p->offset;
+ return p->offset+strlen(str);
+}
+
+/* Render the number nicely from the given item into a string. */
+static char *print_number(cJSON *item,printbuffer *p)
+{
+ char *str=0;
+ double d=item->valuedouble;
+ if (d==0)
+ {
+ if (p) str=ensure(p,2);
+ else str=(char*)cJSON_malloc(2); /* special case for 0. */
+ if (str) strcpy(str,"0");
+ }
+ else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
+ {
+ if (p) str=ensure(p,21);
+ else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
+ if (str) sprintf(str,"%d",item->valueint);
+ }
+ else
+ {
+ if (p) str=ensure(p,64);
+ else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
+ if (str)
+ {
+ if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
+ else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
+ else sprintf(str,"%f",d);
+ }
+ }
+ return str;
+}
+
+static unsigned parse_hex4(const char *str)
+{
+ unsigned h=0;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ h=h<<4;str++;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ h=h<<4;str++;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ h=h<<4;str++;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ return h;
+}
+
+/* Parse the input text into an unescaped cstring, and populate item. */
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+static const char *parse_string(cJSON *item,const char *str)
+{
+ const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
+ if (*str!='\"') {ep=str;return 0;} /* not a string! */
+
+ while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
+
+ out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
+ if (!out) return 0;
+
+ ptr=str+1;ptr2=out;
+ while (*ptr!='\"' && *ptr)
+ {
+ if (*ptr!='\\') *ptr2++=*ptr++;
+ else
+ {
+ ptr++;
+ switch (*ptr)
+ {
+ case 'b': *ptr2++='\b'; break;
+ case 'f': *ptr2++='\f'; break;
+ case 'n': *ptr2++='\n'; break;
+ case 'r': *ptr2++='\r'; break;
+ case 't': *ptr2++='\t'; break;
+ case 'u': /* transcode utf16 to utf8. */
+ uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
+
+ if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
+
+ if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
+ {
+ if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
+ uc2=parse_hex4(ptr+3);ptr+=6;
+ if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
+ uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
+ }
+
+ len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
+
+ switch (len) {
+ case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+ case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+ case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+ case 1: *--ptr2 =(uc | firstByteMark[len]);
+ }
+ ptr2+=len;
+ break;
+ default: *ptr2++=*ptr; break;
+ }
+ ptr++;
+ }
+ }
+ *ptr2=0;
+ if (*ptr=='\"') ptr++;
+ item->valuestring=out;
+ item->type=cJSON_String;
+ return ptr;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static char *print_string_ptr(const char *str,printbuffer *p)
+{
+ const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
+
+ for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
+ if (!flag)
+ {
+ len=ptr-str;
+ if (p) out=ensure(p,len+3);
+ else out=(char*)cJSON_malloc(len+3);
+ if (!out) return 0;
+ ptr2=out;*ptr2++='\"';
+ strcpy(ptr2,str);
+ ptr2[len]='\"';
+ ptr2[len+1]=0;
+ return out;
+ }
+
+ if (!str)
+ {
+ if (p) out=ensure(p,3);
+ else out=(char*)cJSON_malloc(3);
+ if (!out) return 0;
+ strcpy(out,"\"\"");
+ return out;
+ }
+ ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
+
+ if (p) out=ensure(p,len+3);
+ else out=(char*)cJSON_malloc(len+3);
+ if (!out) return 0;
+
+ ptr2=out;ptr=str;
+ *ptr2++='\"';
+ while (*ptr)
+ {
+ if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
+ else
+ {
+ *ptr2++='\\';
+ switch (token=*ptr++)
+ {
+ case '\\': *ptr2++='\\'; break;
+ case '\"': *ptr2++='\"'; break;
+ case '\b': *ptr2++='b'; break;
+ case '\f': *ptr2++='f'; break;
+ case '\n': *ptr2++='n'; break;
+ case '\r': *ptr2++='r'; break;
+ case '\t': *ptr2++='t'; break;
+ default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
+ }
+ }
+ }
+ *ptr2++='\"';*ptr2++=0;
+ return out;
+}
+/* Invote print_string_ptr (which is useful) on an item. */
+static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);}
+
+/* Predeclare these prototypes. */
+static const char *parse_value(cJSON *item,const char *value);
+static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
+static const char *parse_array(cJSON *item,const char *value);
+static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
+static const char *parse_object(cJSON *item,const char *value);
+static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);
+
+/* Utility to jump whitespace and cr/lf */
+static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
+
+/* Parse an object - create a new root, and populate. */
+cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
+{
+ const char *end=0;
+ cJSON *c=cJSON_New_Item();
+ ep=0;
+ if (!c) return 0; /* memory fail */
+
+ end=parse_value(c,skip(value));
+ if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
+ if (return_parse_end) *return_parse_end=end;
+ return c;
+}
+/* Default options for cJSON_Parse */
+cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
+
+/* Render a cJSON item/entity/structure to text. */
+char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);}
+char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);}
+
+char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
+{
+ printbuffer p;
+ p.buffer=(char*)cJSON_malloc(prebuffer);
+ p.length=prebuffer;
+ p.offset=0;
+ return print_value(item,0,fmt,&p);
+ return p.buffer;
+}
+
+
+/* Parser core - when encountering text, process appropriately. */
+static const char *parse_value(cJSON *item,const char *value)
+{
+ if (!value) return 0; /* Fail on null. */
+ if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
+ if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
+ if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
+ if (*value=='\"') { return parse_string(item,value); }
+ if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
+ if (*value=='[') { return parse_array(item,value); }
+ if (*value=='{') { return parse_object(item,value); }
+
+ ep=value;return 0; /* failure. */
+}
+
+/* Render a value to text. */
+static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
+{
+ char *out=0;
+ if (!item) return 0;
+ if (p)
+ {
+ switch ((item->type)&255)
+ {
+ case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;}
+ case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;}
+ case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;}
+ case cJSON_Number: out=print_number(item,p);break;
+ case cJSON_String: out=print_string(item,p);break;
+ case cJSON_Array: out=print_array(item,depth,fmt,p);break;
+ case cJSON_Object: out=print_object(item,depth,fmt,p);break;
+ }
+ }
+ else
+ {
+ switch ((item->type)&255)
+ {
+ case cJSON_NULL: out=cJSON_strdup("null"); break;
+ case cJSON_False: out=cJSON_strdup("false");break;
+ case cJSON_True: out=cJSON_strdup("true"); break;
+ case cJSON_Number: out=print_number(item,0);break;
+ case cJSON_String: out=print_string(item,0);break;
+ case cJSON_Array: out=print_array(item,depth,fmt,0);break;
+ case cJSON_Object: out=print_object(item,depth,fmt,0);break;
+ }
+ }
+ return out;
+}
+
+/* Build an array from input text. */
+static const char *parse_array(cJSON *item,const char *value)
+{
+ cJSON *child;
+ if (*value!='[') {ep=value;return 0;} /* not an array! */
+
+ item->type=cJSON_Array;
+ value=skip(value+1);
+ if (*value==']') return value+1; /* empty array. */
+
+ item->child=child=cJSON_New_Item();
+ if (!item->child) return 0; /* memory fail */
+ value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+
+ while (*value==',')
+ {
+ cJSON *new_item;
+ if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
+ child->next=new_item;new_item->prev=child;child=new_item;
+ value=skip(parse_value(child,skip(value+1)));
+ if (!value) return 0; /* memory fail */
+ }
+
+ if (*value==']') return value+1; /* end of array */
+ ep=value;return 0; /* malformed. */
+}
+
+/* Render an array to text */
+static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
+{
+ char **entries;
+ char *out=0,*ptr,*ret;int len=5;
+ cJSON *child=item->child;
+ int numentries=0,i=0,fail=0;
+ size_t tmplen=0;
+
+ /* How many entries in the array? */
+ while (child) numentries++,child=child->next;
+ /* Explicitly handle numentries==0 */
+ if (!numentries)
+ {
+ if (p) out=ensure(p,3);
+ else out=(char*)cJSON_malloc(3);
+ if (out) strcpy(out,"[]");
+ return out;
+ }
+
+ if (p)
+ {
+ /* Compose the output array. */
+ i=p->offset;
+ ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++;
+ child=item->child;
+ while (child && !fail)
+ {
+ print_value(child,depth+1,fmt,p);
+ p->offset=update(p);
+ if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
+ child=child->next;
+ }
+ ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0;
+ out=(p->buffer)+i;
+ }
+ else
+ {
+ /* Allocate an array to hold the values for each */
+ entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+ if (!entries) return 0;
+ memset(entries,0,numentries*sizeof(char*));
+ /* Retrieve all the results: */
+ child=item->child;
+ while (child && !fail)
+ {
+ ret=print_value(child,depth+1,fmt,0);
+ entries[i++]=ret;
+ if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
+ child=child->next;
+ }
+
+ /* If we didn't fail, try to malloc the output string */
+ if (!fail) out=(char*)cJSON_malloc(len);
+ /* If that fails, we fail. */
+ if (!out) fail=1;
+
+ /* Handle failure. */
+ if (fail)
+ {
+ for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
+ cJSON_free(entries);
+ return 0;
+ }
+
+ /* Compose the output array. */
+ *out='[';
+ ptr=out+1;*ptr=0;
+ for (i=0;i<numentries;i++)
+ {
+ tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
+ if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
+ cJSON_free(entries[i]);
+ }
+ cJSON_free(entries);
+ *ptr++=']';*ptr++=0;
+ }
+ return out;
+}
+
+/* Build an object from the text. */
+static const char *parse_object(cJSON *item,const char *value)
+{
+ cJSON *child;
+ if (*value!='{') {ep=value;return 0;} /* not an object! */
+
+ item->type=cJSON_Object;
+ value=skip(value+1);
+ if (*value=='}') return value+1; /* empty array. */
+
+ item->child=child=cJSON_New_Item();
+ if (!item->child) return 0;
+ value=skip(parse_string(child,skip(value)));
+ if (!value) return 0;
+ child->string=child->valuestring;child->valuestring=0;
+ if (*value!=':') {ep=value;return 0;} /* fail! */
+ value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+
+ while (*value==',')
+ {
+ cJSON *new_item;
+ if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
+ child->next=new_item;new_item->prev=child;child=new_item;
+ value=skip(parse_string(child,skip(value+1)));
+ if (!value) return 0;
+ child->string=child->valuestring;child->valuestring=0;
+ if (*value!=':') {ep=value;return 0;} /* fail! */
+ value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+ }
+
+ if (*value=='}') return value+1; /* end of array */
+ ep=value;return 0; /* malformed. */
+}
+
+/* Render an object to text. */
+static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
+{
+ char **entries=0,**names=0;
+ char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
+ cJSON *child=item->child;
+ int numentries=0,fail=0;
+ size_t tmplen=0;
+ /* Count the number of entries. */
+ while (child) numentries++,child=child->next;
+ /* Explicitly handle empty object case */
+ if (!numentries)
+ {
+ if (p) out=ensure(p,fmt?depth+4:3);
+ else out=(char*)cJSON_malloc(fmt?depth+4:3);
+ if (!out) return 0;
+ ptr=out;*ptr++='{';
+ if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
+ *ptr++='}';*ptr++=0;
+ return out;
+ }
+ if (p)
+ {
+ /* Compose the output: */
+ i=p->offset;
+ len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0;
+ *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len;
+ child=item->child;depth++;
+ while (child)
+ {
+ if (fmt)
+ {
+ ptr=ensure(p,depth); if (!ptr) return 0;
+ for (j=0;j<depth;j++) *ptr++='\t';
+ p->offset+=depth;
+ }
+ print_string_ptr(child->string,p);
+ p->offset=update(p);
+
+ len=fmt?2:1;
+ ptr=ensure(p,len); if (!ptr) return 0;
+ *ptr++=':';if (fmt) *ptr++='\t';
+ p->offset+=len;
+
+ print_value(child,depth,fmt,p);
+ p->offset=update(p);
+
+ len=(fmt?1:0)+(child->next?1:0);
+ ptr=ensure(p,len+1); if (!ptr) return 0;
+ if (child->next) *ptr++=',';
+ if (fmt) *ptr++='\n';*ptr=0;
+ p->offset+=len;
+ child=child->next;
+ }
+ ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0;
+ if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
+ *ptr++='}';*ptr=0;
+ out=(p->buffer)+i;
+ }
+ else
+ {
+ /* Allocate space for the names and the objects */
+ entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+ if (!entries) return 0;
+ names=(char**)cJSON_malloc(numentries*sizeof(char*));
+ if (!names) {cJSON_free(entries);return 0;}
+ memset(entries,0,sizeof(char*)*numentries);
+ memset(names,0,sizeof(char*)*numentries);
+
+ /* Collect all the results into our arrays: */
+ child=item->child;depth++;if (fmt) len+=depth;
+ while (child)
+ {
+ names[i]=str=print_string_ptr(child->string,0);
+ entries[i++]=ret=print_value(child,depth,fmt,0);
+ if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
+ child=child->next;
+ }
+
+ /* Try to allocate the output string */
+ if (!fail) out=(char*)cJSON_malloc(len);
+ if (!out) fail=1;
+
+ /* Handle failure */
+ if (fail)
+ {
+ for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
+ cJSON_free(names);cJSON_free(entries);
+ return 0;
+ }
+
+ /* Compose the output: */
+ *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
+ for (i=0;i<numentries;i++)
+ {
+ if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
+ tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
+ *ptr++=':';if (fmt) *ptr++='\t';
+ strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
+ if (i!=numentries-1) *ptr++=',';
+ if (fmt) *ptr++='\n';*ptr=0;
+ cJSON_free(names[i]);cJSON_free(entries[i]);
+ }
+
+ cJSON_free(names);cJSON_free(entries);
+ if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
+ *ptr++='}';*ptr++=0;
+ }
+ return out;
+}
+
+/* Get Array size/item / object item. */
+int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
+cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
+cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
+/* Utility for handling references. */
+static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
+
+/* Add item to array/object. */
+void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
+void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
+void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
+void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
+void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
+
+cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
+ if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
+void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
+cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
+void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
+
+/* Replace array/object items with new ones. */
+void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
+ newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
+void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
+ newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
+ if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
+void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
+
+/* Create basic types: */
+cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
+cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
+cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
+cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
+cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
+cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
+cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
+cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
+
+/* Create Arrays: */
+cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+
+/* Duplication */
+cJSON *cJSON_Duplicate(cJSON *item,int recurse)
+{
+ cJSON *newitem,*cptr,*nptr=0,*newchild;
+ /* Bail on bad ptr */
+ if (!item) return 0;
+ /* Create new item */
+ newitem=cJSON_New_Item();
+ if (!newitem) return 0;
+ /* Copy over all vars */
+ newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
+ if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
+ if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
+ /* If non-recursive, then we're done! */
+ if (!recurse) return newitem;
+ /* Walk the ->next chain for the child. */
+ cptr=item->child;
+ while (cptr)
+ {
+ newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild) {cJSON_Delete(newitem);return 0;}
+ if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
+ cptr=cptr->next;
+ }
+ return newitem;
+}
+
+void cJSON_Minify(char *json)
+{
+ char *into=json;
+ while (*json)
+ {
+ if (*json==' ') json++;
+ else if (*json=='\t') json++; /* Whitespace characters. */
+ else if (*json=='\r') json++;
+ else if (*json=='\n') json++;
+ else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */
+ else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */
+ else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */
+ else *into++=*json++; /* All other characters. */
+ }
+ *into=0; /* and null-terminate. */
+}
diff --git a/src/comm_audit.cpp b/src/comm_audit.cpp
new file mode 100644
index 0000000..5ffaa05
--- /dev/null
+++ b/src/comm_audit.cpp
@@ -0,0 +1,968 @@
+/*
+ * comm_audit.cpp
+ *
+ * Created on: 2017-8-14
+ * Last Modified: 2017-11-24
+ * Author: zhangxi
+ */
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <atomic>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "project_requirement.h"
+#include "identify.h"
+#include "cJSON.h"
+#include "comm_audit.h"
+#include "maxminddb.h"
+//#define LOG_DEBUG 0
+
+using namespace std;
+
+int COMM_AUDIT_VERSION_20171124 = 0;
+
+comm_prog_configure_t g_comm_prog_configure;
+comm_prog_runtime_parameter_t g_comm_prog_para;
+atomic_flag lock = ATOMIC_FLAG_INIT;
+
+static int log_nums;
+static int times = 0;
+static int log = 0;
+static int now = 0;
+// static char FDIR[12]={0};
+
+
+//获取IP归属地
+int get_ip_coun(char * filename, char *ip_address, char ** name_en)
+{
+ MMDB_s mmdb;
+ int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
+
+ if(MMDB_SUCCESS != status)
+ {
+ //fprintf(stderr, "\n Can't open %s - %s\n",filename, MMDB_strerror(status));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR", "Can't open %s - %s\n",filename, MMDB_strerror(status));
+ if(MMDB_IO_ERROR == status)
+ {
+ //fprintf(stderr, "IO error: %s\n", strerror(errno));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","IO error: %s\n", strerror(errno));
+ }
+ return 1; //error
+ }
+
+ int gai_error, mmdb_error;
+
+ MMDB_lookup_result_s result =
+ MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error);
+
+ if (0 != gai_error)
+ {
+ fprintf(stderr, "\n Error from getaddrinfo for %s - %s\n\n", ip_address, gai_strerror(gai_error));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","Error from getaddrinfo for %s - %s", ip_address, gai_strerror(gai_error));
+ return 2; //error
+ }
+
+ if (MMDB_SUCCESS != mmdb_error)
+ {
+ fprintf(stderr,"\n Got an error from libmaxminddb: %s\n\n", MMDB_strerror(mmdb_error));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","Got an error from libmaxminddb: %s", MMDB_strerror(mmdb_error));
+ return 3; //error
+ }
+
+ MMDB_entry_data_s entry_data;
+
+ int exit_code = 0;
+ if (result.found_entry)
+ {
+
+ int status = MMDB_get_value(&result.entry, &entry_data, "COUNTRY", NULL);
+
+ if (MMDB_SUCCESS != status)
+ {
+ fprintf(stderr,"Got an error looking up the entry data - %s\n", MMDB_strerror(status));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","Got an error looking up the entry data - %s\n", MMDB_strerror(status));
+ exit_code = 4;
+ goto end;
+ }
+
+ if (entry_data.has_data)
+ {
+ *name_en = (char *)malloc(sizeof(entry_data.data_size + 1));
+ memset(*name_en, '\0', sizeof(entry_data.data_size + 1));
+ memcpy(*name_en, entry_data.utf8_string, entry_data.data_size);
+ //printf ("%s\n", name_en);
+ }
+ }
+ else
+ {
+ //fprintf(stderr,"\n No entry for this IP address (%s) was found\n\n", ip_address);
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","No entry for this IP address (%s) was found", ip_address);
+ exit_code = 5;
+ }
+
+end:
+ MMDB_close(&mmdb);
+ //exit(exit_code);
+ return exit_code;
+}
+
+
+//读取json格式文件
+void parseJson(char * buf)
+{
+ if(NULL == buf)
+ {
+ return;
+ }
+ cJSON * json = cJSON_Parse(buf);
+ if (!json)
+ {
+ printf("JSON FILE READ FAIL! PLEASE CHECK net_log_upload_pz.txt's FORMAT.\n");
+ printf("USE LAST UPLOAD_PZ NOW.\n");
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "UPLOAD_PZ JSON FILE READ FAIL!ERROR NUM IS %s.", strerror(errno));
+ }
+ else
+ {
+ int size = cJSON_GetArraySize(json);
+ cJSON *object;
+ for(int i = 0; i < size; i++)
+ {
+ object = cJSON_GetArrayItem(json,i);
+ int interval = cJSON_GetObjectItem(object, "interval")->valueint;
+ int max_num = cJSON_GetObjectItem(object, "num")->valueint;
+ if(interval != g_comm_prog_configure.write_interval || max_num != g_comm_prog_configure.write_max_num)
+ {
+ g_comm_prog_configure.write_interval = interval;
+ g_comm_prog_configure.write_max_num = max_num;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "INFO", "UPLOAD_PZ JSON FILE READ SUCC! interval is %d, num is %d.", g_comm_prog_configure.write_interval, g_comm_prog_configure.write_max_num);
+ }
+ }
+ }
+
+ cJSON_Delete(json);
+}
+
+
+void read_json_file(int num)
+{
+
+ string read_path = g_comm_prog_configure.upload_pz_path;
+ if (read_path[read_path.size() - 1] != '/')
+ read_path+='/';
+
+ fstream handle;
+ string in_file_name = read_path + "net_log_upload_pz.txt";
+ handle.open(in_file_name.c_str(), ios::binary|ios::in);
+ if(handle.is_open())
+ {
+ char *buf = new char[MAX_LEN];
+ handle.read(buf, MAX_LEN);
+ parseJson(buf);
+ handle.close();
+
+ delete buf;
+ }
+
+}
+
+// 定时读取json线程
+void *set_timer(void * pParam)
+{
+ signal(SIGALRM, read_json_file);
+
+ struct itimerval tick;
+ tick.it_value.tv_sec = 1; //1秒钟后将启动定时器
+ tick.it_value.tv_usec = 0;
+ tick.it_interval.tv_sec = g_comm_prog_configure.read_interval; //定时器启动后,每隔指定秒数将执行相应的函数
+ tick.it_interval.tv_usec = 0;
+
+ //setitimer将触发SIGALRM信号
+ int ret = setitimer(ITIMER_REAL, &tick, NULL);
+
+ if ( ret != 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "SET TIMER ERROR! ERROR NUM IS %s.", strerror(errno));
+ return NULL;
+ }
+
+ while(1){sleep(1);}
+
+}
+
+// 写数据
+int send_data(htable_data_t* send_data, FILE *fp)
+{
+ log = 1;
+ long long EndTime;
+ EndTime = time(NULL);
+
+ char stime[24];
+ struct tm stm;
+ time_t sTime = (time_t)send_data->start_time;
+ localtime_r(&sTime, &stm);
+ sprintf(stime, "%d-%02d-%02d %d:%d:%d", stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec);
+
+ char etime[24];
+ struct tm ptm;
+ time_t eTime;
+ if(send_data->end_time == 0)
+ eTime = (time_t)EndTime;
+ else
+ eTime = (time_t)send_data->end_time;
+ localtime_r(&eTime, &ptm);
+ sprintf(etime, "%d-%02d-%02d %d:%d:%d", ptm.tm_year+1900, ptm.tm_mon+1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
+ // memcpy(stat_info->time_data.end_time, etime, 24);
+
+ char sendInnerIP[IPLEN]={0};
+ inet_ntop(AF_INET, &send_data->inner_ip, sendInnerIP ,IPLEN);
+ // sprintf(sendInnerIP, "%s", inet_ntop(AF_INET, &send_data->inner_ip, sendInnerIP ,IPLEN));
+ char sendExtIP[IPLEN]={0};
+ inet_ntop(AF_INET, &send_data->ext_ip, sendExtIP ,IPLEN);
+ // sprintf(sendExtIP, "%s", inet_ntop(AF_INET, &send_data->ext_ip, sendExtIP ,IPLEN));
+
+ string app = APP_TYPE(send_data->app);
+ string protocol = STREAM_TYPE(send_data->protocol);
+ string tcp_flag = TCP_FLAG(send_data->tcp_flag);
+
+ fprintf(fp, "%s#%u#%s#%s#%u#%s#%s#%s#%s#%llu#%llu#%llu#%llu#%s#%s\n",
+ sendInnerIP,
+ ntohs(send_data->inner_port),
+ send_data->inner_mac,
+ sendExtIP,
+ ntohs(send_data->ext_port),
+ send_data->ext_mac,
+ protocol.c_str(),
+ app.c_str(),
+ tcp_flag.c_str(),
+ send_data->in_bytes,
+ send_data->out_bytes,
+ send_data->in_pkts,
+ send_data->out_pkts,
+ stime,
+ etime
+ );
+ // log_nums条记录写入一个txt
+ if(log_nums < g_comm_prog_configure.write_max_num-1)
+ log_nums++;
+ else
+ {
+ log_nums = 0;
+ times++;
+ }
+
+ return 0;
+}
+
+// 遍历哈希表写文件
+void iterate_cb(const uchar * key, uint size, void * data, void *arg)
+{
+ htable_data_t* info = (htable_data_t*)data;
+ char * writetime = ((del_para_t*)arg)->writetime;
+ int thread_seq = ((del_para_t*)arg)->thread_seq;
+ char writefile[50];
+ writefile[0]='\0';
+
+ // string write_path = g_comm_prog_configure.upload_log_path;
+ // if (write_path[write_path.size() - 1] != '/')
+ // write_path+='/';
+ // #ifdef LOG_DEBUG
+ // cout<<"write_path:"<<write_path<<endl;
+ // #endif
+
+ string tmp_log_path = g_comm_prog_configure.tmp_log_path;
+ if (tmp_log_path[tmp_log_path.size() - 1] != '/')
+ tmp_log_path+='/';
+#ifdef LOG_DEBUG
+ cout<<"tmp_log_path:"<<tmp_log_path<<endl;
+#endif
+
+ sprintf(writefile, "%s%s-%d.txt", tmp_log_path.c_str(), writetime, times);
+#ifdef LOG_DEBUG
+ cout<<"writefile:"<<writefile<<endl;
+#endif
+
+ FILE *fp = fopen(writefile, "a+");
+ if(fp != NULL)
+ {
+ send_data(info, fp);
+ }
+ else
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "FOPEN ERROR! ERROR NUM IS %s.", strerror(errno));
+ }
+ fclose(fp);
+ fp = NULL;
+
+ /*
+ if(log_nums == 0 && log == 1)
+ {
+ g_comm_prog_para.last_send_time = time(NULL);
+
+ char cmd[200] = {0};
+ sprintf(cmd, "cd %s; gzip -q %s-%d.txt; mv *.gz %s%s", g_comm_prog_configure.tmp_log_path, writetime, times-1, write_path.c_str(), FDIR);
+ // system(cmd);
+ FILE * ret = popen(cmd, "w");
+ if(!ret)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s IS FAILED! ERROR NUM IS %s",cmd, strerror(errno));
+ else
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "Pack %s/%s.gz is submit.", FDIR, writetime);
+ pclose(ret);
+ }
+ */
+
+ if(MESA_htable_del(g_comm_prog_para.htable_handle[thread_seq][1], key, size, NULL) < 0)
+ {
+ perror("MESA_htable_del()");
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MESA_htable_del error!");
+ }
+}
+
+// 写日志线程
+void * thread_time(void * pParam)
+{
+ while(1)
+ {
+
+ int last;
+ if(g_comm_prog_configure.write_interval <= 0)
+ {
+ g_comm_prog_configure.write_interval = 1;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "write_interval arg is not more than 0! reset interval to 1.");
+ }
+
+ time_t sTime = (time_t)g_comm_prog_para.last_send_time;
+ struct tm stm;
+ localtime_r(&sTime, &stm);
+ last = stm.tm_hour * 10000 + stm.tm_min * 100 + stm.tm_sec;
+
+ // sprintf(FDIR, "%d-%02d-%02d", stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday);
+ // char mkdir[50]={0};
+ // sprintf(mkdir, "mkdir -p %s/%s", g_comm_prog_configure.upload_log_path, FDIR);
+ // FILE * ret = popen(mkdir, "w");
+ // if(!ret)
+ // MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s FAILED! ERROR IS %s",mkdir, strerror(errno));
+ // pclose(ret);
+
+ char FNAME[10];
+ char TXT[8];
+ sprintf(FNAME, "%d-%d-%d", stm.tm_hour, stm.tm_min, stm.tm_sec);
+ //sprintf(TXT, "%d-%d-%d", stm.tm_hour, stm.tm_min, stm.tm_sec);
+ sprintf(TXT, "%d%02d%02d", stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday);
+ //sprintf(etime, "%d-%d-%d %d:%d:%d", ptm.tm_year+1900, ptm.tm_mon+1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
+
+ // times = 1;
+ log_nums = 0;
+ if(g_comm_prog_configure.write_max_num <= 0)
+ {
+ g_comm_prog_configure.write_max_num = 1000;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "write_interval arg is not more than 0! reset interval to 1000.");
+ }
+
+ sleep(g_comm_prog_configure.sleep);
+
+ // pthread_mutex_lock(&g_comm_prog_para.mutex);
+ while (lock.test_and_set(std::memory_order_acquire)); // spin
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ MESA_htable_handle tmp = g_comm_prog_para.htable_handle[i][0];
+ g_comm_prog_para.htable_handle[i][0] = g_comm_prog_para.htable_handle[i][1];
+ g_comm_prog_para.htable_handle[i][1] = tmp;
+ }
+ lock.clear(std::memory_order_release); // release lock
+ // pthread_mutex_unlock(&g_comm_prog_para.mutex);
+
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ del_para_t arg;
+ arg.writetime = TXT;
+ arg.thread_seq = i;
+ MESA_htable_iterate(g_comm_prog_para.htable_handle[i][1], iterate_cb, (void *)&arg);
+ }
+
+ sTime = (time_t)g_comm_prog_para.last_send_time;
+ localtime_r(&sTime, &stm);
+ last = stm.tm_hour * 10000 + stm.tm_min * 100 + stm.tm_sec;
+
+ long long NowTime = time(NULL);
+ time_t eTime = (time_t)NowTime;
+ struct tm ptm;
+ localtime_r(&eTime, &ptm);
+ now = ptm.tm_hour * 10000 + ptm.tm_min * 100 + ptm.tm_sec;
+
+
+ if(log == 1)
+ {
+ if(now - last >= g_comm_prog_configure.write_interval * 100)
+ {
+ /*
+ char cmd[200] = {0};
+ string log_path = g_comm_prog_configure.upload_log_path;
+ if (log_path[log_path.size() - 1] != '/')
+ log_path+='/';
+#ifdef LOG_DEBUG
+cout<<"log_path:"<<log_path<<endl;
+#endif
+
+sprintf(cmd, "cd %s; count=`ls|grep .txt|wc -l`; if [[ $count -gt 0 ]]; then tar -zcf %s%s/%s.tar.gz *.txt; rm -f *.txt; fi;", \
+g_comm_prog_configure.tmp_log_path, log_path.c_str(), FDIR, FNAME);
+#ifdef LOG_DEBUG
+cout<<cmd<<endl;
+#endif
+
+FILE * ret = popen(cmd, "w");
+if(!ret)
+MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MKDIR IS FAILED! ERROR IS %s",strerror(errno));
+else
+MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "Pack %s/%s.tar.gz is submit.", FDIR, FNAME);
+pclose(ret);
+*/
+ times++;
+ g_comm_prog_para.last_send_time = time(NULL);
+ }
+ else if(now < last)
+ {
+ times = 1;
+ g_comm_prog_para.last_send_time = time(NULL);
+ }
+ }
+ }
+ return NULL;
+
+}
+
+
+static long search_cb(void* data, const uchar* key, uint size, void* arg)
+{
+ if(data == NULL)
+ return -1;
+
+ struct streaminfo * a_stream = (struct streaminfo *)((htable_search_arg *)arg)->stream;
+ void * a_packet = (void *)((htable_search_arg *)arg)->packet;
+ int is_end = ((htable_search_arg *)arg)->is_end;
+ htable_data_t * info = (htable_data_t *)data;
+
+ if(a_stream->type == STREAM_TYPE_TCP)
+ {
+ struct tcpdetail* a_tcp = (struct tcpdetail*)(a_stream->ptcpdetail);
+ if(a_stream->curdir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ info->out_bytes += a_tcp->datalen;
+ info->out_pkts++;
+ }
+ else
+ {
+ info->in_bytes += a_tcp->datalen;
+ info->in_pkts++;
+ }
+ // struct tcpdetail* a_tcp = (struct tcpdetail*)(a_stream->ptcpdetail);
+ // info->tcp_flag = info->tcp_flag & a_stream->stream_state;
+ if(a_packet != NULL)
+ {
+ struct tcphdr* tcp_header = (struct tcphdr*)(a_packet + sizeof(struct iphdr));
+ info->tcp_flag = 32*tcp_header->urg + 16*tcp_header->ack + 8*tcp_header->psh + 4*tcp_header->rst + \
+ 2*tcp_header->syn + tcp_header->fin;
+ }
+ }
+ else
+ {
+ struct udpdetail* a_udp = (struct udpdetail*)(a_stream->pudpdetail);
+ if(a_stream->curdir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ info->out_bytes += a_udp->datalen;
+ info->out_pkts++;
+ }
+ else
+ {
+ info->in_bytes += a_udp->datalen;
+ info->in_pkts++;
+ }
+ info->tcp_flag = 0;
+ }
+ if(is_end)
+ info->end_time = time(NULL);
+
+ return 0;
+}
+
+
+
+int judge_ip_location(unsigned int inner_ip, char ** inner_name_en, unsigned int ext_ip, char ** ext_name_en)
+{
+ char innerIP[IPLEN] = {0};
+ char extIP[IPLEN] = {0};
+ int res1 = 0;
+ int res2 = 0;
+ //char * inner_name_en = NULL;
+ //char * ext_name_en = NULL;
+ inet_ntop(AF_INET, &inner_ip, innerIP ,IPLEN);
+ inet_ntop(AF_INET, &ext_ip, extIP ,IPLEN);
+ res1 = get_ip_coun(g_comm_prog_configure.mmdb_path, innerIP, inner_name_en);
+ res2 = get_ip_coun(g_comm_prog_configure.mmdb_path, extIP, ext_name_en);
+ if(0 != res1 && 0 != res2)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "JUDGE_IP", "judge_innerip_location INNER[%s] EXT[%s] error!", innerIP, extIP);
+ return 0;
+ }
+ if ((NULL!=*inner_name_en && 0!=strncmp(*inner_name_en, "China", 5)) || (NULL!=*ext_name_en && 0 != strncmp(*ext_name_en, "China", 5))) //有境外IP
+ {
+ return 1;
+ }
+ else //全部都是境内IP
+ {
+ return 2;
+ }
+}
+
+
+void time_mode_op(struct streaminfo* a_stream, int thread_seq, void * a_packet, int state, int is_end)
+{
+ stDntyProInfo * pro_info = (stDntyProInfo *)project_req_get_struct(a_stream,g_comm_prog_para.project_id_pro);
+ if(pro_info == NULL)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "project_req_get_struct is NULL. LACK OF IDENTIFY'S CONF!");
+ return ;
+ }
+
+ long ret;
+ int judge_res = 0;
+
+ htable_search_arg arg;
+ arg.stream = a_stream;
+ arg.packet = a_packet;
+
+ // pthread_mutex_lock(&g_comm_prog_para.mutex);
+ if(NULL == MESA_htable_search_cb(g_comm_prog_para.htable_handle[thread_seq][0], (unsigned char*)&a_stream->addr, sizeof(a_stream->addr), search_cb, (void *)&arg, &ret))
+ {
+ htable_data_t * value = (htable_data_t*)calloc(1, sizeof(htable_data_t));
+ if(a_stream->addr.addrtype == ADDR_TYPE_IPV4)
+ {
+ value->inner_ip = a_stream->addr.tuple4_v4->saddr;
+ value->inner_port = a_stream->addr.tuple4_v4->source;
+ value->ext_ip = a_stream->addr.tuple4_v4->daddr;
+ value->ext_port = a_stream->addr.tuple4_v4->dest;
+ if(g_comm_prog_configure.flag == 0) //flag == 0, 只记录包含境外IP的通联数据
+ {
+ char * inner_name_en = NULL;
+ char * ext_name_en = NULL;
+ judge_res = judge_ip_location(value->inner_ip, &inner_name_en, value->ext_ip, &ext_name_en);
+ if(judge_res == 0) //查找IP归属失败,仍然记录
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "find IP[%u or %u] location error!.", value->inner_ip, value->ext_ip);
+ }
+ else if(judge_res == 1) //有境外IP,需要记录
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "find IP1[%u:%s] IP2[%u:%s].", value->inner_ip,inner_name_en, value->ext_ip, ext_name_en);
+ }
+ else if(judge_res == 2) //全都是境内IP,不做记录,直接返回
+ {
+ return ;
+ }
+ }
+ }
+ if(a_stream->type == STREAM_TYPE_TCP)
+ {
+ struct tcpdetail* a_tcp = (struct tcpdetail*)(a_stream->ptcpdetail);
+ if(a_stream->routedir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ value->in_bytes = 0;
+ value->in_pkts = 0;
+ value->out_bytes = a_tcp->datalen;
+ value->out_pkts = 1;
+ }
+ else
+ {
+ value->in_bytes = a_tcp->datalen;
+ value->in_pkts = 1;
+ value->out_bytes = 0;
+ value->out_pkts = 0;
+ }
+ if(a_packet != NULL)
+ {
+ struct tcphdr* tcp_header = (struct tcphdr*)(a_packet + sizeof(struct iphdr));
+ value->tcp_flag = 32*tcp_header->urg + 16*tcp_header->ack + 8*tcp_header->psh + 4*tcp_header->rst + 2*tcp_header->syn + tcp_header->fin;
+ }
+ }
+ else
+ {
+ struct udpdetail* a_udp = (struct udpdetail*)(a_stream->pudpdetail);
+ if(a_stream->routedir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ value->in_bytes = 0;
+ value->in_pkts = 0;
+ value->out_bytes = a_udp->datalen;
+ value->out_pkts = 1;
+ }
+ else
+ {
+ value->in_bytes = a_udp->datalen;
+ value->in_pkts = 1;
+ value->out_bytes = 0;
+ value->out_pkts = 0;
+ }
+ value->tcp_flag = 0;
+ }
+
+ value->protocol = a_stream->type;
+ value->app = pro_info->protocol_type;
+
+ struct streaminfo *father = a_stream->pfather;
+ while(father)
+ {
+ if(father->addr.addrtype != ADDR_TYPE_MAC)
+ {
+ father = father->pfather;
+ continue;
+ }
+ else
+ {
+ memset(value->inner_mac, 0, 60);
+ sprintf(value->inner_mac, "%02x-%02x-%02x-%02x-%02x-%02x", father->addr.mac->src_mac[0], father->addr.mac->src_mac[1],\
+ father->addr.mac->src_mac[2], father->addr.mac->src_mac[3], father->addr.mac->src_mac[4], father->addr.mac->src_mac[5]);
+ memset(value->ext_mac, 0, 60);
+ sprintf(value->ext_mac, "%02x-%02x-%02x-%02x-%02x-%02x", father->addr.mac->dst_mac[0], father->addr.mac->dst_mac[1],\
+ father->addr.mac->dst_mac[2], father->addr.mac->dst_mac[3], father->addr.mac->dst_mac[4], father->addr.mac->dst_mac[5]);
+ break;
+ }
+ }
+
+ value->start_time = time(NULL);
+ value->end_time = 0;
+
+ if(MESA_htable_add(g_comm_prog_para.htable_handle[thread_seq][0], (const unsigned char *)&a_stream->addr, \
+ sizeof(a_stream->addr), (void *)value) < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "htable_add error.ERROR IS %s.", strerror(errno));
+ free(value);
+ value = NULL;
+ }
+ }
+ // pthread_mutex_unlock(&g_comm_prog_para.mutex);
+ // free(arg);
+ // arg = NULL;
+}
+
+
+char op_state_data(struct streaminfo *a_stream, void **pme, int thread_seq, void *a_packet, int state, int is_end)
+{
+ // struct tcpdetail *pdetail = (struct tcpdetail*)a_stream->ptcpdetail;
+ // comm_audit_t* stat_info = (comm_audit_t*)(*pme);
+ // assert(stat_info != NULL);
+
+ if(a_packet == NULL && state != OP_STATE_CLOSE)
+ return APP_STATE_GIVEME;
+
+ time_mode_op(a_stream, thread_seq, a_packet, state, is_end);
+
+ return APP_STATE_GIVEME;
+}
+
+// char op_state_pending(struct streaminfo *a_stream, void **pme, int thread_seq,void *a_packet, int state, int is_end)
+// {
+// // init_pme_info(pme);
+
+// op_state_data(a_stream, pme, thread_seq, a_packet, state, is_end);
+
+// return APP_STATE_GIVEME;
+// }
+
+
+char op_state_close(struct streaminfo *a_stream, void **pme, int thread_seq,void *a_packet, int state, int is_end)
+{
+ op_state_data(a_stream, pme, thread_seq, a_packet, state, is_end);
+
+ // free_pme_info(pme);
+
+ return APP_STATE_DROPME;
+}
+
+
+char COMM_AUDIT_ENTRY(struct streaminfo *a_stream, void **pme, int thread_seq, void *a_packet)
+{
+ if(g_comm_prog_configure.flag == 2) //flag == 2,不记录任何通联数据,直接返回
+ {
+ return APP_STATE_DROPME;
+ }
+ char ret = APP_STATE_GIVEME;
+ int state;
+ if(a_stream->type == STREAM_TYPE_TCP)
+ state = a_stream->pktstate;
+ else
+ state = a_stream->opstate;
+ int is_end = 0;
+ switch(state)
+ {
+ case OP_STATE_PENDING:
+ case OP_STATE_DATA:
+ ret = op_state_data(a_stream, pme, thread_seq, a_packet, state, is_end);
+ break;
+
+ case OP_STATE_CLOSE:
+ is_end=1;
+ ret = op_state_close(a_stream, pme, thread_seq, a_packet, state, is_end);
+ break;
+
+ default:
+ ret = APP_STATE_DROPME;
+ break;
+ }
+
+ return ret;
+}
+
+void htable_del1(const uchar * key, uint size, void * data, void * arg)
+{
+ int thread_seq = *(int*)arg;
+ if(MESA_htable_del(g_comm_prog_para.htable_handle[thread_seq][0], key, size, NULL) < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MESA_htable_del error!");
+ }
+}
+
+void htable_del2(const uchar * key, uint size, void * data, void * arg)
+{
+ int thread_seq = *(int*)arg;
+ if(MESA_htable_del(g_comm_prog_para.htable_handle[thread_seq][1], key, size, NULL) < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MESA_htable_del error!");
+ }
+}
+
+void COMM_AUDIT_DESTROY()
+{
+
+ // free(g_comm_prog_configure.upload_log_path);
+ free(g_comm_prog_configure.tmp_log_path);
+ free(g_comm_prog_configure.upload_pz_path);
+
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ if(MESA_htable_iterate(g_comm_prog_para.htable_handle[i][0], htable_del1, (void*)&i) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_iterate error!");
+ // printf("iterate error!\n");
+ if(MESA_htable_destroy(g_comm_prog_para.htable_handle[i][0], NULL) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_destroy error!");
+ // printf("destroy error!\n");
+
+ if(MESA_htable_iterate(g_comm_prog_para.htable_handle[i][1], htable_del2, (void*)&i) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_iterate error!");
+ // printf("iterate error!\n");
+ if(MESA_htable_destroy(g_comm_prog_para.htable_handle[i][1], NULL) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_destroy error!");
+ // printf("destroy error!\n");
+ }
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ free(g_comm_prog_para.htable_handle[i]);
+ free(g_comm_prog_para.htable_handle);
+
+ pthread_exit(NULL);
+ //printf("destroy COMM_AUDIT_DESTROY success!\n");
+
+}
+
+void htable_free(void * data)
+{
+ htable_data_t * info = (htable_data_t *)data;
+ free(info);
+ data = NULL;
+}
+
+int init_hash_table()
+{
+ MESA_htable_handle ** handle = (MESA_htable_handle**)malloc(g_comm_prog_para.thread_num*sizeof(MESA_htable_handle*));
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ handle[i] = (MESA_htable_handle*)malloc(2 * sizeof(MESA_htable_handle));
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ MESA_htable_create_args_t htable_args1;
+ memset(&htable_args1, 0, sizeof(htable_args1));
+ htable_args1.recursive = 1;
+ htable_args1.thread_safe = 0;
+ htable_args1.hash_slot_size = 4096*4096;
+ htable_args1.max_elem_num = g_comm_prog_configure.htable_size;
+ htable_args1.data_free = htable_free;
+ htable_args1.data_expire_with_condition = NULL;
+ htable_args1.eliminate_type = HASH_ELIMINATE_ALGO_LRU;
+ htable_args1.expire_time = 0;
+ handle[i][0] = MESA_htable_create(&htable_args1, sizeof(htable_args1));
+ if(handle[i][0] == NULL)
+ return -1;
+
+ MESA_htable_create_args_t htable_args2;
+ memset(&htable_args2, 0, sizeof(htable_args2));
+ htable_args2.recursive = 1;
+ htable_args2.thread_safe = 0;
+ htable_args2.hash_slot_size = 4096*4096;
+ htable_args2.max_elem_num = g_comm_prog_configure.htable_size;
+ htable_args2.data_free = htable_free;
+ htable_args2.data_expire_with_condition = NULL;
+ htable_args2.eliminate_type = HASH_ELIMINATE_ALGO_LRU;
+ htable_args2.expire_time = 0;
+ handle[i][1] = MESA_htable_create(&htable_args2, sizeof(htable_args2));
+ if(handle[i][1] == NULL)
+ return -1;
+ }
+
+ g_comm_prog_para.htable_handle = handle;
+ return 0;
+}
+
+int comm_read_conf(const char *file_name)
+{
+ short log_level = 30;
+ char log_filename[256];
+ log_filename[0]='\0';
+ int ret;
+
+ if(MESA_load_profile_short_nodef(file_name, "DEFAULT", "log_level", (short*)&log_level)<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] log_level error!");
+ return -1;
+ }
+ if(MESA_load_profile_string_nodef(file_name, "DEFAULT", "log_path", log_filename, sizeof(log_filename))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] log_path error!");
+ return -1;
+ }
+ g_comm_prog_para.log_handle = MESA_create_runtime_log_handle(log_filename, log_level);
+ if(g_comm_prog_para.log_handle == NULL)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "Create log_handle error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name, "DEFAULT", "htable_size", (int*)&g_comm_prog_configure.htable_size))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] htable_size error!");
+ return -1;
+ }
+ if((ret=MESA_load_profile_int_nodef(file_name, "DEFAULT", "sleep", (int*)&g_comm_prog_configure.sleep))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] sleep error!");
+ return -1;
+ }
+ if(g_comm_prog_configure.sleep <= 0)
+ {
+ g_comm_prog_configure.sleep = 10;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "comm_read_conf",\
+ "conf [DEFAULT] sleep is not more than 0! Reset interval to 10.");
+ }
+
+
+ // g_comm_prog_configure.upload_log_path = (char *)calloc(1, 256*sizeof(char));
+ // if((ret=MESA_load_profile_string_nodef(file_name, "UPLOAD_LOG", "upload_log_path", g_comm_prog_configure.upload_log_path, 256*sizeof(char)))<0)
+ // {
+ // MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_LOG] upload_log_path error!");
+ // return -1;
+ // }
+ // char upload_log_path[50]={0};
+ // sprintf(upload_log_path, "mkdir -p %s", g_comm_prog_configure.upload_log_path);
+ // FILE * pret = popen(upload_log_path, "w");
+ // if(!pret)
+ // MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s IS FAILED! ERROR IS %s",upload_log_path, strerror(errno));
+ // pclose(pret);
+
+ g_comm_prog_configure.tmp_log_path = (char *)calloc(1, 256*sizeof(char));
+ if((ret=MESA_load_profile_string_nodef(file_name, "UPLOAD_LOG", "tmp_log_path", g_comm_prog_configure.tmp_log_path, 256*sizeof(char)))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_LOG] tmp_log_path error!");
+ return -1;
+ }
+ char tmp_log_path[50]={0};
+ sprintf(tmp_log_path, "mkdir -p %s", g_comm_prog_configure.tmp_log_path);
+ FILE * pret = popen(tmp_log_path, "w");
+ if(!pret)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s IS FAILED! ERROR IS %s",tmp_log_path, strerror(errno));
+ pclose(pret);
+
+
+ g_comm_prog_configure.upload_pz_path = (char *)calloc(1, 256*sizeof(char));
+ if((ret=MESA_load_profile_string_nodef(file_name, "UPLOAD_PZ", "upload_pz_path", g_comm_prog_configure.upload_pz_path,256*sizeof(char)))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] upload_pz_path error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"UPLOAD_PZ","read_upload_pz_interval",&g_comm_prog_configure.read_interval))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] read_upload_pz_interval error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"UPLOAD_PZ","default_upload_interval",&g_comm_prog_configure.write_interval))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] default_upload_interval error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"UPLOAD_PZ","defailt_upload_max_num",&g_comm_prog_configure.write_max_num))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] defailt_upload_max_num error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"IPDB_PZ","flag",&g_comm_prog_configure.flag))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [IPDB_PZ] flag error!");
+ return -1;
+ }
+
+ g_comm_prog_configure.mmdb_path = (char *)calloc(1, 256*sizeof(char));
+ if((ret=MESA_load_profile_string_nodef(file_name, "IPDB_PZ", "mmdb_path", g_comm_prog_configure.mmdb_path, 256*sizeof(char)))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [IPDB_PZ] mmdb_path error!");
+ return -1;
+ }
+ return 0;
+}
+
+int COMM_AUDIT_INIT()
+{
+ int ret;
+ if(-1 == comm_read_conf("./djconf/comm_audit.conf"))
+ return -1;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "COMM_AUDIT_INIT", "COMM_AUDIT_INIT conf read over!");
+
+ g_comm_prog_para.project_id_pro = project_customer_register(DNTY_PPROJECT_PRO, DNTY_PPROJECT_TYPE);
+ if(g_comm_prog_para.project_id_pro < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_INIT. project_req_register error. LACK OF IDENTIFY'S CONF!");
+ return -1;
+ }
+
+
+ int thread_num = get_thread_count();
+ g_comm_prog_para.thread_num = thread_num;
+#ifdef LOG_DEBUG
+ printf("thread_num:%d\n", g_comm_prog_para.thread_num);
+#endif
+ ret = init_hash_table();
+ if(ret < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_INIT. init_hash_table error!");
+ //printf("init_hash_table() error!\n");
+ return -1;
+ }
+
+ g_comm_prog_para.last_send_time = time(NULL);
+ // pthread_mutex_init(&g_comm_prog_para.mutex, NULL);
+
+
+ //创建写文件线程
+ pthread_t hd_write;
+ pthread_create(&hd_write, NULL, thread_time, NULL);
+
+ //创建读json配置线程
+ pthread_t hd_read;
+ pthread_create(&hd_read, NULL, set_timer, NULL);
+
+ // printf("init COMM_AUDIT_INIT success!\n");
+
+ return 0;
+}
+