summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author[email protected] <[email protected]>2021-11-30 12:55:56 +0800
committer[email protected] <[email protected]>2021-11-30 12:55:56 +0800
commitc9c3fe7fbdc9f12648ae16a9ea50e886509c7238 (patch)
treeccb645bae903996df95c25916a631f9322ab48bc /src
Diffstat (limited to 'src')
-rw-r--r--src/Makefile21
-rw-r--r--src/include/connector.h86
-rw-r--r--src/qq_file_entry.c868
-rw-r--r--src/qq_file_entry.h125
-rw-r--r--src/qq_file_global.c308
-rw-r--r--src/qq_file_global.h21
6 files changed, 1429 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..ee38172
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,21 @@
+CC=g++
+CCC=g++
+
+INC_PATH = -I./include
+CFLAGS = -Wall -g -fPIC $(INC_PATH)
+
+LIBS = -lMESA_prof_load -lMESA_handle_logger -ldocumentanalyze -lMESA_field_stat -lpthread
+
+OBJS = qq_file_global.o qq_file_entry.o
+
+TARGET = qq_file_trans.so
+
+$(TARGET):$(OBJS)
+ $(CCC) -fPIC -shared $^ -o $@ $(LIBS)
+ cp $@ /home/zhangcw/sapp/plug/business/qq_file_trans/
+
+.c.o:
+ $(CC) -c $(CFLAGS) $<
+
+clean:
+ rm -f $(TARGET) $(OBJS)
diff --git a/src/include/connector.h b/src/include/connector.h
new file mode 100644
index 0000000..b1c10f1
--- /dev/null
+++ b/src/include/connector.h
@@ -0,0 +1,86 @@
+#ifndef CONNECTOR_H_
+#define CONNECTOR_H_
+
+extern int CONNECTOR_VERSION_1_20170704;
+
+typedef unsigned long ulong64;
+typedef unsigned int uint32;
+
+typedef enum
+{
+ APPD_SENDBACK=0, //ǰ����Ӧ�ò����ݻش�����
+ APPD_FILE=1, //�������ļ�����ģ����Ӧ�ò����ݷַ�
+}APPD_HEADER_TYPE;
+
+typedef enum
+{
+ DEST_APPD=0, //���ݷַ�����appd
+ DEST_WM=1, //webmail������������WM
+ DEST_MLFA=2, //���������mlfa
+}APPD_DESTINATION;
+
+typedef enum
+{
+ COMPLETE=0,
+ FRAG=1,
+ FRAG_END=2,
+}APPD_MSG_TYPE;
+
+typedef struct _appd_basic_t
+{
+ APPD_HEADER_TYPE appd_type; //Ӧ�ò����ݻ����ļ�����
+ const char* service_name; //������������,'\0'����
+ APPD_DESTINATION destination; //���ݽ��ճ���
+ ulong64* streamid; //��̬����ָ�룬��id
+ uint32 streamid_num;
+ struct ipaddr* addr; //��̬����ָ�룬 ����Ԫ��
+ uint32 addr_num;
+}appd_basic_t;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*��ʼ�������connector����� ÿһ������������һ��*/
+//void* connector_start(appd_basic_t* baisc_info);
+void* connector_start(appd_basic_t* baisc_info, const struct streaminfo *a_tcp);
+/* msg_type:�������� COMPLETE FRAG FRAG_END*/
+void connector(void* handler, APPD_MSG_TYPE msg_type, void* simple_opt_handle, void* nested_opt_handle);
+/*ÿһ����������������*/
+void connector_finish(void* handler);
+
+
+/*��ѡ�����������������*/
+/*1. ���ü�ѡ��ĸ���������simple_opt_handle*/
+void* connector_create_simple_opt(uint32 max_size);
+/*2. ���ѡ��*/
+int connector_append_simple_opt(void* simple_opt_handle, const char* opt_name, char* opt_value, uint32 opt_len);
+/*3. �ͷ�*/
+void connector_free_simple_opt(void** simple_opt_handle);
+
+
+/*Ƕ��ѡ�����������������*/
+/*1. ������������Ƕ��ѡ����ܸ���������nested_opt_handle*/
+void* connector_create_nested_opt(uint32 max_size);
+/*2. ������������ij��Ƕ��ѡ��������Լ��ڲ�ѡ��ĸ���������nested_unit_handle*/
+void* connector_create_nested_opt_unit(const char* nested_unit_name, uint32 max_size);
+/*3.��䵥��Ƕ��ѡ����ڲ�ѡ��*/
+/*opt_unit_handle ��connector_create_nested_opt_unit�ķ���ֵ*/
+/*����ֵ 0 OK -1 ERROR*/
+int connector_append_nested_opt_unit(void* nested_unit_handle, const char* subopt_name, char* subopt_value, uint32 subopt_len);
+/*4. ������Ƕ��ѡ��׷����Ƕ��ѡ����nested_opt_handle��*/
+/*����ֵ 0 OK -1 ERROR*/
+int connector_append_nested_opt(void* nested_opt_handle, void* nested_unit_handle);
+/*5. �ͷŵ���Ƕ��ѡ��*/
+void connector_free_nested_opt_unit(void** nested_unit_handle);
+/*6. �ͷ�*/
+void connector_free_nested_opt(void** nested_opt_handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
diff --git a/src/qq_file_entry.c b/src/qq_file_entry.c
new file mode 100644
index 0000000..ad49b50
--- /dev/null
+++ b/src/qq_file_entry.c
@@ -0,0 +1,868 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <MESA/stream.h>
+#include <MESA/MESA_prof_load.h>
+#include <MESA/MESA_handle_logger.h>
+#include <MESA/field_stat.h>
+
+#include "qq_file_entry.h"
+#include "qq_file_global.h"
+#include "connector.h"
+
+qq_global_info_t g_qq_global_info;
+
+int data_hit_feature(const char *data, unsigned int datalen, unsigned int min_len, FEATURE_INDEX_T index)
+{
+ unsigned int i, j;
+
+ if(datalen > min_len)
+ {
+ for(i=0; i<g_qq_global_info.fnum[index]; i++)
+ {
+ for(j=0; j<g_qq_global_info.rulenum[index][i]; j++)
+ {
+ //������ƥ��
+ if(datalen <= (g_qq_global_info.ftoff[index][i][j] + g_qq_global_info.ftlen[index][i][j]) || \
+ memcmp(data+g_qq_global_info.ftoff[index][i][j], g_qq_global_info.feature[index][i][j], g_qq_global_info.ftlen[index][i][j]))
+ {
+ break;
+ }
+ }
+ //һ�������ڵ����й���ƥ�䣬������
+ if(j == g_qq_global_info.rulenum[index][i])
+ {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+QQ_PACKET_TYPE_t is_qq_protocol_tcp(const char *data, unsigned int datalen)
+{
+ if(data_hit_feature(data, datalen, 0, FINDEX_TCPFILE))
+ return QQ_PACKET_TCPFILE;
+ if(data_hit_feature(data, datalen, PACKET_MIN_LEN_TCPNAME, FINDEX_TCPNAME))
+ return QQ_PACKET_TCPFILENAME;
+ //�ŵ�FINDEX_TCPFILE��FINDEX_TCPNAME֮����Ϊ������Ҳ������FINDEX_TCPNUM���Ͷ��������ݣ�UDPһ��������
+ if(data_hit_feature(data, datalen, PACKET_MIN_LEN_QQNUM, FINDEX_TCPNUM))
+ return QQ_PACKET_QQNUM;
+ if(data_hit_feature(data, datalen, 0, FINDEX_TCPPROT))
+ return QQ_PACKET_OTHER;
+
+ return QQ_PACKET_NOT;
+}
+
+QQ_PACKET_TYPE_t is_qq_protocol_udp(const char *data, unsigned int datalen)
+{
+ if(data_hit_feature(data, datalen, 0, FINDEX_UDPFILE))
+ return QQ_PACKET_UDPFILE;
+ if(data_hit_feature(data, datalen, PACKET_MIN_LEN_UDPNAME, FINDEX_UDPNAME))
+ return QQ_PACKET_UDPFILENAME;
+ if(data_hit_feature(data, datalen, 0, FINDEX_UDPFILE_END))
+ return QQ_PACKET_UDPFILE_END;
+ if(data_hit_feature(data, datalen, PACKET_MIN_LEN_QQNUM, FINDEX_UDPNUM))
+ return QQ_PACKET_QQNUM;
+ if(data_hit_feature(data, datalen, 0, FINDEX_UDPPROT))
+ return QQ_PACKET_OTHER;
+
+ return QQ_PACKET_NOT;
+}
+
+
+QQ_STATE_t assign_qq_state(QQ_PACKET_TYPE_t type)
+{
+ switch(type)
+ {
+ case QQ_PACKET_QQNUM: return QQ_STATE_QQNUM;
+
+ case QQ_PACKET_TCPFILE:
+ case QQ_PACKET_UDPFILE: return QQ_STATE_FCONT_START;
+
+ case QQ_PACKET_UDPFILE_END: return QQ_STATE_FCONT_END;
+
+ case QQ_PACKET_TCPFILENAME:
+ case QQ_PACKET_UDPFILENAME: return QQ_STATE_FNAME;
+
+ case QQ_PACKET_NOT:
+ case QQ_PACKET_OTHER: return QQ_STATE_INIT;
+ default:
+ assert(0);
+ return QQ_STATE_INIT;
+ }
+}
+
+static int init_qq_pme_info(qq_proto_pme_t **pme, int thread_id, char tcp_flag)
+{
+ qq_proto_pme_t *qq_pme=NULL;
+
+ qq_pme= (qq_proto_pme_t *)dictator_malloc(thread_id, sizeof(qq_proto_pme_t));
+ memset(qq_pme, 0, sizeof(qq_proto_pme_t));
+ qq_pme->thread_id = thread_id;
+ qq_pme->qq_state = QQ_STATE_INIT;
+ qq_pme->pending_flag = 1;
+ qq_pme->fileinfo.block_seq = -1; //UDP��ʼ�������-1������ʶ���ش������
+ qq_pme->tcp_flag = tcp_flag;
+
+ *pme = qq_pme;
+
+ if(g_qq_global_info.stat_trig)
+ {
+ stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_SESSION_NUM], FS_OP_TYPE_ADD, 1);
+ stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_NEW_SESSION], FS_OP_TYPE_ADD, 1);
+ }
+
+ return 0;
+}
+
+static void clear_qq_pme_info(qq_proto_pme_t *qq_pme, struct streaminfo *a_udp, const void *raw_pkt)
+{
+ if(qq_pme->connector_hdl != NULL)
+ {
+ connector_finish(qq_pme->connector_hdl);
+ }
+ if(qq_pme->fileinfo.buf)
+ {
+ dictator_free(qq_pme->thread_id, qq_pme->fileinfo.buf);
+ }
+
+ dictator_free(qq_pme->thread_id, qq_pme);
+
+ if(g_qq_global_info.stat_trig)
+ {
+ stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_SESSION_NUM], FS_OP_TYPE_ADD, -1);
+ stat_field_operation(g_qq_global_info.stat_handle, g_qq_global_info.stat_id[STAT_ID_DEL_SESSION], FS_OP_TYPE_ADD, 1);
+ }
+}
+
+QQ_STATE_t analyse_udp_pdata_state(QQ_STATE_t state, const char *data, int datalen)
+{
+ if(state != QQ_STATE_INIT)
+ return state;
+
+ return assign_qq_state(is_qq_protocol_udp(data, datalen));
+}
+
+QQ_STATE_t analyse_tcp_pdata_state(QQ_STATE_t state, const char *data, int datalen)
+{
+ if(state != QQ_STATE_INIT)
+ return state;
+
+ return assign_qq_state(is_qq_protocol_tcp(data, datalen));
+}
+
+int process_udp_data_state(struct streaminfo *a_udp, qq_proto_pme_t *qq_pme, int thread_seq,const void *raw_pkt)
+{
+ char *data = (char *)a_udp->pudpdetail->pdata;
+ int datalen = a_udp->pudpdetail->datalen;
+ char filename[512];
+ int tmp, i, j;
+
+ switch(qq_pme->qq_state)
+ {
+ case QQ_STATE_QQNUM:
+ qq_pme->qq_state = QQ_STATE_INIT;
+ if(qq_pme->qqnum[a_udp->curdir-1] || qq_pme->qqnum_from)
+ break;
+
+ if(*data == 0x03 && datalen==27)
+ {
+ qq_pme->qqnum[a_udp->curdir-1] = ntohl(*((unsigned int *)&data[23]));
+ }
+ else if(*data == 0x04) //TODO
+ {
+ qq_pme->qqnum_from = ntohl(*((unsigned int *)&data[9]));
+ }
+ break;
+
+ case QQ_STATE_FNAME:
+ qq_pme->qq_state = QQ_STATE_INIT;
+ qq_pme->file_dir = a_udp->curdir - 1;
+
+ if(*data == 0x05 && datalen < 800) //800---�����
+ {
+ qq_pme->total_file_len = ntohl(*((unsigned int *)&data[11]));
+ for (i = 23, j = 0; i < datalen - 1; i+=2, j+=2)
+ {
+ if ((data[i] == 0x00) && (data[i + 1] == 0x00))
+ break;
+ filename[j] = data[i];
+ filename[j+1] = data[i+1];
+ }
+ tmp = j;
+ }
+ else if(*data == 0x04 && datalen < 800)
+ {
+ if(qq_pme->qqnum_from == 0)
+ {
+ qq_pme->qqnum_from = ntohl(*((unsigned int *)&data[9]));
+ }
+ qq_pme->total_file_len = ntohl(*((unsigned int *)&data[42]));
+ for (i = 54, j = 0; i < datalen - 1; i+=2, j+=2)
+ {
+ if ((data[i] == 0x00) && (data[i + 1] == 0x00))
+ break;
+ filename[j] = data[i];
+ filename[j+1] = data[i+1];
+ }
+ tmp = j;
+ }
+ else
+ {
+ return APP_STATE_GIVEME;
+ }
+ return protocol_process(qq_pme, QQ_FILENAME, filename, tmp, a_udp, raw_pkt);
+
+ case QQ_STATE_FCONT_START:
+ qq_pme->qq_state = QQ_STATE_INIT; //ÿ����ǰ�涼������
+ if(*data == 0x05 && datalen>18)
+ {
+ tmp = ntohl(*((int *)&data[10])); //TODO��֪��int�ͻ���short
+ if(qq_pme->fileinfo.block_seq >= tmp)
+ return APP_STATE_GIVEME;
+
+ qq_pme->fileinfo.block_seq = tmp;
+ qq_pme->compress_flag = data[17];
+ return protocol_process(qq_pme, QQ_FILECONT, data+18, datalen-18, a_udp, raw_pkt);
+ }
+ else if(*data==0x04 && datalen>50)
+ {
+ tmp = ntohl(*((int *)&data[41])); //TODO��֪��int�ͻ���short
+ if(qq_pme->fileinfo.block_seq >= tmp)
+ return APP_STATE_GIVEME;
+
+ qq_pme->fileinfo.block_seq = tmp;
+ qq_pme->compress_flag = data[48];
+ return protocol_process(qq_pme, QQ_FILECONT, data+49, datalen-50, a_udp, raw_pkt);
+ }
+ break;
+
+ case QQ_STATE_FCONT_END:
+ qq_pme->qq_state = QQ_STATE_INIT;
+ if(*data == 0x05 && datalen>18)
+ {
+ qq_pme->compress_flag = data[17];
+ return protocol_process(qq_pme, QQ_FILECONT_END, data+18, datalen-18, a_udp, raw_pkt);
+ }
+ else if(*data == 0x04 && datalen>50)
+ {
+ qq_pme->compress_flag = data[48];
+ return protocol_process(qq_pme, QQ_FILECONT_END, data+49, datalen-50, a_udp, raw_pkt);
+ }
+ break;
+
+ case QQ_STATE_FCONT:
+ case QQ_STATE_INIT:
+ default:
+ break;
+ }
+
+ return APP_STATE_GIVEME;
+}
+
+extern "C" char QQ_PROT_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq,const void *raw_pkt)
+{
+ QQ_PACKET_TYPE_t type;
+ qq_proto_pme_t *qq_pme=(qq_proto_pme_t*)(*pme);
+ int rec = APP_STATE_GIVEME;
+
+ switch(a_udp->opstate)
+ {
+ case OP_STATE_PENDING:
+ type = is_qq_protocol_udp((char *)a_udp->pudpdetail->pdata, a_udp->pudpdetail->datalen);
+ if(type)
+ {
+ if(init_qq_pme_info(&qq_pme, a_udp->threadnum, 0))
+ return APP_STATE_DROPME;
+ qq_pme->qq_state = assign_qq_state(type);
+ *pme = qq_pme;
+ }
+ else
+ {
+ return APP_STATE_DROPME;
+ }
+ //no break here
+
+ case OP_STATE_DATA:
+ qq_pme->qq_state = analyse_udp_pdata_state(qq_pme->qq_state, (char *)a_udp->pudpdetail->pdata, a_udp->pudpdetail->datalen);
+
+ rec = process_udp_data_state(a_udp, qq_pme, thread_seq, raw_pkt);
+ break;
+
+ case OP_STATE_CLOSE:
+ clear_qq_pme_info(qq_pme, a_udp, raw_pkt);
+ break;
+
+ default:
+ return APP_STATE_DROPME;
+ }
+
+ if(rec & APP_STATE_DROPME)
+ {
+ clear_qq_pme_info(qq_pme, a_udp, raw_pkt);
+ }
+
+ return rec;
+}
+
+
+int process_tcp_data_state(struct streaminfo *a_tcp, qq_proto_pme_t *qq_pme, int thread_seq,const void *raw_pkt)
+{
+ char *data = (char *)a_tcp->pudpdetail->pdata;
+ int datalen = a_tcp->pudpdetail->datalen;
+ char filename[512];
+ int cur_len=0, i, j, rec = APP_STATE_GIVEME, need_len;
+
+ switch(qq_pme->qq_state)
+ {
+ case QQ_STATE_QQNUM:
+ qq_pme->qq_state = QQ_STATE_INIT;
+ if(qq_pme->qqnum_from)
+ break;
+
+ if(*data == 0x04) //TODO
+ {
+ qq_pme->qqnum_from = ntohl(*((unsigned int *)&data[9]));
+ }
+ break;
+
+ case QQ_STATE_FNAME:
+ qq_pme->qq_state = QQ_STATE_INIT;
+ qq_pme->file_dir = a_tcp->curdir - 1;
+
+ //ȡ���ļ������ļ�����UNICODE�����
+ if(*data == TCPFILE_START_CHAR0c && datalen < 800) //800---�����
+ {
+ qq_pme->total_file_len = ntohl(*((unsigned int *)&data[27]));
+ for (i = 39, j = 0; i < datalen - 1; i+=2, j+=2)
+ {
+ if ((data[i] == 0x00) && (data[i + 1] == 0x00))
+ break;
+ filename[j] = data[i];
+ filename[j+1] = data[i+1];
+ }
+ cur_len = j;
+ }
+ else if(*data == TCPFILE_START_CHAR04 && datalen < 800)
+ {
+ qq_pme->total_file_len = ntohl(*((unsigned int *)&data[90]));
+ for (i = 102, j = 0; i < datalen - 1; i+=2, j+=2)
+ {
+ if ((data[i] == 0x00) && (data[i + 1] == 0x00))
+ break;
+ filename[j] = data[i];
+ filename[j+1] = data[i+1];
+ }
+ cur_len = j;
+ }
+ else
+ {
+ return APP_STATE_GIVEME;
+ }
+ return protocol_process(qq_pme, QQ_FILENAME, filename, cur_len, a_tcp, raw_pkt);
+
+ case QQ_STATE_FCONT_START:
+ //��UDP��ͬ���ǣ�TCP����ͷ����һ���ǰ���ƥ����������ʽ���䣻
+ if(a_tcp->curdir != qq_pme->file_dir+1)
+ break;
+
+ if(a_tcp->ptcpdetail->lostlen) //����������Ѱ�Ұ���ͷ
+ {
+ qq_pme->fileinfo.len = 0;
+ qq_pme->qq_state = QQ_STATE_INIT;
+ break;
+ }
+ if(qq_pme->fileinfo.len > 0)
+ {
+ if(qq_pme->fileinfo.len < TCPFILE_HDR_LEN04+1) //�ж�������ʱ��Ҫ�����ݳ��ȴ���ͷ������
+ {
+ need_len = TCPFILE_HDR_LEN04+1 - qq_pme->fileinfo.len;
+ if(datalen < need_len)
+ {
+ if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0)
+ {
+ return APP_STATE_DROPME;
+ }
+ return APP_STATE_GIVEME;
+ }
+ memcpy(qq_pme->fileinfo.buf+qq_pme->fileinfo.len, data, need_len);
+ qq_pme->fileinfo.len += need_len;
+ data += need_len;
+ datalen -= need_len;
+ if(data_hit_feature(qq_pme->fileinfo.buf, qq_pme->fileinfo.len, 0, FINDEX_TCPFILE))
+ {
+ qq_pme->fileinfo.prot_flag = QQ_FILECONT;
+ }
+ else if(data_hit_feature(qq_pme->fileinfo.buf, qq_pme->fileinfo.len, 0, FINDEX_TCPFILE_END))
+ {
+ qq_pme->fileinfo.prot_flag = QQ_FILECONT_END;
+ }
+ else
+ {
+ return APP_STATE_DROPME;
+ }
+ if(*(qq_pme->fileinfo.buf) == TCPFILE_START_CHAR04)
+ {
+ qq_pme->fileinfo.block_len = ntohs(*((unsigned short *)&qq_pme->fileinfo.buf[3]));
+ qq_pme->compress_flag = qq_pme->fileinfo.buf[TCPFILE_HDR_LEN04-1];
+ }
+ }
+
+ //����һ��������ij���
+ need_len = qq_pme->fileinfo.block_len - qq_pme->fileinfo.len;
+ if(need_len > datalen)
+ {
+ if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0)
+ {
+ return APP_STATE_DROPME;
+ }
+ return APP_STATE_GIVEME;
+ }
+ if(save_initial_tcp_data(&qq_pme->fileinfo, data, need_len, qq_pme->thread_id) < 0)
+ {
+ return APP_STATE_DROPME;
+ }
+ qq_pme->fileinfo.len = 0;
+ data += need_len;
+ datalen -= need_len;
+
+ if(*(qq_pme->fileinfo.buf) == TCPFILE_START_CHAR04 && qq_pme->fileinfo.block_len>TCPFILE_HDR_LEN04)
+ {
+ if(*(qq_pme->fileinfo.buf + qq_pme->fileinfo.block_len - 1) != TCPFILE_END_CHAR04)
+ return APP_STATE_DROPME;
+ rec = protocol_process(qq_pme, qq_pme->fileinfo.prot_flag, qq_pme->fileinfo.buf+TCPFILE_HDR_LEN04, qq_pme->fileinfo.block_len-TCPFILE_HDR_LEN04-1, a_tcp, raw_pkt);
+ }
+ if(rec & APP_STATE_DROPME)
+ {
+ return rec;
+ }
+ }
+
+ while(datalen>0)
+ {
+ //ͷ���������Ȳ�������������
+ if(datalen < TCPFILE_HDR_LEN04+1)
+ {
+ if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0)
+ {
+ return APP_STATE_DROPME;
+ }
+ return APP_STATE_GIVEME;
+ }
+
+ if(data_hit_feature(data, datalen, 0, FINDEX_TCPFILE))
+ {
+ qq_pme->fileinfo.prot_flag = QQ_FILECONT;
+ }
+ else if(data_hit_feature(data, datalen, 0, FINDEX_TCPFILE_END))
+ {
+ qq_pme->fileinfo.prot_flag = QQ_FILECONT_END;
+ }
+ else
+ {
+ //�е�ʱ�򿴵��м����С�飬�轫���߳�
+ unsigned short block_len = ntohs(*((unsigned short *)&data[3]));
+ if(*data == TCPFILE_START_CHAR04 && block_len < TCPFILE_HDR_LEN04)
+ {
+ data += block_len;
+ datalen -= block_len;
+ }
+ else
+ {
+ return APP_STATE_DROPME;
+ }
+ }
+
+ //ͷ�����ȹ�����ͷ��ȡ���鳤�ȣ��鲻��Ҳ��������
+ if(*data == TCPFILE_START_CHAR04 && datalen>TCPFILE_HDR_LEN04)
+ {
+ qq_pme->fileinfo.block_len = ntohs(*((unsigned short *)&data[3]));
+ qq_pme->compress_flag = data[TCPFILE_HDR_LEN04-1];
+ if(datalen < qq_pme->fileinfo.block_len)
+ {
+ if(save_initial_tcp_data(&qq_pme->fileinfo, data, datalen, qq_pme->thread_id) < 0)
+ {
+ return APP_STATE_DROPME;
+ }
+ return APP_STATE_GIVEME;
+ }
+
+ rec = protocol_process(qq_pme, qq_pme->fileinfo.prot_flag, data+TCPFILE_HDR_LEN04, qq_pme->fileinfo.block_len-TCPFILE_HDR_LEN04-1, a_tcp, raw_pkt);
+ if(rec & APP_STATE_DROPME)
+ {
+ return rec;
+ }
+ data += qq_pme->fileinfo.block_len;
+ datalen -= qq_pme->fileinfo.block_len;
+ }
+ }
+ break;
+
+ case QQ_STATE_FCONT_END:
+ case QQ_STATE_FCONT:
+ case QQ_STATE_INIT:
+ default:
+ break;
+ }
+
+ return APP_STATE_GIVEME;
+}
+
+extern "C" char QQ_PROT_TCP_ENTRY(struct streaminfo *a_tcp, void **pme, int thread_seq,const void *raw_pkt)
+{
+ QQ_PACKET_TYPE_t type;
+ qq_proto_pme_t *qq_pme=(qq_proto_pme_t*)(*pme);
+ int rec = APP_STATE_GIVEME;
+
+ switch(a_tcp->opstate)
+ {
+ case OP_STATE_PENDING:
+ type = is_qq_protocol_tcp((char *)a_tcp->ptcpdetail->pdata, a_tcp->ptcpdetail->datalen);
+ if(type)
+ {
+ if(init_qq_pme_info(&qq_pme, a_tcp->threadnum, 1))
+ return APP_STATE_DROPME;
+ qq_pme->qq_state = assign_qq_state(type);
+ *pme = qq_pme;
+ }
+ else
+ {
+ return APP_STATE_DROPME;
+ }
+ //no break here
+
+ case OP_STATE_DATA:
+ qq_pme->qq_state = analyse_tcp_pdata_state(qq_pme->qq_state, (char *)a_tcp->ptcpdetail->pdata, a_tcp->ptcpdetail->datalen);
+
+ rec = process_tcp_data_state(a_tcp, qq_pme, thread_seq, raw_pkt);
+ break;
+
+ case OP_STATE_CLOSE:
+ clear_qq_pme_info(qq_pme, a_tcp, raw_pkt);
+ break;
+
+ default:
+ return APP_STATE_DROPME;
+ }
+
+ if(rec & APP_STATE_DROPME)
+ {
+ clear_qq_pme_info(qq_pme, a_tcp, raw_pkt);
+ }
+
+ return rec;
+}
+
+int mkdir_according_path(const char * path)
+{
+ char buffer[256];
+ const char *ps=path, *pc;
+
+ if(*ps == '/')
+ ps += 1;
+
+ while((pc = strchr(ps, '/')) != NULL)
+ {
+ while(*(pc+1) == '/')
+ pc++;
+
+ memcpy(buffer, path, pc - path);
+ buffer[pc-path] = '\0';
+
+ if(access(buffer, F_OK))
+ {
+ if(mkdir(buffer, 0777))
+ {
+ return -1;
+ }
+ }
+
+ ps = pc + 1;
+ }
+ if(access(path, F_OK))
+ {
+ if(mkdir(path, 0777))
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int register_field_stat(const char *logpath)
+{
+ unsigned int stat_cycle;
+ int ret, i;
+ char stat_log[128];
+ const char *region_name[STAT_ID_NUM]={"NEW_SESSION", "DEL_SESSION", "SESSION_NUM"};
+
+ snprintf(stat_log, 128, "%s/qq_stat.log", logpath);
+
+ ret = MESA_load_profile_uint_def(CONF_FILENAME, "MODULE", "STAT_FIELD_CYCLE",&stat_cycle, 5);
+ if(ret < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"get [MODULE] STAT_FIELD_CYCLE failed, using default 5.");
+ }
+ ret = MESA_load_profile_int_def(CONF_FILENAME, "MODULE", "STAT_FIELD_TRIG",&g_qq_global_info.stat_trig, 0);
+ if(ret < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"get [MODULE] STAT_FIELD_TRIG failed, using default 0.");
+ }
+
+ if(g_qq_global_info.stat_trig==0)
+ return 0;
+
+ FILE* stat_fd = fopen(stat_log, "w");
+ if(stat_fd == NULL)
+ {
+ MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"fopen %s failed.", stat_log);
+ return -1;
+ }
+
+ g_qq_global_info.stat_handle = init_screen_stat(stat_fd, stat_cycle, g_qq_global_info.stat_trig);
+ if(g_qq_global_info.stat_handle==NULL)
+ {
+ MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"init_screen_stat failed.");
+ return -1;
+ }
+
+ for(i=0;i<STAT_ID_NUM;i++)
+ {
+ g_qq_global_info.stat_id[i] = stat_field_register(g_qq_global_info.stat_handle, region_name[i]);
+ if(g_qq_global_info.stat_id[i] < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOG(g_qq_global_info.runtime_log, RLOG_LV_INFO, MODULE_NAME,"stat_field_register %s failed.", region_name[i]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*������������ʽ(��ʾ��)��
+ *FEATURE_QQ_TCPFILENAME=0:04&13:00,01,00,00,00,00,00&31:0c,00,00,00,00,2b;3:00,2b,52,00,00&34:00,2b,52,00,00
+ *1.�Էֺŷָ�һ�����ã������ж�����ã������ǻ�Ĺ�ϵ��
+ *2.��&�ָ�һ�������ڵĶ���������������Ĺ�ϵ��
+ *3.ÿ�������ǰ��һ�����ֺ�ð�ű�ʾ��ʮ�����ƴ���һ�����ڵ�ƫ����(�ֽ�)��ÿ��ʮ����������ռ��λ���ö��ŷָ
+*/
+int decode_feature_to_binary(char *feature, const char *feature_name,
+ char *feature_bin[MAX_QQ_FEATURE_NUM][MAX_AND_RULE],
+ unsigned int feature_len[MAX_QQ_FEATURE_NUM][MAX_AND_RULE],
+ unsigned int feature_off[MAX_QQ_FEATURE_NUM][MAX_AND_RULE],
+ unsigned int rulenum[MAX_QQ_FEATURE_NUM],
+ unsigned int *feature_num)
+{
+ char *ptmp0, *save_ptr0=NULL, *ptmp1, *save_ptr1=NULL, *ptmp2, *save_ptr2=NULL;
+ int fnum=0, rnum, i, val;
+
+ for(ptmp0 = strtok_r(feature, ";", &save_ptr0); ptmp0 != NULL; ptmp0 = strtok_r(NULL, ";", &save_ptr0))
+ {
+ rnum = 0;
+ for(ptmp1 = strtok_r(ptmp0, "&", &save_ptr1); ptmp1 != NULL; ptmp1 = strtok_r(NULL, "&", &save_ptr1))
+ {
+ feature_bin[fnum][rnum] = (char *)calloc(1, strlen(ptmp1)/2+1);
+ i = 0;
+ if(sscanf(ptmp1, "%u:", &feature_off[fnum][rnum]) != 1)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Decode [FEATURE] %s error, format invalid.", feature_name);
+ return -1;
+ }
+ while(*ptmp1 != ':')
+ ptmp1++;
+ for(ptmp2 = strtok_r(ptmp1+1, ",", &save_ptr2); ptmp2 != NULL; ptmp2 = strtok_r(NULL, ",", &save_ptr2))
+ {
+ if(strlen(ptmp2)!=2 || sscanf(ptmp2, "%02x", &val)!=1)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Decode [FEATURE] %s error, format invalid.", feature_name);
+ return -1;
+ }
+ feature_bin[fnum][rnum][i++] = val;
+ }
+ feature_len[fnum][rnum] = i;
+ rnum++;
+ }
+ rulenum[fnum] = rnum;
+ fnum++;
+ }
+
+ *feature_num = fnum;
+ return 0;
+}
+
+extern "C" int QQ_PROT_INIT(void)
+{
+ int log_level;
+ char tmp_buffer[512]={0}, tmp_buffer2[512]={0};
+
+ memset(&g_qq_global_info, 0, sizeof(qq_global_info_t));
+
+ MESA_load_profile_string_def(CONF_FILENAME, "MODULE", "RUN_LOG_DIR", tmp_buffer, sizeof(tmp_buffer), "./log/qq_file_trans");
+ MESA_load_profile_int_def(CONF_FILENAME, "MODULE", "RUN_LOG_LEVEL", &log_level,10);
+ if(mkdir_according_path(tmp_buffer))
+ {
+ printf("mkdir %s failed: %s\n", tmp_buffer, strerror(errno));
+ assert(0);
+ return -1;
+ }
+ snprintf(tmp_buffer2, sizeof(tmp_buffer2), "%s/qq_file_trans.log", tmp_buffer);
+ g_qq_global_info.runtime_log = MESA_create_runtime_log_handle(tmp_buffer2, log_level);
+ if(g_qq_global_info.runtime_log==NULL)
+ {
+ assert(0);
+ return -1;
+ }
+
+ if(register_field_stat(tmp_buffer) < 0)
+ {
+ assert(0);
+ return -1;
+ }
+
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQTCP_PROTOCOL", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQTCP_PROTOCOL error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQTCP_PROTOCOL", g_qq_global_info.feature[FINDEX_TCPPROT], g_qq_global_info.ftlen[FINDEX_TCPPROT], g_qq_global_info.ftoff[FINDEX_TCPPROT], g_qq_global_info.rulenum[FINDEX_TCPPROT], &g_qq_global_info.fnum[FINDEX_TCPPROT]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQUDP_PROTOCOL", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQUDP_PROTOCOL error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQUDP_PROTOCOL", g_qq_global_info.feature[FINDEX_UDPPROT], g_qq_global_info.ftlen[FINDEX_UDPPROT], g_qq_global_info.ftoff[FINDEX_UDPPROT], g_qq_global_info.rulenum[FINDEX_UDPPROT], &g_qq_global_info.fnum[FINDEX_UDPPROT]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_NUMBER_TCP", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_NUMBER_TCP error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_NUMBER_TCP", g_qq_global_info.feature[FINDEX_TCPNUM], g_qq_global_info.ftlen[FINDEX_TCPNUM], g_qq_global_info.ftoff[FINDEX_TCPNUM], g_qq_global_info.rulenum[FINDEX_TCPNUM], &g_qq_global_info.fnum[FINDEX_TCPNUM]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_NUMBER_UDP", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_NUMBER_UDP error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_NUMBER_UDP", g_qq_global_info.feature[FINDEX_UDPNUM], g_qq_global_info.ftlen[FINDEX_UDPNUM], g_qq_global_info.ftoff[FINDEX_UDPNUM], g_qq_global_info.rulenum[FINDEX_UDPNUM], &g_qq_global_info.fnum[FINDEX_UDPNUM]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_TCPFILE", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_TCPFILE error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_TCPFILE", g_qq_global_info.feature[FINDEX_TCPFILE], g_qq_global_info.ftlen[FINDEX_TCPFILE], g_qq_global_info.ftoff[FINDEX_TCPFILE], g_qq_global_info.rulenum[FINDEX_TCPFILE], &g_qq_global_info.fnum[FINDEX_TCPFILE]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_TCPFILE_END", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_TCPFILE_END error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_TCPFILE_END", g_qq_global_info.feature[FINDEX_TCPFILE_END], g_qq_global_info.ftlen[FINDEX_TCPFILE_END], g_qq_global_info.ftoff[FINDEX_TCPFILE_END], g_qq_global_info.rulenum[FINDEX_TCPFILE_END], &g_qq_global_info.fnum[FINDEX_TCPFILE_END]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_TCPFILENAME", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_TCPFILENAME error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_TCPFILENAME", g_qq_global_info.feature[FINDEX_TCPNAME], g_qq_global_info.ftlen[FINDEX_TCPNAME], g_qq_global_info.ftoff[FINDEX_TCPNAME], g_qq_global_info.rulenum[FINDEX_TCPNAME], &g_qq_global_info.fnum[FINDEX_TCPNAME]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_UDPFILE_START", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_UDPFILE_START error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_UDPFILE_START", g_qq_global_info.feature[FINDEX_UDPFILE], g_qq_global_info.ftlen[FINDEX_UDPFILE], g_qq_global_info.ftoff[FINDEX_UDPFILE], g_qq_global_info.rulenum[FINDEX_UDPFILE], &g_qq_global_info.fnum[FINDEX_UDPFILE]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_UDPFILE_END", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_UDPFILE_END error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_UDPFILE_END", g_qq_global_info.feature[FINDEX_UDPFILE_END], g_qq_global_info.ftlen[FINDEX_UDPFILE_END], g_qq_global_info.ftoff[FINDEX_UDPFILE_END], g_qq_global_info.rulenum[FINDEX_UDPFILE_END], &g_qq_global_info.fnum[FINDEX_UDPFILE_END]))
+ {
+ return -1;
+ }
+ memset(tmp_buffer, 0 , sizeof(tmp_buffer));
+ if(MESA_load_profile_string_nodef(CONF_FILENAME, "FEATURE", "FEATURE_QQ_UDPFILENAME", tmp_buffer, sizeof(tmp_buffer)) < 0)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "Get [FEATURE] FEATURE_QQ_UDPFILENAME error.");
+ assert(0);
+ return -1;
+ }
+ if(decode_feature_to_binary(tmp_buffer, "FEATURE_QQ_UDPFILENAME", g_qq_global_info.feature[FINDEX_UDPNAME], g_qq_global_info.ftlen[FINDEX_UDPNAME], g_qq_global_info.ftoff[FINDEX_UDPNAME], g_qq_global_info.rulenum[FINDEX_UDPNAME], &g_qq_global_info.fnum[FINDEX_UDPNAME]))
+ {
+ return -1;
+ }
+ g_qq_global_info.instanse = docanalyze_initialize(get_thread_count());
+ if(g_qq_global_info.instanse==NULL)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_FATAL, MODULE_NAME, "docanalyze_initialize() error.");
+ assert(0);
+ return -1;
+ }
+
+ MESA_load_profile_int_def(CONF_FILENAME, "MODULE", "DEBUG_SWITCH", &g_qq_global_info.debug_sw, 0);
+ if(g_qq_global_info.debug_sw)
+ {
+ if(mkdir_according_path(QQ_DEBUG_FILEPATH))
+ {
+ printf("mkdir %s failed: %s\n", tmp_buffer, strerror(errno));
+ assert(0);
+ return -1;
+ }
+ }
+
+ g_qq_global_info.project_id = project_customer_register("STREAMID", "long");
+ assert(g_qq_global_info.project_id >= 0);
+
+ srand(time(NULL));
+ return 0;
+}
+
+extern "C" void QQ_PROT_DESTROY(void)
+{
+}
+
diff --git a/src/qq_file_entry.h b/src/qq_file_entry.h
new file mode 100644
index 0000000..23e6a32
--- /dev/null
+++ b/src/qq_file_entry.h
@@ -0,0 +1,125 @@
+#ifndef __QQ_FILE_ENTRY_H__
+#define __QQ_FILE_ENTRY_H__
+
+#include <pthread.h>
+
+#include <MESA/DocumentAnalyze.h>
+
+#define CONF_FILENAME "./conf/qq_file_trans.conf"
+#define QQ_DEBUG_FILEPATH "./qq_files"
+#define MODULE_NAME "QQ_FILE"
+
+#define MAX_QQ_FEATURE_NUM 16
+#define MAX_AND_RULE 32
+
+#define PACKET_MIN_LEN_QQNUM 16
+#define PACKET_MIN_LEN_TCPNAME 551
+#define PACKET_MIN_LEN_UDPNAME 535
+
+#define TCPFILE_START_CHAR04 0x04
+#define TCPFILE_END_CHAR04 0x03
+#define TCPFILE_HDR_LEN04 53
+
+#define TCPFILE_START_CHAR0c 0x0c
+#define TCPFILE_HDR_LEN0c 22
+
+typedef enum __QQ_PACKET_TYPE
+{
+ QQ_PACKET_NOT=0,
+ QQ_PACKET_QQNUM,
+ QQ_PACKET_TCPFILE,
+ QQ_PACKET_TCPFILENAME,
+ QQ_PACKET_UDPFILE,
+ QQ_PACKET_UDPFILE_END,
+ QQ_PACKET_UDPFILENAME,
+ QQ_PACKET_OTHER,
+}QQ_PACKET_TYPE_t;
+
+typedef enum __QQ_STATE
+{
+ QQ_STATE_INIT=0,
+ QQ_STATE_QQNUM,
+ QQ_STATE_FNAME,
+ QQ_STATE_FCONT_START,
+ QQ_STATE_FCONT,
+ QQ_STATE_FCONT_END,
+}QQ_STATE_t;
+
+typedef enum __FEATURE_INDEX
+{
+ FINDEX_TCPPROT=0,
+ FINDEX_TCPNUM,
+ FINDEX_TCPNAME,
+ FINDEX_TCPFILE,
+ FINDEX_TCPFILE_END,
+ FINDEX_UDPPROT,
+ FINDEX_UDPNUM,
+ FINDEX_UDPNAME,
+ FINDEX_UDPFILE,
+ FINDEX_UDPFILE_END,
+
+ FINDEX_NUM,
+}FEATURE_INDEX_T;
+
+enum __FIELD_STAT_ID
+{
+ STAT_ID_NEW_SESSION,
+ STAT_ID_DEL_SESSION,
+ STAT_ID_SESSION_NUM,
+ STAT_ID_NUM,
+};
+
+typedef struct __trans_file_info
+{
+ char *buf;
+ unsigned int len;
+ unsigned int max_len;
+ long long prot_flag;
+
+ int block_seq; //���ݰ�����ţ�������ʱ���ش������UDP
+ unsigned short block_len; //һ��С��Ĵ�С������һ����һ�����Ĵ�С�����TCP
+ unsigned short file_seq; //һ��С��Ĵ�С������һ����һ�����Ĵ�С�����TCP
+}trans_file_info_t;
+
+typedef struct __qq_proto_pme
+{
+ void *connector_hdl;
+ char filename[512];
+ int filename_len;
+ QQ_STATE_t qq_state;
+ unsigned int qqnum[2];
+ unsigned int qqnum_from;
+ unsigned int qqnum_to;
+
+ trans_file_info_t fileinfo;
+
+ int thread_id;
+ unsigned int file_dir;
+ unsigned int total_file_len;
+ unsigned int curr_file_len;
+ char pending_flag;
+ char end_flag;
+ char compress_flag;
+ char tcp_flag;
+ unsigned int random;
+}qq_proto_pme_t;
+
+typedef struct __qq_global_info
+{
+ void *runtime_log;
+ void *stat_handle;
+ docanalyze_instance_t instanse;
+ char *feature[FINDEX_NUM][MAX_QQ_FEATURE_NUM][MAX_AND_RULE];
+ unsigned int ftlen[FINDEX_NUM][MAX_QQ_FEATURE_NUM][MAX_AND_RULE];
+ unsigned int ftoff[FINDEX_NUM][MAX_QQ_FEATURE_NUM][MAX_AND_RULE];
+ unsigned int rulenum[FINDEX_NUM][MAX_QQ_FEATURE_NUM]; //ÿһ�������ڲ�����������
+ unsigned int fnum[FINDEX_NUM];
+
+ int project_id;
+ int stat_trig;
+ int stat_id[STAT_ID_NUM];
+ int debug_sw;
+}qq_global_info_t;
+
+#endif
+
diff --git a/src/qq_file_global.c b/src/qq_file_global.c
new file mode 100644
index 0000000..ce74f1c
--- /dev/null
+++ b/src/qq_file_global.c
@@ -0,0 +1,308 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <assert.h>
+#include <iconv.h>
+#include <pthread.h>
+
+#include <MESA/stream.h>
+#include <MESA/DocumentAnalyze.h>
+#include <MESA/MESA_handle_logger.h>
+
+#include "qq_file_entry.h"
+#include "qq_file_global.h"
+#include "connector.h"
+
+#define QQ_OPT_SERVICE "SERVICE_IMQQ"
+#define QQ_OPT_FILESET "opt_file_set"
+#define QQ_OPT_FILENAME "opt_file_name"
+#define QQ_OPT_FILECONT "opt_file_content"
+#define QQ_OPT_NUMFROM "opt_im_from"
+#define QQ_OPT_NUMTO "opt_im_to"
+#define QQ_OPT_ACCOUNT "opt_im_account"
+
+extern qq_global_info_t g_qq_global_info;
+const unsigned char gzip_feature[4]={0x1f, 0x8b, 0x08, 0x00};
+
+int write_file_cont2disk(char *buffer, int filelen, char *filename, int seq, int random)
+{
+ FILE *fp;
+ int writelen, offset=0;
+ char filenamestr[512];
+
+ sprintf(filenamestr, "%s/%d_%u_%s", QQ_DEBUG_FILEPATH, seq, random, filename);
+
+ fp = fopen(filenamestr, "ab+");
+ if(fp == NULL)
+ {
+ printf("fopen file %s failed.\n", filenamestr);
+ return -1;
+ }
+
+ while(offset < filelen)
+ {
+ writelen = fwrite(buffer + offset, 1, filelen - offset, fp);
+ if(writelen < 0)
+ {
+ printf("read error: %s\n", strerror(errno));
+ return -1;
+ }
+
+ offset += writelen;
+ }
+ fclose(fp);
+ return 0;
+}
+
+int buf_cache_check_size(trans_file_info_t *pdstBuf, int wantedlen, int thread_seq)
+{
+ int ret=0, needlen, block_num=0;
+
+ if(pdstBuf->max_len > wantedlen + pdstBuf->len)
+ return 0;
+
+ needlen = wantedlen + pdstBuf->len - pdstBuf->max_len;
+ block_num = needlen/REALLOC_BLOCK_SIZE;
+ if(needlen%REALLOC_BLOCK_SIZE)
+ block_num += 1;
+
+ pdstBuf->max_len += block_num*REALLOC_BLOCK_SIZE;
+
+ if(pdstBuf->max_len > MAX_MALLOC_SIZE)
+ {
+ pdstBuf->max_len -= block_num*REALLOC_BLOCK_SIZE;
+ return -1;
+ }
+
+ if(pdstBuf->buf == NULL)
+ {
+ pdstBuf->buf = (char *)dictator_malloc(thread_seq, pdstBuf->max_len);
+ }
+ else
+ {
+ pdstBuf->buf = (char *)dictator_realloc(thread_seq, pdstBuf->buf, pdstBuf->max_len);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+int save_initial_tcp_data(trans_file_info_t *pdstBuf, char *data, int datalen, int thread_seq)
+{
+ if(buf_cache_check_size(pdstBuf, datalen, thread_seq) < 0)
+ {
+ return -1;
+ }
+ memcpy(pdstBuf->buf+pdstBuf->len, data, datalen);
+ pdstBuf->len += datalen;
+
+ return 0;
+}
+
+
+int convert_from_unicode2utf8(char *in, int in_len, char *out, int *out_len)
+{
+ iconv_t cd;
+ size_t inlen = in_len, outlen=*out_len, ret;
+
+ cd = iconv_open("utf-8", "unicode");
+ if(cd == (iconv_t)-1)
+ {
+ return -1;
+ }
+ ret = iconv(cd, &in, &inlen, &out, &outlen);
+ if(ret == (size_t)-1)
+ {
+ iconv_close(cd);
+ return -1;
+ }
+ iconv_close(cd);
+ *out_len = outlen;
+
+ return 0;
+}
+
+int sendback_qq_data(qq_proto_pme_t *qq_pme, struct streaminfo *a_udp, char *filecont, int contlen)
+{
+ int nest_opt_num = 1;
+ void *nested_opt_handle, *nested_opt_unit_handle, *simple_opt=NULL;
+
+ if(qq_pme->connector_hdl == NULL)
+ {
+ appd_basic_t basic;
+ ulong64 streamid[1];
+ char qqfrom[32], qq_to[32];
+
+ streamid[0] = project_req_get_ulong(a_udp, g_qq_global_info.project_id);
+
+ basic.addr = (struct ipaddr*)&a_udp->addr;
+ basic.addr_num = 1;
+ basic.appd_type = APPD_SENDBACK;
+ basic.destination = DEST_APPD;
+ basic.service_name = QQ_OPT_SERVICE;
+ basic.streamid = streamid;
+ basic.streamid_num = 1;
+
+ qq_pme->connector_hdl = connector_start(&basic, a_udp);
+ if(qq_pme->connector_hdl == NULL)
+ return APP_STATE_DROPME;
+
+ if(qq_pme->filename_len > 0)
+ {
+ nest_opt_num = 2;
+ }
+ sprintf(qqfrom, "%u", qq_pme->qqnum_from);
+ sprintf(qq_to, "%u", qq_pme->qqnum_to);
+
+ simple_opt = connector_create_simple_opt(3);
+ connector_append_simple_opt(simple_opt, QQ_OPT_NUMFROM,qqfrom, strlen(qqfrom));
+ connector_append_simple_opt(simple_opt, QQ_OPT_ACCOUNT,qqfrom, strlen(qqfrom));
+ connector_append_simple_opt(simple_opt, QQ_OPT_NUMTO,qq_to, strlen(qq_to));
+ connector(qq_pme->connector_hdl, COMPLETE, simple_opt, NULL);
+ connector_free_simple_opt(&simple_opt);
+ }
+
+ nested_opt_handle = connector_create_nested_opt(1);
+ nested_opt_unit_handle = connector_create_nested_opt_unit(QQ_OPT_FILESET, nest_opt_num);
+ if(nest_opt_num == 2)
+ {
+ connector_append_nested_opt_unit(nested_opt_unit_handle, QQ_OPT_FILENAME,qq_pme->filename, qq_pme->filename_len);
+ }
+ connector_append_nested_opt_unit(nested_opt_unit_handle, QQ_OPT_FILECONT,filecont, contlen);
+ connector_append_nested_opt(nested_opt_handle,nested_opt_unit_handle);
+
+ if(qq_pme->end_flag)
+ {
+ connector(qq_pme->connector_hdl, FRAG_END, NULL, nested_opt_handle);
+ connector_finish(qq_pme->connector_hdl);
+ qq_pme->connector_hdl = NULL;
+ }
+ else
+ {
+ connector(qq_pme->connector_hdl, FRAG, NULL, nested_opt_handle);
+ }
+ connector_free_nested_opt_unit(&nested_opt_unit_handle);
+ connector_free_nested_opt(&nested_opt_handle);
+
+ return APP_STATE_GIVEME;
+}
+
+int protocol_process(qq_proto_pme_t *qq_pme, long long prot_flag, char *buf_in, int inlen, struct streaminfo *a_udp, const void *raw_pkt)
+{
+ int rec = APP_STATE_GIVEME;
+ char buffer[512]={0}, *buf=buf_in;
+ int outlen=512, ret, buflen=inlen, k;
+ result_array_t result_array;
+
+ switch(prot_flag)
+ {
+ case QQ_FILENAME:
+ if(qq_pme->pending_flag==0)
+ break;
+ else
+ {
+ qq_pme->fileinfo.block_seq = -1; //���ݿ����¼������
+ qq_pme->end_flag = 0;
+ qq_pme->pending_flag = 0;
+ qq_pme->fileinfo.file_seq += 1;
+
+ if(qq_pme->qqnum_from == 0)
+ {
+ qq_pme->qqnum_to = qq_pme->qqnum[qq_pme->file_dir];
+ if(qq_pme->qqnum_to == qq_pme->qqnum[0])
+ qq_pme->qqnum_from = qq_pme->qqnum[1];
+ else
+ qq_pme->qqnum_from = qq_pme->qqnum[0];
+ }
+
+ if(g_qq_global_info.debug_sw)
+ {
+ qq_pme->random = rand();
+ }
+ }
+ if(!convert_from_unicode2utf8(buf_in, inlen, buffer, &outlen))
+ {
+ snprintf(qq_pme->filename, sizeof(qq_pme->filename), "%s", buffer);
+ qq_pme->filename_len = strlen(qq_pme->filename);
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_DEBUG, MODULE_NAME, "DETECT_QQ_FILE %s, QQ_FROM: %u, QQ_TO: %u, FILE_LEN: %u, FILENAME: %s", \
+ qq_pme->tcp_flag?"TCP":"UDP", qq_pme->qqnum_from, qq_pme->qqnum_to, qq_pme->total_file_len,qq_pme->filename);
+ }
+ else
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_INFO, MODULE_NAME, "convert_from_unicode2utf8 error: %s\n", strerror(errno));
+ return APP_STATE_DROPME;
+ }
+ break;
+
+ case QQ_FILECONT_END:
+ case QQ_FILECONT:
+ if(qq_pme->filename_len == 0)
+ return APP_STATE_DROPME;
+
+ if(prot_flag==QQ_FILECONT_END)
+ {
+ if(qq_pme->end_flag || qq_pme->pending_flag)
+ break;
+ else
+ {
+ qq_pme->end_flag = 1;
+ qq_pme->pending_flag = 1;
+ }
+ }
+ else if(qq_pme->pending_flag)
+ {
+ qq_pme->end_flag = 0;
+ qq_pme->pending_flag = 0;
+ }
+
+ if(inlen >= 4 && !memcmp(buf_in, gzip_feature, 4) && qq_pme->compress_flag)
+ {
+ docanalyze_streamparam_t doc_hanlde = docanalyze_startstream(DOC_GZIP_TYPE, g_qq_global_info.instanse, qq_pme->thread_id);
+ if(doc_hanlde ==NULL)
+ {
+ MESA_HANDLE_RUNTIME_LOGV2(g_qq_global_info.runtime_log,RLOG_LV_DEBUG, MODULE_NAME, "docanalyze_startstream() error.");
+ return APP_STATE_GIVEME;
+ }
+ memset(&result_array, 0, sizeof(result_array_t));
+ ret = docanalyze_parsestream(doc_hanlde, buf_in, inlen, &result_array);
+ if(ret == DOC_PRO_OK)
+ {
+ for (k=0; k < result_array.result_num; k++)
+ {
+ buf = result_array.result_buff[k].presult;
+ buflen = result_array.result_buff[k].size;
+ }
+ }
+ qq_pme->curr_file_len += buflen;
+
+ if(g_qq_global_info.debug_sw)
+ {
+ write_file_cont2disk(buf, buflen, qq_pme->filename, qq_pme->fileinfo.file_seq, qq_pme->random);
+ }
+ rec = sendback_qq_data(qq_pme, a_udp, buf, buflen);
+
+ docanalyze_freeresult(&result_array);
+ docanalyze_endstream(doc_hanlde);
+ }
+ else
+ {
+ qq_pme->curr_file_len += buflen;
+
+ if(g_qq_global_info.debug_sw)
+ {
+ write_file_cont2disk(buf, buflen, qq_pme->filename, qq_pme->fileinfo.file_seq, qq_pme->random);
+ }
+ rec = sendback_qq_data(qq_pme, a_udp, buf, buflen);
+ }
+ break;
+
+ default: break;
+ }
+
+ return rec;
+}
+
diff --git a/src/qq_file_global.h b/src/qq_file_global.h
new file mode 100644
index 0000000..2f1ad94
--- /dev/null
+++ b/src/qq_file_global.h
@@ -0,0 +1,21 @@
+#ifndef __QQ_FILE_GLOBAL_H__
+#define __QQ_FILE_GLOBAL_H__
+
+#define QQ_FILENAME 1
+#define QQ_FILECONT 2
+#define QQ_FILECONT_END 4
+
+#define MAX_MALLOC_SIZE (16*1024)
+#define REALLOC_BLOCK_SIZE 1024
+
+#define MESA_HANDLE_RUNTIME_LOGV2(handle, lv, mod, fmt, args...) \
+ MESA_handle_runtime_log((handle), (lv), (mod), "%s:%d, " fmt, \
+ __FILE__, __LINE__, ##args)
+
+int buf_cache_check_size(trans_file_info_t *pdstBuf, int wantedlen, int thread_seq);
+int save_initial_tcp_data(trans_file_info_t *pdstBuf, char *data, int datalen, int thread_seq);
+
+int protocol_process(qq_proto_pme_t *qq_pme, long long prot_flag, char *buf, int buflen, struct streaminfo *a_udp, const void *raw_pkt);
+
+#endif
+