#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "MESA_handle_logger.h" #include "service.h" #include "common.h" #include "bizman.h" #include "my_socket.h" #include "AV_interface.h" #include "AV_sendback_in.h" #include "frag_reassembly_in.h" #include "log.h" #include "frag_proc.h" #include "frag_voip.h" extern frag_rssb_parameter_t g_frag_run; extern frag_rssb_configure_t g_frag_cfg; extern frag_rssb_status_t g_frag_stat; extern frag_reassembly_t frag_rssb; //use media hash extern const char* hash_eliminate_type[3]; media_type_t g_av_mediatype_des[MEDIATYPE_MAXNUM] = { {FILE_UNKNOWN, "unkonwn"}, {FILE_VIDEO, "video"}, {FILE_WMV, "wmv"}, {FILE_MPG, "mpg"}, {FILE_FLV, "flv"}, {FILE_RMFF, "rmff"}, {FILE_AVI, "avi"}, {FILE_SWF, "swf"}, {FILE_MPG4, "mpg4"}, {FILE_AIFF, "aiff"}, {FILE_OGG, "ogg"}, {FILE_DRC, "drc"}, {FILE_DIRECTSHOW, "directshow"}, {FILE_FLIC, "flic"}, {FILE_INDEO, "indeo"}, {FILE_MKV, "mkv"}, {FILE_AUDIO, "audio"}, {FILE_MP3, "mp3"}, {MMS_TYPE, "mms"}, {RTSP_RDT_TYPE, "rtsp_rdt"}, {RTSP_RTP_TYPE, "rtsp_rtp"}, {FILE_HLS, "ts"}, {FILE_OSMF, "osmf"}, {FILE_IMAGE, "image"}, {FILE_JPG, "jpg"}, {FILE_BMP, "omp"}, {FILE_GIF, "gif"}, }; media_type_t g_voip_mediatype_des[VOIP_MEDIATYPE_MAXNUM] = { {AUDIO_UNKNOWN,"unkonwn"}, {AUDIO_G711_ULAW,"G711_U"}, {AUDIO_G711_ALAW,"G711_A"}, {AUDIO_G722,"G722"}, {AUDIO_G723,"G723"}, {AUDIO_G726_40,"G726_40"}, {AUDIO_G726_32,"G726_32"}, {AUDIO_G726_24,"G726_24"}, {AUDIO_G726_16,"G726_16"}, {AUDIO_AAL2_G726_40,"G726_40"}, {AUDIO_AAL2_G726_32,"G726_32"}, {AUDIO_AAL2_G726_24,"G726_24"}, {AUDIO_AAL2_G726_16,"G726_16"}, {AUDIO_G728,"G728"}, {AUDIO_G729D,"G729D"}, {AUDIO_G729E,"G729E"}, {AUDIO_GSM,"GSM"}, {AUDIO_GSM_EFR,"GSM_EFR"}, {AUDIO_ILBC,"ILBC"}, {AUDIO_AMR,"AMR"}, {AUDIO_AMR_WB,"AMR_WB"}, {AUDIO_SILK,"SILK"}, {AUDIO_LPC,"LPC"}, {AUDIO_LPC1016,"LPC1016"}, {AUDIO_LPC1015,"LPC1015"}, {AUDIO_L16,"L16"}, {AUDIO_SPEEX,"SPEEX"}, {AUDIO_L8,"L8"}, {AUDIO_MPA,"MPA"}, {AUDIO_DVI4,"DVI4"}, {AUDIO_VDVI,"VDVI"}, {AUDIO_CN,"CN"}, {AUDIO_RED,"RED"}, {AUDIO_QCELP,"QCELP"}, {AUDIO_EVRC0,"EVRC0"}, {AUDIO_EVRCB0,"EVRCB0"}, {AUDIO_G729,"G729"}, {AUDIO_VIVOX,"VIVOX"} }; /***************************************dumpfile service***************************************************/ int free_file_frag(file_frag_t *data) { file_frag_t* file_frag = (file_frag_t*)data; if(NULL!=file_frag) { if(file_frag->data!=NULL) { free(file_frag->data); } free(file_frag); } return 0; } int gen_monitor_file_dir(time_t create_time, uint64_t prog_id, char *path, int len) { if(NULL == path || len < 256 || 0 == prog_id) { return(-1); } char today[64] = {0}; static const char* hex = "0123456789ABCDEF"; uint16_t* p16 = NULL; char* p = NULL; int i = 0; int step = 0; int write_len = 0; struct tm a_tm; localtime_r(&create_time,&a_tm); memset(today, 0, sizeof(today) ); strftime(today, sizeof(today), "%Y%m%d", &a_tm); p = path; if(g_frag_cfg.monitor_file_root_dir[strlen(g_frag_cfg.monitor_file_root_dir)-1]=='/') { g_frag_cfg.monitor_file_root_dir[strlen(g_frag_cfg.monitor_file_root_dir)-1]='\0'; } if(g_frag_cfg.monitor_file_days) { write_len= snprintf(p,len, "%s/%s", g_frag_cfg.monitor_file_root_dir,today); if(write_len==len) { return -1; } p += write_len; } p16 = (uint16_t*)&prog_id; for(i = 0; i < 5; i += 1) { *p++ = '/'; if(i % 2 == 1) { *p++ = hex[(0xf000 & *p16) >> 12]; step = 2; } *p++ = hex[(0x0f00 & *p16) >> 8]; *p++ = hex[(0x00f0 & *p16) >> 4]; if(i % 2 == 0) { *p++ = hex[(0x000f & *p16)]; step = 1; } *p = '\0'; p16 = (uint16_t*)( (uint8_t*)p16 + step); } return p-path; } int gen_monitor_file_path(time_t create_time, uint64_t prog_id, char *file_suffix, char *path, int len) { int offset=0; int write_len=0; if(NULL == path || len < 256 || 0 == prog_id) { return -1; } offset = gen_monitor_file_dir(create_time, prog_id, path, len); write_len = snprintf(path+offset,len-offset, "/%" PRIu64 ".%s", prog_id, file_suffix); if(write_len==len-offset) { return -1; } offset += write_len; offset++; return offset; } void free_dumpfile_hash_node(void* data) { dumpfile_hash_node_t* dump_hnode = (dumpfile_hash_node_t*)data; if(NULL!=dump_hnode) { if(NULL!=dump_hnode->fp) { fclose(dump_hnode->fp); } free(dump_hnode); dump_hnode = NULL; } } int expire_dumpfile_hash_node(void *data, int eliminate_type) { dumpfile_hash_node_t* dump_hnode = (dumpfile_hash_node_t*)data; switch(eliminate_type) { case ELIMINATE_TYPE_NUM: atomic_inc(&g_frag_stat.sysinfo_stat[DUMPFILE_HASH][HASH_NUM_EXPIRE]); break; case ELIMINATE_TYPE_TIME: atomic_inc(&g_frag_stat.sysinfo_stat[DUMPFILE_HASH][HASH_TIME_EXPIRE]); break; default: break; } MESA_handle_runtime_log(g_frag_run.logger, RLOG_LV_INFO, FRAG_REASSEMBLY_MODULE_NAME, "{%s:%d} expire_dumpfile_hash_node %s: [filemane: %s]", __FILE__,__LINE__, hash_eliminate_type[eliminate_type], dump_hnode->filename); return 1; } char* gen_filesuffix_by_mediatype(char *file_suffix, uint8_t mediatype, uint8_t proto) { if(g_frag_cfg.cpz_type == CPZ_VOIP) { for(int i=1;ikey.filename; FILE* fp = NULL; int rec = 0; dumpfile_hash_node_t* dump_hnode = (dumpfile_hash_node_t*)data; if(NULL==dump_hnode) { rec = mkdir_r(filename); if(rec>=0) { fp = fopen(filename,"r+"); if(NULL==fp) { fp = fopen(filename,"w"); if(NULL!=fp) { fclose(fp); } fp = fopen(filename,"r+"); } if(NULL!=fp) { dump_hnode = (dumpfile_hash_node_t*)calloc(1, sizeof(dumpfile_hash_node_t)); dump_hnode->fp = fp; memcpy(dump_hnode->filename, filename, strlen(filename)); rec = MESA_htable_add(g_frag_run.dumpfile_hash, key, size,(const void*)dump_hnode); if(0>rec) { MESA_handle_runtime_log(g_frag_run.logger, RLOG_LV_FATAL, FRAG_REASSEMBLY_MODULE_NAME, "{%s:%d} dumpfile_hash MESA_htable_add error: [filename: %s]", __FILE__,__LINE__, filename); free_dumpfile_hash_node(dump_hnode); dump_hnode = NULL; } } } else { MESA_handle_runtime_log(g_frag_run.logger, RLOG_LV_FATAL, FRAG_REASSEMBLY_MODULE_NAME, "{%s:%d} dumpfile gen_monitor_file_path error: [filename:%s, mid: %llu]", __FILE__,__LINE__, filename, file_frag->key.mid); } } if(NULL!=dump_hnode && NULL!=dump_hnode->fp) { file_frag->key.fp = dump_hnode->fp; MESA_handle_runtime_log(g_frag_run.frag_logger, RLOG_LV_INFO, FRAG_REASSEMBLY_MODULE_NAME, "{%s:%d} DUMP FILE [filename:%s, MID:%llu, offset_in:%llu, datalen:%u]", __FILE__,__LINE__,filename, file_frag->key.mid, file_frag->offset_in, file_frag->datalen); } else { MESA_handle_runtime_log(g_frag_run.logger, RLOG_LV_FATAL, FRAG_REASSEMBLY_MODULE_NAME, "{%s:%d} dumpfile open monitor_file_path error, maybe fd is full: [filename:%s, mid: %llu]", __FILE__,__LINE__, filename, file_frag->key.mid); } return 0; } /*---------------monitor_service_dump_file_thread---------------*/ void* monitor_service_dump_file_thread(void *param) { file_frag_t* file_frag = NULL; long file_frag_len = sizeof(file_frag); long rec_cb = 0; long tid = (long)param; while(1) { file_frag = NULL; MESA_lqueue_read_head(g_frag_run.monitor_file_lq[tid], &file_frag, &file_frag_len); MESA_htable_search_cb(g_frag_run.dumpfile_hash, (const uint8_t*)&file_frag->key.mid, sizeof(file_frag->key.mid), dumpfile_hash_search_cb, file_frag, &rec_cb); if(NULL!=file_frag->key.fp) { fseek(file_frag->key.fp, file_frag->offset_in, SEEK_SET); fwrite(file_frag->data, file_frag->datalen, 1, file_frag->key.fp); //fflush(file_frag->key.fp); atomic_inc(&g_frag_stat.sysinfo_stat[DUMPFILE_QUEUE][QUEUE_OUT]); atomic_inc(&g_frag_stat.stat_info[MONITOR_DUMP_FILE][TOTAL_PKTS]); atomic_add(&g_frag_stat.stat_info[MONITOR_DUMP_FILE][TOTAL_BYTES], file_frag->datalen); MESA_lqueue_get_head(g_frag_run.monitor_file_lq[tid], &file_frag, &file_frag_len); MESA_handle_runtime_log(g_frag_run.frag_logger, RLOG_LV_DEBUG, FRAG_REASSEMBLY_MODULE_NAME, "{%s:%d} DUMP FILE from queue [MID:%llu, offset_in:%llu, datalen:%u]", __FILE__,__LINE__,file_frag->key.mid, file_frag->offset_in, file_frag->datalen); free_file_frag(file_frag); } else { /*file full, sleep to wait expire*/ sleep(g_frag_cfg.dumpfile_hash_expire_time/2); } file_frag = NULL; } return NULL; } void monitor_service_dump_file(frag_in_t* frg, media_t* mdi) { if(mdi->monitor_path==NULL) return; file_frag_t* file_frag = (file_frag_t*)calloc(1, sizeof(file_frag_t)); if(g_frag_cfg.cpz_type==CPZ_VOIP) { /*SIP的数据包含8个字节的time+SEQ,在写本地文件的时候过滤掉*/ file_frag->data = (char*)malloc(frg->datalen-VOIP_DATA_TIME_SEQ_LEN); file_frag->datalen = frg->datalen-VOIP_DATA_TIME_SEQ_LEN; memcpy(file_frag->data, frg->data+VOIP_DATA_TIME_SEQ_LEN, file_frag->datalen); } else { file_frag->data = (char*)malloc(frg->datalen); file_frag->datalen = frg->datalen; memcpy(file_frag->data, frg->data, file_frag->datalen); } file_frag->offset_in = frg->offset; file_frag->key.mid = frg->mid; //file_frag->key.proto = mdi->proto; //file_frag->key.media_type = mdi->media_type; //file_frag->key.create_time = mdi->create_time; memcpy(file_frag->key.filename, mdi->monitor_path, strlen(mdi->monitor_path)); MESA_lqueue_join_tail(g_frag_run.monitor_file_lq[frg->thread_seq], &file_frag, sizeof(file_frag)); atomic_inc(&g_frag_stat.sysinfo_stat[DUMPFILE_QUEUE][QUEUE_IN]); MESA_handle_runtime_log(g_frag_run.frag_logger, RLOG_LV_DEBUG, FRAG_REASSEMBLY_MODULE_NAME, "{%s:%d} DUMP FILE to queue [MID:%llu, offset_in:%llu, datalen:%u]", __FILE__,__LINE__,file_frag->key.mid, file_frag->offset_in, file_frag->datalen); } /**************************************monitor service************************************/ int create_monitor(char *buf, int bufsize, media_t* mdi, uint8_t cfg_id, uint8_t service) { char ip_str[64] = {0}; int local_path_len = 0; int path_len = 0; msg_header_t* monitor_header = NULL; resp_checkresult_t* monitor_msg = NULL; char* file_suffix =NULL; monitor_header = (msg_header_t*)buf; monitor_msg = (resp_checkresult_t*)((char*)monitor_header + MSG_HEADER_LEN); monitor_header->magic_num = PROTO_MAGICNUM; monitor_header->version = PROTO_VERSION; monitor_header->msg_type = MSG_RESP_CHECKRESULT; monitor_header->cont_len = 0; memcpy(monitor_msg->prog_id, &mdi->mid, sizeof(mdi->mid)); monitor_msg->service = service; monitor_msg->level = 100; /* any number >0 is OK */ monitor_msg->cfg_id = (uint32_t)cfg_id; /*文件路径*/ if(mdi->monitor_path==NULL) { mdi->monitor_path = (char*)calloc(1, MAX_PATH_LEN); /*根据media_type命名文件后缀*/ if(g_frag_cfg.all_hit_filename) { file_suffix = gen_filesuffix_by_mediatype(file_suffix, mdi->media_type, mdi->proto); } else { if(mdi->proto==AV_PROTOCOL_HTTP_STREAM) { file_suffix = (char*)"jpeg"; } else { file_suffix = (char*)"flv"; } } local_path_len = gen_monitor_file_path(mdi->create_time, mdi->mid, file_suffix, mdi->monitor_path, 1460-MSG_HEADER_LEN-MSG_RESP_CHECKRESULT_LEN); if(local_path_len < 0) { return 0; } } inet_ntop(AF_INET, &g_frag_cfg.local_ip_nr, ip_str, sizeof(ip_str)); path_len = snprintf((char*)monitor_msg + MSG_RESP_CHECKRESULT_LEN, 1460-MSG_HEADER_LEN-MSG_RESP_CHECKRESULT_LEN, "%s:%s", ip_str, mdi->monitor_path); path_len++; //snprintf's return lenth not including '\0',add one. monitor_header->cont_len = path_len + MSG_RESP_CHECKRESULT_LEN; return monitor_header->cont_len + MSG_HEADER_LEN; } long search_monitor_hash_cb(void *data, const uint8_t *key, uint size, void *user_arg) { if(NULL!=data) { return 1; } return 0; } /*---------------audio_lang_monitor_service when create_media for every frag_unit ---------------*/ void audio_lang_monitor_service(uint32_t src_ip, media_t* mdi) { long rec_cb = 0; char monitor_buf[MONITOR_BUFSIZE] = {0}; int monitor_len = 0; char pbuf[32] = {0}; int buf_len = 32; MESA_htable_search_cb(g_frag_run.media_monitor_hash, (const unsigned char*)&mdi->mid, sizeof(mdi->mid), search_monitor_hash_cb, NULL, &rec_cb); if(rec_cb) { monitor_len = create_monitor(monitor_buf, MONITOR_BUFSIZE, mdi, 1 , SERVICE_AUDIO_LANG_FULL); FLAG_SET(mdi->flag, PROG_FLAG_DUMP); bizman_send(g_frag_run.answer_sapp_bizman, mdi->thread_seq, src_ip , g_frag_cfg.msg_port, monitor_buf, monitor_len, 1,BIZMAN_RELIABLE_SEND|BIZMAN_SMOOTH_DEST|BIZMAN_PUSH_SEND); inet_ntop(AF_INET, &src_ip, pbuf, buf_len); resp_write_to_log(SEND_LANG_MONITOR, NULL, mdi, pbuf,0); atomic_inc(&g_frag_stat.stat_info[AUDIO_LANG_MONITOR_OUT][TOTAL_PKTS]); atomic_add(&g_frag_stat.stat_info[AUDIO_LANG_MONITOR_OUT][TOTAL_BYTES], monitor_len); } } /*---------------config_monitor_service when create_media if frag_unit hit service 0x80 form sapp---------------*/ void config_monitor_service(uint32_t src_ip, media_t* mdi) { char monitor_buf[MONITOR_BUFSIZE] = {0}; int monitor_len = 0; char pbuf[32] = {0}; int buf_len = 32; /*回复多源之前的建议,否则前端找不到节目*/ monitor_len = create_monitor(monitor_buf, MONITOR_BUFSIZE, mdi, 0, mdi->hit_service); FLAG_SET(mdi->flag, PROG_FLAG_DUMP); bizman_send(g_frag_run.answer_sapp_bizman, mdi->thread_seq, src_ip, g_frag_cfg.msg_port, monitor_buf, monitor_len, 1,BIZMAN_RELIABLE_SEND|BIZMAN_SMOOTH_DEST|BIZMAN_PUSH_SEND); inet_ntop(AF_INET, &src_ip, pbuf, buf_len); resp_write_to_log(SEND_CONFIG_MONITOR, NULL, mdi, pbuf,0); atomic_inc(&g_frag_stat.stat_info[CONFIG_MONITOR_OUT][TOTAL_PKTS]); atomic_add(&g_frag_stat.stat_info[CONFIG_MONITOR_OUT][TOTAL_BYTES] , monitor_len); } /******************************************************sendto wins system service****************************************************/ int is_hit_media_detail_character(const unsigned char* buf,int buf_len) { int i=0,inuse_character_num=1; const unsigned char mp4_character[]={0x66,0x74,0x79,0x70};//mp4 from zhangdongming 20120903 media_character_t accept_media_character[MAX_MEDIA_CHARACTER_NUM]; accept_media_character[0].character=mp4_character; accept_media_character[0].start_offset=4; accept_media_character[0].len=sizeof(mp4_character); for(i=0;i=accept_media_character[i].len+accept_media_character[i].start_offset &&0==memcmp(buf+accept_media_character[i].start_offset,accept_media_character[i].character,accept_media_character[i].len)) { return 1; } } return 0; } /*---------------update_special_media_service when frag offset=0-----------------*/ long update_special_media_service(media_t* mdi, frag_in_t* frg) { //deep judge media type to windows if(0==is_hit_media_detail_character((const unsigned char*)frg->data, frg->datalen)) { FLAG_CLEAR(mdi->flag, PROG_FLAG_EXCP); } return 0; } /*---------------set_special_media_service when create_media--------------------*/ void set_special_media_service(uint16_t media_type, media_t* mdi) { if(g_frag_run.special_media_table[media_type]) { FLAG_SET(mdi->flag, PROG_FLAG_EXCP); } }