607 lines
20 KiB
C
607 lines
20 KiB
C
#include <time.h>
|
|
#include <arpa/inet.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <MESA/MESA_prof_load.h>
|
|
#include <MESA/MESA_handle_logger.h>
|
|
#include <MESA/MESA_htable.h>
|
|
#include <MESA/stream.h>
|
|
#include <nirvana_client.h>
|
|
#include "http.h"
|
|
#define LOG_PATH "./log/qq_file/runtime.log"
|
|
|
|
#define ONLINE_SEND 0
|
|
#define OFFLINE_SEND 1
|
|
#define NAME_SIZE 128
|
|
#define MAX_HTABLE_NUM 96
|
|
#define UUID_LENGTH 35
|
|
|
|
#define NIRVANA
|
|
|
|
int QQ_FILE_SEND_VERSION_1_20201124 = 0;
|
|
void qq_file_send_version_1_20201124()
|
|
{
|
|
//20201124
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t send_type; // OFFLINE_SEND
|
|
char uuid[UUID_LENGTH+1];
|
|
uint16_t content_len; // content length in current packet
|
|
char filename[NAME_SIZE*2];
|
|
struct nirvana_streaming_ctx *ctx;
|
|
uint8_t next_flag; // 1: next packet contains separator
|
|
// 0: not contain
|
|
uint64_t *file_len; // file length
|
|
uchar curdir;
|
|
uint id; // same like file count , from 0 to start
|
|
}qq_pme_info,*qq_pme_info_p;
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t feature_type;
|
|
char *separator_header;
|
|
uint header_len;
|
|
uint uuid_deviation;
|
|
char *uuid_suffix;
|
|
uint uuid_suffix_len;
|
|
uint content_deviation;
|
|
char *end_suffix;
|
|
uint end_suffix_len;
|
|
}struct_separator_feature;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
uint id;
|
|
uint8_t send_type;
|
|
char filename[NAME_SIZE*2];
|
|
struct nirvana_streaming_ctx *ctx;
|
|
uint64_t *file_len; // file length
|
|
}file_info;
|
|
|
|
uint capture_file_cnt = 0;
|
|
|
|
struct_separator_feature online_feature,offline_feature;
|
|
MESA_htable_handle file_htable;
|
|
char save_directory[NAME_SIZE];
|
|
int locally_save; // save file to local machine
|
|
void *runtime_log;
|
|
struct nirvana_instance *instance_asyn;
|
|
|
|
/*
|
|
* @Description: Use this function instead of strncmp ,because strncmp may have problems matching features
|
|
* @param: the main string
|
|
* @param: the pattern string to be searched
|
|
* @param: the len of pattern sting
|
|
* @return: 0 : success
|
|
-1 : fail
|
|
*/
|
|
int bicmp(char *str,char *ptn,int len)
|
|
{
|
|
int i;
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
if(str[i] != ptn[i])
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* @Description: Extract the information of private protocols in payload
|
|
* @param: payload
|
|
* @param: payload_len
|
|
* @param: features of separators
|
|
* @param: pme
|
|
* @return: =0 : success
|
|
<0 : fail
|
|
*/
|
|
int parse_separator(char **payload,int payload_len,struct_separator_feature separator_feature,qq_pme_info **pme)
|
|
{
|
|
int uuid_len = UUID_LENGTH;
|
|
//match by header
|
|
if( bicmp(*payload,separator_feature.separator_header, separator_feature.header_len) != 0)
|
|
{
|
|
return -1;
|
|
}
|
|
// match by the suffix which is after uuid
|
|
if( bicmp( (*payload)+separator_feature.uuid_deviation + uuid_len + 1, separator_feature.uuid_suffix,separator_feature.uuid_suffix_len) != 0)
|
|
{
|
|
return -2;
|
|
}
|
|
qq_pme_info_p qq_pme = *pme;
|
|
strncpy(qq_pme->uuid,(*payload) + separator_feature.uuid_deviation,uuid_len);
|
|
qq_pme->uuid[uuid_len] = '\0';
|
|
//printf("this uuid:%s\n",qq_pme->uuid);
|
|
|
|
(*payload)+=separator_feature.content_deviation;
|
|
|
|
qq_pme->content_len = payload_len-separator_feature.content_deviation;
|
|
qq_pme->send_type = separator_feature.feature_type;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* @Description: find end suffix in response payload
|
|
if found,means the end of the current file transfer
|
|
* @param: payload
|
|
* @param: payload_len
|
|
* @param: separator_feature
|
|
* @param: file_id
|
|
* @return: =0 : success
|
|
<0 : fail
|
|
*/
|
|
int parse_end_suffix(char *payload,int payload_len,struct_separator_feature separator_feature,uint file_id)
|
|
{
|
|
|
|
if( bicmp(separator_feature.end_suffix,payload,separator_feature.end_suffix_len) != 0)
|
|
{
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_DEBUG,"match","file %u not finish",file_id);
|
|
return -1;
|
|
}
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_DEBUG,"match","file %u finish",file_id);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* @Description: Converts a string in hex to decimal(int)
|
|
* @param: a hex char ,range : 0-9a-f
|
|
* @return: int , range : 0-15
|
|
*/
|
|
int hexch_to_int(char ch)
|
|
{
|
|
if ((ch >= 'A') && (ch <='F'))
|
|
{
|
|
return 10+ch-'A';
|
|
}
|
|
else if ((ch >= 'a') && (ch <='f'))
|
|
{
|
|
return 10+ch-'a';
|
|
}
|
|
else{
|
|
return ch-'0';
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @Description: 'abcd00' -> {0xab,0xcd,0x00}
|
|
* @param: in_str
|
|
* @param: the len of out_str
|
|
* @param: out_str
|
|
* @return: None
|
|
*/
|
|
void str_to_ascii(char *in_str,int str_len,char* out_str)
|
|
{
|
|
int i;
|
|
for (i=0;i<str_len;i++)
|
|
{
|
|
out_str[i] = hexch_to_int(in_str[i*2])*16 + hexch_to_int(in_str[i*2+1]);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @Description: read the feature of the separator in the profile
|
|
* @param: [IN] profile name
|
|
* @param: [OUT] p_separator_feature
|
|
* @param: [IN] section name
|
|
* @param: [IN] feature type eg ONLINE_SEND/OFFLINE_SEND
|
|
* @return:
|
|
0 : success
|
|
>0: fail
|
|
*/
|
|
int read_profile_of_separator(const char *inf_file,struct_separator_feature *p_separator_feature,char *section,int feature_type)
|
|
{
|
|
|
|
char *separator_header_array,*uuid_suffix_array,*end_suffix_array;
|
|
int read_res = 0;
|
|
|
|
p_separator_feature->feature_type = feature_type;
|
|
|
|
//header_len
|
|
read_res += MESA_load_profile_uint_nodef(inf_file,section,"header_len",&(p_separator_feature->header_len));
|
|
|
|
//header
|
|
p_separator_feature->separator_header = (char *)malloc(p_separator_feature->header_len+1);
|
|
separator_header_array = (char *)malloc((p_separator_feature->header_len)<<1|1);
|
|
if(MESA_load_profile_string_nodef(inf_file,section,"separator_header",separator_header_array,p_separator_feature->header_len<<1|1)<0)
|
|
{
|
|
read_res += -1;
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"init","[%s] separator_header error",section);
|
|
}
|
|
str_to_ascii(separator_header_array,p_separator_feature->header_len,p_separator_feature->separator_header);
|
|
free(separator_header_array);
|
|
|
|
//uuid_deviation
|
|
read_res += MESA_load_profile_uint_nodef(inf_file,section,"uuid_deviation",&(p_separator_feature->uuid_deviation));
|
|
|
|
//uuid_suffix_len
|
|
read_res += MESA_load_profile_uint_nodef(inf_file,section,"uuid_suffix_len",&(p_separator_feature->uuid_suffix_len));
|
|
|
|
//uuid_suffix
|
|
p_separator_feature->uuid_suffix = (char *)malloc(p_separator_feature->uuid_suffix_len+1);
|
|
uuid_suffix_array = (char *)malloc(p_separator_feature->uuid_suffix_len<<2|1);
|
|
if(MESA_load_profile_string_nodef(inf_file,section,"uuid_suffix",uuid_suffix_array,p_separator_feature->uuid_suffix_len<<1|1)<0)
|
|
{
|
|
read_res += -1;
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"init","[%s] uuid_suffix error",section);
|
|
}
|
|
str_to_ascii(uuid_suffix_array,p_separator_feature->uuid_suffix_len,p_separator_feature->uuid_suffix);
|
|
free(uuid_suffix_array);
|
|
|
|
//content_deviation
|
|
read_res += MESA_load_profile_uint_nodef(inf_file,section,"content_deviation",&(p_separator_feature->content_deviation));
|
|
|
|
//end_suffix_len
|
|
read_res += MESA_load_profile_uint_nodef(inf_file,section,"end_suffix_len",&(p_separator_feature->end_suffix_len));
|
|
|
|
//end_suffix
|
|
p_separator_feature->end_suffix = (char *)malloc(p_separator_feature->end_suffix_len+1);
|
|
end_suffix_array = (char *)malloc(p_separator_feature->end_suffix_len<<1|1);
|
|
if(MESA_load_profile_string_nodef(inf_file,section,"end_suffix",end_suffix_array,p_separator_feature->end_suffix_len<<1|1)<0)
|
|
{
|
|
read_res += -1;
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"init","[%s] end_suffix error",section);
|
|
}
|
|
str_to_ascii(end_suffix_array,p_separator_feature->end_suffix_len,p_separator_feature->end_suffix);
|
|
free(end_suffix_array);
|
|
return read_res;
|
|
}
|
|
|
|
/*
|
|
* @Description: Used to delete value from hash table
|
|
* @param: file_info *
|
|
* @return: Null
|
|
*/
|
|
void free_fileinfo(void *thisfile)
|
|
{
|
|
//thisfile = thisfile;
|
|
file_info *p = (file_info *)thisfile;
|
|
#ifdef NIRVANA
|
|
nirvana_streaming_update_end(p->ctx);
|
|
#endif
|
|
if (p->send_type == OFFLINE_SEND)
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_INFO,"offline","save file %d , size: %lld bytes",p->id, *(p->file_len));
|
|
else
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_INFO,"online","save file %d , size: %lld bytes",p->id, *(p->file_len));
|
|
if(p->file_len)
|
|
free(p->file_len);
|
|
free(p);
|
|
}
|
|
|
|
|
|
/*
|
|
* @Description: different files have different uuids.
|
|
Fragments with the same UUID belong to the same file
|
|
get the pme according to the current uuid
|
|
* @param: pme
|
|
* @param: content len
|
|
* @param: send_type
|
|
* @return:
|
|
0: not exist
|
|
1: exist
|
|
*/
|
|
int match_uuid(qq_pme_info **pme)
|
|
{
|
|
qq_pme_info_p qq_pme = *pme;
|
|
file_info* thisfile = (file_info *) MESA_htable_search(file_htable,(u_char *)qq_pme->uuid,UUID_LENGTH);
|
|
if (thisfile == NULL)
|
|
{
|
|
// new file create
|
|
file_info *newfile;
|
|
newfile = (file_info *)malloc(sizeof(file_info));
|
|
|
|
qq_pme->id = capture_file_cnt;
|
|
capture_file_cnt++;
|
|
newfile->id = qq_pme->id;
|
|
sprintf(qq_pme->filename,"%s/%d-%s",save_directory,qq_pme->id,qq_pme->uuid);
|
|
|
|
strncpy(newfile->filename,qq_pme->filename,NAME_SIZE);
|
|
newfile->filename[strlen(qq_pme->filename)] = '\0';
|
|
|
|
uint64_t *file_len = (uint64_t *)malloc(sizeof(uint64_t));
|
|
*file_len = 0;
|
|
qq_pme->file_len = file_len;
|
|
newfile->file_len = file_len;
|
|
newfile->send_type = qq_pme->send_type;
|
|
#ifdef NIRVANA
|
|
// nirvana section
|
|
struct nirvana_streaming_ctx *ctx;
|
|
union nirvana_progid progid;
|
|
struct streaming_meta streammeta;
|
|
struct nvn_opt_unit opt[1];
|
|
int opt_num = 0;
|
|
memset(&streammeta,0,sizeof(streammeta));
|
|
streammeta.msg_type = NVN_MSG_TYPE_DOC_IM;
|
|
if(qq_pme->send_type == ONLINE_SEND)
|
|
streammeta.msg_subtype = NVN_MSG_SUBTYPE_IM_QQ_ONLINE;
|
|
else
|
|
streammeta.msg_subtype = NVN_MSG_SUBTYPE_IM_QQ_OFFLINE;
|
|
streammeta.protocol = NVN_PROTOCOL_QQ;
|
|
|
|
streammeta.cont_code = 0;
|
|
streammeta.live_streaming = 0;
|
|
streammeta.cap_IP = 0;
|
|
streammeta.dir = DIR_C2S;
|
|
streammeta.request_single_flow = 0;
|
|
|
|
calculate_md5_for_progid(newfile->filename, strlen(newfile->filename), &progid);
|
|
streammeta.balance_seed = caculate_seed_using_sdbm_hash((char*)&progid, sizeof(progid));
|
|
ctx = nirvana_streaming_update_start(instance_asyn, &progid, &streammeta);
|
|
|
|
if(ctx == NULL)
|
|
{
|
|
return PROT_STATE_DROPME;
|
|
}
|
|
nirvana_streaming_update_meta(ctx, opt, opt_num);
|
|
qq_pme->ctx = ctx;
|
|
newfile->ctx = ctx;
|
|
#endif
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_INFO,"match","found %d file\tuuid:%s ",qq_pme->id,qq_pme->uuid);
|
|
MESA_htable_add(file_htable,(u_char *) qq_pme->uuid, UUID_LENGTH, (void *)newfile);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// there is a file point in htable
|
|
// so change the pme
|
|
qq_pme->id = thisfile->id;
|
|
qq_pme->file_len = thisfile->file_len;
|
|
qq_pme->send_type = thisfile->send_type;
|
|
strncpy(qq_pme->filename,thisfile->filename,strlen(thisfile->filename));
|
|
#ifdef NIRVANA
|
|
qq_pme->ctx = thisfile->ctx;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* @Description: free memory of pme
|
|
*/
|
|
void free_pme(qq_pme_info **pme)
|
|
{
|
|
qq_pme_info_p qq_pme = *pme;
|
|
//free(qq_pme->ctx);
|
|
free(qq_pme);
|
|
}
|
|
|
|
|
|
uchar qq_file_send_entry(stSessionInfo* session_info,void **pme,int thread_seq,struct streaminfo *a_tcp,void *a_packet)
|
|
{
|
|
int res = 0;
|
|
uchar rec = PROT_STATE_GIVEME;
|
|
|
|
//int payload_len = tcp_detail->datalen;
|
|
//char *payload =(char *)tcp_detail->pdata;
|
|
|
|
qq_pme_info_p qq_pme = (qq_pme_info_p) *pme;
|
|
http_infor* a_http = (http_infor *)(session_info->app_info);
|
|
|
|
switch(session_info->prot_flag)
|
|
{
|
|
case HTTP_REQ_LINE:
|
|
if(a_http->method!=HTTP_METHOD_POST)
|
|
{
|
|
rec = PROT_STATE_DROPME;
|
|
}
|
|
if (*pme == NULL)
|
|
{
|
|
*pme =(qq_pme_info_p)malloc(sizeof(qq_pme_info));
|
|
qq_pme = *pme;
|
|
memset(qq_pme->filename,0,NAME_SIZE);
|
|
}
|
|
qq_pme->curdir = a_http->curdir;
|
|
break;
|
|
case HTTP_RES_LINE:
|
|
if (qq_pme == NULL)
|
|
{
|
|
rec = PROT_STATE_DROPME;
|
|
}
|
|
break;
|
|
case HTTP_MESSAGE_URL:
|
|
{
|
|
char bmd5[33];
|
|
int url_decoded_len;
|
|
url_decoded_len = session_info->buflen;
|
|
char *url_decoded = (char*)calloc(url_decoded_len+1,sizeof(char));
|
|
memcpy(url_decoded, session_info->buf, session_info->buflen);
|
|
res = sscanf(url_decoded,"%*d.%*d.%*d.%*d:%*d/ftn_handler?bmd5=%32s",bmd5);
|
|
if(res>0)
|
|
{
|
|
qq_pme->next_flag = 0;
|
|
// separator_flag is 1 means that the next TCP packet contains a separator
|
|
}
|
|
else
|
|
{
|
|
rec = PROT_STATE_DROPME;
|
|
}
|
|
free(url_decoded);
|
|
break;
|
|
}
|
|
case HTTP_CONTENT:
|
|
{
|
|
int content_len = session_info->buflen;
|
|
char *payload = (char *)malloc(content_len);
|
|
memcpy(payload,session_info->buf,content_len);
|
|
char *content = payload;
|
|
if (content_len==0)
|
|
{
|
|
free(payload);
|
|
break;
|
|
}
|
|
if (qq_pme->curdir != a_http->curdir)
|
|
{
|
|
// looking for end suffix
|
|
if(qq_pme->send_type == ONLINE_SEND)
|
|
{
|
|
res = parse_end_suffix(content,content_len,online_feature,qq_pme->id);
|
|
}
|
|
else
|
|
{
|
|
res = parse_end_suffix(content,content_len,offline_feature,qq_pme->id);
|
|
}
|
|
if(res == 0)
|
|
{
|
|
MESA_htable_del(file_htable,(u_char *)qq_pme->uuid,UUID_LENGTH,free_fileinfo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(qq_pme->next_flag == 0)
|
|
{
|
|
res = parse_separator(&content,content_len,offline_feature,&qq_pme);
|
|
if(res < 0)
|
|
{
|
|
// If offline matching fails, the online rule will be matched again
|
|
res = parse_separator(&content,content_len,online_feature,&qq_pme);
|
|
if(res < 0)
|
|
{
|
|
// If both matches fail, the rule sis wrong or the traffic is wrong
|
|
if (res == -1)
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"match","feature fail,check rule");
|
|
else
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"match","feature fail,unkown type");
|
|
// if the current http stream is transferring a file with a half,and the rule matches fail
|
|
// there will be a streamctx still open and no way to close
|
|
// but this situation seems won't happen
|
|
rec = PROT_STATE_DROPME;
|
|
free(payload);
|
|
break;
|
|
}
|
|
else
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_DEBUG,"match","online feature success,uuid:%s",qq_pme->uuid);
|
|
}
|
|
else
|
|
{
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_DEBUG,"match","offline feature success,uuid:%s",qq_pme->uuid);
|
|
}
|
|
qq_pme->next_flag = 1;
|
|
content_len = qq_pme->content_len;
|
|
match_uuid(&qq_pme);
|
|
}
|
|
*(qq_pme->file_len) += content_len;
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_DEBUG,"match","file %d saved %d Bytes, content_len:%d",qq_pme->id,*(qq_pme->file_len),content_len);
|
|
if(locally_save == 1)
|
|
{
|
|
//save file to disk
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_DEBUG,"match","file %d saved as %s",qq_pme->id,qq_pme->filename);
|
|
FILE *fp = fopen(qq_pme->filename,"ab");
|
|
fwrite(content,content_len,1,fp);
|
|
fclose(fp);
|
|
}
|
|
#ifdef NIRVANA
|
|
nirvana_streaming_update_data(qq_pme->ctx, content, content_len);
|
|
#endif
|
|
}
|
|
free(payload);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if(session_info->session_state&SESSION_STATE_CLOSE || rec == PROT_STATE_DROPME)
|
|
{
|
|
if(pme != NULL)
|
|
{
|
|
free_pme((qq_pme_info **)pme);
|
|
}
|
|
}
|
|
return rec;
|
|
}
|
|
|
|
int suggestion_inform_callback(struct suggest_receive_info *info, struct nirvana_message_survey *detail, const char *snap_URL, struct nvn_opt_unit *opts, void *privdata)
|
|
{
|
|
char fromip_str[64];
|
|
|
|
inet_ntop(AF_INET, &info->from_ip, fromip_str, 64);
|
|
|
|
printf("Receive suggest from: %s, progid=0x%lu_%lu\n", fromip_str, detail->progid.progid_long.progidH, detail->progid.progid_long.progidL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void nirvana_client_init()
|
|
{
|
|
struct nirvana_parameter *parameter;
|
|
parameter = nirvana_client_parameter_new("./plug/business/qq_file_send/qq_file_send.conf", "NIRVANA", runtime_log);
|
|
//assert(parameter != NULL);
|
|
instance_asyn = nirvana_evbase_instance_new(parameter, runtime_log, suggestion_inform_callback, NULL);
|
|
//assert(instance_asyn!=NULL);
|
|
}
|
|
|
|
void QQ_FILE_SEND_DESTROY()
|
|
{
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_INFO,"destroy","------------exit------------");
|
|
}
|
|
|
|
int qq_file_send_init()
|
|
{
|
|
printf("qq_file_send init\n");
|
|
int read_res = 0;
|
|
|
|
runtime_log = MESA_create_runtime_log_handle(LOG_PATH, 20);
|
|
|
|
char *inf_file = "./plug/business/qq_file_send/qq_file_send.conf";
|
|
read_res += read_profile_of_separator(inf_file,&online_feature,"ONLINE_FEATURE",ONLINE_SEND);
|
|
read_res += read_profile_of_separator(inf_file,&offline_feature,"OFFLINE_FEATURE",OFFLINE_SEND);
|
|
|
|
//read_res += MESA_load_profile_string_nodef(inf_file,"CAPTURE","post_header",post_header,NAME_SIZE);
|
|
MESA_load_profile_int_def(inf_file,"CAPTURE","locally_save",&locally_save,0);
|
|
if(locally_save == 1)
|
|
{
|
|
if(MESA_load_profile_string_def(inf_file,"CAPTURE","save_directory",save_directory,NAME_SIZE,"./plug/business/qq_file_send/")<0)
|
|
{
|
|
read_res += -1;
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"init","load save directory failed");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy(save_directory,"./plug/business/qq_file_send/");
|
|
}
|
|
if(access(save_directory,W_OK) != 0 && locally_save == 1)
|
|
{
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"init","save directory %s not found or cannot write\n",save_directory);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_DEBUG,"init","save directory is %s",save_directory);
|
|
}
|
|
|
|
//free(inf_file);
|
|
if(read_res == 0)
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_INFO,"init","------------load feature success------------");
|
|
else
|
|
{
|
|
MESA_handle_runtime_log(runtime_log,RLOG_LV_FATAL,"init","------------load feature failed:%d------------",read_res);
|
|
return -1;
|
|
}
|
|
#ifdef NIRVANA
|
|
nirvana_client_init();
|
|
#endif
|
|
|
|
MESA_htable_create_args_t *htable_args;
|
|
htable_args = (MESA_htable_create_args_t *)malloc(sizeof(MESA_htable_create_args_t));
|
|
htable_args->thread_safe = 1;
|
|
htable_args->recursive = 0;
|
|
htable_args->hash_slot_size = 1048576;
|
|
htable_args->max_elem_num = MAX_HTABLE_NUM;
|
|
htable_args->key_comp = NULL;
|
|
htable_args->key2index = NULL;
|
|
htable_args->data_free = free_fileinfo;
|
|
htable_args->data_expire_with_condition = NULL;
|
|
htable_args->eliminate_type = 0;
|
|
htable_args->expire_time = 60;
|
|
file_htable = MESA_htable_create(htable_args,1);
|
|
MESA_htable_print_crtl(file_htable,0);
|
|
return 0;
|
|
}
|