diff --git a/build/decoder/Makefile b/build/decoder/Makefile index 563ae93..7b62361 100644 --- a/build/decoder/Makefile +++ b/build/decoder/Makefile @@ -6,7 +6,7 @@ PROJECT_ROOT= /home/cmhu/vpt_ascend_arm DEPEND_DIR = $(PROJECT_ROOT)/bin SRC_ROOT = $(PROJECT_ROOT)/src -TARGET= $(PROJECT_ROOT)/bin/test_dec +TARGET= $(PROJECT_ROOT)/bin/test_28181 THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release @@ -14,7 +14,11 @@ OPENCV_ROOT = $(THIRDPARTY_ROOT)/opencv_4_1 JSON_ROOT = $(THIRDPARTY_ROOT)/jsoncpp-1.9.5/release FFMPEG_ROOT = $(THIRDPARTY_ROOT)/ffmpeg-4.4.4/release -DEFS = -DENABLE_DVPP_INTERFACE +GB28181_SDK = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd +JRTP_ROOT = $(GB28181_SDK)/jrtp_export +SIP_SDK = $(GB28181_SDK)/release + +DEFS = -DENABLE_DVPP_INTERFACE -DUSE_DVPP include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \ -I $(SPDLOG_ROOT)/include \ @@ -22,6 +26,11 @@ include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \ -I $(OPENCV_ROOT)/include \ -I $(JSON_ROOT)/include \ -I $(FFMPEG_ROOT)/include \ + -I $(JRTP_ROOT)/jrtplib/include/jrtplib3 \ + -I $(SIP_SDK)/include \ + -I $(SRC_ROOT)/decoder/gb28181/rtp \ + -I $(SRC_ROOT)/decoder/gb28181/sip \ + -I $(SRC_ROOT)/decoder/gb28181 \ lib_dir=-L/usr/local/Ascend/ascend-toolkit/6.3.RC1/runtime/lib64 \ -L/usr/local/Ascend/ascend-toolkit/latest/lib64 \ @@ -33,13 +42,21 @@ lib=-lacl_dvpp -lascendcl -lacl_dvpp_mpi -lruntime -lascendalog -lc_sec -lmsprof -lplatform -lqos_manager LIBS= -L $(FFMPEG_ROOT)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \ + -L $(JRTP_ROOT)/jrtplib/lib -l:libjrtp.a \ + -L $(SIP_SDK)/lib -l:libeXosip2.a -l:libosipparser2.a -l:libosip2.a -lcares\ CXXFLAGS= -g -O0 -fPIC $(include_dir) $(lib_dir) $(lib) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl SRCS:=$(wildcard $(SRC_ROOT)/decoder/interface/*.cpp) \ - $(wildcard $(SRC_ROOT)/decoder/dvpp/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/dvpp/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/gb28181/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/gb28181/rtp/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/Message/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/tinyxml2/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/gb28181/sip/Utils/*.cpp) \ $(wildcard $(SRC_ROOT)/decoder/*.cpp) \ OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS))) @@ -53,6 +70,24 @@ $(TARGET):$(OBJS) %.o:$(SRC_ROOT)/decoder/dvpp/%.cpp $(XX) $(CXXFLAGS) -c $< +%.o:$(SRC_ROOT)/decoder/gb28181/%.cpp + $(XX) $(CXXFLAGS) -c $< + +%.o:$(SRC_ROOT)/decoder/gb28181/rtp/%.cpp + $(XX) $(CXXFLAGS) -c $< + +%.o:$(SRC_ROOT)/decoder/gb28181/sip/%.cpp + $(XX) $(CXXFLAGS) -c $< + +%.o:$(SRC_ROOT)/decoder/gb28181/sip/Message/%.cpp + $(XX) $(CXXFLAGS) -c $< + +%.o:$(SRC_ROOT)/decoder/gb28181/sip/tinyxml2/%.cpp + $(XX) $(CXXFLAGS) -c $< + +%.o:$(SRC_ROOT)/decoder/gb28181/sip/Utils/%.cpp + $(XX) $(CXXFLAGS) -c $< + %.o:$(SRC_ROOT)/decoder/interface/%.cpp $(XX) $(CXXFLAGS) -c $< diff --git a/build/decoder/Makefile.dvpp b/build/decoder/Makefile.dvpp new file mode 100644 index 0000000..563ae93 --- /dev/null +++ b/build/decoder/Makefile.dvpp @@ -0,0 +1,63 @@ +XX = g++ + + +PROJECT_ROOT= /home/cmhu/vpt_ascend_arm + +DEPEND_DIR = $(PROJECT_ROOT)/bin +SRC_ROOT = $(PROJECT_ROOT)/src + +TARGET= $(PROJECT_ROOT)/bin/test_dec + +THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty +SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release +OPENCV_ROOT = $(THIRDPARTY_ROOT)/opencv_4_1 +JSON_ROOT = $(THIRDPARTY_ROOT)/jsoncpp-1.9.5/release +FFMPEG_ROOT = $(THIRDPARTY_ROOT)/ffmpeg-4.4.4/release + +DEFS = -DENABLE_DVPP_INTERFACE + +include_dir=-I/usr/local/Ascend/ascend-toolkit/6.3.RC1/aarch64-linux/include \ + -I $(SPDLOG_ROOT)/include \ + -I $(SRC_ROOT)/common \ + -I $(OPENCV_ROOT)/include \ + -I $(JSON_ROOT)/include \ + -I $(FFMPEG_ROOT)/include \ + +lib_dir=-L/usr/local/Ascend/ascend-toolkit/6.3.RC1/runtime/lib64 \ + -L/usr/local/Ascend/ascend-toolkit/latest/lib64 \ + -L/usr/local/Ascend/ascend-toolkit/latest/runtime/lib64 \ + -L/usr/local/Ascend/ascend-toolkit/latest/acllib/lib64 \ + -L/usr/local/Ascend/ascend-toolkit/6.3.RC1/runtime/lib64/stub \ + +lib=-lacl_dvpp -lascendcl -lacl_dvpp_mpi -lruntime -lascendalog -lc_sec -lmsprofiler -lgert -lmmpa -lascend_hal -lexe_graph -lge_executor -lgraph -lprofapi -lascend_protobuf -lerror_manager -lregister -lge_common \ + -lplatform -lqos_manager + +LIBS= -L $(FFMPEG_ROOT)/lib -lavformat -lavcodec -lswscale -lavutil -lavfilter -lswresample -lavdevice \ + +CXXFLAGS= -g -O0 -fPIC $(include_dir) $(lib_dir) $(lib) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl + + + +SRCS:=$(wildcard $(SRC_ROOT)/decoder/interface/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/dvpp/*.cpp) \ + $(wildcard $(SRC_ROOT)/decoder/*.cpp) \ + +OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS))) + + +$(TARGET):$(OBJS) + rm -f $(TARGET) + $(XX) -o $@ $^ $(CXXFLAGS) + rm -f *.o + +%.o:$(SRC_ROOT)/decoder/dvpp/%.cpp + $(XX) $(CXXFLAGS) -c $< + +%.o:$(SRC_ROOT)/decoder/interface/%.cpp + $(XX) $(CXXFLAGS) -c $< + +%.o:$(SRC_ROOT)/decoder/%.cpp + $(XX) $(CXXFLAGS) -c $< + +clean: + rm -f *.o $(TARGET) diff --git a/build/gb28181/Makefile b/build/gb28181/Makefile index a79940f..d8e671a 100755 --- a/build/gb28181/Makefile +++ b/build/gb28181/Makefile @@ -15,8 +15,7 @@ SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release GB28181_ROOT = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd JRTP_ROOT = $(GB28181_ROOT)/jrtp_export - -SIP_SDK = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd/release +SIP_SDK = $(GB28181_ROOT)/release SRC_ROOT = /home/cmhu/vpt_ascend_arm/src/decoder/gb28181 diff --git a/src/decoder/dvpp/DvppDecoder.cpp b/src/decoder/dvpp/DvppDecoder.cpp index 6a9b1ec..4f77a12 100644 --- a/src/decoder/dvpp/DvppDecoder.cpp +++ b/src/decoder/dvpp/DvppDecoder.cpp @@ -90,7 +90,7 @@ bool DvppDecoder::init(FFDecConfig cfg){ return false; } - bool bRet = init_vdpp(cfg, avctx); + bool bRet = init_dvpp(cfg); if(!bRet){ return false; } @@ -238,7 +238,6 @@ void DvppDecoder::calcOutResolution(int width, int height) { out_frame_width = width; out_frame_height = height; } - } int DvppDecoder::getVdecType(int videoType, int profile) @@ -281,7 +280,7 @@ int DvppDecoder::getVdecType(int videoType, int profile) return streamFormat; } - bool DvppDecoder::init_vdpp(FFDecConfig cfg) { + bool DvppDecoder::init_dvpp(FFDecConfig cfg) { LOG_INFO("[{}]- Init device start...", m_dec_name); diff --git a/src/decoder/dvpp/DvppDecoder.h b/src/decoder/dvpp/DvppDecoder.h index 4e82e8d..53b5021 100644 --- a/src/decoder/dvpp/DvppDecoder.h +++ b/src/decoder/dvpp/DvppDecoder.h @@ -68,7 +68,7 @@ public: private: AVCodecContext* init_FFmpeg(FFDecConfig config); - bool init_vdpp(FFDecConfig cfg); + bool init_dvpp(FFDecConfig cfg); void release_ffmpeg(); void read_thread(); diff --git a/src/decoder/dvpp/DvppStreamDecoder.cpp b/src/decoder/dvpp/DvppStreamDecoder.cpp index d9392ee..91f8dde 100644 --- a/src/decoder/dvpp/DvppStreamDecoder.cpp +++ b/src/decoder/dvpp/DvppStreamDecoder.cpp @@ -1,13 +1,23 @@ #include "DvppStreamDecoder.h" +#include "DvppSourceManager.h" +#define CHECK_AND_RETURN(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return ret;} +#define CHECK_NOT_RETURN(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message);} +#define CHECK_AND_RETURN_NOVALUE(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return;} +#define CHECK_AND_BREAK(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); break;} + struct Vdec_CallBack_UserData { uint64_t frameId; uint64_t frame_nb; long startTime; long sendTime; - DvppDecoder* self; + DvppStreamDecoder* self; Vdec_CallBack_UserData() { frameId = 0; @@ -44,6 +54,8 @@ DvppStreamDecoder::DvppStreamDecoder(/* args */) DvppStreamDecoder::~DvppStreamDecoder() { Close(); + + LOG_DEBUG("[{}]- ~DvppDecoder() in_count:{} out_count:{}", m_dec_name, m_in_count, m_out_count); } bool DvppStreamDecoder::Init(FFDecConfig cfg) { @@ -75,6 +87,8 @@ bool DvppStreamDecoder::Init(FFDecConfig cfg) { return false; } + m_bResize = cfg.resize; + m_vpcUtils.init(m_deviceId); decode_finished_cbk = cfg.decode_finished_cbk; @@ -89,6 +103,7 @@ bool DvppStreamDecoder::Init(FFDecConfig cfg) { } void DvppStreamDecoder::release_dvpp(){ + if(m_context){ aclError ret = aclrtDestroyContext(m_context); if(ret != ACL_ERROR_NONE){ @@ -123,7 +138,7 @@ int DvppStreamDecoder::getVdecType(int videoType) void DvppStreamDecoder::doProcessReport(){ - aclError ret = aclrtSetDevice(m_dvpp_deviceId); + aclError ret = aclrtSetDevice(m_deviceId); if(ret != ACL_ERROR_NONE){ // cout << "aclrtSetDevice failed" << endl; LOG_ERROR("aclrtSetDevice failed !"); @@ -131,7 +146,7 @@ void DvppStreamDecoder::doProcessReport(){ } aclrtContext ctx; - ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); + ret = aclrtCreateContext(&ctx, m_deviceId); if (ret != ACL_ERROR_NONE) { // cout << "aclrtCreateContext failed " << endl; LOG_ERROR("aclrtCreateContext failed !"); @@ -187,20 +202,6 @@ void DvppStreamDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicD bool bCached = false; if(width > 0 && height > 0 && outputSize > 0){ - - if (!m_bReal) { - while(!m_bExitReportThd) { - // 非实时流,即为文件情形,因为不存在花屏问题,为保证不丢帧,这里做个循环等待 - m_decoded_data_queue_mtx.lock(); - if(m_decoded_data_queue.size() >= 5){ - m_decoded_data_queue_mtx.unlock(); - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - continue; - } - m_decoded_data_queue_mtx.unlock(); - break; - } - } // cout << m_dec_name << " 解码时间间隔: " << get_cur_time_ms() - last_ts << endl; // last_ts = get_cur_time_ms(); @@ -225,18 +226,23 @@ void DvppStreamDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicD outWidth += 1; } } + + out_frame_width = outWidth; + out_frame_height = outHeight; mem = m_vpcUtils.resize(output, outWidth, outHeight); if (mem) { acldvppFree(outputDataDev); outputDataDev = nullptr; - mem->setDeviceId(to_string(m_dvpp_deviceId)); + mem->setDeviceId(to_string(m_deviceId)); mem->setId(m_dec_name); mem->setFrameNb(frame_nb); } } else { - mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, frame_nb, (unsigned char *)outputDataDev); + mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_deviceId), false, frame_nb, (unsigned char *)outputDataDev); + out_frame_width = width; + out_frame_height = height; } if(mem){ @@ -408,22 +414,38 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u return -2; } - int ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); - if(ret != 0){ - LOG_ERROR("[{}]- pthread_create failed", m_dec_name); - return -2; - } + do + { + ret = -2; - acldvppStreamFormat enType = getVdecType(videoType); + ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); + if(ret != 0){ + LOG_ERROR("[{}]- pthread_create failed", m_dec_name); + break; + } + + int iType = getVdecType(videoType); + if(-1 == iType) { + break; + } + acldvppStreamFormat enType = static_cast(iType); + + // 通道ID在dvpp层面为0~31 + CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); + CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); + + ret = 0; + } while (0); - // 创建 channel dec结构体 - // 通道ID在dvpp层面为0~31 - CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); - CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); + if (ret < 0) { + release_channeldesc(); + LOG_ERROR("[{}]- Set Channel Desc failed", m_dec_name); + return ret; + } } AVPacket* pkt = av_packet_alloc(); @@ -432,8 +454,6 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u pkt->size = len; pkt->data = (uint8_t*)data; - int ret = -2; - do { int vdec_out_size = parse_stream_info(videoType, pkt); @@ -453,7 +473,7 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u int nSended = -1; while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { - if(!m_bExit){ + if(m_bExit){ break; } @@ -529,9 +549,9 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { } const AVBitStreamFilter * filter = nullptr; - if(VIDEO_TYPE_H264 == videoType){ + if(0 == videoType){ filter = av_bsf_get_by_name("h264_mp4toannexb"); - }else if(VIDEO_TYPE_H265 == videoType){ + }else if(1 == videoType){ filter = av_bsf_get_by_name("hevc_mp4toannexb"); }else { LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); @@ -585,9 +605,7 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { return m_vdec_out_size; } -void DvppStreamDecoder::Close() { - m_bExit = true; - +void DvppStreamDecoder::release_channeldesc() { if (vdecChannelDesc) { sendVdecEos(vdecChannelDesc); @@ -598,7 +616,12 @@ void DvppStreamDecoder::Close() { m_bExitReportThd = true; CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed"); } +} + +void DvppStreamDecoder::Close() { + m_bExit = true; + release_channeldesc(); release_dvpp(); if(h264bsfc){ diff --git a/src/decoder/dvpp/DvppStreamDecoder.h b/src/decoder/dvpp/DvppStreamDecoder.h index 691b3a4..1b3a657 100644 --- a/src/decoder/dvpp/DvppStreamDecoder.h +++ b/src/decoder/dvpp/DvppStreamDecoder.h @@ -32,6 +32,10 @@ private: int parse_stream_info(int videoType, AVPacket* pkt); + void release_dvpp(); + void release_channeldesc(); + int getVdecType(int videoType); + private: string m_dec_name {""}; int m_deviceId {-1}; @@ -47,6 +51,8 @@ private: int m_fps {-1}; int frameW {-1}; int frameH {-1}; + int out_frame_width{0}; + int out_frame_height{0}; VpcUtils m_vpcUtils; @@ -62,6 +68,11 @@ private: DECODE_FINISHED_CALLBACK decode_finished_cbk {nullptr}; AVBSFContext * h264bsfc{nullptr}; + + uint64_t m_in_count {0}; + uint64_t m_out_count {0}; + + bool m_bResize {false}; }; diff --git a/src/decoder/gb28181/DvppGB28181Decoder.cpp b/src/decoder/gb28181/DvppGB28181Decoder.cpp index 134fde1..26c8c87 100644 --- a/src/decoder/gb28181/DvppGB28181Decoder.cpp +++ b/src/decoder/gb28181/DvppGB28181Decoder.cpp @@ -2,8 +2,6 @@ #include #include "DvppGB28181Decoder.h" - - extern "C" { #include "libavutil/avstring.h" #include "libavformat/avformat.h" @@ -13,8 +11,6 @@ extern "C" { #include"RTPTcpReceiver.h" #include"RTPUdpReceiver.h" -#include - #include "common_header.h" // #include "../nvdec/FFCuContextManager.h" @@ -25,6 +21,7 @@ extern "C" { #define ECLOSING 1 #define ERUNNING 2 #define EPAUSE 3 +#define EINITED 4 static void RTP_Stream_CallBack(void* userdata, int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts) { @@ -48,10 +45,10 @@ DvppGB28181Decoder::~DvppGB28181Decoder() { close(); - if (m_pAVCodecCtx) { - avcodec_close(m_pAVCodecCtx); - avcodec_free_context(&m_pAVCodecCtx); - } + // if (m_pAVCodecCtx) { + // avcodec_close(m_pAVCodecCtx); + // avcodec_free_context(&m_pAVCodecCtx); + // } m_dec_keyframe = false; @@ -75,19 +72,13 @@ void DvppGB28181Decoder::close(){ m_rtpPtr = nullptr; } - if (gpu_options) av_dict_free(&gpu_options); + // if (gpu_options) av_dict_free(&gpu_options); if (m_post_decode_thread != 0) { pthread_join(m_post_decode_thread,0); } - while(mFrameQueue.size() > 0){ - AVFrame * gpuFrame = mFrameQueue.front(); - av_frame_free(&gpuFrame); - mFrameQueue.pop(); - } - m_status = ECLOSED; LOG_INFO("解码器关闭成功 --{}", m_dec_name); @@ -123,6 +114,8 @@ bool DvppGB28181Decoder::init(FFDecConfig& cfg){ LOG_INFO("init - {} ", m_dec_name); + m_status = EINITED; + return true; } @@ -140,6 +133,8 @@ bool DvppGB28181Decoder::start() { return (void*)0; } ,this); + + return true; } LOG_ERROR("[{}] - rtp receiver open failed !", m_dec_name); @@ -185,95 +180,95 @@ void DvppGB28181Decoder::stream_callback(int videoType, char* data, int len, int int DvppGB28181Decoder::ff_decode(int videoType, AVPacket* pkt) { - if (m_pAVCodecCtx == nullptr) { - LOG_INFO("frame data is zero --{}", m_dec_name); - if (VIDEO_TYPE_H264 == videoType) { - if (m_gpuid >= 0){ - m_pAVCodec = avcodec_find_decoder_by_name("h264_cuvid"); - } - else{ - m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H264); - } - LOG_INFO("m_avCodecName is H264"); - } - else if (VIDEO_TYPE_H265 == videoType) - { - if (m_gpuid >= 0){ - m_pAVCodec = avcodec_find_decoder_by_name("hevc_cuvid"); - } - else{ - m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H265); - } - LOG_INFO("m_avCodecName is H265"); - } - else{ - LOG_INFO("m_avCodecName is unknown, videoType is {}", videoType); - } - - if (!m_pAVCodec) - { - LOG_ERROR("frameCallback frame decode error, ERROR_DECODER_NOT_FOUND"); - return; - } - - m_pAVCodecCtx = avcodec_alloc_context3(m_pAVCodec); - - if (m_gpuid >= 0) { - char gpui[8] = { 0 }; - sprintf(gpui, "%d", m_gpuid); - av_dict_set(&gpu_options, "gpu", gpui, 0); - - m_pAVCodecCtx->get_format = get_hw_format; - - FFCuContextManager* pCtxMgr = FFCuContextManager::getInstance(); - m_pAVCodecCtx->hw_device_ctx = av_buffer_ref(pCtxMgr->getCuCtx(gpui)); - if (nullptr == m_pAVCodecCtx->hw_device_ctx){ - // TODO 这里应该抛出错误 - return ; - } - } - - if (avcodec_open2(m_pAVCodecCtx, m_pAVCodec, &gpu_options) < 0) - return; - } - - //开始解码 - int ret = avcodec_send_packet(m_pAVCodecCtx, pkt); - if (ret < 0) { - //send_exception(RunMessageType::E2002, e_msg); - LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret); - return; - } + // if (m_pAVCodecCtx == nullptr) { + // LOG_INFO("frame data is zero --{}", m_dec_name); + // if (VIDEO_TYPE_H264 == videoType) { + // if (m_gpuid >= 0){ + // m_pAVCodec = avcodec_find_decoder_by_name("h264_cuvid"); + // } + // else{ + // m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H264); + // } + // LOG_INFO("m_avCodecName is H264"); + // } + // else if (VIDEO_TYPE_H265 == videoType) + // { + // if (m_gpuid >= 0){ + // m_pAVCodec = avcodec_find_decoder_by_name("hevc_cuvid"); + // } + // else{ + // m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H265); + // } + // LOG_INFO("m_avCodecName is H265"); + // } + // else{ + // LOG_INFO("m_avCodecName is unknown, videoType is {}", videoType); + // } + + // if (!m_pAVCodec) + // { + // LOG_ERROR("frameCallback frame decode error, ERROR_DECODER_NOT_FOUND"); + // return; + // } + + // m_pAVCodecCtx = avcodec_alloc_context3(m_pAVCodec); + + // if (m_gpuid >= 0) { + // char gpui[8] = { 0 }; + // sprintf(gpui, "%d", m_gpuid); + // av_dict_set(&gpu_options, "gpu", gpui, 0); + + // m_pAVCodecCtx->get_format = get_hw_format; + + // FFCuContextManager* pCtxMgr = FFCuContextManager::getInstance(); + // m_pAVCodecCtx->hw_device_ctx = av_buffer_ref(pCtxMgr->getCuCtx(gpui)); + // if (nullptr == m_pAVCodecCtx->hw_device_ctx){ + // // TODO 这里应该抛出错误 + // return ; + // } + // } + + // if (avcodec_open2(m_pAVCodecCtx, m_pAVCodec, &gpu_options) < 0) + // return; + // } + + // //开始解码 + // int ret = avcodec_send_packet(m_pAVCodecCtx, pkt); + // if (ret < 0) { + // //send_exception(RunMessageType::E2002, e_msg); + // LOG_ERROR("Real stream视频解码失败,请检查视频设备{}: avcodec_send_packet failed. ret={}", m_dec_name, ret); + // return; + // } - if (frameW < 1) { - frameW = m_pAVCodecCtx->width; - frameH = m_pAVCodecCtx->height; - if (frameW <= 0 || frameH <= 0) { - LOG_ERROR("[{}] frame W or H is error! ({},{})", m_dec_name, frameW, frameH); - return; - } - } - - m_fps = av_q2d(m_pAVCodecCtx->framerate); - - AVFrame* gpuFrame = av_frame_alloc(); - ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame); - if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){ - LOG_ERROR("{} - Failed to receive frame: {}", m_dec_name, ret); - av_frame_free(&gpuFrame); - gpuFrame = nullptr; - return; - } + // if (frameW < 1) { + // frameW = m_pAVCodecCtx->width; + // frameH = m_pAVCodecCtx->height; + // if (frameW <= 0 || frameH <= 0) { + // LOG_ERROR("[{}] - frame W or H is error! ({},{})", m_dec_name, frameW, frameH); + // return; + // } + // } + + // m_fps = av_q2d(m_pAVCodecCtx->framerate); + + // AVFrame* gpuFrame = av_frame_alloc(); + // ret = avcodec_receive_frame(m_pAVCodecCtx, gpuFrame); + // if ((ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) || ret < 0){ + // LOG_ERROR("[{}] - Failed to receive frame: {}", m_dec_name, ret); + // av_frame_free(&gpuFrame); + // gpuFrame = nullptr; + // return; + // } - if (gpuFrame->width != frameW || gpuFrame->height != frameH){ - LOG_INFO("AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", gpuFrame->width, gpuFrame->height, frameW, frameH , m_dec_name); - av_frame_free(&gpuFrame); - gpuFrame = nullptr; - return; - } - - av_frame_free(&gpuFrame); - gpuFrame = nullptr; + // if (gpuFrame->width != frameW || gpuFrame->height != frameH){ + // LOG_INFO("[{}] - AVFrame is inconsistent: width is {}, height is {}; original frameW is {}, frameH is {}--{}", m_dec_name, gpuFrame->width, gpuFrame->height, frameW, frameH); + // av_frame_free(&gpuFrame); + // gpuFrame = nullptr; + // return; + // } + + // av_frame_free(&gpuFrame); + // gpuFrame = nullptr; } void DvppGB28181Decoder::display_thread(){ @@ -285,26 +280,26 @@ void DvppGB28181Decoder::display_thread(){ if(mem) { if ((m_frameSkip == 1 || index % m_frameSkip == 0) && post_decoded_cbk){ post_decoded_cbk(m_postDecArg, mem); + } else { + delete mem; + mem = nullptr; } index++; if(index >= 100000){ index = 0; } - } else { - delete mem; - mem = nullptr; - } + } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - LOG_INFO("display thread exited."); + LOG_INFO("[{}] - display thread exited.", m_dec_name); } void DvppGB28181Decoder::stream_end_callback() { - LOG_INFO("send_video_eof--{}", m_dec_name); + LOG_INFO("[{}] - send_video_eof", m_dec_name); decode_finished_cbk(m_finishedDecArg); @@ -321,12 +316,12 @@ void DvppGB28181Decoder::setFinishedDecArg(const void* finishedDecArg){ void DvppGB28181Decoder::pause() { m_status = EPAUSE; - LOG_INFO("pause --{}", m_dec_name); + LOG_INFO("[{}] - pause", m_dec_name); } void DvppGB28181Decoder::resume() { m_status = ERUNNING; - LOG_INFO("resume --{}", m_dec_name); + LOG_INFO("[{}] - resume", m_dec_name); } bool DvppGB28181Decoder::isRunning(){ @@ -356,6 +351,12 @@ bool DvppGB28181Decoder::getResolution( int &width, int &height ){ return true; } +bool DvppGB28181Decoder::getOutResolution( int &width, int &height ) { + width = frameW; + height = frameH; + return true; +} + float DvppGB28181Decoder::fps() { return m_fps; } @@ -367,4 +368,16 @@ bool DvppGB28181Decoder::isSurport(FFDecConfig& cfg){ int DvppGB28181Decoder::getCachedQueueLength(){ return m_rtpPtr->GetPsFrameListSize(); +} + +DeviceMemory* DvppGB28181Decoder::snapshot() { + return nullptr; +} + +void DvppGB28181Decoder::doRecode(RecoderInfo& recoderInfo) { + +} + +void DvppGB28181Decoder::set_mq_callback(std::function mq_publish) { + } \ No newline at end of file diff --git a/src/decoder/gb28181/DvppGB28181Decoder.h b/src/decoder/gb28181/DvppGB28181Decoder.h index 6c36057..b42ee95 100644 --- a/src/decoder/gb28181/DvppGB28181Decoder.h +++ b/src/decoder/gb28181/DvppGB28181Decoder.h @@ -38,6 +38,7 @@ public: bool isFinished(); bool isPausing(); bool getResolution( int &width, int &height ); + bool getOutResolution( int &width, int &height ); bool isSurport(FFDecConfig& cfg); @@ -45,7 +46,9 @@ public: float fps(); - DECODER_TYPE getDecoderType(){ return DECODER_TYPE_GB28181; } + DECODER_TYPE getDecoderType(){ return DECODER_TYPE_DVPP_GB28181; } + + DeviceMemory* snapshot(); void setName(string nm){ m_dec_name = nm; @@ -58,6 +61,10 @@ public: void setPostDecArg(const void* postDecArg); void setFinishedDecArg(const void* finishedDecArg); + void doRecode(RecoderInfo& recoderInfo); + + void set_mq_callback(std::function mq_publish); + public: void stream_callback(int videoType, char* data, int len, int isKey, uint64_t pts, uint64_t localPts); void stream_end_callback(); diff --git a/src/decoder/gb28181/main.cpp b/src/decoder/gb28181/main.cpp.28181 index de6ea1c..de6ea1c 100644 --- a/src/decoder/gb28181/main.cpp +++ b/src/decoder/gb28181/main.cpp.28181 diff --git a/src/decoder/gb28181/rtp/RTPReceiver.cpp b/src/decoder/gb28181/rtp/RTPReceiver.cpp index 94bd575..e48801b 100644 --- a/src/decoder/gb28181/rtp/RTPReceiver.cpp +++ b/src/decoder/gb28181/rtp/RTPReceiver.cpp @@ -163,8 +163,18 @@ void RTPReceiver::OnPsDemux(unsigned char streamId, BYTE *data, int len, bool ke if (m_LastPTS != pts) { + int stream_type = 0; + if (VIDEO_TYPE_H264 == streamId) { + stream_type = 0; + } else if(VIDEO_TYPE_H265 == streamId) { + stream_type = 1; + } else { + LOG_ERROR("[{}] - video type not support!", m_SipChannelId); + } + + m_notToDecodCount = 0; - m_h264DataFunc(m_usrParam, streamId, (char *)m_SliceBuf.head(), m_SliceBuf.len(), m_LastIsKeyFrame, m_LastPTS, localPts); + m_h264DataFunc(m_usrParam, stream_type, (char *)m_SliceBuf.head(), m_SliceBuf.len(), m_LastIsKeyFrame, m_LastPTS, localPts); m_SliceBuf.reset(); @@ -310,11 +320,20 @@ int RTPReceiver::allocRtpPort() { if (s_rtpPort % 2) ++s_rtpPort; + int count = 0; + while (true) { - s_rtpPort = s_rtpPort >= MAX_RTP_PORT ? MIN_RTP_PORT : s_rtpPort; + if (s_rtpPort >= MAX_RTP_PORT) { + s_rtpPort = MIN_RTP_PORT; + count ++; + if (count > 1) { + LOG_ERROR("[{}] - 10000 到 60000 没有可用的port", m_SipChannelId); + } + } - for (int i = 0; i < 2; i++) { + int i = 0; + for (; i < 2; i++) { sockaddr_in sRecvAddr; int s = socket(AF_INET, SOCK_DGRAM, 0); @@ -330,10 +349,13 @@ int RTPReceiver::allocRtpPort() { nResult = close(s); if (nResult != 0) { LOG_ERROR("[{}] - closesocket failed : {}", m_SipChannelId, nResult); - return -1; + break; } } + if (i == 2) + break; + s_rtpPort += 2; } diff --git a/src/decoder/gb28181/rtp/RTPTcpReceiver.cpp b/src/decoder/gb28181/rtp/RTPTcpReceiver.cpp index 8b960bf..c93f75f 100644 --- a/src/decoder/gb28181/rtp/RTPTcpReceiver.cpp +++ b/src/decoder/gb28181/rtp/RTPTcpReceiver.cpp @@ -373,7 +373,7 @@ bool RTPTcpReceiver::RequestStream(){ SipServer* pServer = SipServer::getInstance(); int ret = -1; if (pServer){ - ret = pServer->RequestInvite_UDP(m_SipChannelId.c_str(), m_rtp_port); + ret = pServer->RequestInvite_TCP_a(m_SipChannelId.c_str(), m_rtp_port); } return (ret > 0) ; diff --git a/src/decoder/gb28181/rtp/RTPUdpReceiver.cpp b/src/decoder/gb28181/rtp/RTPUdpReceiver.cpp index 4021563..0dabebd 100644 --- a/src/decoder/gb28181/rtp/RTPUdpReceiver.cpp +++ b/src/decoder/gb28181/rtp/RTPUdpReceiver.cpp @@ -123,6 +123,8 @@ bool RTPUdpReceiver::Open(string channel_id) return false; } + RequestStream(); + m_bOpened = true; LOG_INFO("[{}] Open ok", m_SipChannelId); diff --git a/src/decoder/gb28181/sip/SipServer.cpp b/src/decoder/gb28181/sip/SipServer.cpp index c70e3ff..d316ae9 100644 --- a/src/decoder/gb28181/sip/SipServer.cpp +++ b/src/decoder/gb28181/sip/SipServer.cpp @@ -270,6 +270,8 @@ void SipServer::response_register(eXosip_event_t *evtp) { mClientMap.insert(std::make_pair(client->getDevice(),client)); //this->request_invite(client); + // NVR注册成功,立即请求设备目录 + RequestCatalog(client); } else { this->response_message_answer(evtp,401); @@ -389,15 +391,31 @@ int SipServer::RequestInvite_UDP(const char* dst_channel, int rtpPort) { sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort()); sprintf(to, "sip:%s@%s:%d", dst_channel, client->getIp().c_str(), client->getPort()); - snprintf(sdp, 2048, + // snprintf(sdp, 2048, + // "v=0\r\n" + // "o=%s 0 0 IN IP4 %s\r\n" + // "s=Play\r\n" + // "c=IN IP4 %s\r\n" + // "t=0 0\r\n" + // "m=video %d RTP/AVP 96 98 97\r\n" + // "a=recvonly\r\n" + // "a=rtpmap:96 PS/90000\r\n" + // "a=rtpmap:98 H264/90000\r\n" + // "a=rtpmap:97 MPEG4/90000\r\n" + // "a=setup:passive\r\n" + // "a=connection:new\r\n" + // "y=0100000001\r\n" + // "f=\r\n", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getIp().c_str(), rtpPort); + + snprintf(sdp, 2048, "v=0\r\n" "o=%s 0 0 IN IP4 %s\r\n" "s=Play\r\n" "c=IN IP4 %s\r\n" "t=0 0\r\n" - "m=video %d RTP/AVP 96 98 97\r\n" + "m=video %d RTP/AVP 98 97\r\n" "a=recvonly\r\n" - "a=rtpmap:96 PS/90000\r\n" + // "a=rtpmap:96 PS/90000\r\n" "a=rtpmap:98 H264/90000\r\n" "a=rtpmap:97 MPEG4/90000\r\n" "a=setup:passive\r\n" diff --git a/src/decoder/interface/DecoderManager.cpp b/src/decoder/interface/DecoderManager.cpp index b1ecb6d..d900529 100644 --- a/src/decoder/interface/DecoderManager.cpp +++ b/src/decoder/interface/DecoderManager.cpp @@ -7,6 +7,7 @@ #ifdef USE_DVPP #include "../dvpp/DvppDecoderApi.h" +#include "../gb28181/DvppGB28181Decoder.h" #endif #include "logger.hpp" @@ -49,9 +50,7 @@ AbstractDecoder* DecoderManager::createDecoder(MgrDecConfig config){ #ifdef USE_NVDEC if(DECODER_TYPE_FFMPEG == config.dec_type){ dec = new FFNvDecoder(); - } - - if(DECODER_TYPE_GB28181 == config.dec_type){ + } else if(DECODER_TYPE_GB28181 == config.dec_type){ dec = new FFGB28181Decoder(); } #endif @@ -59,6 +58,8 @@ AbstractDecoder* DecoderManager::createDecoder(MgrDecConfig config){ #ifdef USE_DVPP if(DECODER_TYPE_DVPP == config.dec_type){ dec = new DvppDecoderApi(); + } else if(DECODER_TYPE_DVPP_GB28181 == config.dec_type){ + dec = new DvppGB28181Decoder(); } #endif diff --git a/src/decoder/interface/interface_headers.h b/src/decoder/interface/interface_headers.h index 281eea4..b7751f2 100644 --- a/src/decoder/interface/interface_headers.h +++ b/src/decoder/interface/interface_headers.h @@ -44,7 +44,8 @@ struct FFDecConfig{ enum DECODER_TYPE{ DECODER_TYPE_GB28181, DECODER_TYPE_FFMPEG, - DECODER_TYPE_DVPP + DECODER_TYPE_DVPP, + DECODER_TYPE_DVPP_GB28181 }; #endif \ No newline at end of file diff --git a/src/decoder/sip/Makefile b/src/decoder/sip/Makefile deleted file mode 100755 index 32b3939..0000000 --- a/src/decoder/sip/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -XX = g++ - - -PROJECT_ROOT= /home/cmhu/vpt_ascend_arm - -DEPEND_DIR = $(PROJECT_ROOT)/bin -SRC_ROOT = /home/cmhu/vpt_ascend_arm/src/decoder/sip - -TARGET= $(PROJECT_ROOT)/bin/test_sip - -THIRDPARTY_ROOT = $(PROJECT_ROOT)/3rdparty -SPDLOG_ROOT = $(THIRDPARTY_ROOT)/spdlog-1.9.2/release -SIP_ROOT = /home/cmhu/vpt_ascend_arm/3rdparty/gb28181_3rd/release - -DEFS = -DLinux - -INCLUDE=-I $(SPDLOG_ROOT)/include \ - -I $(SIP_ROOT)/include \ - - -LIBS= -L $(SPDLOG_ROOT)/lib -l:libspdlog.a \ - -L $(SIP_ROOT)/lib -l:libeXosip2.a -l:libosipparser2.a -l:libosip2.a -lcares\ - - -CXXFLAGS= -g -O0 -fPIC $(INCLUDE) $(LIBS) $(DEFS) -lpthread -lrt -lz -fexceptions -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -fvisibility=hidden -Wall -Wno-deprecated -Wdeprecated-declarations -Wl,-Bsymbolic -ldl - - - -SRCS:=$(wildcard $(SRC_ROOT)/Utils/*.cpp) \ - $(wildcard $(SRC_ROOT)/Message/*.cpp) \ - $(wildcard $(SRC_ROOT)/tinyxml2/*.cpp) \ - $(wildcard $(SRC_ROOT)/src/*.cpp) \ - -OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS))) - - -$(TARGET):$(OBJS) - rm -f $(TARGET) - $(XX) -o $@ $^ $(CXXFLAGS) - rm -f *.o - -%.o:$(SRC_ROOT)/Utils/%.cpp - $(XX) $(CXXFLAGS) -c $< - -%.o:$(SRC_ROOT)/Message/%.cpp - $(XX) $(CXXFLAGS) -c $< - -%.o:$(SRC_ROOT)/tinyxml2/%.cpp - $(XX) $(CXXFLAGS) -c $< - -%.o:$(SRC_ROOT)/src/%.cpp - $(XX) $(CXXFLAGS) -c $< - -clean: - rm -f *.o $(TARGET) diff --git a/src/decoder/sip/Message/CatalogParser.cpp b/src/decoder/sip/Message/CatalogParser.cpp deleted file mode 100644 index 5c890e5..0000000 --- a/src/decoder/sip/Message/CatalogParser.cpp +++ /dev/null @@ -1,631 +0,0 @@ -#include "CatalogParser.h" -#include -#include - -#include "../Utils/logger.hpp" - -static const char* g_event_desc[] = -{ - "ON", - "OFF", - "VLOST", - "DEFECT", - "ADD", - "DEL", - "UPDATE" -}; - - -bool CCatalogParser::Encode( std::string &message ) -{ - std::ostringstream content; - content<<"\r\n"; - content<<"\r\n"; - content<<"Catalog\r\n"; - content<<""<< m_sn <<"\r\n"; - content<<""<< m_deviceid <<"\r\n"; - content<<"OK\r\n"; - content<<""<< m_sum <<"\r\n"; - content<<"\r\n"; - - for( auto it = m_devices.begin(); it != m_devices.end(); ++it ) - { - // У��Ŀ¼��ı�ѡ���� - const DeviceInfo &catalog = (*it); - content<<"\r\n"; - content<<""<\r\n"; - content<<""<< g_event_desc[catalog.event] <<"\r\n"; - - if( catalog.event == EVENT_ADD || catalog.event == EVENT_UPDATE ) - { - content<<""<< catalog.name <<"\r\n"; - content<<""<< catalog.manufacturer <<"\r\n"; - content<<""<< catalog.model <<"\r\n"; - content<<""<< catalog.owner <<"\r\n"; - - if( !catalog.civil.empty() ) - { - content<<""<\r\n"; - } - else - { - content<<""<\r\n"; - } - - if( !catalog.block.empty() ) - { - content<<""<< catalog.block <<"\r\n"; - } - - content<<"
"<< catalog.address <<"
\r\n"; - content<<""<< catalog.parental <<"\r\n"; - content<<""<< catalog.parentid <<"\r\n"; - - if( !catalog.safetyway.empty() ) - { - content<<""<< catalog.safetyway <<"\r\n"; - } - - content<<""<< catalog.registerway <<"\r\n"; - - if( !catalog.certnum.empty() ) - { - content<<""<< catalog.certnum <<"\r\n"; - } - - if( !catalog.certifiable.empty() ) - { - content<<""<< catalog.certifiable <<"\r\n"; - } - - if( !catalog.errcode.empty() ) - { - content<<""<< catalog.errcode <<"\r\n"; - } - - if( !catalog.endtime.empty() ) - { - content<<""<< catalog.endtime <<"\r\n"; - } - - content<<""<< catalog.secrecy <<"\r\n"; - - if( !catalog.ip.empty() ) - { - content<<""<< catalog.ip <<"\r\n"; - } - - if( !catalog.port.empty() ) - { - content<<""<< catalog.port <<"\r\n"; - } - - if( !catalog.password.empty() ) - { - content<<""<< catalog.password <<"\r\n"; - } - - content<<""<\r\n"; - - if( !catalog.longitude.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.latitude.empty() ) - { - content<<""<\r\n"; - } - - content<<"\r\n"; - if( !catalog.ptz.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.position.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.room.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.use.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.supplylight.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.direction.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.resolution.empty() ) - { - content<<""<\r\n"; - } - - if( !catalog.businessgroup.empty() ) - { - content<<""<\r\n"; - } - - content<<"\r\n"; - } - - content<<"
\r\n"; - } - content<<"
\r\n"; - content<<"
\r\n\r\n"; - - message = content.str(); - return true; -} - -std::vector< DeviceInfo > CCatalogParser::Decode( const std::vector< tinyxml2::XMLNode* > &nodes) -{ - std::vector< DeviceInfo > cat_list; - // �������У�� - tinyxml2::XMLNode *pSumNum = NULL; - size_t size = nodes.size(); - for( size_t i = 0; i < size; ++i ) - { - tinyxml2::XMLNode *pNode = nodes[i]; - if( pNode == NULL ) - { - LOG_DEBUG( "��������" ); - continue; - } - - const char* type = pNode->Value(); - if( type == NULL ) - { - LOG_DEBUG( "��������Ϊ��" ); - continue; - } - - if( CGBMessage::CompareNoCase( type, "SumNum" ) ) - { - pSumNum = pNode; - } - } - - // ��ѡ���������� - if( pSumNum == NULL ) - { - LOG_ERROR( "����SumNumû�б�����" ); - return cat_list; - } - - // �������� - std::list< tinyxml2::XMLNode* > items; - for( size_t i = 0; i < size; ++i ) - { - tinyxml2::XMLNode *pNode = nodes[i]; - if( pNode == NULL ) - { - LOG_DEBUG( "��������" ); - continue; - } - - const char* type = pNode->Value(); - if( type == NULL ) - { - LOG_DEBUG( "��������Ϊ��" ); - continue; - } - - if( CGBMessage::CompareNoCase( type, "Status" ) ) - { - tinyxml2::XMLNode *pChild = pNode->FirstChild(); - if( pChild == NULL ) - { - LOG_DEBUG( "����ֵû������" ); - continue; - } - - const char *value = pChild->Value(); - if( value == NULL ) - { - LOG_DEBUG( "����ֵΪ��" ); - continue; - } - else - { - m_status = value; - } - } - else if( CGBMessage::CompareNoCase( type, "SumNum" ) ) - { - tinyxml2::XMLNode *pChild = pNode->FirstChild(); - if( pChild == NULL ) - { - LOG_DEBUG( "����ֵû������" ); - continue; - } - - const char *value = pChild->Value(); - if( value == NULL ) - { - LOG_DEBUG( "����ֵΪ��" ); - continue; - } - else - { - m_sum = atoi( value ); - } - } - else if( CGBMessage::CompareNoCase( type, "DeviceList" ) ) - { - for(tinyxml2::XMLNode *pItem = pNode->FirstChild(); pItem != NULL; pItem = pItem->NextSibling() ) - { - const char *type = pItem->Value(); - if( type == NULL ) - { - LOG_DEBUG( "��������Ϊ��" ); - continue; - } - - if( CGBMessage::CompareNoCase( type, "Item" ) ) - { - items.push_back( pItem ); - } - else - { - LOG_DEBUG( "����δ����IJ���:{}" , type ); - continue; - } - } - } - else - { - LOG_DEBUG( "����δ����IJ���:{}" , type ); - continue; - } - } - - // Ŀ¼�� - std::list< tinyxml2::XMLNode* >::iterator it = items.begin(); - std::list< tinyxml2::XMLNode* >::iterator end = items.end(); - for( /*it*/; it != end; ++it ) - { - DeviceInfo catalog; - for(tinyxml2::XMLNode *pItem = (*it)->FirstChild(); pItem != NULL; pItem = pItem->NextSibling() ) - { - const char *type = pItem->Value(); - if( type == NULL ) - { - LOG_DEBUG( "��������Ϊ��" ); - continue; - } - - tinyxml2::XMLNode *pValue = pItem->FirstChild(); - if( pValue == NULL ) - { - LOG_DEBUG( "����ֵû������" ); - continue; - } - - const char *value = pValue->Value(); - if( value == NULL ) - { - LOG_DEBUG( "����ֵΪ��" ); - continue; - } - - if( CGBMessage::CompareNoCase( type, "DeviceID" ) ) - { - catalog.id = value; - } - else if( CGBMessage::CompareNoCase( type, "Event" ) ) - { - if( CGBMessage::CompareNoCase( value, "ON" ) ) - { - catalog.event = EVENT_ON; - } - else if( CGBMessage::CompareNoCase( value, "OFF" ) ) - { - catalog.event = EVENT_OFF; - } - else if( CGBMessage::CompareNoCase( value, "VLOST" ) ) - { - catalog.event = EVENT_VLOST; - } - else if( CGBMessage::CompareNoCase( value, "DEFECT" ) ) - { - catalog.event = EVENT_DEFECT; - } - else if( CGBMessage::CompareNoCase( value, "ADD" ) ) - { - catalog.event = EVENT_ADD; - } - else if( CGBMessage::CompareNoCase( value, "DEL" ) ) - { - catalog.event = EVENT_DEL; - } - else if( CGBMessage::CompareNoCase( value, "UPDATE" ) ) - { - catalog.event = EVENT_UPDATE; - } - else - { - LOG_ERROR( "Event����ֵ\'{}\'��Ч", value ); - return cat_list; - } - } - else if( CGBMessage::CompareNoCase( type, "Name" ) ) - { - catalog.name = value; - } - else if( CGBMessage::CompareNoCase( type, "Manufacturer" ) ) - { - catalog.manufacturer = value; - } - else if( CGBMessage::CompareNoCase( type, "Model" ) ) - { - catalog.model = value; - } - else if( CGBMessage::CompareNoCase( type, "Owner" ) ) - { - catalog.owner = value; - } - else if( CGBMessage::CompareNoCase( type, "CivilCode" ) ) - { - catalog.civil = value; - } - else if( CGBMessage::CompareNoCase( type, "Block" ) ) - { - catalog.block = value; - } - else if( CGBMessage::CompareNoCase( type, "Address" ) ) - { - catalog.address = value; - } - else if( CGBMessage::CompareNoCase( type, "Parental" ) ) - { - catalog.parental = value; - } - else if( CGBMessage::CompareNoCase( type, "ParentID" ) ) - { - catalog.parentid = value; - } - else if( CGBMessage::CompareNoCase( type, "SafetyWay" ) ) - { - catalog.safetyway = value; - } - else if( CGBMessage::CompareNoCase( type, "RegisterWay" ) ) - { - catalog.registerway = value; - } - else if( CGBMessage::CompareNoCase( type, "CertNum" ) ) - { - catalog.certnum = value; - } - else if( CGBMessage::CompareNoCase( type, "Certifiable" ) ) - { - catalog.certifiable = value; - } - else if( CGBMessage::CompareNoCase( type, "ErrCode" ) ) - { - catalog.errcode = value; - } - else if( CGBMessage::CompareNoCase( type, "EndTime" ) ) - { - catalog.endtime = value; - } - else if( CGBMessage::CompareNoCase( type, "Secrecy" ) ) - { - catalog.secrecy = value; - } - else if( CGBMessage::CompareNoCase( type, "IPAddress" ) ) - { - catalog.ip = value; - } - else if( CGBMessage::CompareNoCase( type, "Port" ) ) - { - catalog.port = value; - } - else if( CGBMessage::CompareNoCase( type, "Password" ) ) - { - catalog.password = value; - } - else if( CGBMessage::CompareNoCase( type, "Status" ) ) - { - catalog.status = value; - } - else if( CGBMessage::CompareNoCase( type, "Longitude" ) ) - { - catalog.longitude = value; - } - else if( CGBMessage::CompareNoCase( type, "Latitude" ) ) - { - catalog.latitude = value; - } - else if( CGBMessage::CompareNoCase( type, "PTZType" ) ) - { - catalog.ptz = value; - } - else if( CGBMessage::CompareNoCase( type, "PositionType" ) ) - { - catalog.position = value; - } - else if( CGBMessage::CompareNoCase( type, "RoomType" ) ) - { - catalog.room = value; - } - else if( CGBMessage::CompareNoCase( type, "UseType" ) ) - { - catalog.use = value; - } - else if( CGBMessage::CompareNoCase( type, "SupplyLightType" ) ) - { - catalog.supplylight = value; - } - else if( CGBMessage::CompareNoCase( type, "DirectionType" ) ) - { - catalog.direction = value; - } - else if( CGBMessage::CompareNoCase( type, "Resolution" ) ) - { - catalog.resolution = value; - } - else if( CGBMessage::CompareNoCase( type, "BusinessGroupID" ) ) - { - catalog.businessgroup = value; - } - else if( CGBMessage::CompareNoCase( type, "Info" ) ) - { - for(tinyxml2::XMLNode *pInfo = pItem->FirstChild(); pInfo != NULL; pInfo = pInfo->NextSibling() ) - { - pValue = pInfo->FirstChild(); - if( pValue == NULL ) - { - LOG_DEBUG( "����ֵû������" ); - continue; - } - - const char *type = pInfo->Value(); - if( type == NULL ) - { - LOG_DEBUG( "��������Ϊ��" ); - continue; - } - - const char *value = pValue->Value(); - if( value == NULL ) - { - LOG_DEBUG( "����ֵΪ��" ); - continue; - } - - if( CGBMessage::CompareNoCase( type, "PTZType" ) ) - { - catalog.ptz = value; - } - else if( CGBMessage::CompareNoCase( type, "PositionType" ) ) - { - catalog.position = value; - } - else if( CGBMessage::CompareNoCase( type, "RoomType" ) ) - { - catalog.room = value; - } - else if( CGBMessage::CompareNoCase( type, "UseType" ) ) - { - catalog.use = value; - } - else if( CGBMessage::CompareNoCase( type, "SupplyLightType" ) ) - { - catalog.supplylight = value; - } - else if( CGBMessage::CompareNoCase( type, "DirectionType" ) ) - { - catalog.direction = value; - } - else if( CGBMessage::CompareNoCase( type, "Resolution" ) ) - { - catalog.resolution = value; - } - else if( CGBMessage::CompareNoCase( type, "BusinessGroupID" ) ) - { - catalog.businessgroup = value; - } - else - { - LOG_DEBUG( "����δ����IJ���:{}" , type ); - } - } - } - else - { - LOG_DEBUG( "����δ����IJ���:{}" , type ); - } - } - - // add to devices - m_devices.push_back( catalog ); - } - - return m_devices; -} - -std::vector< DeviceInfo > CCatalogParser::Decode_Catlog(const char* body) -{ - std::vector< DeviceInfo > cat_list; - if (body == NULL) - { - return cat_list; - } - - tinyxml2::XMLDocument doc; - doc.Parse(body); - tinyxml2::XMLElement* pRoot = doc.RootElement(); - if (pRoot == NULL) - { - return cat_list; - } - - tinyxml2::XMLNode* pCmd = 0; - tinyxml2::XMLNode* pSN = 0; - tinyxml2::XMLNode* pDeviceID = 0; - std::vector< tinyxml2::XMLNode* > nodes; - for (tinyxml2::XMLNode* pNode = pRoot->FirstChild(); pNode != 0; pNode = pNode->NextSibling()) - { - std::string value = pNode->Value(); - if (value == "CmdType") - { - pCmd = pNode->FirstChild(); - } - else if (value == "SN") - { - pSN = pNode->FirstChild(); - } - else if (value == "DeviceID") - { - pDeviceID = pNode->FirstChild(); - } - else - { - nodes.push_back(pNode); - } - } - - if (pCmd == NULL || pSN == NULL || pDeviceID == NULL) - { - return cat_list; - } - - std::string sn = pSN->Value(); - if (sn.empty()) - { - return cat_list; - } - - std::string deviceid = pDeviceID->Value(); - if (deviceid.empty()) - { - return cat_list; - } - - std::string msgType = pRoot->Value(); - std::string cmdType = pCmd->Value(); - if (msgType == "Response" && cmdType == "Catalog") - { - cat_list = Decode(nodes); - if (cat_list.empty()) - { - LOG_ERROR("��Ϣ���������!"); - } - } - - - return cat_list; -} \ No newline at end of file diff --git a/src/decoder/sip/Message/CatalogParser.h b/src/decoder/sip/Message/CatalogParser.h deleted file mode 100644 index 96050da..0000000 --- a/src/decoder/sip/Message/CatalogParser.h +++ /dev/null @@ -1,238 +0,0 @@ -#ifndef MSG_NOTIFY_MSG_HPP_ -#define MSG_NOTIFY_MSG_HPP_ - -#include "GBMessage.h" -#include - -enum EEventType -{ - EVENT_ON = 0, // - EVENT_OFF, // - EVENT_VLOST, // Ƶʧ - EVENT_DEFECT, // - EVENT_ADD, // - EVENT_DEL, // ɾ - EVENT_UPDATE, // - - EVENT_UNKNOW, -}; - -struct DeviceInfo -{ - EEventType event; - std::string id; - std::string name; - std::string manufacturer; - std::string model; - std::string owner; - std::string civil; - std::string block; - std::string address; - std::string safetyway; - std::string registerway; - std::string certnum; - std::string certifiable; - std::string errcode; - std::string secrecy; - std::string parental; - std::string parentid; - std::string endtime; - std::string ip; - std::string port; - std::string password; - std::string status; - std::string longitude; - std::string latitude; - std::string ptz; - std::string position; - std::string room; - std::string use; - std::string supplylight; - std::string direction; - std::string resolution; - std::string businessgroup; -}; - -////////////////////////////////////////////////////////////////////////// -class CCatalogParser : public CGBMessage -{ -public: - CCatalogParser() - { - } - -public: - bool Encode( std::string &message ); - - std::vector< DeviceInfo > Decode_Catlog(const char* body); - - static std::string GetStrName(EEventType eType) - { - switch (eType) - { - case EVENT_ON: - return "ON"; - case EVENT_OFF: - return "OFF"; - case EVENT_VLOST: - return "VLOST"; - case EVENT_DEFECT: - return "DEFECT"; - case EVENT_ADD: - return "ADD"; - case EVENT_DEL: - return "DEL"; - case EVENT_UPDATE: - return "UPDATE"; - default: //EVENT_UNKNOW - return "UNKNOW"; - } - - return "UNKNOW"; - } - - EEventType GetEnumName(const std::string &sType) - { - if (sType == "ON") - return EVENT_ON; - if (sType == "OFF") - return EVENT_OFF; - if (sType == "VLOSE") - return EVENT_VLOST; - if (sType == "DEFECT") - return EVENT_DEFECT; - if (sType == "ADD") - return EVENT_ADD; - if (sType == "DEL") - return EVENT_DEL; - if (sType == "UPDATE") - return EVENT_UPDATE; - - return EVENT_UNKNOW; - - } - - -public: - - inline const std::string& GetSN() const - { - return m_sn; - } - - inline const std::string& GetDeviceID() const - { - return m_deviceid; - } - - inline void SetDeviceID( const std::string &deviceid ) - { - m_deviceid = deviceid; - } - - inline void SetSN( const std::string &sn ) - { - m_sn = sn; - } - - inline const std::string& GetStatus() const - { - return m_status; - } - - inline void SetStatus( const std::string &status ) - { - m_status = status; - } - - inline int GetSum() const - { - return m_sum; - } - - inline void SetSum( int sum ) - { - m_sum = sum; - } - - inline const std::vector< DeviceInfo >& GetDevices() const - { - return m_devices; - } - - inline void AddEvent(const std::string &id, EEventType eventType) - { - DeviceInfo catalog; - catalog.id = id; - catalog.event = eventType; - m_devices.push_back( catalog ); - } - - inline void AddOnEvent( const std::string &id ) - { - DeviceInfo catalog; - catalog.id = id; - catalog.event = EVENT_ON; - m_devices.push_back( catalog ); - } - - inline void AddOffEvent( const std::string &id ) - { - DeviceInfo catalog; - catalog.id = id; - catalog.event = EVENT_OFF; - m_devices.push_back( catalog ); - } - - inline void AddVLostEvent( const std::string &id ) - { - DeviceInfo catalog; - catalog.id = id; - catalog.event = EVENT_VLOST; - m_devices.push_back( catalog ); - } - - inline void AddDefectEvent( const std::string &id ) - { - DeviceInfo catalog; - catalog.id = id; - catalog.event = EVENT_DEFECT; - m_devices.push_back( catalog ); - } - - inline void AddDelEvent( const std::string &id ) - { - DeviceInfo catalog; - catalog.id = id; - catalog.event = EVENT_DEL; - m_devices.push_back( catalog ); - } - - inline void AddAddEvent( const DeviceInfo &catalog ) - { - if( catalog.event == EVENT_ADD ) - { - m_devices.push_back( catalog ); - } - } - - inline void AddUpdateEvent( const DeviceInfo &catalog ) - { - if( catalog.event == EVENT_UPDATE ) - { - m_devices.push_back( catalog ); - } - } - -private: - std::vector< DeviceInfo > Decode(const std::vector< tinyxml2::XMLNode* >& nodes); - -private: - std::string m_sn; - std::string m_deviceid; - std::string m_status; - int m_sum; - std::vector< DeviceInfo > m_devices; -}; - -#endif // MSG_NOTIFY_MSG_HPP_ \ No newline at end of file diff --git a/src/decoder/sip/Message/GBMessage.cpp b/src/decoder/sip/Message/GBMessage.cpp deleted file mode 100644 index 68162d2..0000000 --- a/src/decoder/sip/Message/GBMessage.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#include "GBMessage.h" -//#include "ILocker.h" -#include -static std::atomic g_msgsn(0); -//static CLocker g_msg_lock; - -bool CGBMessage::CompareNoCase( const char *type, const char *label ) -{ - // У - if( type == NULL || label == NULL ) - { - return false; - } - - // ȽǷ - char ch1 = type[0]; - char ch2 = label[0]; - size_t i = 0; - while( ch1 != 0 && ch2 != 0 ) - { - if( ch1 >= 'a' && ch1 <= 'z' ) - { - ch1 -= 'a'; - ch1 += 'A'; - } - - if( ch2 >= 'a' && ch2 <= 'z' ) - { - ch2 -= 'a'; - ch2 += 'A'; - } - - if( ch1 != ch2 ) - { - return false; - } - else - { - ++i; - ch1 = type[i]; - ch2 = label[i]; - } - } - - return( ch1 == 0 && ch2 == 0 ); -} - - -bool CGBMessage::CompareNoCase( const std::string &str, const char *label ) -{ - // У - const char* type = str.c_str(); - if( type == NULL || label == NULL ) - { - return false; - } - - // ȽǷ - char ch1 = type[0]; - char ch2 = label[0]; - size_t i = 0; - while( ch1 != 0 && ch2 != 0 ) - { - if( ch1 >= 'a' && ch1 <= 'z' ) - { - ch1 -= 'a'; - ch1 += 'A'; - } - - if( ch2 >= 'a' && ch2 <= 'z' ) - { - ch2 -= 'a'; - ch2 += 'A'; - } - - if( ch1 != ch2 ) - { - return false; - } - else - { - ++i; - ch1 = type[i]; - ch2 = label[i]; - } - } - - return( ch1 == 0 && ch2 == 0 ); -} - -unsigned int CGBMessage::GetNextSN() -{ - //CNPAutoLock locker( g_msg_lock ); - g_msgsn++; - return g_msgsn; -} - -bool CGBMessage::DecodeSubject() -{ - std::vector< std::string > vec; - size_t b = 0; - size_t e = 0; - while( b != std::string::npos ) - { - e = m_subject.find_first_of( ',', b ); - vec.push_back( m_subject.substr( b, e ) ); - if( e != std::string::npos ) - { - b = e + 1; - } - else - { - break; - } - } - - if( vec.size() != 2 ) - { - return false; - } - - // - std::string send = vec[0]; - std::string recv = vec[1]; - - // IDк - vec.clear(); - b = 0; - while( b != std::string::npos ) - { - e = send.find_first_of( ':', b ); - vec.push_back( send.substr( b, e ) ); - if( e != std::string::npos ) - { - b = e + 1; - } - else - { - break; - } - } - - if( vec.size() != 2 ) - { - return false; - } - else - { - m_sender.id = vec[0]; - m_sender.seq = vec[1]; - } - - // IDк - vec.clear(); - b = 0; - while( b != std::string::npos ) - { - e = recv.find_first_of( ':', b ); - vec.push_back( recv.substr( b, e ) ); - if( e != std::string::npos ) - { - b = e + 1; - } - else - { - break; - } - } - - if( vec.size() != 2 ) - { - return false; - } - else - { - m_recver.id = vec[0]; - m_recver.seq = vec[1]; - } - - return true; -} - diff --git a/src/decoder/sip/Message/GBMessage.h b/src/decoder/sip/Message/GBMessage.h deleted file mode 100644 index 61c1894..0000000 --- a/src/decoder/sip/Message/GBMessage.h +++ /dev/null @@ -1,441 +0,0 @@ -#ifndef GBMESSAGE_HPP_ -#define GBMESSAGE_HPP_ - -#include -#include -#include -#include -#include "../tinyxml2/tinyxml2.h" - - -#if defined(CATCH_RESIP_EXCEPTION) -#undef __DUM_TRY -#undef __DUM_CATCH -#define __DUM_TRY try { -#define __DUM_CATCH \ -} catch(resip::DumException* be) { \ - resip::Data ex; \ - ex = "RESIP 쳣name = "; \ - ex += be->name(); \ - ex += "what = "; \ - ex += be->what(); \ - throw new std::exception(ex.c_str()); \ -} -#else -#undef __DUM_TRY -#undef __DUM_CATCH -#define __DUM_TRY -#define __DUM_CATCH -#endif - - -class CGBMessage -{ -public: - enum EGBResultType - { - RESULT_OK = 0, - RESULT_ERROR, - }; - - struct SDate - { - int year; - int month; - int day; - int hour; - int minute; - int second; - int millisecond; - }; - - struct SSubject - { - std::string id; - std::string seq; - }; - - struct SUserIdentity - { - std::string user; - std::string deviceid; - std::string organization; - std::string policetype; - std::string duty; - }; - -public: - CGBMessage() : m_adjusttime( false ), m_port( 0 ), m_cseq( 0 ), m_forwards( 0 ), m_expires( 0 ), m_statusCode( 0 ) - { - } - - virtual ~CGBMessage() - { - } - -private: - CGBMessage( const CGBMessage &rhs ); - CGBMessage& operator=( const CGBMessage &rhs ); - -public: - inline bool Ok() const - { - return( m_statusCode == 200 ); - } - - inline bool AdjustTime() const - { - return m_adjusttime; - } - - inline const std::string& GetSubjectSendID() const - { - return m_sender.id; - } - - inline const std::string& GetSubjectSendSeq() const - { - return m_sender.seq; - } - - inline const std::string& GetSubjectRecvID() const - { - return m_recver.id; - } - - inline const std::string& GetSubjectRecvSeq() const - { - return m_recver.seq; - } - - inline const std::string& GetUser() const - { - return m_request; - } - - inline const std::string& GetSubject() const - { - return m_subject; - } - - inline const std::string& GetFrom() const - { - return m_from; - } - - inline const std::string& GetFromTag() const - { - return m_tagfrom; - } - - inline const std::string& GetTo() const - { - return m_to; - } - - inline const std::string& GetToTag() const - { - return m_tagto; - } - - inline unsigned long GetCSeq() const - { - return m_cseq; - } - - inline int GetStatusCode() const - { - return m_statusCode; - } - - inline int GetMaxFrowards() const - { - return m_forwards; - } - - inline int GetExpires() const - { - return m_expires; - } - - inline const std::string& GetIP() const - { - return m_ip; - } - - inline int GetPort() const - { - return m_port; - } - - inline const std::string& GetCallID() const - { - return m_callid; - } - - inline const SDate& GetDate() const - { - return m_date; - } - - inline const SUserIdentity& GetUserIdentity() const - { - return m_useridentity; - } - - inline const std::vector< std::string >& GetContacts() const - { - return m_contacts; - } - - inline const std::vector< std::string >& GetVias() const - { - return m_vias; - } - - inline void SetSubjectSendID( const std::string &id ) - { - m_sender.id = id; - } - - inline void SetSubjectSendSeq( const std::string &seq ) - { - m_sender.seq = seq; - } - - inline void SetSubjectRecvID( const std::string &id ) - { - m_recver.id = id; - } - - inline void SetSubjectRecvSeq( const std::string &seq ) - { - m_recver.seq = seq; - } - - inline void SetUser( const char *user ) - { - if( user != NULL ) - { - m_request = user; - } - } - - inline void SetUser( const std::string &user ) - { - m_request = user; - } - - inline void SetSubject( const char *uri ) - { - if( uri != NULL ) - { - m_subject = uri; - DecodeSubject(); - } - } - - inline void SetSubject( const std::string &uri ) - { - m_subject = uri; - DecodeSubject(); - } - - inline void SetFrom( const char *code ) - { - if( code != NULL ) - { - m_from = code; - } - } - - inline void SetFrom( const std::string &code ) - { - m_from = code; - } - - inline void SetFromTag( const char *tag ) - { - if( tag != NULL ) - { - m_tagfrom = tag; - } - } - - inline void SetFromTag( const std::string &code ) - { - m_tagfrom = code; - } - - inline void SetTo( const char *code ) - { - if( code != NULL ) - { - m_to = code; - } - } - - inline void SetTo( const std::string &code ) - { - m_to = code; - } - - inline void SetToTag( const char *tag ) - { - if( tag != NULL ) - { - m_tagto = tag; - } - } - - inline void SetToTag( const std::string &tag ) - { - m_tagto = tag; - } - - inline void SetCSeq( unsigned long cseq ) - { - m_cseq = cseq; - } - - inline void SetExpires( int expires ) - { - m_expires = expires; - } - - inline void SetStatusCode( int code ) - { - m_statusCode = code; - } - - inline void SetMaxFrowards( int forwards ) - { - m_forwards = forwards; - } - - inline void SetCallID( const char *callid ) - { - if( callid != NULL ) - { - m_callid = callid; - } - } - - inline void SetCallID( const std::string &callid ) - { - m_callid = callid; - } - - inline void SetIP( const std::string &ip ) - { - m_ip = ip; - } - - inline void SetIP( const char *ip ) - { - if( ip != NULL ) - { - m_ip = ip; - } - } - - inline void SetPort( int port ) - { - m_port = port; - } - - inline void SetDate( int year, int month, int day, int hour, int minute, int second, int millisecond ) - { - m_adjusttime = true; - m_date.year = year; - m_date.month = month; - m_date.day = day; - m_date.hour = hour; - m_date.minute = minute; - m_date.second = second; - m_date.millisecond = millisecond; - } - - inline void AddContacts( const char *contacts ) - { - if( contacts != NULL ) - { - m_contacts.push_back( contacts ); - } - } - - inline void AddContacts( const std::string &contacts ) - { - m_contacts.push_back( contacts ); - } - - inline void AddVias( const char *host, long port ) - { - if( host != NULL ) - { - char buf[16] = { 0 }; - sprintf( buf, "%d", port ); - std::string via = host; - via += ":"; - via += buf; - m_vias.push_back( via ); - } - } - - inline void AddVias( const std::string &host, long port ) - { - char buf[16] = { 0 }; - sprintf( buf, "%d", port ); - std::string via = host; - via += ":"; - via += buf; - m_vias.push_back( via ); - } - - inline void SetUserIdentity( const std::string &user, const std::string& deviceid, const std::string& organization, const std::string& policetype, const std::string& duty ) - { - m_useridentity.user = user; - m_useridentity.deviceid = deviceid; - m_useridentity.organization = organization; - m_useridentity.policetype = policetype; - m_useridentity.duty = duty; - } - -public: - - virtual bool Response( int status ) - { - return false; - } - -public: - static bool CompareNoCase( const char *type, const char *label ); - static bool CompareNoCase( const std::string &type, const char *label ); - static unsigned int GetNextSN(); - bool DecodeSubject(); - -protected: - SSubject m_sender; // subject - SSubject m_recver; // subject - std::string m_request; - std::string m_subject; - std::string m_callid; - std::string m_from; - std::string m_tagfrom; - std::string m_to; - std::string m_tagto; - SDate m_date; - std::vector< std::string > m_contacts; - std::vector< std::string > m_vias; - std::string m_ip; - bool m_adjusttime; // message has date header - int m_port; - unsigned long m_cseq; - int m_forwards; - int m_expires; - int m_statusCode; - SUserIdentity m_useridentity; -}; - -////////////////////////////////////////////////////////////////////////// -#endif // GBMESSAGE_HPP_ diff --git a/src/decoder/sip/Utils/HTTPDigest.cpp b/src/decoder/sip/Utils/HTTPDigest.cpp deleted file mode 100644 index 26fb8f6..0000000 --- a/src/decoder/sip/Utils/HTTPDigest.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "MD5.h" -#include -#include "HTTPDigest.h" - -#ifdef _WIN32 -//#define strcasecmp _stricmp -//#define strncasecmp _strnicmp -#endif -#ifdef _MSC_VER -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#endif - -void my_CvtHex( - IN HASH Bin, - OUT HASHHEX Hex - ) -{ - unsigned short i; - unsigned char j; - for (i = 0; i < HASHLEN; i++) { - j = (Bin[i] >> 4) & 0xf; - if (j <= 9) - Hex[i*2] = (j + '0'); - else - Hex[i*2] = (j + 'a' - 10); - j = Bin[i] & 0xf; - if (j <= 9) - Hex[i*2+1] = (j + '0'); - else - Hex[i*2+1] = (j + 'a' - 10); - }; - Hex[HASHHEXLEN] = '\0'; -} - -/* calculate H(A1) as per spec */ -void -DigestCalcHA1 (IN const char *pszAlg, - IN const char *pszUserName, - IN const char *pszRealm, - IN const char *pszPassword, - IN const char *pszNonce, - IN const char *pszCNonce, - OUT HASHHEX SessionKey) -{ - MD5_CTX Md5Ctx; - HASH HA1; - - MD5Init (&Md5Ctx); - MD5Update (&Md5Ctx, (unsigned char *) pszUserName, (unsigned int) strlen (pszUserName)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszRealm, (unsigned int) strlen (pszRealm)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszPassword, (unsigned int) strlen (pszPassword)); - MD5Final ((unsigned char *) HA1, &Md5Ctx); - if ((pszAlg != NULL) && strcasecmp (pszAlg, "md5-sess") == 0) { - MD5Init (&Md5Ctx); - MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHLEN); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, (unsigned int) strlen (pszCNonce)); - MD5Final ((unsigned char *) HA1, &Md5Ctx); - } - my_CvtHex (HA1, SessionKey); -} - -/* calculate request-digest/response-digest as per HTTP Digest spec */ -void -DigestCalcResponse (IN HASHHEX HA1, /* H(A1) */ - IN const char *pszNonce, /* nonce from server */ - IN const char *pszNonceCount, /* 8 hex digits */ - IN const char *pszCNonce, /* client nonce */ - IN const char *pszQop, /* qop-value: "", "auth", "auth-int" */ - IN int Aka, /* Calculating AKAv1-MD5 response */ - IN const char *pszMethod, /* method from the request */ - IN const char *pszDigestUri, /* requested URL */ - IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ - OUT HASHHEX Response - /* request-digest or response-digest */ ) -{ - MD5_CTX Md5Ctx; - HASH HA2; - HASH RespHash; - HASHHEX HA2Hex; - - /* calculate H(A2) */ - MD5Init (&Md5Ctx); - MD5Update (&Md5Ctx, (unsigned char *) pszMethod, (unsigned int) strlen (pszMethod)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszDigestUri, (unsigned int) strlen (pszDigestUri)); - - if (pszQop == NULL) { - goto auth_withoutqop; - } - else if (0 == strcasecmp (pszQop, "auth-int")) { - goto auth_withauth_int; - } - else if (0 == strcasecmp (pszQop, "auth")) { - goto auth_withauth; - } - -auth_withoutqop: - MD5Final ((unsigned char *) HA2, &Md5Ctx); - my_CvtHex (HA2, HA2Hex); - - /* calculate response */ - MD5Init (&Md5Ctx); - MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - - goto end; - -auth_withauth_int: - - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) HEntity, HASHHEXLEN); - -auth_withauth: - MD5Final ((unsigned char *) HA2, &Md5Ctx); - my_CvtHex (HA2, HA2Hex); - - /* calculate response */ - MD5Init (&Md5Ctx); - MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - if (Aka == 0) { - MD5Update (&Md5Ctx, (unsigned char *) pszNonceCount, (unsigned int) strlen (pszNonceCount)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, (unsigned int) strlen (pszCNonce)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - MD5Update (&Md5Ctx, (unsigned char *) pszQop, (unsigned int) strlen (pszQop)); - MD5Update (&Md5Ctx, (unsigned char *) ":", 1); - } -end: - MD5Update (&Md5Ctx, (unsigned char *) HA2Hex, HASHHEXLEN); - MD5Final ((unsigned char *) RespHash, &Md5Ctx); - my_CvtHex (RespHash, Response); -} diff --git a/src/decoder/sip/Utils/HTTPDigest.h b/src/decoder/sip/Utils/HTTPDigest.h deleted file mode 100644 index d13884c..0000000 --- a/src/decoder/sip/Utils/HTTPDigest.h +++ /dev/null @@ -1,26 +0,0 @@ -#define HASHLEN 16 -typedef char HASH[HASHLEN]; -#define HASHHEXLEN 32 -typedef char HASHHEX[HASHHEXLEN+1]; -#define IN -#define OUT -/* calculate H(A1) as per HTTP Digest spec */ -void DigestCalcHA1 (IN const char *pszAlg, - IN const char *pszUserName, - IN const char *pszRealm, - IN const char *pszPassword, - IN const char *pszNonce, - IN const char *pszCNonce, - OUT HASHHEX SessionKey); -/* calculate request-digest/response-digest as per HTTP Digest spec */ -void DigestCalcResponse (IN HASHHEX HA1, /* H(A1) */ - IN const char *pszNonce, /* nonce from server */ - IN const char *pszNonceCount, /* 8 hex digits */ - IN const char *pszCNonce, /* client nonce */ - IN const char *pszQop, /* qop-value: "", "auth", "auth-int" */ - IN int Aka, /* Calculating AKAv1-MD5 response */ - IN const char *pszMethod, /* method from the request */ - IN const char *pszDigestUri, /* requested URL */ - IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ - OUT HASHHEX Response - /* request-digest or response-digest */ ); diff --git a/src/decoder/sip/Utils/Log.h b/src/decoder/sip/Utils/Log.h deleted file mode 100644 index 0ed8b09..0000000 --- a/src/decoder/sip/Utils/Log.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created bxc on 2022/11/25. -// - -#ifndef BXC_SIPSERVER_LOG_H -#define BXC_SIPSERVER_LOG_H -#include -#include - -static std::string getTime() { - const char* time_fmt = "%Y-%m-%d %H:%M:%S"; - time_t t = time(nullptr); - char time_str[64]; - strftime(time_str, sizeof(time_str), time_fmt, localtime(&t)); - - return time_str; -} -// __FILE__ 获取源文件的相对路径和名字 -// __LINE__ 获取该行代码在文件中的行号 -// __func__ 或 __FUNCTION__ 获取函数名 - -#define LOGI(format, ...) fprintf(stderr,"[INFO]%s [%s:%d %s()] " format "\n", getTime().data(),__FILE__,__LINE__,__func__ ,##__VA_ARGS__) -#define LOGE(format, ...) fprintf(stderr,"[ERROR]%s [%s:%d %s()] " format "\n",getTime().data(),__FILE__,__LINE__,__func__ ,##__VA_ARGS__) - -#endif //BXC_SIPSERVER_LOG_H \ No newline at end of file diff --git a/src/decoder/sip/Utils/MD5.cpp b/src/decoder/sip/Utils/MD5.cpp deleted file mode 100644 index f7c836d..0000000 --- a/src/decoder/sip/Utils/MD5.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm -*/ -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. -These notices must be retained in any copies of any part of this -documentation and/or software. -*/ -#include "MD5.h" -/* Constants for MD5Transform routine. -*/ -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - -#if 0 -static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); -static void Encode PROTO_LIST - ((unsigned char *, UINT4 *, unsigned int)); -static void Decode PROTO_LIST - ((UINT4 *, unsigned char *, unsigned int)); -static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); -static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); -#endif - -static void MD5Transform(UINT4 [4], unsigned char [64]); -static void Encode(unsigned char *, UINT4 *, unsigned int); -static void Decode(UINT4 *, unsigned char *, unsigned int); -static void MD5_memcpy(POINTER, POINTER, unsigned int); -static void MD5_memset(POINTER, int, unsigned int); - - -static unsigned char PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; -/* F, G, H and I are basic MD5 functions. -*/ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) -/* ROTATE_LEFT rotates x left n bits. -*/ -#define ROTATE_LEFT(x , n) (((x) << (n)) | ((x) >> (32-(n)))) -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. -Rotation is separate from addition to prevent recomputation. -*/ -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s));\ - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -/* MD5 initialization. Begins an MD5 operation, writing a new context. -*/ -void MD5Init (MD5_CTX * context) -{ - context->count[0] = context->count[1] = 0; - /* Load magic initialization constants. - */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; -} -/* MD5 block update operation. Continues an MD5 message-digest -operation, processing another message block, and updating the -context. -*/ -void MD5Update (MD5_CTX * context,unsigned char *input,unsigned int inputLen) -{ - unsigned int i, index, partLen; - /* Compute number of bytes mod 64 */ - index = (unsigned int)((context->count[0] >> 3) & 0x3F); - /* Update number of bits */ - if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4)inputLen >> 29); - partLen = 64 - index; - /* Transform as many times as possible. - */ - if (inputLen >= partLen) { - MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen); - MD5Transform (context->state, context->buffer); - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform (context->state, &input[i]); - index = 0; - } - else - i = 0; - /* Buffer remaining input */ - MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i],inputLen-i); -} -/* MD5 finalization. Ends an MD5 message-digest operation, writing the -the message digest and zeroizing the context. -*/ -void MD5Final(unsigned char digest[16],MD5_CTX * context) -{ - unsigned char bits[8]; - unsigned int index, padLen; - /* Save number of bits */ - Encode(bits, context->count, 8); - /* Pad out to 56 mod 64. - */ - index = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - MD5Update (context, PADDING, padLen); - /* Append length (before padding) */ - MD5Update (context, bits, 8); - /* Store state in digest */ - Encode (digest, context->state, 16); - /* Zeroize sensitive information. - */ - MD5_memset ((POINTER)context, 0, sizeof (*context)); -} - - -/* MD5 basic transformation. Transforms state based on block. -*/ -static void MD5Transform(UINT4 state[4], unsigned char block[64]) -{ - UINT4 a = state[0], b = state[1], c = state[2], d = state[3],x[16]; - Decode(x, block, 64); - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44,0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - /* Zeroize sensitive information. - - */ - MD5_memset((POINTER)x, 0, sizeof (x)); -} -/* Encodes input (UINT4) into output (unsigned char). Assumes len is -a multiple of 4. -*/ -static void Encode(unsigned char * output,UINT4 * input,unsigned int len) -{ - unsigned int i, j; - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} - -/* Decodes input (unsigned char) into output (UINT4). Assumes len is -a multiple of 4. -*/ -static void Decode(UINT4 * output,unsigned char * input,unsigned int len) -{ - unsigned int i, j; - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | - (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -} - -/* Note: Replace "for loop" with standard memcpy if possible. -*/ -static void MD5_memcpy(POINTER output,POINTER input,unsigned int len) -{ - unsigned int i; - for (i = 0; i < len; i++) - output[i] = input[i]; -} -/* Note: Replace "for loop" with standard memset if possible. -*/ -static void MD5_memset( POINTER output, int value,unsigned int len) -{ - unsigned int i; - for (i = 0; i < len; i++) - ((char *)output)[i] = (char)value; -} diff --git a/src/decoder/sip/Utils/MD5.h b/src/decoder/sip/Utils/MD5.h deleted file mode 100644 index 87f0e45..0000000 --- a/src/decoder/sip/Utils/MD5.h +++ /dev/null @@ -1,68 +0,0 @@ - -/* GLOBAL.H - RSAREF types and constants -*/ -/* PROTOTYPES should be set to one if and only if the compiler supports -function argument prototyping. -The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags. -*/ - - -#ifndef PROTOTYPES -#define PROTOTYPES 0 -#endif -/* POINTER defines a generic pointer type */ -typedef unsigned char *POINTER; -/* UINT2 defines a two byte word */ -typedef unsigned short int UINT2; -/* UINT4 defines a four byte word */ -typedef unsigned long int UINT4; -/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. -If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it -returns an empty list. -*/ -#if PROTOTYPES -#define PROTO_LIST(list) list -#else -#define PROTO_LIST(list) () -#endif - - - -/* MD5.H - header file for MD5C.C -*/ -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. -These notices must be retained in any copies of any part of this -documentation and/or software. -*/ -/* MD5 context. */ - - -typedef struct { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ -} MD5_CTX; - -#if 0 -void MD5Init PROTO_LIST ((MD5_CTX *)); -void MD5Update PROTO_LIST - ((MD5_CTX *, unsigned char *, unsigned int)); -void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); -#endif - -void MD5Init(MD5_CTX *); -void MD5Update(MD5_CTX *, unsigned char *, unsigned int); -void MD5Final(unsigned char [16], MD5_CTX *); diff --git a/src/decoder/sip/src/SipServer.cpp b/src/decoder/sip/src/SipServer.cpp deleted file mode 100644 index 861c3b2..0000000 --- a/src/decoder/sip/src/SipServer.cpp +++ /dev/null @@ -1,524 +0,0 @@ -// -// Created bxc on 2022/11/25. -// - -#include "SipServer.h" - -#ifndef WIN32 -// Linux系统 -#include -#else -#include -#endif // !WIN32 - -#pragma comment(lib, "ws2_32.lib") - -#include -#include "../Utils/logger.hpp" -#include "../Utils/HTTPDigest.h" - -#include - -using namespace std; - -static void event_loop_thread(void* arg) { - SipServer* _this = (SipServer*)arg; - if (_this != nullptr) { - _this->event_loop(); - } - else { - LOG_ERROR("event_loop线程启动失败 !"); - } -} - -static void dt_printSipMsg(osip_message_t* msg) { - osip_message_t* clone_event = NULL; - size_t length = 0; - char* message = NULL; - osip_message_clone(msg, &clone_event); - osip_message_to_str(clone_event, &message, &length); - LOG_INFO("{}", message); -} - -SipServer::SipServer(): - mQuit(false), - mSipCtx(nullptr){ -#ifdef WIN32 - WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) - { - LOG_ERROR("WSAStartup Error"); - return; - } -#endif // WIN32 - -} -SipServer::~SipServer() { - LOG_INFO("~SipServer"); - - if (m_event_loop_thread) - { - mQuit = true; - m_event_loop_thread->join(); - - delete m_event_loop_thread; - m_event_loop_thread = nullptr; - } - - this->clearClientMap(); -#ifdef WIN32 - WSACleanup(); -#endif // WIN32 -} - -bool SipServer::Init(ServerInfo info) { - mInfo = info; - LOG_INFO("{}:{}", mInfo.getIp(), mInfo.getPort()); - return true; -} - -int SipServer::sip_event_handle(eXosip_event_t *evtp) { - - switch(evtp->type) { - case EXOSIP_CALL_MESSAGE_NEW://14 - LOG_INFO("EXOSIP_CALL_MESSAGE_NEW type={}", evtp->type); - this->dump_request(evtp); - this->dump_response(evtp); - break; - - case EXOSIP_CALL_CLOSED://21 - LOG_INFO("EXOSIP_CALL_CLOSED type={}",evtp->type); - this->dump_request(evtp); - this->dump_response(evtp); - break; - - case EXOSIP_CALL_RELEASED://22 - LOG_INFO("EXOSIP_CALL_RELEASED type={}", evtp->type); - this->dump_request(evtp); - this->dump_response(evtp); - - this->clearClientMap(); - break; - case EXOSIP_MESSAGE_NEW://23 - LOG_INFO("EXOSIP_MESSAGE_NEW type={}",evtp->type); - - if (MSG_IS_REGISTER(evtp->request)) { - this->response_register(evtp); - } - else if (MSG_IS_MESSAGE(evtp->request)) { - this->response_message(evtp); - } - else if(MSG_IS_BYE(evtp->request)){ - LOG_ERROR("unknown1"); - } - else{ - LOG_ERROR("unknown2"); - } - break; - case EXOSIP_MESSAGE_ANSWERED: - this->dump_request(evtp); - break; - case EXOSIP_MESSAGE_REQUESTFAILURE: - LOG_INFO("EXOSIP_MESSAGE_REQUESTFAILURE type={}: Receive feedback on sending failure after actively sending a message", evtp->type); - this->dump_request(evtp); - this->dump_response(evtp); - break; - case EXOSIP_CALL_INVITE: - LOG_INFO("EXOSIP_CALL_INVITE type={}: The server receives the Invite request actively sent by the client", evtp->type); - break; - case EXOSIP_CALL_PROCEEDING://5 - LOG_INFO("EXOSIP_CALL_PROCEEDING type={}: When the server receives the Invite (SDP) confirmation reply from the client", evtp->type); - this->dump_request(evtp); - this->dump_response(evtp); - break; - case EXOSIP_CALL_ANSWERED:// 7 - LOG_INFO("EXOSIP_CALL_ANSWERED type={}: The server receives an invite (SDP) confirmation reply from the client", evtp->type); - this->dump_request(evtp); - this->dump_response(evtp); - - this->response_invite_ack(evtp); - break; - case EXOSIP_CALL_SERVERFAILURE: - LOG_INFO("EXOSIP_CALL_SERVERFAILURE type={}", evtp->type); - break; - case EXOSIP_IN_SUBSCRIPTION_NEW: - LOG_INFO("EXOSIP_IN_SUBSCRIPTION_NEW type={}", evtp->type); - break; - default: - LOG_INFO("type={} unknown", evtp->type); - break; - } - - return 0; -} - -int SipServer::init_sip_server() { - mSipCtx = eXosip_malloc(); - if (!mSipCtx) { - LOG_ERROR("eXosip_malloc error"); - return -1; - } - if (eXosip_init(mSipCtx)) { - LOG_ERROR("eXosip_init error"); - return -1; - } - if (eXosip_listen_addr(mSipCtx, IPPROTO_UDP, nullptr, mInfo.getPort(), AF_INET, 0)) { - LOG_ERROR("eXosip_listen_addr error"); - return -1; - } - eXosip_set_user_agent(mSipCtx, mInfo.getUa().c_str()); - if (eXosip_add_authentication_info(mSipCtx, mInfo.getSipId().c_str(), mInfo.getSipId().c_str(), mInfo.getSipPass().c_str(), NULL, mInfo.getSipRealm().c_str())) { - LOG_ERROR("eXosip_add_authentication_info error"); - return -1; - } - - return 0; -} - -void SipServer::Start() { - m_event_loop_thread = new std::thread(event_loop_thread, this); -} - -void SipServer::event_loop() { - - if(this->init_sip_server() !=0 ){ - return; - } - while(!mQuit) { - eXosip_event_t *evtp = eXosip_event_wait(mSipCtx, 0, 20); - if (!evtp){ - eXosip_automatic_action(mSipCtx); - osip_usleep(100000); - continue; - } - eXosip_automatic_action(mSipCtx); - this->sip_event_handle(evtp); - eXosip_event_free(evtp); - } -} - -void SipServer::response_message_answer(eXosip_event_t *evtp,int code){ - - int returnCode = 0 ; - osip_message_t * pRegister = nullptr; - returnCode = eXosip_message_build_answer (mSipCtx,evtp->tid,code,&pRegister); - bool bRegister = false; - if(pRegister){ - bRegister = true; - } - if (returnCode == 0 && bRegister) - { - eXosip_lock(mSipCtx); - eXosip_message_send_answer (mSipCtx,evtp->tid,code,pRegister); - eXosip_unlock(mSipCtx); - } - else{ - LOG_ERROR("code={},returnCode={},bRegister={}",code,returnCode,bRegister); - } - -} -void SipServer::response_register(eXosip_event_t *evtp) { - - - osip_authorization_t * auth = nullptr; - osip_message_get_authorization(evtp->request, 0, &auth); - - if(auth && auth->username){ - - char *method = NULL, // REGISTER - *algorithm = NULL, // MD5 - *username = NULL,// 340200000013200000024 - *realm = NULL, // sip服务器传给客户端,客户端携带并提交上来的sip服务域 - *nonce = NULL, //sip服务器传给客户端,客户端携带并提交上来的nonce - *nonce_count = NULL, - *uri = NULL; // sip:34020000002000000001@3402000000 - - osip_contact_t *contact = nullptr; - osip_message_get_contact (evtp->request, 0, &contact); - - method = evtp->request->sip_method; - char calc_response[HASHHEXLEN]; - HASHHEX HA1, HA2 = "", Response; - -#define SIP_STRDUP(field) if (auth->field) (field) = osip_strdup_without_quote(auth->field) - - SIP_STRDUP(algorithm); - SIP_STRDUP(username); - SIP_STRDUP(realm); - SIP_STRDUP(nonce); - SIP_STRDUP(nonce_count); - SIP_STRDUP(uri); - - DigestCalcHA1(algorithm, username, realm, mInfo.getSipPass().c_str(), nonce, nonce_count, HA1); - DigestCalcResponse(HA1, nonce, nonce_count, auth->cnonce, auth->message_qop, 0, method, uri, HA2, Response); - - HASHHEX temp_HA1; - HASHHEX temp_response; - DigestCalcHA1("REGISTER", username, mInfo.getSipRealm().c_str(), mInfo.getSipPass().c_str(), mInfo.getNonce().c_str(), NULL, temp_HA1); - DigestCalcResponse(temp_HA1, mInfo.getNonce().c_str(), NULL, NULL, NULL, 0, method, uri, NULL, temp_response); - memcpy(calc_response, temp_response, HASHHEXLEN); - - - - if (!memcmp(calc_response, Response, HASHHEXLEN)) { - this->response_message_answer(evtp,200); - - Client* client = new Client(strdup(contact->url->host), - atoi(contact->url->port), - strdup(username)); - - LOG_INFO("Camera registration succee,ip={},port={},device={}",client->getIp(),client->getPort(),client->getDevice()); - - mClientMap.insert(std::make_pair(client->getDevice(),client)); - - //this->request_invite(client); - - } else { - this->response_message_answer(evtp,401); - LOG_INFO("Camera registration error, p={},port={},device={}", strdup(contact->url->host), atoi(contact->url->port), strdup(username)); - } - - osip_free(algorithm); - osip_free(username); - osip_free(realm); - osip_free(nonce); - osip_free(nonce_count); - osip_free(uri); - } else { - response_register_401unauthorized(evtp); - } - -} - -void SipServer::response_register_401unauthorized(eXosip_event_t *evtp) { - - char *dest = nullptr; - osip_message_t * reg = nullptr; - osip_www_authenticate_t * header = nullptr; - - osip_www_authenticate_init(&header); - osip_www_authenticate_set_auth_type (header, osip_strdup("Digest")); - osip_www_authenticate_set_realm(header,osip_enquote(mInfo.getSipRealm().c_str())); - osip_www_authenticate_set_nonce(header,osip_enquote(mInfo.getNonce().c_str())); - osip_www_authenticate_to_str(header, &dest); - int ret = eXosip_message_build_answer (mSipCtx, evtp->tid, 401, ®); - if ( ret == 0 && reg != nullptr ) { - osip_message_set_www_authenticate(reg, dest); - osip_message_set_content_type(reg, "Application/MANSCDP+xml"); - eXosip_lock(mSipCtx); - eXosip_message_send_answer (mSipCtx, evtp->tid,401, reg); - eXosip_unlock(mSipCtx); - LOG_INFO("response_register_401unauthorized success"); - }else { - LOG_INFO("response_register_401unauthorized error"); - } - - osip_www_authenticate_free(header); - osip_free(dest); - -} - -void SipServer::response_message(eXosip_event_t *evtp) { - - osip_body_t* body = nullptr; - char CmdType[64] = {0}; - char DeviceID[64] = {0}; - osip_message_get_body(evtp->request, 0, &body); - if(body){ - parse_xml(body->body, "", false, "", false, CmdType); - parse_xml(body->body, "", false, "", false, DeviceID); - } - -// Client *client = getClientByDevice(DeviceID); -// if(client){ -// LOG_INFO("response_message:{} 已注册",DeviceID); -// }else{ -// LOG_ERROR("response_message:{} 未注册",DeviceID); -// } - LOG_INFO("CmdType={},DeviceID={}", CmdType, DeviceID); - - if(!strcmp(CmdType, "Catalog")) { - this->response_message_answer(evtp,200); - // 需要根据对方的Catelog请求,做一些相应的应答请求 - CCatalogParser catPaser; - m_vec_device = catPaser.Decode_Catlog(body->body); - } - else if(!strcmp(CmdType, "Keepalive")){ - this->response_message_answer(evtp,200); - }else{ - this->response_message_answer(evtp,200); - } - -} - -void SipServer::response_invite_ack(eXosip_event_t *evtp){ - - osip_message_t* msg = nullptr; - int ret = eXosip_call_build_ack(mSipCtx, evtp->did, &msg); - if (!ret && msg) { - eXosip_call_send_ack(mSipCtx, evtp->did, msg); - } else { - LOG_ERROR("eXosip_call_send_ack error={}", ret); - } - -} -int SipServer::request_bye(eXosip_event_t* evtp) { - - eXosip_lock(mSipCtx); - int ret = eXosip_call_terminate(mSipCtx, evtp->cid, evtp->did); - eXosip_unlock(mSipCtx); - - return ret; -} - -int SipServer::RequestInvite(Client* client, const DeviceInfo& device) { - LOG_INFO("INVITE"); - - char session_exp[1024] = { 0 }; - osip_message_t* msg = nullptr; - char from[1024] = { 0 }; - char to[1024] = { 0 }; - char sdp[2048] = { 0 }; - char head[1024] = { 0 }; - - const char* dest_channel = "34020000001320000001"; - const char* nvr_ip = "192.168.60.82"; - const char* nvr_port = "5060"; - - sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort()); - sprintf(to, "sip:%s@%s:%d", dest_channel, client->getIp().c_str(), client->getPort()); - snprintf(sdp, 2048, - "v=0\r\n" - "o=%s 0 0 IN IP4 %s\r\n" - "s=Play\r\n" - "c=IN IP4 %s\r\n" - "t=0 0\r\n" - "m=video %d RTP/AVP 96 98 97\r\n" - "a=recvonly\r\n" - "a=rtpmap:96 PS/90000\r\n" - "a=rtpmap:98 H264/90000\r\n" - "a=rtpmap:97 MPEG4/90000\r\n" - "a=setup:passive\r\n" - "a=connection:new\r\n" - "y=0100000001\r\n" - "f=\r\n", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getIp().c_str(), mInfo.getRtpPort()); - - int ret = eXosip_call_build_initial_invite(mSipCtx, &msg, to, from, nullptr, nullptr); - if (ret) { - LOG_ERROR("eXosip_call_build_initial_invite error: {} {} ret:{}", from, to, ret); - return -1; - } - - osip_message_set_body(msg, sdp, strlen(sdp)); - osip_message_set_content_type(msg, "application/sdp"); - snprintf(session_exp, sizeof(session_exp) - 1, "%i;refresher=uac", mInfo.getTimeout()); - osip_message_set_header(msg, "Session-Expires", session_exp); - osip_message_set_supported(msg, "timer"); - - int call_id = eXosip_call_send_initial_invite(mSipCtx, msg); - if (call_id > 0) { - LOG_INFO("eXosip_call_send_initial_invite success: call_id={}", call_id); - } - else { - LOG_ERROR("eXosip_call_send_initial_invite error: call_id={}", call_id); - } - return ret; -} - -void SipServer::RequestCatlog(Client* client) { - - eXosip_lock(mSipCtx); - - osip_message_t* catlog_msg = NULL; - char to[100];/*sip:主叫用户名@被叫IP地址*/ - char from[100];/*sip:被叫IP地址:被叫IP端口*/ - char xml_body[4096]; - - memset(to, 0, 100); - memset(from, 0, 100); - memset(xml_body, 0, 4096); - - sprintf(from, "sip:%s@%s:%d", mInfo.getSipId().c_str(), mInfo.getIp().c_str(), mInfo.getPort()); - sprintf(to, "sip:%s@%s:%d", client->getDevice().c_str(), client->getIp().c_str(), client->getPort()); - eXosip_message_build_request(mSipCtx, &catlog_msg, "MESSAGE", to, from, NULL);/*构建"MESSAGE"请求*/ - - snprintf(xml_body, 4096, - "" - "" - "Catalog" - "%d" - "%s" - "", rand() % (99999 - 10000 + 1) + 10000, client->getDevice().c_str()); - - osip_message_set_body(catlog_msg, xml_body, strlen(xml_body)); - osip_message_set_content_type(catlog_msg, "Application/MANSCDP+xml"); - eXosip_message_send_request(mSipCtx, catlog_msg); - - eXosip_unlock(mSipCtx); -} - -int SipServer::clearClientMap(){ - for (auto iter=mClientMap.begin(); iter!=mClientMap.end(); iter++) { - delete iter->second; - iter->second = nullptr; - } - mClientMap.clear(); - - return 0; -} - -Client * SipServer::GetClientByDevice(string device) { - auto it = mClientMap.find(device); - if(it == mClientMap.end()){ - return nullptr; - } - return it->second; -} - -void SipServer::DeleteClientByDevice(string device) { - auto it = mClientMap.find(device); - if (it == mClientMap.end()) { - return ; - } - delete it->second; - it->second = nullptr; - mClientMap.erase(it); -} - -std::map SipServer::GetClientMap() { - return mClientMap; -} - -std::vector< DeviceInfo > SipServer::GetDeviceList() { - return m_vec_device; -} - -int SipServer::parse_xml(const char *data, const char *s_mark, bool with_s_make, const char *e_mark, bool with_e_make, char *dest) { - const char* satrt = strstr( data, s_mark ); - - if(satrt != NULL) { - const char* end = strstr(satrt, e_mark); - - if(end != NULL){ - int s_pos = with_s_make ? 0 : strlen(s_mark); - int e_pos = with_e_make ? strlen(e_mark) : 0; - - strncpy( dest, satrt+s_pos, (end+e_pos) - (satrt+s_pos) ); - } - return 0; - } - return -1; - -} -void SipServer::dump_request(eXosip_event_t *evtp) { - char *s; - size_t len; - osip_message_to_str(evtp->request, &s, &len); - LOG_INFO("\nprint request start\ntype={}\n{}\nprint request end\n",evtp->type,s); -} -void SipServer::dump_response(eXosip_event_t *evtp) { - char *s; - size_t len; - osip_message_to_str(evtp->response, &s, &len); - LOG_INFO("\nprint response start\ntype={}\n{}\nprint response end\n",evtp->type,s); -} \ No newline at end of file diff --git a/src/decoder/sip/src/SipServer.h b/src/decoder/sip/src/SipServer.h deleted file mode 100644 index a6a2fc8..0000000 --- a/src/decoder/sip/src/SipServer.h +++ /dev/null @@ -1,170 +0,0 @@ -// -// Created bxc on 2022/11/25. -// - -#ifndef BXC_SIPSERVER_SIPSERVER_H -#define BXC_SIPSERVER_SIPSERVER_H -extern "C" { -#include -#include -} -#include -#include -#include -#include - -#include "../Message/CatalogParser.h" - -using namespace std; - -class ServerInfo { -public: - ServerInfo() {} - - ServerInfo(string ua,string nonce, string ip, int port, int rtpPort, - string sipId, string sipRealm, string sipPass, int sipTimeout, int sipExpiry): - mUa(ua), - mNonce(nonce),mIp(ip),mPort(port),mRtpPort(rtpPort),mSipId(sipId), - mSipRealm(sipRealm),mSipPass(sipPass),mSipTimeout(sipTimeout), - mSipExpiry(sipExpiry){} - - ~ServerInfo() = default; -public: - string getUa() const{ - return mUa; - } - string getNonce() const{ - return mNonce; - } - string getIp() const{ - return mIp; - } - int getPort() const { - return mPort; - } - int getRtpPort() const { - return mRtpPort; - } - string getSipId() const{ - return mSipId; - } - string getSipRealm() const{ - return mSipRealm; - } - string getSipPass() const{ - return mSipPass; - } - int getTimeout() const { - return mSipTimeout; - } - int getExpiry() const { - return mSipExpiry; - } - -private: - string mUa; - string mNonce;//SIP服务随机数值 - string mIp;//SIP服务IP - int mPort;//SIP服务端口 - string mSipId; //SIP服务器ID - string mSipRealm;//SIP服务器域 - string mSipPass;//SIP password - int mSipTimeout; //SIP timeout - int mSipExpiry;// SIP到期 - int mRtpPort; //SIP-RTP服务端口 -}; - -class Client { -public: - Client(string ip, int port, string device) : - mIp(ip), - mPort(port), - mRtpPort(0), - mDevice(device), - mIsReg(false){ - } - ~Client() = default; -public: - - void setRtpPort(int rtpPort) { - mRtpPort = rtpPort; - } - - void setReg(bool isReg) { - mIsReg = isReg; - } - string getDevice() const{ - return mDevice; - } - string getIp() const{ - return mIp; - } - int getPort() const{ - return mPort; - } - -private: - // step1 - string mIp; // client ip - int mPort; // client port - string mDevice;// 340200000013200000024 - // step2 - bool mIsReg; - // step3 - int mRtpPort{}; - -}; - - -class SipServer { -public: - SipServer(); - ~SipServer(); -public: - bool Init(ServerInfo info); - void Start(); - - Client* GetClientByDevice(string device); - void DeleteClientByDevice(string device); - - std::vector< DeviceInfo > GetDeviceList(); - - std::map GetClientMap(); - - int RequestInvite(Client* client, const DeviceInfo& device); - - void RequestCatlog(Client* client); - -public: - void event_loop(); - -private: - int init_sip_server(); - int sip_event_handle(eXosip_event_t *evtp); - - void response_message_answer(eXosip_event_t *evtp,int code); - void response_register(eXosip_event_t *evtp); - void response_register_401unauthorized(eXosip_event_t *evt); - void response_message(eXosip_event_t *evtp); - void response_invite_ack(eXosip_event_t *evtp); - int request_bye(eXosip_event_t* evtp);// 通知相机停止推流 - int parse_xml(const char* data, const char* s_mark, bool with_s_make, const char* e_mark, bool with_e_make, char* dest); - void dump_request(eXosip_event_t *evtp); - void dump_response(eXosip_event_t *evtp); - - int clearClientMap(); - -private: - bool mQuit{ false }; - eXosip_t *mSipCtx; - ServerInfo mInfo; - - std::map mClientMap;// - - std::vector< DeviceInfo > m_vec_device; - - thread* m_event_loop_thread; -}; - - -#endif //BXC_SIPSERVER_SIPSERVER_H diff --git a/src/decoder/sip/src/main.cpp b/src/decoder/sip/src/main.cpp deleted file mode 100644 index c1f0520..0000000 --- a/src/decoder/sip/src/main.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// -// Created bxc on 2022/11/25. -// - -#include "SipServer.h" - -#include -#include -#include - -using namespace std; - -int main(int argc, char *argv[]) { - - ServerInfo info( - "SY_SipServer", - "12345678", - "192.168.60.179", - 15061, - 30026, - "34020000002000000002", - "3402000000", - "sy123456", - 1800, - 3600); - - SipServer sipServer; - sipServer.Init(info); - sipServer.Start(); - - std::this_thread::sleep_for(std::chrono::seconds(5)); - - std::map client_map; - std::vector< DeviceInfo > vec_device; - char oper = 'g'; - while (oper != 'q') { - oper = getchar(); - switch (oper) - { - case 'g': - client_map = sipServer.GetClientMap(); - if (client_map.size() <= 0) - { - cout << "no IPC" << endl; - } - else { - cout << "client size:" << client_map.size() << endl; - } - break; - case 'i': - vec_device = sipServer.GetDeviceList(); - if (vec_device.size() <= 0) - { - cout << "no device" << endl; - break; - } - - if (client_map.size() <= 0) - { - cout << "no IPC" << endl; - } - else { - auto it = client_map.begin(); - sipServer.RequestInvite(it->second, vec_device[0]); - } - break; - case 'b': - break; - case 'c': - if (client_map.size() <= 0) - { - cout << "no IPC" << endl; - } - else { - auto it = client_map.begin(); - sipServer.RequestCatlog(it->second); - } - break; - default: - break; - } - } - - return 0; -} \ No newline at end of file diff --git a/src/decoder/sip/tinyxml2/tinyxml2.cpp b/src/decoder/sip/tinyxml2/tinyxml2.cpp deleted file mode 100644 index 89b7913..0000000 --- a/src/decoder/sip/tinyxml2/tinyxml2.cpp +++ /dev/null @@ -1,2826 +0,0 @@ -/* -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include "tinyxml2.h" - -#include // yes, this one new style header, is in the Android SDK. -#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) -# include -# include -#else -# include -# include -#endif - -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) - // Microsoft Visual Studio, version 2005 and higher. Not WinCE. - /*int _snprintf_s( - char *buffer, - size_t sizeOfBuffer, - size_t count, - const char *format [, - argument] ... - );*/ - static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) - { - va_list va; - va_start( va, format ); - int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); - va_end( va ); - return result; - } - - static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va ) - { - int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); - return result; - } - - #define TIXML_VSCPRINTF _vscprintf - #define TIXML_SSCANF sscanf_s -#elif defined _MSC_VER - // Microsoft Visual Studio 2003 and earlier or WinCE - #define TIXML_SNPRINTF _snprintf - #define TIXML_VSNPRINTF _vsnprintf - #define TIXML_SSCANF sscanf - #if (_MSC_VER < 1400 ) && (!defined WINCE) - // Microsoft Visual Studio 2003 and not WinCE. - #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have. - #else - // Microsoft Visual Studio 2003 and earlier or WinCE. - static inline int TIXML_VSCPRINTF( const char* format, va_list va ) - { - int len = 512; - for (;;) { - len = len*2; - char* str = new char[len](); - const int required = _vsnprintf(str, len, format, va); - delete[] str; - if ( required != -1 ) { - TIXMLASSERT( required >= 0 ); - len = required; - break; - } - } - TIXMLASSERT( len >= 0 ); - return len; - } - #endif -#else - // GCC version 3 and higher - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_VSNPRINTF vsnprintf - static inline int TIXML_VSCPRINTF( const char* format, va_list va ) - { - int len = vsnprintf( 0, 0, format, va ); - TIXMLASSERT( len >= 0 ); - return len; - } - #define TIXML_SSCANF sscanf -#endif - - -static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF -static const char LF = LINE_FEED; -static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out -static const char CR = CARRIAGE_RETURN; -static const char SINGLE_QUOTE = '\''; -static const char DOUBLE_QUOTE = '\"'; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// ef bb bf (Microsoft "lead bytes") - designates UTF-8 - -static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -namespace tinyxml2 -{ - -struct Entity { - const char* pattern; - int length; - char value; -}; - -static const int NUM_ENTITIES = 5; -static const Entity entities[NUM_ENTITIES] = { - { "quot", 4, DOUBLE_QUOTE }, - { "amp", 3, '&' }, - { "apos", 4, SINGLE_QUOTE }, - { "lt", 2, '<' }, - { "gt", 2, '>' } -}; - - -StrPair::~StrPair() -{ - Reset(); -} - - -void StrPair::TransferTo( StrPair* other ) -{ - if ( this == other ) { - return; - } - // This in effect implements the assignment operator by "moving" - // ownership (as in auto_ptr). - - TIXMLASSERT( other != 0 ); - TIXMLASSERT( other->_flags == 0 ); - TIXMLASSERT( other->_start == 0 ); - TIXMLASSERT( other->_end == 0 ); - - other->Reset(); - - other->_flags = _flags; - other->_start = _start; - other->_end = _end; - - _flags = 0; - _start = 0; - _end = 0; -} - - -void StrPair::Reset() -{ - if ( _flags & NEEDS_DELETE ) { - delete [] _start; - } - _flags = 0; - _start = 0; - _end = 0; -} - - -void StrPair::SetStr( const char* str, int flags ) -{ - TIXMLASSERT( str ); - Reset(); - size_t len = strlen( str ); - TIXMLASSERT( _start == 0 ); - _start = new char[ len+1 ]; - memcpy( _start, str, len+1 ); - _end = _start + len; - _flags = flags | NEEDS_DELETE; -} - - -char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr ) -{ - TIXMLASSERT( p ); - TIXMLASSERT( endTag && *endTag ); - TIXMLASSERT(curLineNumPtr); - - char* start = p; - char endChar = *endTag; - size_t length = strlen( endTag ); - - // Inner loop of text parsing. - while ( *p ) { - if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { - Set( start, p, strFlags ); - return p + length; - } else if (*p == '\n') { - ++(*curLineNumPtr); - } - ++p; - TIXMLASSERT( p ); - } - return 0; -} - - -char* StrPair::ParseName( char* p ) -{ - if ( !p || !(*p) ) { - return 0; - } - if ( !XMLUtil::IsNameStartChar( *p ) ) { - return 0; - } - - char* const start = p; - ++p; - while ( *p && XMLUtil::IsNameChar( *p ) ) { - ++p; - } - - Set( start, p, 0 ); - return p; -} - - -void StrPair::CollapseWhitespace() -{ - // Adjusting _start would cause undefined behavior on delete[] - TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); - // Trim leading space. - _start = XMLUtil::SkipWhiteSpace( _start, 0 ); - - if ( *_start ) { - const char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( *p ) { - if ( XMLUtil::IsWhiteSpace( *p )) { - p = XMLUtil::SkipWhiteSpace( p, 0 ); - if ( *p == 0 ) { - break; // don't write to q; this trims the trailing space. - } - *q = ' '; - ++q; - } - *q = *p; - ++q; - ++p; - } - *q = 0; - } -} - - -const char* StrPair::GetStr() -{ - TIXMLASSERT( _start ); - TIXMLASSERT( _end ); - if ( _flags & NEEDS_FLUSH ) { - *_end = 0; - _flags ^= NEEDS_FLUSH; - - if ( _flags ) { - const char* p = _start; // the read pointer - char* q = _start; // the write pointer - - while( p < _end ) { - if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { - // CR-LF pair becomes LF - // CR alone becomes LF - // LF-CR becomes LF - if ( *(p+1) == LF ) { - p += 2; - } - else { - ++p; - } - *q = LF; - ++q; - } - else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { - if ( *(p+1) == CR ) { - p += 2; - } - else { - ++p; - } - *q = LF; - ++q; - } - else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { - // Entities handled by tinyXML2: - // - special entities in the entity table [in/out] - // - numeric character reference [in] - // 中 or 中 - - if ( *(p+1) == '#' ) { - const int buflen = 10; - char buf[buflen] = { 0 }; - int len = 0; - char* adjusted = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); - if ( adjusted == 0 ) { - *q = *p; - ++p; - ++q; - } - else { - TIXMLASSERT( 0 <= len && len <= buflen ); - TIXMLASSERT( q + len <= adjusted ); - p = adjusted; - memcpy( q, buf, len ); - q += len; - } - } - else { - bool entityFound = false; - for( int i = 0; i < NUM_ENTITIES; ++i ) { - const Entity& entity = entities[i]; - if ( strncmp( p + 1, entity.pattern, entity.length ) == 0 - && *( p + entity.length + 1 ) == ';' ) { - // Found an entity - convert. - *q = entity.value; - ++q; - p += entity.length + 2; - entityFound = true; - break; - } - } - if ( !entityFound ) { - // fixme: treat as error? - ++p; - ++q; - } - } - } - else { - *q = *p; - ++p; - ++q; - } - } - *q = 0; - } - // The loop below has plenty going on, and this - // is a less useful mode. Break it out. - if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) { - CollapseWhitespace(); - } - _flags = (_flags & NEEDS_DELETE); - } - TIXMLASSERT( _start ); - return _start; -} - - - - -// --------- XMLUtil ----------- // - -const char* XMLUtil::writeBoolTrue = "true"; -const char* XMLUtil::writeBoolFalse = "false"; - -void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) -{ - static const char* defTrue = "true"; - static const char* defFalse = "false"; - - writeBoolTrue = (writeTrue) ? writeTrue : defTrue; - writeBoolFalse = (writeFalse) ? writeFalse : defFalse; -} - - -const char* XMLUtil::ReadBOM( const char* p, bool* bom ) -{ - TIXMLASSERT( p ); - TIXMLASSERT( bom ); - *bom = false; - const unsigned char* pu = reinterpret_cast(p); - // Check for BOM: - if ( *(pu+0) == TIXML_UTF_LEAD_0 - && *(pu+1) == TIXML_UTF_LEAD_1 - && *(pu+2) == TIXML_UTF_LEAD_2 ) { - *bom = true; - p += 3; - } - TIXMLASSERT( p ); - return p; -} - - -void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) { - *length = 1; - } - else if ( input < 0x800 ) { - *length = 2; - } - else if ( input < 0x10000 ) { - *length = 3; - } - else if ( input < 0x200000 ) { - *length = 4; - } - else { - *length = 0; // This code won't convert this correctly anyway. - return; - } - - output += *length; - - // Scary scary fall throughs are annotated with carefully designed comments - // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc - switch (*length) { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - //fall through - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - break; - default: - TIXMLASSERT( false ); - } -} - - -const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) -{ - // Presume an entity, and pull it out. - *length = 0; - - if ( *(p+1) == '#' && *(p+2) ) { - unsigned long ucs = 0; - TIXMLASSERT( sizeof( ucs ) >= 4 ); - ptrdiff_t delta = 0; - unsigned mult = 1; - static const char SEMICOLON = ';'; - - if ( *(p+2) == 'x' ) { - // Hexadecimal. - const char* q = p+3; - if ( !(*q) ) { - return 0; - } - - q = strchr( q, SEMICOLON ); - - if ( !q ) { - return 0; - } - TIXMLASSERT( *q == SEMICOLON ); - - delta = q-p; - --q; - - while ( *q != 'x' ) { - unsigned int digit = 0; - - if ( *q >= '0' && *q <= '9' ) { - digit = *q - '0'; - } - else if ( *q >= 'a' && *q <= 'f' ) { - digit = *q - 'a' + 10; - } - else if ( *q >= 'A' && *q <= 'F' ) { - digit = *q - 'A' + 10; - } - else { - return 0; - } - TIXMLASSERT( digit < 16 ); - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); - const unsigned int digitScaled = mult * digit; - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); - ucs += digitScaled; - TIXMLASSERT( mult <= UINT_MAX / 16 ); - mult *= 16; - --q; - } - } - else { - // Decimal. - const char* q = p+2; - if ( !(*q) ) { - return 0; - } - - q = strchr( q, SEMICOLON ); - - if ( !q ) { - return 0; - } - TIXMLASSERT( *q == SEMICOLON ); - - delta = q-p; - --q; - - while ( *q != '#' ) { - if ( *q >= '0' && *q <= '9' ) { - const unsigned int digit = *q - '0'; - TIXMLASSERT( digit < 10 ); - TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); - const unsigned int digitScaled = mult * digit; - TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); - ucs += digitScaled; - } - else { - return 0; - } - TIXMLASSERT( mult <= UINT_MAX / 10 ); - mult *= 10; - --q; - } - } - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - return p + delta + 1; - } - return p+1; -} - - -void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); -} - - -void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); -} - - -void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); -} - -/* - ToStr() of a number is a very tricky topic. - https://github.com/leethomason/tinyxml2/issues/106 -*/ -void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); -} - - -void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) -{ - TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); -} - - -void XMLUtil::ToStr(int64_t v, char* buffer, int bufferSize) -{ - // horrible syntax trick to make the compiler happy about %lld - TIXML_SNPRINTF(buffer, bufferSize, "%lld", (long long)v); -} - - -bool XMLUtil::ToInt( const char* str, int* value ) -{ - if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) -{ - if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { - return true; - } - return false; -} - -bool XMLUtil::ToBool( const char* str, bool* value ) -{ - int ival = 0; - if ( ToInt( str, &ival )) { - *value = (ival==0) ? false : true; - return true; - } - if ( StringEqual( str, "true" ) ) { - *value = true; - return true; - } - else if ( StringEqual( str, "false" ) ) { - *value = false; - return true; - } - return false; -} - - -bool XMLUtil::ToFloat( const char* str, float* value ) -{ - if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { - return true; - } - return false; -} - - -bool XMLUtil::ToDouble( const char* str, double* value ) -{ - if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { - return true; - } - return false; -} - - -bool XMLUtil::ToInt64(const char* str, int64_t* value) -{ - long long v = 0; // horrible syntax trick to make the compiler happy about %lld - if (TIXML_SSCANF(str, "%lld", &v) == 1) { - *value = (int64_t)v; - return true; - } - return false; -} - - -char* XMLDocument::Identify( char* p, XMLNode** node ) -{ - TIXMLASSERT( node ); - TIXMLASSERT( p ); - char* const start = p; - int const startLine = _parseCurLineNum; - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); - if( !*p ) { - *node = 0; - TIXMLASSERT( p ); - return p; - } - - // These strings define the matching patterns: - static const char* xmlHeader = { "( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += xmlHeaderLen; - } - else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { - returnNode = CreateUnlinkedNode( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += commentHeaderLen; - } - else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { - XMLText* text = CreateUnlinkedNode( _textPool ); - returnNode = text; - returnNode->_parseLineNum = _parseCurLineNum; - p += cdataHeaderLen; - text->SetCData( true ); - } - else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { - returnNode = CreateUnlinkedNode( _commentPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += dtdHeaderLen; - } - else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { - returnNode = CreateUnlinkedNode( _elementPool ); - returnNode->_parseLineNum = _parseCurLineNum; - p += elementHeaderLen; - } - else { - returnNode = CreateUnlinkedNode( _textPool ); - returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character - p = start; // Back it up, all the text counts. - _parseCurLineNum = startLine; - } - - TIXMLASSERT( returnNode ); - TIXMLASSERT( p ); - *node = returnNode; - return p; -} - - -bool XMLDocument::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - if ( visitor->VisitEnter( *this ) ) { - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { - if ( !node->Accept( visitor ) ) { - break; - } - } - } - return visitor->VisitExit( *this ); -} - - -// --------- XMLNode ----------- // - -XMLNode::XMLNode( XMLDocument* doc ) : - _document( doc ), - _parent( 0 ), - _value(), - _parseLineNum( 0 ), - _firstChild( 0 ), _lastChild( 0 ), - _prev( 0 ), _next( 0 ), - _userData( 0 ), - _memPool( 0 ) -{ -} - - -XMLNode::~XMLNode() -{ - DeleteChildren(); - if ( _parent ) { - _parent->Unlink( this ); - } -} - -const char* XMLNode::Value() const -{ - // Edge case: XMLDocuments don't have a Value. Return null. - if ( this->ToDocument() ) - return 0; - return _value.GetStr(); -} - -void XMLNode::SetValue( const char* str, bool staticMem ) -{ - if ( staticMem ) { - _value.SetInternedStr( str ); - } - else { - _value.SetStr( str ); - } -} - -XMLNode* XMLNode::DeepClone(XMLDocument* target) const -{ - XMLNode* clone = this->ShallowClone(target); - if (!clone) return 0; - - for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) { - XMLNode* childClone = child->DeepClone(target); - TIXMLASSERT(childClone); - clone->InsertEndChild(childClone); - } - return clone; -} - -void XMLNode::DeleteChildren() -{ - while( _firstChild ) { - TIXMLASSERT( _lastChild ); - DeleteChild( _firstChild ); - } - _firstChild = _lastChild = 0; -} - - -void XMLNode::Unlink( XMLNode* child ) -{ - TIXMLASSERT( child ); - TIXMLASSERT( child->_document == _document ); - TIXMLASSERT( child->_parent == this ); - if ( child == _firstChild ) { - _firstChild = _firstChild->_next; - } - if ( child == _lastChild ) { - _lastChild = _lastChild->_prev; - } - - if ( child->_prev ) { - child->_prev->_next = child->_next; - } - if ( child->_next ) { - child->_next->_prev = child->_prev; - } - child->_next = 0; - child->_prev = 0; - child->_parent = 0; -} - - -void XMLNode::DeleteChild( XMLNode* node ) -{ - TIXMLASSERT( node ); - TIXMLASSERT( node->_document == _document ); - TIXMLASSERT( node->_parent == this ); - Unlink( node ); - TIXMLASSERT(node->_prev == 0); - TIXMLASSERT(node->_next == 0); - TIXMLASSERT(node->_parent == 0); - DeleteNode( node ); -} - - -XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - InsertChildPreamble( addThis ); - - if ( _lastChild ) { - TIXMLASSERT( _firstChild ); - TIXMLASSERT( _lastChild->_next == 0 ); - _lastChild->_next = addThis; - addThis->_prev = _lastChild; - _lastChild = addThis; - - addThis->_next = 0; - } - else { - TIXMLASSERT( _firstChild == 0 ); - _firstChild = _lastChild = addThis; - - addThis->_prev = 0; - addThis->_next = 0; - } - addThis->_parent = this; - return addThis; -} - - -XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - InsertChildPreamble( addThis ); - - if ( _firstChild ) { - TIXMLASSERT( _lastChild ); - TIXMLASSERT( _firstChild->_prev == 0 ); - - _firstChild->_prev = addThis; - addThis->_next = _firstChild; - _firstChild = addThis; - - addThis->_prev = 0; - } - else { - TIXMLASSERT( _lastChild == 0 ); - _firstChild = _lastChild = addThis; - - addThis->_prev = 0; - addThis->_next = 0; - } - addThis->_parent = this; - return addThis; -} - - -XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) -{ - TIXMLASSERT( addThis ); - if ( addThis->_document != _document ) { - TIXMLASSERT( false ); - return 0; - } - - TIXMLASSERT( afterThis ); - - if ( afterThis->_parent != this ) { - TIXMLASSERT( false ); - return 0; - } - if ( afterThis == addThis ) { - // Current state: BeforeThis -> AddThis -> OneAfterAddThis - // Now AddThis must disappear from it's location and then - // reappear between BeforeThis and OneAfterAddThis. - // So just leave it where it is. - return addThis; - } - - if ( afterThis->_next == 0 ) { - // The last node or the only node. - return InsertEndChild( addThis ); - } - InsertChildPreamble( addThis ); - addThis->_prev = afterThis; - addThis->_next = afterThis->_next; - afterThis->_next->_prev = addThis; - afterThis->_next = addThis; - addThis->_parent = this; - return addThis; -} - - - - -const XMLElement* XMLNode::FirstChildElement( const char* name ) const -{ - for( const XMLNode* node = _firstChild; node; node = node->_next ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::LastChildElement( const char* name ) const -{ - for( const XMLNode* node = _lastChild; node; node = node->_prev ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::NextSiblingElement( const char* name ) const -{ - for( const XMLNode* node = _next; node; node = node->_next ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const -{ - for( const XMLNode* node = _prev; node; node = node->_prev ) { - const XMLElement* element = node->ToElementWithName( name ); - if ( element ) { - return element; - } - } - return 0; -} - - -char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) -{ - // This is a recursive method, but thinking about it "at the current level" - // it is a pretty simple flat list: - // - // - // - // With a special case: - // - // - // - // - // Where the closing element (/foo) *must* be the next thing after the opening - // element, and the names must match. BUT the tricky bit is that the closing - // element will be read by the child. - // - // 'endTag' is the end tag for this node, it is returned by a call to a child. - // 'parentEnd' is the end tag for the parent, which is filled in and returned. - - XMLDocument::DepthTracker tracker(_document); - if (_document->Error()) - return 0; - - while( p && *p ) { - XMLNode* node = 0; - - p = _document->Identify( p, &node ); - TIXMLASSERT( p ); - if ( node == 0 ) { - break; - } - - int initialLineNum = node->_parseLineNum; - - StrPair endTag; - p = node->ParseDeep( p, &endTag, curLineNumPtr ); - if ( !p ) { - DeleteNode( node ); - if ( !_document->Error() ) { - _document->SetError( XML_ERROR_PARSING, initialLineNum, 0); - } - break; - } - - XMLDeclaration* decl = node->ToDeclaration(); - if ( decl ) { - // Declarations are only allowed at document level - bool wellLocated = ( ToDocument() != 0 ); - if ( wellLocated ) { - // Multiple declarations are allowed but all declarations - // must occur before anything else - for ( const XMLNode* existingNode = _document->FirstChild(); existingNode; existingNode = existingNode->NextSibling() ) { - if ( !existingNode->ToDeclaration() ) { - wellLocated = false; - break; - } - } - } - if ( !wellLocated ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value()); - DeleteNode( node ); - break; - } - } - - XMLElement* ele = node->ToElement(); - if ( ele ) { - // We read the end tag. Return it to the parent. - if ( ele->ClosingType() == XMLElement::CLOSING ) { - if ( parentEndTag ) { - ele->_value.TransferTo( parentEndTag ); - } - node->_memPool->SetTracked(); // created and then immediately deleted. - DeleteNode( node ); - return p; - } - - // Handle an end tag returned to this level. - // And handle a bunch of annoying errors. - bool mismatch = false; - if ( endTag.Empty() ) { - if ( ele->ClosingType() == XMLElement::OPEN ) { - mismatch = true; - } - } - else { - if ( ele->ClosingType() != XMLElement::OPEN ) { - mismatch = true; - } - else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) { - mismatch = true; - } - } - if ( mismatch ) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name()); - DeleteNode( node ); - break; - } - } - InsertEndChild( node ); - } - return 0; -} - -/*static*/ void XMLNode::DeleteNode( XMLNode* node ) -{ - if ( node == 0 ) { - return; - } - TIXMLASSERT(node->_document); - if (!node->ToDocument()) { - node->_document->MarkInUse(node); - } - - MemPool* pool = node->_memPool; - node->~XMLNode(); - pool->Free( node ); -} - -void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const -{ - TIXMLASSERT( insertThis ); - TIXMLASSERT( insertThis->_document == _document ); - - if (insertThis->_parent) { - insertThis->_parent->Unlink( insertThis ); - } - else { - insertThis->_document->MarkInUse(insertThis); - insertThis->_memPool->SetTracked(); - } -} - -const XMLElement* XMLNode::ToElementWithName( const char* name ) const -{ - const XMLElement* element = this->ToElement(); - if ( element == 0 ) { - return 0; - } - if ( name == 0 ) { - return element; - } - if ( XMLUtil::StringEqual( element->Name(), name ) ) { - return element; - } - return 0; -} - -// --------- XMLText ---------- // -char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - if ( this->CData() ) { - p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_CDATA, _parseLineNum, 0 ); - } - return p; - } - else { - int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; - if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { - flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING; - } - - p = _value.ParseText( p, "<", flags, curLineNumPtr ); - if ( p && *p ) { - return p-1; - } - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_TEXT, _parseLineNum, 0 ); - } - } - return 0; -} - - -XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? - text->SetCData( this->CData() ); - return text; -} - - -bool XMLText::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLText* text = compare->ToText(); - return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); -} - - -bool XMLText::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - - -// --------- XMLComment ---------- // - -XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLComment::~XMLComment() -{ -} - - -char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Comment parses as text. - p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_COMMENT, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? - return comment; -} - - -bool XMLComment::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLComment* comment = compare->ToComment(); - return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); -} - - -bool XMLComment::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - - -// --------- XMLDeclaration ---------- // - -XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLDeclaration::~XMLDeclaration() -{ - //printf( "~XMLDeclaration\n" ); -} - - -char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Declaration parses as text. - p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( p == 0 ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? - return dec; -} - - -bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLDeclaration* declaration = compare->ToDeclaration(); - return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); -} - - - -bool XMLDeclaration::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - -// --------- XMLUnknown ---------- // - -XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) -{ -} - - -XMLUnknown::~XMLUnknown() -{ -} - - -char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) -{ - // Unknown parses as text. - p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); - if ( !p ) { - _document->SetError( XML_ERROR_PARSING_UNKNOWN, _parseLineNum, 0 ); - } - return p; -} - - -XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? - return text; -} - - -bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLUnknown* unknown = compare->ToUnknown(); - return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); -} - - -bool XMLUnknown::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - return visitor->Visit( *this ); -} - -// --------- XMLAttribute ---------- // - -const char* XMLAttribute::Name() const -{ - return _name.GetStr(); -} - -const char* XMLAttribute::Value() const -{ - return _value.GetStr(); -} - -char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr ) -{ - // Parse using the name rules: bug fix, was using ParseText before - p = _name.ParseName( p ); - if ( !p || !*p ) { - return 0; - } - - // Skip white space before = - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( *p != '=' ) { - return 0; - } - - ++p; // move up to opening quote - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( *p != '\"' && *p != '\'' ) { - return 0; - } - - char endTag[2] = { *p, 0 }; - ++p; // move past opening quote - - p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr ); - return p; -} - - -void XMLAttribute::SetName( const char* n ) -{ - _name.SetStr( n ); -} - - -XMLError XMLAttribute::QueryIntValue( int* value ) const -{ - if ( XMLUtil::ToInt( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const -{ - if ( XMLUtil::ToUnsigned( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryInt64Value(int64_t* value) const -{ - if (XMLUtil::ToInt64(Value(), value)) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryBoolValue( bool* value ) const -{ - if ( XMLUtil::ToBool( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryFloatValue( float* value ) const -{ - if ( XMLUtil::ToFloat( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -XMLError XMLAttribute::QueryDoubleValue( double* value ) const -{ - if ( XMLUtil::ToDouble( Value(), value )) { - return XML_SUCCESS; - } - return XML_WRONG_ATTRIBUTE_TYPE; -} - - -void XMLAttribute::SetAttribute( const char* v ) -{ - _value.SetStr( v ); -} - - -void XMLAttribute::SetAttribute( int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute( unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -void XMLAttribute::SetAttribute(int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - _value.SetStr(buf); -} - - - -void XMLAttribute::SetAttribute( bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - -void XMLAttribute::SetAttribute( float v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - _value.SetStr( buf ); -} - - -// --------- XMLElement ---------- // -XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), - _closingType( OPEN ), - _rootAttribute( 0 ) -{ -} - - -XMLElement::~XMLElement() -{ - while( _rootAttribute ) { - XMLAttribute* next = _rootAttribute->_next; - DeleteAttribute( _rootAttribute ); - _rootAttribute = next; - } -} - - -const XMLAttribute* XMLElement::FindAttribute( const char* name ) const -{ - for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { - if ( XMLUtil::StringEqual( a->Name(), name ) ) { - return a; - } - } - return 0; -} - - -const char* XMLElement::Attribute( const char* name, const char* value ) const -{ - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return 0; - } - if ( !value || XMLUtil::StringEqual( a->Value(), value )) { - return a->Value(); - } - return 0; -} - -int XMLElement::IntAttribute(const char* name, int defaultValue) const -{ - int i = defaultValue; - QueryIntAttribute(name, &i); - return i; -} - -unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const -{ - unsigned i = defaultValue; - QueryUnsignedAttribute(name, &i); - return i; -} - -int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const -{ - int64_t i = defaultValue; - QueryInt64Attribute(name, &i); - return i; -} - -bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const -{ - bool b = defaultValue; - QueryBoolAttribute(name, &b); - return b; -} - -double XMLElement::DoubleAttribute(const char* name, double defaultValue) const -{ - double d = defaultValue; - QueryDoubleAttribute(name, &d); - return d; -} - -float XMLElement::FloatAttribute(const char* name, float defaultValue) const -{ - float f = defaultValue; - QueryFloatAttribute(name, &f); - return f; -} - -const char* XMLElement::GetText() const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - return FirstChild()->Value(); - } - return 0; -} - - -void XMLElement::SetText( const char* inText ) -{ - if ( FirstChild() && FirstChild()->ToText() ) - FirstChild()->SetValue( inText ); - else { - XMLText* theText = GetDocument()->NewText( inText ); - InsertFirstChild( theText ); - } -} - - -void XMLElement::SetText( int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText( unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText(int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - SetText(buf); -} - - -void XMLElement::SetText( bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText( float v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -void XMLElement::SetText( double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - SetText( buf ); -} - - -XMLError XMLElement::QueryIntText( int* ival ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToInt( t, ival ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToUnsigned( t, uval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryInt64Text(int64_t* ival) const -{ - if (FirstChild() && FirstChild()->ToText()) { - const char* t = FirstChild()->Value(); - if (XMLUtil::ToInt64(t, ival)) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryBoolText( bool* bval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToBool( t, bval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryDoubleText( double* dval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToDouble( t, dval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - - -XMLError XMLElement::QueryFloatText( float* fval ) const -{ - if ( FirstChild() && FirstChild()->ToText() ) { - const char* t = FirstChild()->Value(); - if ( XMLUtil::ToFloat( t, fval ) ) { - return XML_SUCCESS; - } - return XML_CAN_NOT_CONVERT_TEXT; - } - return XML_NO_TEXT_NODE; -} - -int XMLElement::IntText(int defaultValue) const -{ - int i = defaultValue; - QueryIntText(&i); - return i; -} - -unsigned XMLElement::UnsignedText(unsigned defaultValue) const -{ - unsigned i = defaultValue; - QueryUnsignedText(&i); - return i; -} - -int64_t XMLElement::Int64Text(int64_t defaultValue) const -{ - int64_t i = defaultValue; - QueryInt64Text(&i); - return i; -} - -bool XMLElement::BoolText(bool defaultValue) const -{ - bool b = defaultValue; - QueryBoolText(&b); - return b; -} - -double XMLElement::DoubleText(double defaultValue) const -{ - double d = defaultValue; - QueryDoubleText(&d); - return d; -} - -float XMLElement::FloatText(float defaultValue) const -{ - float f = defaultValue; - QueryFloatText(&f); - return f; -} - - -XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) -{ - XMLAttribute* last = 0; - XMLAttribute* attrib = 0; - for( attrib = _rootAttribute; - attrib; - last = attrib, attrib = attrib->_next ) { - if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { - break; - } - } - if ( !attrib ) { - attrib = CreateAttribute(); - TIXMLASSERT( attrib ); - if ( last ) { - TIXMLASSERT( last->_next == 0 ); - last->_next = attrib; - } - else { - TIXMLASSERT( _rootAttribute == 0 ); - _rootAttribute = attrib; - } - attrib->SetName( name ); - } - return attrib; -} - - -void XMLElement::DeleteAttribute( const char* name ) -{ - XMLAttribute* prev = 0; - for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { - if ( XMLUtil::StringEqual( name, a->Name() ) ) { - if ( prev ) { - prev->_next = a->_next; - } - else { - _rootAttribute = a->_next; - } - DeleteAttribute( a ); - break; - } - prev = a; - } -} - - -char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) -{ - XMLAttribute* prevAttribute = 0; - - // Read the attributes. - while( p ) { - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - if ( !(*p) ) { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() ); - return 0; - } - - // attribute. - if (XMLUtil::IsNameStartChar( *p ) ) { - XMLAttribute* attrib = CreateAttribute(); - TIXMLASSERT( attrib ); - attrib->_parseLineNum = _document->_parseCurLineNum; - - int attrLineNum = attrib->_parseLineNum; - - p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr ); - if ( !p || Attribute( attrib->Name() ) ) { - DeleteAttribute( attrib ); - _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() ); - return 0; - } - // There is a minor bug here: if the attribute in the source xml - // document is duplicated, it will not be detected and the - // attribute will be doubly added. However, tracking the 'prevAttribute' - // avoids re-scanning the attribute list. Preferring performance for - // now, may reconsider in the future. - if ( prevAttribute ) { - TIXMLASSERT( prevAttribute->_next == 0 ); - prevAttribute->_next = attrib; - } - else { - TIXMLASSERT( _rootAttribute == 0 ); - _rootAttribute = attrib; - } - prevAttribute = attrib; - } - // end of the tag - else if ( *p == '>' ) { - ++p; - break; - } - // end of the tag - else if ( *p == '/' && *(p+1) == '>' ) { - _closingType = CLOSED; - return p+2; // done; sealed element. - } - else { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, 0 ); - return 0; - } - } - return p; -} - -void XMLElement::DeleteAttribute( XMLAttribute* attribute ) -{ - if ( attribute == 0 ) { - return; - } - MemPool* pool = attribute->_memPool; - attribute->~XMLAttribute(); - pool->Free( attribute ); -} - -XMLAttribute* XMLElement::CreateAttribute() -{ - TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); - XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); - TIXMLASSERT( attrib ); - attrib->_memPool = &_document->_attributePool; - attrib->_memPool->SetTracked(); - return attrib; -} - -// -// -// foobar -// -char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) -{ - // Read the element name. - p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); - - // The closing element is the form. It is - // parsed just like a regular element then deleted from - // the DOM. - if ( *p == '/' ) { - _closingType = CLOSING; - ++p; - } - - p = _value.ParseName( p ); - if ( _value.Empty() ) { - return 0; - } - - p = ParseAttributes( p, curLineNumPtr ); - if ( !p || !*p || _closingType != OPEN ) { - return p; - } - - p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); - return p; -} - - - -XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const -{ - if ( !doc ) { - doc = _document; - } - XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? - for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { - element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? - } - return element; -} - - -bool XMLElement::ShallowEqual( const XMLNode* compare ) const -{ - TIXMLASSERT( compare ); - const XMLElement* other = compare->ToElement(); - if ( other && XMLUtil::StringEqual( other->Name(), Name() )) { - - const XMLAttribute* a=FirstAttribute(); - const XMLAttribute* b=other->FirstAttribute(); - - while ( a && b ) { - if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { - return false; - } - a = a->Next(); - b = b->Next(); - } - if ( a || b ) { - // different count - return false; - } - return true; - } - return false; -} - - -bool XMLElement::Accept( XMLVisitor* visitor ) const -{ - TIXMLASSERT( visitor ); - if ( visitor->VisitEnter( *this, _rootAttribute ) ) { - for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { - if ( !node->Accept( visitor ) ) { - break; - } - } - } - return visitor->VisitExit( *this ); -} - - -// --------- XMLDocument ----------- // - -// Warning: List must match 'enum XMLError' -const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { - "XML_SUCCESS", - "XML_NO_ATTRIBUTE", - "XML_WRONG_ATTRIBUTE_TYPE", - "XML_ERROR_FILE_NOT_FOUND", - "XML_ERROR_FILE_COULD_NOT_BE_OPENED", - "XML_ERROR_FILE_READ_ERROR", - "UNUSED_XML_ERROR_ELEMENT_MISMATCH", - "XML_ERROR_PARSING_ELEMENT", - "XML_ERROR_PARSING_ATTRIBUTE", - "UNUSED_XML_ERROR_IDENTIFYING_TAG", - "XML_ERROR_PARSING_TEXT", - "XML_ERROR_PARSING_CDATA", - "XML_ERROR_PARSING_COMMENT", - "XML_ERROR_PARSING_DECLARATION", - "XML_ERROR_PARSING_UNKNOWN", - "XML_ERROR_EMPTY_DOCUMENT", - "XML_ERROR_MISMATCHED_ELEMENT", - "XML_ERROR_PARSING", - "XML_CAN_NOT_CONVERT_TEXT", - "XML_NO_TEXT_NODE", - "XML_ELEMENT_DEPTH_EXCEEDED" -}; - - -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : - XMLNode( 0 ), - _writeBOM( false ), - _processEntities( processEntities ), - _errorID(XML_SUCCESS), - _whitespaceMode( whitespaceMode ), - _errorStr(), - _errorLineNum( 0 ), - _charBuffer( 0 ), - _parseCurLineNum( 0 ), - _parsingDepth(0), - _unlinked(), - _elementPool(), - _attributePool(), - _textPool(), - _commentPool() -{ - // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) - _document = this; -} - - -XMLDocument::~XMLDocument() -{ - Clear(); -} - - -void XMLDocument::MarkInUse(XMLNode* node) -{ - TIXMLASSERT(node); - TIXMLASSERT(node->_parent == 0); - - for (int i = 0; i < _unlinked.Size(); ++i) { - if (node == _unlinked[i]) { - _unlinked.SwapRemove(i); - break; - } - } -} - -void XMLDocument::Clear() -{ - DeleteChildren(); - while( _unlinked.Size()) { - DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete. - } - -#ifdef TINYXML2_DEBUG - const bool hadError = Error(); -#endif - ClearError(); - - delete [] _charBuffer; - _charBuffer = 0; - _parsingDepth = 0; - -#if 0 - _textPool.Trace( "text" ); - _elementPool.Trace( "element" ); - _commentPool.Trace( "comment" ); - _attributePool.Trace( "attribute" ); -#endif - -#ifdef TINYXML2_DEBUG - if ( !hadError ) { - TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); - TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); - TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); - TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); - } -#endif -} - - -void XMLDocument::DeepCopy(XMLDocument* target) const -{ - TIXMLASSERT(target); - if (target == this) { - return; // technically success - a no-op. - } - - target->Clear(); - for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) { - target->InsertEndChild(node->DeepClone(target)); - } -} - -XMLElement* XMLDocument::NewElement( const char* name ) -{ - XMLElement* ele = CreateUnlinkedNode( _elementPool ); - ele->SetName( name ); - return ele; -} - - -XMLComment* XMLDocument::NewComment( const char* str ) -{ - XMLComment* comment = CreateUnlinkedNode( _commentPool ); - comment->SetValue( str ); - return comment; -} - - -XMLText* XMLDocument::NewText( const char* str ) -{ - XMLText* text = CreateUnlinkedNode( _textPool ); - text->SetValue( str ); - return text; -} - - -XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) -{ - XMLDeclaration* dec = CreateUnlinkedNode( _commentPool ); - dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); - return dec; -} - - -XMLUnknown* XMLDocument::NewUnknown( const char* str ) -{ - XMLUnknown* unk = CreateUnlinkedNode( _commentPool ); - unk->SetValue( str ); - return unk; -} - -static FILE* callfopen( const char* filepath, const char* mode ) -{ - TIXMLASSERT( filepath ); - TIXMLASSERT( mode ); -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filepath, mode ); - if ( err ) { - return 0; - } -#else - FILE* fp = fopen( filepath, mode ); -#endif - return fp; -} - -void XMLDocument::DeleteNode( XMLNode* node ) { - TIXMLASSERT( node ); - TIXMLASSERT(node->_document == this ); - if (node->_parent) { - node->_parent->DeleteChild( node ); - } - else { - // Isn't in the tree. - // Use the parent delete. - // Also, we need to mark it tracked: we 'know' - // it was never used. - node->_memPool->SetTracked(); - // Call the static XMLNode version: - XMLNode::DeleteNode(node); - } -} - - -XMLError XMLDocument::LoadFile( const char* filename ) -{ - if ( !filename ) { - TIXMLASSERT( false ); - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); - return _errorID; - } - - Clear(); - FILE* fp = callfopen( filename, "rb" ); - if ( !fp ) { - SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ); - return _errorID; - } - LoadFile( fp ); - fclose( fp ); - return _errorID; -} - -// This is likely overengineered template art to have a check that unsigned long value incremented -// by one still fits into size_t. If size_t type is larger than unsigned long type -// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit -// -Wtype-limits warning. This piece makes the compiler select code with a check when a check -// is useful and code with no check when a check is redundant depending on how size_t and unsigned long -// types sizes relate to each other. -template -= sizeof(size_t))> -struct LongFitsIntoSizeTMinusOne { - static bool Fits( unsigned long value ) - { - return value < (size_t)-1; - } -}; - -template <> -struct LongFitsIntoSizeTMinusOne { - static bool Fits( unsigned long ) - { - return true; - } -}; - -XMLError XMLDocument::LoadFile( FILE* fp ) -{ - Clear(); - - fseek( fp, 0, SEEK_SET ); - if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - fseek( fp, 0, SEEK_END ); - const long filelength = ftell( fp ); - fseek( fp, 0, SEEK_SET ); - if ( filelength == -1L ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - TIXMLASSERT( filelength >= 0 ); - - if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) { - // Cannot handle files which won't fit in buffer together with null terminator - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - if ( filelength == 0 ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - - const size_t size = filelength; - TIXMLASSERT( _charBuffer == 0 ); - _charBuffer = new char[size+1]; - size_t read = fread( _charBuffer, 1, size, fp ); - if ( read != size ) { - SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); - return _errorID; - } - - _charBuffer[size] = 0; - - Parse(); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( const char* filename, bool compact ) -{ - if ( !filename ) { - TIXMLASSERT( false ); - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); - return _errorID; - } - - FILE* fp = callfopen( filename, "w" ); - if ( !fp ) { - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ); - return _errorID; - } - SaveFile(fp, compact); - fclose( fp ); - return _errorID; -} - - -XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) -{ - // Clear any error from the last save, otherwise it will get reported - // for *this* call. - ClearError(); - XMLPrinter stream( fp, compact ); - Print( &stream ); - return _errorID; -} - - -XMLError XMLDocument::Parse( const char* p, size_t len ) -{ - Clear(); - - if ( len == 0 || !p || !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return _errorID; - } - if ( len == (size_t)(-1) ) { - len = strlen( p ); - } - TIXMLASSERT( _charBuffer == 0 ); - _charBuffer = new char[ len+1 ]; - memcpy( _charBuffer, p, len ); - _charBuffer[len] = 0; - - Parse(); - if ( Error() ) { - // clean up now essentially dangling memory. - // and the parse fail can put objects in the - // pools that are dead and inaccessible. - DeleteChildren(); - _elementPool.Clear(); - _attributePool.Clear(); - _textPool.Clear(); - _commentPool.Clear(); - } - return _errorID; -} - - -void XMLDocument::Print( XMLPrinter* streamer ) const -{ - if ( streamer ) { - Accept( streamer ); - } - else { - XMLPrinter stdoutStreamer( stdout ); - Accept( &stdoutStreamer ); - } -} - - -void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... ) -{ - TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); - _errorID = error; - _errorLineNum = lineNum; - _errorStr.Reset(); - - size_t BUFFER_SIZE = 1000; - char* buffer = new char[BUFFER_SIZE]; - - TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum); - - if (format) { - size_t len = strlen(buffer); - TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": "); - len = strlen(buffer); - - va_list va; - va_start(va, format); - TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va); - va_end(va); - } - _errorStr.SetStr(buffer); - delete[] buffer; -} - - -/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID) -{ - TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT ); - const char* errorName = _errorNames[errorID]; - TIXMLASSERT( errorName && errorName[0] ); - return errorName; -} - -const char* XMLDocument::ErrorStr() const -{ - return _errorStr.Empty() ? "" : _errorStr.GetStr(); -} - - -void XMLDocument::PrintError() const -{ - printf("%s\n", ErrorStr()); -} - -const char* XMLDocument::ErrorName() const -{ - return ErrorIDToName(_errorID); -} - -void XMLDocument::Parse() -{ - TIXMLASSERT( NoChildren() ); // Clear() must have been called previously - TIXMLASSERT( _charBuffer ); - _parseCurLineNum = 1; - _parseLineNum = 1; - char* p = _charBuffer; - p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); - p = const_cast( XMLUtil::ReadBOM( p, &_writeBOM ) ); - if ( !*p ) { - SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); - return; - } - ParseDeep(p, 0, &_parseCurLineNum ); -} - -void XMLDocument::PushDepth() -{ - _parsingDepth++; - if (_parsingDepth == TINYXML2_MAX_ELEMENT_DEPTH) { - SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." ); - } -} - -void XMLDocument::PopDepth() -{ - TIXMLASSERT(_parsingDepth > 0); - --_parsingDepth; -} - -XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : - _elementJustOpened( false ), - _stack(), - _firstElement( true ), - _fp( file ), - _depth( depth ), - _textDepth( -1 ), - _processEntities( true ), - _compactMode( compact ), - _buffer() -{ - for( int i=0; i'] = true; // not required, but consistency is nice - _buffer.Push( 0 ); -} - - -void XMLPrinter::Print( const char* format, ... ) -{ - va_list va; - va_start( va, format ); - - if ( _fp ) { - vfprintf( _fp, format, va ); - } - else { - const int len = TIXML_VSCPRINTF( format, va ); - // Close out and re-start the va-args - va_end( va ); - TIXMLASSERT( len >= 0 ); - va_start( va, format ); - TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); - char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. - TIXML_VSNPRINTF( p, len+1, format, va ); - } - va_end( va ); -} - - -void XMLPrinter::Write( const char* data, size_t size ) -{ - if ( _fp ) { - fwrite ( data , sizeof(char), size, _fp); - } - else { - char* p = _buffer.PushArr( static_cast(size) ) - 1; // back up over the null terminator. - memcpy( p, data, size ); - p[size] = 0; - } -} - - -void XMLPrinter::Putc( char ch ) -{ - if ( _fp ) { - fputc ( ch, _fp); - } - else { - char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator. - p[0] = ch; - p[1] = 0; - } -} - - -void XMLPrinter::PrintSpace( int depth ) -{ - for( int i=0; i 0 && *q < ENTITY_RANGE ) { - // Check for entities. If one is found, flush - // the stream up until the entity, write the - // entity, and keep looking. - if ( flag[(unsigned char)(*q)] ) { - while ( p < q ) { - const size_t delta = q - p; - const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; - Write( p, toPrint ); - p += toPrint; - } - bool entityPatternPrinted = false; - for( int i=0; i( bom ) ); - } - if ( writeDec ) { - PushDeclaration( "xml version=\"1.0\"" ); - } -} - - -void XMLPrinter::OpenElement( const char* name, bool compactMode ) -{ - SealElementIfJustOpened(); - _stack.Push( name ); - - if ( _textDepth < 0 && !_firstElement && !compactMode ) { - Putc( '\n' ); - } - if ( !compactMode ) { - PrintSpace( _depth ); - } - - Write ( "<" ); - Write ( name ); - - _elementJustOpened = true; - _firstElement = false; - ++_depth; -} - - -void XMLPrinter::PushAttribute( const char* name, const char* value ) -{ - TIXMLASSERT( _elementJustOpened ); - Putc ( ' ' ); - Write( name ); - Write( "=\"" ); - PrintString( value, false ); - Putc ( '\"' ); -} - - -void XMLPrinter::PushAttribute( const char* name, int v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, unsigned v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute(const char* name, int64_t v) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr(v, buf, BUF_SIZE); - PushAttribute(name, buf); -} - - -void XMLPrinter::PushAttribute( const char* name, bool v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::PushAttribute( const char* name, double v ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( v, buf, BUF_SIZE ); - PushAttribute( name, buf ); -} - - -void XMLPrinter::CloseElement( bool compactMode ) -{ - --_depth; - const char* name = _stack.Pop(); - - if ( _elementJustOpened ) { - Write( "/>" ); - } - else { - if ( _textDepth < 0 && !compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - Write ( "" ); - } - - if ( _textDepth == _depth ) { - _textDepth = -1; - } - if ( _depth == 0 && !compactMode) { - Putc( '\n' ); - } - _elementJustOpened = false; -} - - -void XMLPrinter::SealElementIfJustOpened() -{ - if ( !_elementJustOpened ) { - return; - } - _elementJustOpened = false; - Putc( '>' ); -} - - -void XMLPrinter::PushText( const char* text, bool cdata ) -{ - _textDepth = _depth-1; - - SealElementIfJustOpened(); - if ( cdata ) { - Write( "" ); - } - else { - PrintString( text, true ); - } -} - -void XMLPrinter::PushText( int64_t value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - -void XMLPrinter::PushText( int value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( unsigned value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( bool value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( float value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushText( double value ) -{ - char buf[BUF_SIZE]; - XMLUtil::ToStr( value, buf, BUF_SIZE ); - PushText( buf, false ); -} - - -void XMLPrinter::PushComment( const char* comment ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "" ); -} - - -void XMLPrinter::PushDeclaration( const char* value ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "" ); -} - - -void XMLPrinter::PushUnknown( const char* value ) -{ - SealElementIfJustOpened(); - if ( _textDepth < 0 && !_firstElement && !_compactMode) { - Putc( '\n' ); - PrintSpace( _depth ); - } - _firstElement = false; - - Write( "' ); -} - - -bool XMLPrinter::VisitEnter( const XMLDocument& doc ) -{ - _processEntities = doc.ProcessEntities(); - if ( doc.HasBOM() ) { - PushHeader( true, false ); - } - return true; -} - - -bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) -{ - const XMLElement* parentElem = 0; - if ( element.Parent() ) { - parentElem = element.Parent()->ToElement(); - } - const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode; - OpenElement( element.Name(), compactMode ); - while ( attribute ) { - PushAttribute( attribute->Name(), attribute->Value() ); - attribute = attribute->Next(); - } - return true; -} - - -bool XMLPrinter::VisitExit( const XMLElement& element ) -{ - CloseElement( CompactMode(element) ); - return true; -} - - -bool XMLPrinter::Visit( const XMLText& text ) -{ - PushText( text.Value(), text.CData() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLComment& comment ) -{ - PushComment( comment.Value() ); - return true; -} - -bool XMLPrinter::Visit( const XMLDeclaration& declaration ) -{ - PushDeclaration( declaration.Value() ); - return true; -} - - -bool XMLPrinter::Visit( const XMLUnknown& unknown ) -{ - PushUnknown( unknown.Value() ); - return true; -} - -} // namespace tinyxml2 diff --git a/src/decoder/sip/tinyxml2/tinyxml2.h b/src/decoder/sip/tinyxml2/tinyxml2.h deleted file mode 100644 index 66d7b7e..0000000 --- a/src/decoder/sip/tinyxml2/tinyxml2.h +++ /dev/null @@ -1,2314 +0,0 @@ -/* -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#ifndef TINYXML2_INCLUDED -#define TINYXML2_INCLUDED - -#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) -# include -# include -# include -# include -# include -# if defined(__PS3__) -# include -# endif -#else -# include -# include -# include -# include -# include -#endif -#include - -/* - TODO: intern strings instead of allocation. -*/ -/* - gcc: - g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe - - Formatting, Artistic Style: - AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h -*/ - -#if defined( _DEBUG ) || defined (__DEBUG__) -# ifndef TINYXML2_DEBUG -# define TINYXML2_DEBUG -# endif -#endif - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4251) -#endif - -#ifdef _WIN32 -# ifdef TINYXML2_EXPORT -# define TINYXML2_LIB __declspec(dllexport) -# elif defined(TINYXML2_IMPORT) -# define TINYXML2_LIB __declspec(dllimport) -# else -# define TINYXML2_LIB -# endif -#elif __GNUC__ >= 4 -# define TINYXML2_LIB __attribute__((visibility("default"))) -#else -# define TINYXML2_LIB -#endif - - -#if defined(TINYXML2_DEBUG) -# if defined(_MSC_VER) -# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like -# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } -# elif defined (ANDROID_NDK) -# include -# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } -# else -# include -# define TIXMLASSERT assert -# endif -#else -# define TIXMLASSERT( x ) {} -#endif - - -/* Versioning, past 1.0.14: - http://semver.org/ -*/ -static const int TIXML2_MAJOR_VERSION = 6; -static const int TIXML2_MINOR_VERSION = 2; -static const int TIXML2_PATCH_VERSION = 0; - -#define TINYXML2_MAJOR_VERSION 6 -#define TINYXML2_MINOR_VERSION 2 -#define TINYXML2_PATCH_VERSION 0 - -// A fixed element depth limit is problematic. There needs to be a -// limit to avoid a stack overflow. However, that limit varies per -// system, and the capacity of the stack. On the other hand, it's a trivial -// attack that can result from ill, malicious, or even correctly formed XML, -// so there needs to be a limit in place. -static const int TINYXML2_MAX_ELEMENT_DEPTH = 100; - -namespace tinyxml2 -{ -class XMLDocument; -class XMLElement; -class XMLAttribute; -class XMLComment; -class XMLText; -class XMLDeclaration; -class XMLUnknown; -class XMLPrinter; - -/* - A class that wraps strings. Normally stores the start and end - pointers into the XML file itself, and will apply normalization - and entity translation if actually read. Can also store (and memory - manage) a traditional char[] -*/ -class StrPair -{ -public: - enum { - NEEDS_ENTITY_PROCESSING = 0x01, - NEEDS_NEWLINE_NORMALIZATION = 0x02, - NEEDS_WHITESPACE_COLLAPSING = 0x04, - - TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, - TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, - ATTRIBUTE_NAME = 0, - ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, - ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, - COMMENT = NEEDS_NEWLINE_NORMALIZATION - }; - - StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} - ~StrPair(); - - void Set( char* start, char* end, int flags ) { - TIXMLASSERT( start ); - TIXMLASSERT( end ); - Reset(); - _start = start; - _end = end; - _flags = flags | NEEDS_FLUSH; - } - - const char* GetStr(); - - bool Empty() const { - return _start == _end; - } - - void SetInternedStr( const char* str ) { - Reset(); - _start = const_cast(str); - } - - void SetStr( const char* str, int flags=0 ); - - char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr ); - char* ParseName( char* in ); - - void TransferTo( StrPair* other ); - void Reset(); - -private: - void CollapseWhitespace(); - - enum { - NEEDS_FLUSH = 0x100, - NEEDS_DELETE = 0x200 - }; - - int _flags; - char* _start; - char* _end; - - StrPair( const StrPair& other ); // not supported - void operator=( StrPair& other ); // not supported, use TransferTo() -}; - - -/* - A dynamic array of Plain Old Data. Doesn't support constructors, etc. - Has a small initial memory pool, so that low or no usage will not - cause a call to new/delete -*/ -template -class DynArray -{ -public: - DynArray() : - _mem( _pool ), - _allocated( INITIAL_SIZE ), - _size( 0 ) - { - } - - ~DynArray() { - if ( _mem != _pool ) { - delete [] _mem; - } - } - - void Clear() { - _size = 0; - } - - void Push( T t ) { - TIXMLASSERT( _size < INT_MAX ); - EnsureCapacity( _size+1 ); - _mem[_size] = t; - ++_size; - } - - T* PushArr( int count ) { - TIXMLASSERT( count >= 0 ); - TIXMLASSERT( _size <= INT_MAX - count ); - EnsureCapacity( _size+count ); - T* ret = &_mem[_size]; - _size += count; - return ret; - } - - T Pop() { - TIXMLASSERT( _size > 0 ); - --_size; - return _mem[_size]; - } - - void PopArr( int count ) { - TIXMLASSERT( _size >= count ); - _size -= count; - } - - bool Empty() const { - return _size == 0; - } - - T& operator[](int i) { - TIXMLASSERT( i>= 0 && i < _size ); - return _mem[i]; - } - - const T& operator[](int i) const { - TIXMLASSERT( i>= 0 && i < _size ); - return _mem[i]; - } - - const T& PeekTop() const { - TIXMLASSERT( _size > 0 ); - return _mem[ _size - 1]; - } - - int Size() const { - TIXMLASSERT( _size >= 0 ); - return _size; - } - - int Capacity() const { - TIXMLASSERT( _allocated >= INITIAL_SIZE ); - return _allocated; - } - - void SwapRemove(int i) { - TIXMLASSERT(i >= 0 && i < _size); - TIXMLASSERT(_size > 0); - _mem[i] = _mem[_size - 1]; - --_size; - } - - const T* Mem() const { - TIXMLASSERT( _mem ); - return _mem; - } - - T* Mem() { - TIXMLASSERT( _mem ); - return _mem; - } - -private: - DynArray( const DynArray& ); // not supported - void operator=( const DynArray& ); // not supported - - void EnsureCapacity( int cap ) { - TIXMLASSERT( cap > 0 ); - if ( cap > _allocated ) { - TIXMLASSERT( cap <= INT_MAX / 2 ); - int newAllocated = cap * 2; - T* newMem = new T[newAllocated]; - TIXMLASSERT( newAllocated >= _size ); - memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs - if ( _mem != _pool ) { - delete [] _mem; - } - _mem = newMem; - _allocated = newAllocated; - } - } - - T* _mem; - T _pool[INITIAL_SIZE]; - int _allocated; // objects allocated - int _size; // number objects in use -}; - - -/* - Parent virtual class of a pool for fast allocation - and deallocation of objects. -*/ -class MemPool -{ -public: - MemPool() {} - virtual ~MemPool() {} - - virtual int ItemSize() const = 0; - virtual void* Alloc() = 0; - virtual void Free( void* ) = 0; - virtual void SetTracked() = 0; - virtual void Clear() = 0; -}; - - -/* - Template child class to create pools of the correct type. -*/ -template< int ITEM_SIZE > -class MemPoolT : public MemPool -{ -public: - MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} - ~MemPoolT() { - Clear(); - } - - void Clear() { - // Delete the blocks. - while( !_blockPtrs.Empty()) { - Block* lastBlock = _blockPtrs.Pop(); - delete lastBlock; - } - _root = 0; - _currentAllocs = 0; - _nAllocs = 0; - _maxAllocs = 0; - _nUntracked = 0; - } - - virtual int ItemSize() const { - return ITEM_SIZE; - } - int CurrentAllocs() const { - return _currentAllocs; - } - - virtual void* Alloc() { - if ( !_root ) { - // Need a new block. - Block* block = new Block(); - _blockPtrs.Push( block ); - - Item* blockItems = block->items; - for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) { - blockItems[i].next = &(blockItems[i + 1]); - } - blockItems[ITEMS_PER_BLOCK - 1].next = 0; - _root = blockItems; - } - Item* const result = _root; - TIXMLASSERT( result != 0 ); - _root = _root->next; - - ++_currentAllocs; - if ( _currentAllocs > _maxAllocs ) { - _maxAllocs = _currentAllocs; - } - ++_nAllocs; - ++_nUntracked; - return result; - } - - virtual void Free( void* mem ) { - if ( !mem ) { - return; - } - --_currentAllocs; - Item* item = static_cast( mem ); -#ifdef TINYXML2_DEBUG - memset( item, 0xfe, sizeof( *item ) ); -#endif - item->next = _root; - _root = item; - } - void Trace( const char* name ) { - printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", - name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs, - ITEM_SIZE, _nAllocs, _blockPtrs.Size() ); - } - - void SetTracked() { - --_nUntracked; - } - - int Untracked() const { - return _nUntracked; - } - - // This number is perf sensitive. 4k seems like a good tradeoff on my machine. - // The test file is large, 170k. - // Release: VS2010 gcc(no opt) - // 1k: 4000 - // 2k: 4000 - // 4k: 3900 21000 - // 16k: 5200 - // 32k: 4300 - // 64k: 4000 21000 - // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK - // in private part if ITEMS_PER_BLOCK is private - enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE }; - -private: - MemPoolT( const MemPoolT& ); // not supported - void operator=( const MemPoolT& ); // not supported - - union Item { - Item* next; - char itemData[ITEM_SIZE]; - }; - struct Block { - Item items[ITEMS_PER_BLOCK]; - }; - DynArray< Block*, 10 > _blockPtrs; - Item* _root; - - int _currentAllocs; - int _nAllocs; - int _maxAllocs; - int _nUntracked; -}; - - - -/** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a XMLVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs - are simply called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its siblings will be visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the XMLDocument, although all nodes support visiting. - - You should never change the document from a callback. - - @sa XMLNode::Accept() -*/ -class TINYXML2_LIB XMLVisitor -{ -public: - virtual ~XMLVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { - return true; - } - /// Visit a document. - virtual bool VisitExit( const XMLDocument& /*doc*/ ) { - return true; - } - - /// Visit an element. - virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { - return true; - } - /// Visit an element. - virtual bool VisitExit( const XMLElement& /*element*/ ) { - return true; - } - - /// Visit a declaration. - virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { - return true; - } - /// Visit a text node. - virtual bool Visit( const XMLText& /*text*/ ) { - return true; - } - /// Visit a comment node. - virtual bool Visit( const XMLComment& /*comment*/ ) { - return true; - } - /// Visit an unknown node. - virtual bool Visit( const XMLUnknown& /*unknown*/ ) { - return true; - } -}; - -// WARNING: must match XMLDocument::_errorNames[] -enum XMLError { - XML_SUCCESS = 0, - XML_NO_ATTRIBUTE, - XML_WRONG_ATTRIBUTE_TYPE, - XML_ERROR_FILE_NOT_FOUND, - XML_ERROR_FILE_COULD_NOT_BE_OPENED, - XML_ERROR_FILE_READ_ERROR, - UNUSED_XML_ERROR_ELEMENT_MISMATCH, // remove at next major version - XML_ERROR_PARSING_ELEMENT, - XML_ERROR_PARSING_ATTRIBUTE, - UNUSED_XML_ERROR_IDENTIFYING_TAG, // remove at next major version - XML_ERROR_PARSING_TEXT, - XML_ERROR_PARSING_CDATA, - XML_ERROR_PARSING_COMMENT, - XML_ERROR_PARSING_DECLARATION, - XML_ERROR_PARSING_UNKNOWN, - XML_ERROR_EMPTY_DOCUMENT, - XML_ERROR_MISMATCHED_ELEMENT, - XML_ERROR_PARSING, - XML_CAN_NOT_CONVERT_TEXT, - XML_NO_TEXT_NODE, - XML_ELEMENT_DEPTH_EXCEEDED, - - XML_ERROR_COUNT -}; - - -/* - Utility functionality. -*/ -class TINYXML2_LIB XMLUtil -{ -public: - static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) { - TIXMLASSERT( p ); - - while( IsWhiteSpace(*p) ) { - if (curLineNumPtr && *p == '\n') { - ++(*curLineNumPtr); - } - ++p; - } - TIXMLASSERT( p ); - return p; - } - static char* SkipWhiteSpace( char* p, int* curLineNumPtr ) { - return const_cast( SkipWhiteSpace( const_cast(p), curLineNumPtr ) ); - } - - // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't - // correct, but simple, and usually works. - static bool IsWhiteSpace( char p ) { - return !IsUTF8Continuation(p) && isspace( static_cast(p) ); - } - - inline static bool IsNameStartChar( unsigned char ch ) { - if ( ch >= 128 ) { - // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() - return true; - } - if ( isalpha( ch ) ) { - return true; - } - return ch == ':' || ch == '_'; - } - - inline static bool IsNameChar( unsigned char ch ) { - return IsNameStartChar( ch ) - || isdigit( ch ) - || ch == '.' - || ch == '-'; - } - - inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { - if ( p == q ) { - return true; - } - TIXMLASSERT( p ); - TIXMLASSERT( q ); - TIXMLASSERT( nChar >= 0 ); - return strncmp( p, q, nChar ) == 0; - } - - inline static bool IsUTF8Continuation( char p ) { - return ( p & 0x80 ) != 0; - } - - static const char* ReadBOM( const char* p, bool* hasBOM ); - // p is the starting location, - // the UTF-8 value of the entity will be placed in value, and length filled in. - static const char* GetCharacterRef( const char* p, char* value, int* length ); - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - - // converts primitive types to strings - static void ToStr( int v, char* buffer, int bufferSize ); - static void ToStr( unsigned v, char* buffer, int bufferSize ); - static void ToStr( bool v, char* buffer, int bufferSize ); - static void ToStr( float v, char* buffer, int bufferSize ); - static void ToStr( double v, char* buffer, int bufferSize ); - static void ToStr(int64_t v, char* buffer, int bufferSize); - - // converts strings to primitive types - static bool ToInt( const char* str, int* value ); - static bool ToUnsigned( const char* str, unsigned* value ); - static bool ToBool( const char* str, bool* value ); - static bool ToFloat( const char* str, float* value ); - static bool ToDouble( const char* str, double* value ); - static bool ToInt64(const char* str, int64_t* value); - - // Changes what is serialized for a boolean value. - // Default to "true" and "false". Shouldn't be changed - // unless you have a special testing or compatibility need. - // Be careful: static, global, & not thread safe. - // Be sure to set static const memory as parameters. - static void SetBoolSerialization(const char* writeTrue, const char* writeFalse); - -private: - static const char* writeBoolTrue; - static const char* writeBoolFalse; -}; - - -/** XMLNode is a base class for every object that is in the - XML Document Object Model (DOM), except XMLAttributes. - Nodes have siblings, a parent, and children which can - be navigated. A node is always in a XMLDocument. - The type of a XMLNode can be queried, and it can - be cast to its more defined type. - - A XMLDocument allocates memory for all its Nodes. - When the XMLDocument gets deleted, all its Nodes - will also be deleted. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - @endverbatim -*/ -class TINYXML2_LIB XMLNode -{ - friend class XMLDocument; - friend class XMLElement; -public: - - /// Get the XMLDocument that owns this XMLNode. - const XMLDocument* GetDocument() const { - TIXMLASSERT( _document ); - return _document; - } - /// Get the XMLDocument that owns this XMLNode. - XMLDocument* GetDocument() { - TIXMLASSERT( _document ); - return _document; - } - - /// Safely cast to an Element, or null. - virtual XMLElement* ToElement() { - return 0; - } - /// Safely cast to Text, or null. - virtual XMLText* ToText() { - return 0; - } - /// Safely cast to a Comment, or null. - virtual XMLComment* ToComment() { - return 0; - } - /// Safely cast to a Document, or null. - virtual XMLDocument* ToDocument() { - return 0; - } - /// Safely cast to a Declaration, or null. - virtual XMLDeclaration* ToDeclaration() { - return 0; - } - /// Safely cast to an Unknown, or null. - virtual XMLUnknown* ToUnknown() { - return 0; - } - - virtual const XMLElement* ToElement() const { - return 0; - } - virtual const XMLText* ToText() const { - return 0; - } - virtual const XMLComment* ToComment() const { - return 0; - } - virtual const XMLDocument* ToDocument() const { - return 0; - } - virtual const XMLDeclaration* ToDeclaration() const { - return 0; - } - virtual const XMLUnknown* ToUnknown() const { - return 0; - } - - /** The meaning of 'value' changes for the specific type. - @verbatim - Document: empty (NULL is returned, not an empty string) - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - const char* Value() const; - - /** Set the Value of an XML node. - @sa Value() - */ - void SetValue( const char* val, bool staticMem=false ); - - /// Gets the line number the node is in, if the document was parsed from a file. - int GetLineNum() const { return _parseLineNum; } - - /// Get the parent of this node on the DOM. - const XMLNode* Parent() const { - return _parent; - } - - XMLNode* Parent() { - return _parent; - } - - /// Returns true if this node has no children. - bool NoChildren() const { - return !_firstChild; - } - - /// Get the first child node, or null if none exists. - const XMLNode* FirstChild() const { - return _firstChild; - } - - XMLNode* FirstChild() { - return _firstChild; - } - - /** Get the first child element, or optionally the first child - element with the specified name. - */ - const XMLElement* FirstChildElement( const char* name = 0 ) const; - - XMLElement* FirstChildElement( const char* name = 0 ) { - return const_cast(const_cast(this)->FirstChildElement( name )); - } - - /// Get the last child node, or null if none exists. - const XMLNode* LastChild() const { - return _lastChild; - } - - XMLNode* LastChild() { - return _lastChild; - } - - /** Get the last child element or optionally the last child - element with the specified name. - */ - const XMLElement* LastChildElement( const char* name = 0 ) const; - - XMLElement* LastChildElement( const char* name = 0 ) { - return const_cast(const_cast(this)->LastChildElement(name) ); - } - - /// Get the previous (left) sibling node of this node. - const XMLNode* PreviousSibling() const { - return _prev; - } - - XMLNode* PreviousSibling() { - return _prev; - } - - /// Get the previous (left) sibling element of this node, with an optionally supplied name. - const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; - - XMLElement* PreviousSiblingElement( const char* name = 0 ) { - return const_cast(const_cast(this)->PreviousSiblingElement( name ) ); - } - - /// Get the next (right) sibling node of this node. - const XMLNode* NextSibling() const { - return _next; - } - - XMLNode* NextSibling() { - return _next; - } - - /// Get the next (right) sibling element of this node, with an optionally supplied name. - const XMLElement* NextSiblingElement( const char* name = 0 ) const; - - XMLElement* NextSiblingElement( const char* name = 0 ) { - return const_cast(const_cast(this)->NextSiblingElement( name ) ); - } - - /** - Add a child node as the last (right) child. - If the child node is already part of the document, - it is moved from its old location to the new location. - Returns the addThis argument or 0 if the node does not - belong to the same document. - */ - XMLNode* InsertEndChild( XMLNode* addThis ); - - XMLNode* LinkEndChild( XMLNode* addThis ) { - return InsertEndChild( addThis ); - } - /** - Add a child node as the first (left) child. - If the child node is already part of the document, - it is moved from its old location to the new location. - Returns the addThis argument or 0 if the node does not - belong to the same document. - */ - XMLNode* InsertFirstChild( XMLNode* addThis ); - /** - Add a node after the specified child node. - If the child node is already part of the document, - it is moved from its old location to the new location. - Returns the addThis argument or 0 if the afterThis node - is not a child of this node, or if the node does not - belong to the same document. - */ - XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); - - /** - Delete all the children of this node. - */ - void DeleteChildren(); - - /** - Delete a child of this node. - */ - void DeleteChild( XMLNode* node ); - - /** - Make a copy of this node, but not its children. - You may pass in a Document pointer that will be - the owner of the new Node. If the 'document' is - null, then the node returned will be allocated - from the current Document. (this->GetDocument()) - - Note: if called on a XMLDocument, this will return null. - */ - virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; - - /** - Make a copy of this node and all its children. - - If the 'target' is null, then the nodes will - be allocated in the current document. If 'target' - is specified, the memory will be allocated is the - specified XMLDocument. - - NOTE: This is probably not the correct tool to - copy a document, since XMLDocuments can have multiple - top level XMLNodes. You probably want to use - XMLDocument::DeepCopy() - */ - XMLNode* DeepClone( XMLDocument* target ) const; - - /** - Test if 2 nodes are the same, but don't test children. - The 2 nodes do not need to be in the same Document. - - Note: if called on a XMLDocument, this will return false. - */ - virtual bool ShallowEqual( const XMLNode* compare ) const = 0; - - /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the XMLVisitor interface. - - This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - XMLPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( XMLVisitor* visitor ) const = 0; - - /** - Set user data into the XMLNode. TinyXML-2 in - no way processes or interprets user data. - It is initially 0. - */ - void SetUserData(void* userData) { _userData = userData; } - - /** - Get user data set into the XMLNode. TinyXML-2 in - no way processes or interprets user data. - It is initially 0. - */ - void* GetUserData() const { return _userData; } - -protected: - XMLNode( XMLDocument* ); - virtual ~XMLNode(); - - virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); - - XMLDocument* _document; - XMLNode* _parent; - mutable StrPair _value; - int _parseLineNum; - - XMLNode* _firstChild; - XMLNode* _lastChild; - - XMLNode* _prev; - XMLNode* _next; - - void* _userData; - -private: - MemPool* _memPool; - void Unlink( XMLNode* child ); - static void DeleteNode( XMLNode* node ); - void InsertChildPreamble( XMLNode* insertThis ) const; - const XMLElement* ToElementWithName( const char* name ) const; - - XMLNode( const XMLNode& ); // not supported - XMLNode& operator=( const XMLNode& ); // not supported -}; - - -/** XML text. - - Note that a text node can have child element nodes, for example: - @verbatim - This is bold - @endverbatim - - A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCData() and query it with CData(). -*/ -class TINYXML2_LIB XMLText : public XMLNode -{ - friend class XMLDocument; -public: - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLText* ToText() { - return this; - } - virtual const XMLText* ToText() const { - return this; - } - - /// Declare whether this should be CDATA or standard text. - void SetCData( bool isCData ) { - _isCData = isCData; - } - /// Returns true if this is a CDATA text element. - bool CData() const { - return _isCData; - } - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} - virtual ~XMLText() {} - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - bool _isCData; - - XMLText( const XMLText& ); // not supported - XMLText& operator=( const XMLText& ); // not supported -}; - - -/** An XML Comment. */ -class TINYXML2_LIB XMLComment : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLComment* ToComment() { - return this; - } - virtual const XMLComment* ToComment() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLComment( XMLDocument* doc ); - virtual ~XMLComment(); - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); - -private: - XMLComment( const XMLComment& ); // not supported - XMLComment& operator=( const XMLComment& ); // not supported -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXML-2 will happily read or write files without a declaration, - however. - - The text of the declaration isn't interpreted. It is parsed - and written as a string. -*/ -class TINYXML2_LIB XMLDeclaration : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLDeclaration* ToDeclaration() { - return this; - } - virtual const XMLDeclaration* ToDeclaration() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLDeclaration( XMLDocument* doc ); - virtual ~XMLDeclaration(); - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - XMLDeclaration( const XMLDeclaration& ); // not supported - XMLDeclaration& operator=( const XMLDeclaration& ); // not supported -}; - - -/** Any tag that TinyXML-2 doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into XMLUnknowns. -*/ -class TINYXML2_LIB XMLUnknown : public XMLNode -{ - friend class XMLDocument; -public: - virtual XMLUnknown* ToUnknown() { - return this; - } - virtual const XMLUnknown* ToUnknown() const { - return this; - } - - virtual bool Accept( XMLVisitor* visitor ) const; - - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - XMLUnknown( XMLDocument* doc ); - virtual ~XMLUnknown(); - - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - XMLUnknown( const XMLUnknown& ); // not supported - XMLUnknown& operator=( const XMLUnknown& ); // not supported -}; - - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not XMLNodes. You may only query the - Next() attribute in a list. -*/ -class TINYXML2_LIB XMLAttribute -{ - friend class XMLElement; -public: - /// The name of the attribute. - const char* Name() const; - - /// The value of the attribute. - const char* Value() const; - - /// Gets the line number the attribute is in, if the document was parsed from a file. - int GetLineNum() const { return _parseLineNum; } - - /// The next attribute in the list. - const XMLAttribute* Next() const { - return _next; - } - - /** IntValue interprets the attribute as an integer, and returns the value. - If the value isn't an integer, 0 will be returned. There is no error checking; - use QueryIntValue() if you need error checking. - */ - int IntValue() const { - int i = 0; - QueryIntValue(&i); - return i; - } - - int64_t Int64Value() const { - int64_t i = 0; - QueryInt64Value(&i); - return i; - } - - /// Query as an unsigned integer. See IntValue() - unsigned UnsignedValue() const { - unsigned i=0; - QueryUnsignedValue( &i ); - return i; - } - /// Query as a boolean. See IntValue() - bool BoolValue() const { - bool b=false; - QueryBoolValue( &b ); - return b; - } - /// Query as a double. See IntValue() - double DoubleValue() const { - double d=0; - QueryDoubleValue( &d ); - return d; - } - /// Query as a float. See IntValue() - float FloatValue() const { - float f=0; - QueryFloatValue( &f ); - return f; - } - - /** QueryIntValue interprets the attribute as an integer, and returns the value - in the provided parameter. The function will return XML_SUCCESS on success, - and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. - */ - XMLError QueryIntValue( int* value ) const; - /// See QueryIntValue - XMLError QueryUnsignedValue( unsigned int* value ) const; - /// See QueryIntValue - XMLError QueryInt64Value(int64_t* value) const; - /// See QueryIntValue - XMLError QueryBoolValue( bool* value ) const; - /// See QueryIntValue - XMLError QueryDoubleValue( double* value ) const; - /// See QueryIntValue - XMLError QueryFloatValue( float* value ) const; - - /// Set the attribute to a string value. - void SetAttribute( const char* value ); - /// Set the attribute to value. - void SetAttribute( int value ); - /// Set the attribute to value. - void SetAttribute( unsigned value ); - /// Set the attribute to value. - void SetAttribute(int64_t value); - /// Set the attribute to value. - void SetAttribute( bool value ); - /// Set the attribute to value. - void SetAttribute( double value ); - /// Set the attribute to value. - void SetAttribute( float value ); - -private: - enum { BUF_SIZE = 200 }; - - XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {} - virtual ~XMLAttribute() {} - - XMLAttribute( const XMLAttribute& ); // not supported - void operator=( const XMLAttribute& ); // not supported - void SetName( const char* name ); - - char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr ); - - mutable StrPair _name; - mutable StrPair _value; - int _parseLineNum; - XMLAttribute* _next; - MemPool* _memPool; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TINYXML2_LIB XMLElement : public XMLNode -{ - friend class XMLDocument; -public: - /// Get the name of an element (which is the Value() of the node.) - const char* Name() const { - return Value(); - } - /// Set the name of the element. - void SetName( const char* str, bool staticMem=false ) { - SetValue( str, staticMem ); - } - - virtual XMLElement* ToElement() { - return this; - } - virtual const XMLElement* ToElement() const { - return this; - } - virtual bool Accept( XMLVisitor* visitor ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none - exists. For example: - - @verbatim - const char* value = ele->Attribute( "foo" ); - @endverbatim - - The 'value' parameter is normally null. However, if specified, - the attribute will only be returned if the 'name' and 'value' - match. This allow you to write code: - - @verbatim - if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); - @endverbatim - - rather than: - @verbatim - if ( ele->Attribute( "foo" ) ) { - if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); - } - @endverbatim - */ - const char* Attribute( const char* name, const char* value=0 ) const; - - /** Given an attribute name, IntAttribute() returns the value - of the attribute interpreted as an integer. The default - value will be returned if the attribute isn't present, - or if there is an error. (For a method with error - checking, see QueryIntAttribute()). - */ - int IntAttribute(const char* name, int defaultValue = 0) const; - /// See IntAttribute() - unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const; - /// See IntAttribute() - int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const; - /// See IntAttribute() - bool BoolAttribute(const char* name, bool defaultValue = false) const; - /// See IntAttribute() - double DoubleAttribute(const char* name, double defaultValue = 0) const; - /// See IntAttribute() - float FloatAttribute(const char* name, float defaultValue = 0) const; - - /** Given an attribute name, QueryIntAttribute() returns - XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion - can't be performed, or XML_NO_ATTRIBUTE if the attribute - doesn't exist. If successful, the result of the conversion - will be written to 'value'. If not successful, nothing will - be written to 'value'. This allows you to provide default - value: - - @verbatim - int value = 10; - QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 - @endverbatim - */ - XMLError QueryIntAttribute( const char* name, int* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryIntValue( value ); - } - - /// See QueryIntAttribute() - XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryUnsignedValue( value ); - } - - /// See QueryIntAttribute() - XMLError QueryInt64Attribute(const char* name, int64_t* value) const { - const XMLAttribute* a = FindAttribute(name); - if (!a) { - return XML_NO_ATTRIBUTE; - } - return a->QueryInt64Value(value); - } - - /// See QueryIntAttribute() - XMLError QueryBoolAttribute( const char* name, bool* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryBoolValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryDoubleAttribute( const char* name, double* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryDoubleValue( value ); - } - /// See QueryIntAttribute() - XMLError QueryFloatAttribute( const char* name, float* value ) const { - const XMLAttribute* a = FindAttribute( name ); - if ( !a ) { - return XML_NO_ATTRIBUTE; - } - return a->QueryFloatValue( value ); - } - - /// See QueryIntAttribute() - XMLError QueryStringAttribute(const char* name, const char** value) const { - const XMLAttribute* a = FindAttribute(name); - if (!a) { - return XML_NO_ATTRIBUTE; - } - *value = a->Value(); - return XML_SUCCESS; - } - - - - /** Given an attribute name, QueryAttribute() returns - XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion - can't be performed, or XML_NO_ATTRIBUTE if the attribute - doesn't exist. It is overloaded for the primitive types, - and is a generally more convenient replacement of - QueryIntAttribute() and related functions. - - If successful, the result of the conversion - will be written to 'value'. If not successful, nothing will - be written to 'value'. This allows you to provide default - value: - - @verbatim - int value = 10; - QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 - @endverbatim - */ - int QueryAttribute( const char* name, int* value ) const { - return QueryIntAttribute( name, value ); - } - - int QueryAttribute( const char* name, unsigned int* value ) const { - return QueryUnsignedAttribute( name, value ); - } - - int QueryAttribute(const char* name, int64_t* value) const { - return QueryInt64Attribute(name, value); - } - - int QueryAttribute( const char* name, bool* value ) const { - return QueryBoolAttribute( name, value ); - } - - int QueryAttribute( const char* name, double* value ) const { - return QueryDoubleAttribute( name, value ); - } - - int QueryAttribute( const char* name, float* value ) const { - return QueryFloatAttribute( name, value ); - } - - /// Sets the named attribute to value. - void SetAttribute( const char* name, const char* value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, int value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, unsigned value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - - /// Sets the named attribute to value. - void SetAttribute(const char* name, int64_t value) { - XMLAttribute* a = FindOrCreateAttribute(name); - a->SetAttribute(value); - } - - /// Sets the named attribute to value. - void SetAttribute( const char* name, bool value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, double value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - /// Sets the named attribute to value. - void SetAttribute( const char* name, float value ) { - XMLAttribute* a = FindOrCreateAttribute( name ); - a->SetAttribute( value ); - } - - /** - Delete an attribute. - */ - void DeleteAttribute( const char* name ); - - /// Return the first attribute in the list. - const XMLAttribute* FirstAttribute() const { - return _rootAttribute; - } - /// Query a specific attribute in the list. - const XMLAttribute* FindAttribute( const char* name ) const; - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the XMLText child - and accessing it directly. - - If the first child of 'this' is a XMLText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - */ - const char* GetText() const; - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, SetText() is limited compared to creating an XMLText child - and mutating it directly. - - If the first child of 'this' is a XMLText, SetText() sets its value to - the given string, otherwise it will create a first child that is an XMLText. - - This is a convenient method for setting the text of simple contained text: - @verbatim - This is text - fooElement->SetText( "Hullaballoo!" ); - Hullaballoo! - @endverbatim - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then it will not change "This is text", but rather prefix it with a text element: - @verbatim - Hullaballoo!This is text - @endverbatim - - For this XML: - @verbatim - - @endverbatim - SetText() will generate - @verbatim - Hullaballoo! - @endverbatim - */ - void SetText( const char* inText ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( int value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( unsigned value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText(int64_t value); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( bool value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( double value ); - /// Convenience method for setting text inside an element. See SetText() for important limitations. - void SetText( float value ); - - /** - Convenience method to query the value of a child text node. This is probably best - shown by example. Given you have a document is this form: - @verbatim - - 1 - 1.4 - - @endverbatim - - The QueryIntText() and similar functions provide a safe and easier way to get to the - "value" of x and y. - - @verbatim - int x = 0; - float y = 0; // types of x and y are contrived for example - const XMLElement* xElement = pointElement->FirstChildElement( "x" ); - const XMLElement* yElement = pointElement->FirstChildElement( "y" ); - xElement->QueryIntText( &x ); - yElement->QueryFloatText( &y ); - @endverbatim - - @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted - to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. - - */ - XMLError QueryIntText( int* ival ) const; - /// See QueryIntText() - XMLError QueryUnsignedText( unsigned* uval ) const; - /// See QueryIntText() - XMLError QueryInt64Text(int64_t* uval) const; - /// See QueryIntText() - XMLError QueryBoolText( bool* bval ) const; - /// See QueryIntText() - XMLError QueryDoubleText( double* dval ) const; - /// See QueryIntText() - XMLError QueryFloatText( float* fval ) const; - - int IntText(int defaultValue = 0) const; - - /// See QueryIntText() - unsigned UnsignedText(unsigned defaultValue = 0) const; - /// See QueryIntText() - int64_t Int64Text(int64_t defaultValue = 0) const; - /// See QueryIntText() - bool BoolText(bool defaultValue = false) const; - /// See QueryIntText() - double DoubleText(double defaultValue = 0) const; - /// See QueryIntText() - float FloatText(float defaultValue = 0) const; - - // internal: - enum ElementClosingType { - OPEN, // - CLOSED, // - CLOSING // - }; - ElementClosingType ClosingType() const { - return _closingType; - } - virtual XMLNode* ShallowClone( XMLDocument* document ) const; - virtual bool ShallowEqual( const XMLNode* compare ) const; - -protected: - char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); - -private: - XMLElement( XMLDocument* doc ); - virtual ~XMLElement(); - XMLElement( const XMLElement& ); // not supported - void operator=( const XMLElement& ); // not supported - - XMLAttribute* FindAttribute( const char* name ) { - return const_cast(const_cast(this)->FindAttribute( name )); - } - XMLAttribute* FindOrCreateAttribute( const char* name ); - //void LinkAttribute( XMLAttribute* attrib ); - char* ParseAttributes( char* p, int* curLineNumPtr ); - static void DeleteAttribute( XMLAttribute* attribute ); - XMLAttribute* CreateAttribute(); - - enum { BUF_SIZE = 200 }; - ElementClosingType _closingType; - // The attribute list is ordered; there is no 'lastAttribute' - // because the list needs to be scanned for dupes before adding - // a new attribute. - XMLAttribute* _rootAttribute; -}; - - -enum Whitespace { - PRESERVE_WHITESPACE, - COLLAPSE_WHITESPACE -}; - - -/** A Document binds together all the functionality. - It can be saved, loaded, and printed to the screen. - All Nodes are connected and allocated to a Document. - If the Document is deleted, all its Nodes are also deleted. -*/ -class TINYXML2_LIB XMLDocument : public XMLNode -{ - friend class XMLElement; - // Gives access to SetError and Push/PopDepth, but over-access for everything else. - // Wishing C++ had "internal" scope. - friend class XMLNode; - friend class XMLText; - friend class XMLComment; - friend class XMLDeclaration; - friend class XMLUnknown; -public: - /// constructor - XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); - ~XMLDocument(); - - virtual XMLDocument* ToDocument() { - TIXMLASSERT( this == _document ); - return this; - } - virtual const XMLDocument* ToDocument() const { - TIXMLASSERT( this == _document ); - return this; - } - - /** - Parse an XML file from a character string. - Returns XML_SUCCESS (0) on success, or - an errorID. - - You may optionally pass in the 'nBytes', which is - the number of bytes which will be parsed. If not - specified, TinyXML-2 will assume 'xml' points to a - null terminated string. - */ - XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); - - /** - Load an XML file from disk. - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError LoadFile( const char* filename ); - - /** - Load an XML file from disk. You are responsible - for providing and closing the FILE*. - - NOTE: The file should be opened as binary ("rb") - not text in order for TinyXML-2 to correctly - do newline normalization. - - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError LoadFile( FILE* ); - - /** - Save the XML file to disk. - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError SaveFile( const char* filename, bool compact = false ); - - /** - Save the XML file to disk. You are responsible - for providing and closing the FILE*. - - Returns XML_SUCCESS (0) on success, or - an errorID. - */ - XMLError SaveFile( FILE* fp, bool compact = false ); - - bool ProcessEntities() const { - return _processEntities; - } - Whitespace WhitespaceMode() const { - return _whitespaceMode; - } - - /** - Returns true if this document has a leading Byte Order Mark of UTF8. - */ - bool HasBOM() const { - return _writeBOM; - } - /** Sets whether to write the BOM when writing the file. - */ - void SetBOM( bool useBOM ) { - _writeBOM = useBOM; - } - - /** Return the root element of DOM. Equivalent to FirstChildElement(). - To get the first node, use FirstChild(). - */ - XMLElement* RootElement() { - return FirstChildElement(); - } - const XMLElement* RootElement() const { - return FirstChildElement(); - } - - /** Print the Document. If the Printer is not provided, it will - print to stdout. If you provide Printer, this can print to a file: - @verbatim - XMLPrinter printer( fp ); - doc.Print( &printer ); - @endverbatim - - Or you can use a printer to print to memory: - @verbatim - XMLPrinter printer; - doc.Print( &printer ); - // printer.CStr() has a const char* to the XML - @endverbatim - */ - void Print( XMLPrinter* streamer=0 ) const; - virtual bool Accept( XMLVisitor* visitor ) const; - - /** - Create a new Element associated with - this Document. The memory for the Element - is managed by the Document. - */ - XMLElement* NewElement( const char* name ); - /** - Create a new Comment associated with - this Document. The memory for the Comment - is managed by the Document. - */ - XMLComment* NewComment( const char* comment ); - /** - Create a new Text associated with - this Document. The memory for the Text - is managed by the Document. - */ - XMLText* NewText( const char* text ); - /** - Create a new Declaration associated with - this Document. The memory for the object - is managed by the Document. - - If the 'text' param is null, the standard - declaration is used.: - @verbatim - - @endverbatim - */ - XMLDeclaration* NewDeclaration( const char* text=0 ); - /** - Create a new Unknown associated with - this Document. The memory for the object - is managed by the Document. - */ - XMLUnknown* NewUnknown( const char* text ); - - /** - Delete a node associated with this document. - It will be unlinked from the DOM. - */ - void DeleteNode( XMLNode* node ); - - void ClearError() { - SetError(XML_SUCCESS, 0, 0); - } - - /// Return true if there was an error parsing the document. - bool Error() const { - return _errorID != XML_SUCCESS; - } - /// Return the errorID. - XMLError ErrorID() const { - return _errorID; - } - const char* ErrorName() const; - static const char* ErrorIDToName(XMLError errorID); - - /** Returns a "long form" error description. A hopefully helpful - diagnostic with location, line number, and/or additional info. - */ - const char* ErrorStr() const; - - /// A (trivial) utility function that prints the ErrorStr() to stdout. - void PrintError() const; - - /// Return the line where the error occured, or zero if unknown. - int ErrorLineNum() const - { - return _errorLineNum; - } - - /// Clear the document, resetting it to the initial state. - void Clear(); - - /** - Copies this document to a target document. - The target will be completely cleared before the copy. - If you want to copy a sub-tree, see XMLNode::DeepClone(). - - NOTE: that the 'target' must be non-null. - */ - void DeepCopy(XMLDocument* target) const; - - // internal - char* Identify( char* p, XMLNode** node ); - - // internal - void MarkInUse(XMLNode*); - - virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { - return 0; - } - virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { - return false; - } - -private: - XMLDocument( const XMLDocument& ); // not supported - void operator=( const XMLDocument& ); // not supported - - bool _writeBOM; - bool _processEntities; - XMLError _errorID; - Whitespace _whitespaceMode; - mutable StrPair _errorStr; - int _errorLineNum; - char* _charBuffer; - int _parseCurLineNum; - int _parsingDepth; - // Memory tracking does add some overhead. - // However, the code assumes that you don't - // have a bunch of unlinked nodes around. - // Therefore it takes less memory to track - // in the document vs. a linked list in the XMLNode, - // and the performance is the same. - DynArray _unlinked; - - MemPoolT< sizeof(XMLElement) > _elementPool; - MemPoolT< sizeof(XMLAttribute) > _attributePool; - MemPoolT< sizeof(XMLText) > _textPool; - MemPoolT< sizeof(XMLComment) > _commentPool; - - static const char* _errorNames[XML_ERROR_COUNT]; - - void Parse(); - - void SetError( XMLError error, int lineNum, const char* format, ... ); - - // Something of an obvious security hole, once it was discovered. - // Either an ill-formed XML or an excessively deep one can overflow - // the stack. Track stack depth, and error out if needed. - class DepthTracker { - public: - DepthTracker(XMLDocument * document) { - this->_document = document; - document->PushDepth(); - } - ~DepthTracker() { - _document->PopDepth(); - } - private: - XMLDocument * _document; - }; - void PushDepth(); - void PopDepth(); - - template - NodeType* CreateUnlinkedNode( MemPoolT& pool ); -}; - -template -inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT& pool ) -{ - TIXMLASSERT( sizeof( NodeType ) == PoolElementSize ); - TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() ); - NodeType* returnNode = new (pool.Alloc()) NodeType( this ); - TIXMLASSERT( returnNode ); - returnNode->_memPool = &pool; - - _unlinked.Push(returnNode); - return returnNode; -} - -/** - A XMLHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - XMLElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - XMLElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - XMLElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - XMLElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. XMLHandle addresses the verbosity - of such code. A XMLHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - XMLHandle docHandle( &document ); - XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - XMLHandle handleCopy = handle; - @endverbatim - - See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. -*/ -class TINYXML2_LIB XMLHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - XMLHandle( XMLNode* node ) : _node( node ) { - } - /// Create a handle from a node. - XMLHandle( XMLNode& node ) : _node( &node ) { - } - /// Copy constructor - XMLHandle( const XMLHandle& ref ) : _node( ref._node ) { - } - /// Assignment - XMLHandle& operator=( const XMLHandle& ref ) { - _node = ref._node; - return *this; - } - - /// Get the first child of this handle. - XMLHandle FirstChild() { - return XMLHandle( _node ? _node->FirstChild() : 0 ); - } - /// Get the first child element of this handle. - XMLHandle FirstChildElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 ); - } - /// Get the last child of this handle. - XMLHandle LastChild() { - return XMLHandle( _node ? _node->LastChild() : 0 ); - } - /// Get the last child element of this handle. - XMLHandle LastChildElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->LastChildElement( name ) : 0 ); - } - /// Get the previous sibling of this handle. - XMLHandle PreviousSibling() { - return XMLHandle( _node ? _node->PreviousSibling() : 0 ); - } - /// Get the previous sibling element of this handle. - XMLHandle PreviousSiblingElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); - } - /// Get the next sibling of this handle. - XMLHandle NextSibling() { - return XMLHandle( _node ? _node->NextSibling() : 0 ); - } - /// Get the next sibling element of this handle. - XMLHandle NextSiblingElement( const char* name = 0 ) { - return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 ); - } - - /// Safe cast to XMLNode. This can return null. - XMLNode* ToNode() { - return _node; - } - /// Safe cast to XMLElement. This can return null. - XMLElement* ToElement() { - return ( _node ? _node->ToElement() : 0 ); - } - /// Safe cast to XMLText. This can return null. - XMLText* ToText() { - return ( _node ? _node->ToText() : 0 ); - } - /// Safe cast to XMLUnknown. This can return null. - XMLUnknown* ToUnknown() { - return ( _node ? _node->ToUnknown() : 0 ); - } - /// Safe cast to XMLDeclaration. This can return null. - XMLDeclaration* ToDeclaration() { - return ( _node ? _node->ToDeclaration() : 0 ); - } - -private: - XMLNode* _node; -}; - - -/** - A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the - same in all regards, except for the 'const' qualifiers. See XMLHandle for API. -*/ -class TINYXML2_LIB XMLConstHandle -{ -public: - XMLConstHandle( const XMLNode* node ) : _node( node ) { - } - XMLConstHandle( const XMLNode& node ) : _node( &node ) { - } - XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) { - } - - XMLConstHandle& operator=( const XMLConstHandle& ref ) { - _node = ref._node; - return *this; - } - - const XMLConstHandle FirstChild() const { - return XMLConstHandle( _node ? _node->FirstChild() : 0 ); - } - const XMLConstHandle FirstChildElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 ); - } - const XMLConstHandle LastChild() const { - return XMLConstHandle( _node ? _node->LastChild() : 0 ); - } - const XMLConstHandle LastChildElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 ); - } - const XMLConstHandle PreviousSibling() const { - return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); - } - const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); - } - const XMLConstHandle NextSibling() const { - return XMLConstHandle( _node ? _node->NextSibling() : 0 ); - } - const XMLConstHandle NextSiblingElement( const char* name = 0 ) const { - return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 ); - } - - - const XMLNode* ToNode() const { - return _node; - } - const XMLElement* ToElement() const { - return ( _node ? _node->ToElement() : 0 ); - } - const XMLText* ToText() const { - return ( _node ? _node->ToText() : 0 ); - } - const XMLUnknown* ToUnknown() const { - return ( _node ? _node->ToUnknown() : 0 ); - } - const XMLDeclaration* ToDeclaration() const { - return ( _node ? _node->ToDeclaration() : 0 ); - } - -private: - const XMLNode* _node; -}; - - -/** - Printing functionality. The XMLPrinter gives you more - options than the XMLDocument::Print() method. - - It can: - -# Print to memory. - -# Print to a file you provide. - -# Print XML without a XMLDocument. - - Print to Memory - - @verbatim - XMLPrinter printer; - doc.Print( &printer ); - SomeFunction( printer.CStr() ); - @endverbatim - - Print to a File - - You provide the file pointer. - @verbatim - XMLPrinter printer( fp ); - doc.Print( &printer ); - @endverbatim - - Print without a XMLDocument - - When loading, an XML parser is very useful. However, sometimes - when saving, it just gets in the way. The code is often set up - for streaming, and constructing the DOM is just overhead. - - The Printer supports the streaming case. The following code - prints out a trivially simple XML file without ever creating - an XML document. - - @verbatim - XMLPrinter printer( fp ); - printer.OpenElement( "foo" ); - printer.PushAttribute( "foo", "bar" ); - printer.CloseElement(); - @endverbatim -*/ -class TINYXML2_LIB XMLPrinter : public XMLVisitor -{ -public: - /** Construct the printer. If the FILE* is specified, - this will print to the FILE. Else it will print - to memory, and the result is available in CStr(). - If 'compact' is set to true, then output is created - with only required whitespace and newlines. - */ - XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); - virtual ~XMLPrinter() {} - - /** If streaming, write the BOM and declaration. */ - void PushHeader( bool writeBOM, bool writeDeclaration ); - /** If streaming, start writing an element. - The element must be closed with CloseElement() - */ - void OpenElement( const char* name, bool compactMode=false ); - /// If streaming, add an attribute to an open element. - void PushAttribute( const char* name, const char* value ); - void PushAttribute( const char* name, int value ); - void PushAttribute( const char* name, unsigned value ); - void PushAttribute(const char* name, int64_t value); - void PushAttribute( const char* name, bool value ); - void PushAttribute( const char* name, double value ); - /// If streaming, close the Element. - virtual void CloseElement( bool compactMode=false ); - - /// Add a text node. - void PushText( const char* text, bool cdata=false ); - /// Add a text node from an integer. - void PushText( int value ); - /// Add a text node from an unsigned. - void PushText( unsigned value ); - /// Add a text node from an unsigned. - void PushText(int64_t value); - /// Add a text node from a bool. - void PushText( bool value ); - /// Add a text node from a float. - void PushText( float value ); - /// Add a text node from a double. - void PushText( double value ); - - /// Add a comment - void PushComment( const char* comment ); - - void PushDeclaration( const char* value ); - void PushUnknown( const char* value ); - - virtual bool VisitEnter( const XMLDocument& /*doc*/ ); - virtual bool VisitExit( const XMLDocument& /*doc*/ ) { - return true; - } - - virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); - virtual bool VisitExit( const XMLElement& element ); - - virtual bool Visit( const XMLText& text ); - virtual bool Visit( const XMLComment& comment ); - virtual bool Visit( const XMLDeclaration& declaration ); - virtual bool Visit( const XMLUnknown& unknown ); - - /** - If in print to memory mode, return a pointer to - the XML file in memory. - */ - const char* CStr() const { - return _buffer.Mem(); - } - /** - If in print to memory mode, return the size - of the XML file in memory. (Note the size returned - includes the terminating null.) - */ - int CStrSize() const { - return _buffer.Size(); - } - /** - If in print to memory mode, reset the buffer to the - beginning. - */ - void ClearBuffer() { - _buffer.Clear(); - _buffer.Push(0); - _firstElement = true; - } - -protected: - virtual bool CompactMode( const XMLElement& ) { return _compactMode; } - - /** Prints out the space before an element. You may override to change - the space and tabs used. A PrintSpace() override should call Print(). - */ - virtual void PrintSpace( int depth ); - void Print( const char* format, ... ); - void Write( const char* data, size_t size ); - inline void Write( const char* data ) { Write( data, strlen( data ) ); } - void Putc( char ch ); - - void SealElementIfJustOpened(); - bool _elementJustOpened; - DynArray< const char*, 10 > _stack; - -private: - void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. - - bool _firstElement; - FILE* _fp; - int _depth; - int _textDepth; - bool _processEntities; - bool _compactMode; - - enum { - ENTITY_RANGE = 64, - BUF_SIZE = 200 - }; - bool _entityFlag[ENTITY_RANGE]; - bool _restrictedEntityFlag[ENTITY_RANGE]; - - DynArray< char, 20 > _buffer; - - // Prohibit cloning, intentionally not implemented - XMLPrinter( const XMLPrinter& ); - XMLPrinter& operator=( const XMLPrinter& ); -}; - - -} // tinyxml2 - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -#endif // TINYXML2_INCLUDED diff --git a/src/decoder/sip/udp_server b/src/decoder/sip/udp_server deleted file mode 100755 index e4df84f..0000000 --- a/src/decoder/sip/udp_server +++ /dev/null diff --git a/src/decoder/sip/udp_server.cpp0 b/src/decoder/sip/udp_server.cpp0 deleted file mode 100644 index 7ba2902..0000000 --- a/src/decoder/sip/udp_server.cpp0 +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - - -#define BUF_SIZE 1024 - - -int main(int argc, char *argv[]) -{ - struct addrinfo hint, *result; - struct sockaddr_in client_addr; - int res, sfd, client_addr_len; - char buf[BUF_SIZE]; - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(struct sockaddr_in)); - - unsigned short port = 30026; - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - - sfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sfd == -1) - { - perror("socket error!\n"); - exit(1); - } - - res = bind(sfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - if (res == -1) - { - perror("bind error!\n"); - exit(1); - } - - while (1) - { - printf("waiting for client ...\n"); - - res = recv(sfd, buf, BUF_SIZE, 0); - if (res == -1) - { - perror("recvfrom error\n"); - exit(1); - } - printf("revceived data : %s\n", buf); - - snprintf(buf, BUF_SIZE, "hello client! Total reveive : %d.", res); -// // res = sendto(sfd, buf, strlen(buf), 0, (struct sockaddr*)&client_addr, client_addr_len); -// res = send(sfd, buf, strlen(buf), 0); -// if (res != strlen(buf) ) -// { -// perror("sendto error\n"); -// exit(1); -// } - -// printf("send %d bytes to peer", res); - -// printf("send data < %s > to client\n\n", buf); - } -} \ No newline at end of file diff --git a/src/decoder/test_28181.cpp b/src/decoder/test_28181.cpp new file mode 100644 index 0000000..4f37e8d --- /dev/null +++ b/src/decoder/test_28181.cpp @@ -0,0 +1,288 @@ +#include "./interface/DecoderManager.h" +#include +#include +#include +#include "../common/logger.hpp" +#include "./gb28181/sip/SipServer.h" + +using namespace std; + +struct decode_cbk_userdata{ + string task_id; + void* opaque; + void* opaque1; +}; + +deque m_RgbDataList; +mutex m_DataListMtx; + +thread* m_pAlgorthimThread{nullptr}; + +bool m_bfinish{false}; +int m_devId = 0; +const char* task_id = "test0"; +int skip_frame_ = 5; +int m_batch_size = 20; + + +void algorthim_process_thread(); + +void snap_shot_thread(); + +void post_decod_cbk(const void * userPtr, DeviceMemory* devFrame){ + do{ + if(m_bfinish){ + break; + } + m_DataListMtx.lock(); + if(m_RgbDataList.size() >= 30){ + m_DataListMtx.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + continue; + } + m_RgbDataList.push_back(devFrame); + m_DataListMtx.unlock(); + break; + }while (true); +} + +void decode_finished_cbk(const void * userPtr){ + decode_cbk_userdata* ptr = (decode_cbk_userdata*)userPtr; + if (ptr!= nullptr){ + printf("task finished: %s \n", ptr->task_id.c_str()); + delete ptr; + ptr = nullptr; + } +} + +bool create_task(string task_id) { + + // 创建解码任务 + DecoderManager* pDecManager = DecoderManager::getInstance(); + + MgrDecConfig config; + config.name = task_id; + config.cfg.uri = "/data/share/data/Street.uvf"; + config.cfg.post_decoded_cbk = post_decod_cbk; + config.cfg.decode_finished_cbk = decode_finished_cbk; + config.cfg.force_tcp = true; // rtsp用tcp + config.cfg.gpuid = to_string(m_devId); + config.cfg.skip_frame = skip_frame_; + + config.dec_type = DECODER_TYPE_DVPP; + + AbstractDecoder* dec = pDecManager->createDecoder(config); + if (!dec){ + printf("创建解码器失败 \n"); + return false; + } + + // decode_cbk_userdata* userPtr = new decode_cbk_userdata; + // userPtr->task_id = string(task_id); + // pDecManager->setPostDecArg(config.name, userPtr); + // pDecManager->setFinishedDecArg(config.name, userPtr); + + dec->setSnapTimeInterval(1000); + + + int input_image_width = 0; + int input_image_height = 0; + pDecManager->getResolution(config.name, input_image_width, input_image_height); + + pDecManager->startDecodeByName(config.name); + // pDecManager->closeAllDecoder(); + + return true; +} + +bool create_task_28181(string task_id) { + + // 创建解码任务 + DecoderManager* pDecManager = DecoderManager::getInstance(); + + MgrDecConfig config; + config.name = task_id; + config.cfg.uri = "34020000001310004065"; + config.cfg.post_decoded_cbk = post_decod_cbk; + config.cfg.decode_finished_cbk = decode_finished_cbk; + config.cfg.force_tcp = false; // rtsp用tcp + config.cfg.gpuid = to_string(m_devId); + config.cfg.skip_frame = skip_frame_; + + config.dec_type = DECODER_TYPE_DVPP_GB28181; + + AbstractDecoder* dec = pDecManager->createDecoder(config); + if (!dec){ + printf("创建解码器失败 \n"); + return false; + } + + // decode_cbk_userdata* userPtr = new decode_cbk_userdata; + // userPtr->task_id = string(task_id); + // pDecManager->setPostDecArg(config.name, userPtr); + // pDecManager->setFinishedDecArg(config.name, userPtr); + + dec->setSnapTimeInterval(1000); + + + int input_image_width = 0; + int input_image_height = 0; + pDecManager->getResolution(config.name, input_image_width, input_image_height); + + pDecManager->startDecodeByName(config.name); + // pDecManager->closeAllDecoder(); + + return true; +} + +int main(){ + + set_default_logger(LogLevel(0), "test_decode","logs/main.log", 64 * 1024 * 1024, 64 * 1024 * 1024); + LOG_INFO("编译时间:{} {}", __DATE__, __TIME__); + + printf("start... \n"); + + ServerInfo info( + "SY_Sip_Server", + "12345678", + "192.168.60.179", + 15060, + "34020000002000000002", + "3402000000", + "sy123456", + 1800, + 3600); + + SipServer* pSipServer = SipServer::getInstance(); + pSipServer->Init(info); + + + DecoderManager* pDecManager = DecoderManager::getInstance(); + + + // 创建算法线程 + m_pAlgorthimThread = new thread([](void* arg) { + algorthim_process_thread(); + return (void*)0; + } + , nullptr); + + thread snap_thread = thread([](void* arg) { + snap_shot_thread(); + return (void*)0; + } + , nullptr); + + + + char ch = 'a'; + int task_id = 1; + + while (ch != 'q') { + ch = getchar(); + switch (ch) + { + case '4': + for (size_t i = 0; i < 4; i++) + { + create_task(to_string(task_id)); + task_id++; + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + break; + case 'a': + create_task(to_string(task_id)); + task_id++; + std::this_thread::sleep_for(std::chrono::seconds(1)); + break; + case 'c': + pDecManager->closeAllDecoder(); + break; + case 'g': + create_task_28181(to_string(task_id)); + task_id++; + std::this_thread::sleep_for(std::chrono::seconds(1)); + default: + break; + } + } +} + +void do_work(vector vec_gpuMem){ + for(int i=0;i < vec_gpuMem.size(); i++){ + DeviceMemory* mem = vec_gpuMem[i]; + printf("task:%s width:%d height:%d ts:%lld \n", mem->getId().c_str(), mem->getWidth(), mem->getHeight(), mem->getTimesstamp()); + } +} + +void algorthim_process_thread(){ + + while (true){ + if(m_bfinish){ + break; + } + + vector vec_gpuMem; + m_DataListMtx.lock(); + while (!m_RgbDataList.empty()){ + DeviceMemory* gpuMem = m_RgbDataList.front(); + if(gpuMem->getMem() == nullptr){ + // 错误数据,直接删除 + delete gpuMem; + gpuMem = nullptr; + printf("mem is null \n"); + } else { + vec_gpuMem.push_back(gpuMem); + } + m_RgbDataList.pop_front(); + if(vec_gpuMem.size() >= m_batch_size){ + break; + } + } + m_DataListMtx.unlock(); + + if(vec_gpuMem.size() <= 0){ + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + continue; + } + + // do work + do_work(vec_gpuMem); + + for(int i=0;i < vec_gpuMem.size(); i++){ + DeviceMemory* mem = vec_gpuMem[i]; + if(mem->getSize() <= 0){ + continue; + } + delete mem; + mem = nullptr; + } + // vec_gpuMem.clear(); + + vector().swap(vec_gpuMem); + + } + + printf("algorthim_process_thread exit. \n"); +} + +void snap_shot_thread(){ + DecoderManager* pDecManager = DecoderManager::getInstance(); + while (true){ + if(m_bfinish){ + break; + } + + vector vec_devMem = pDecManager->timing_snapshot_all(); + for(auto devMem : vec_devMem){ + delete devMem; + devMem = nullptr; + } + // vec_devMem.clear(); + + vector().swap(vec_devMem); + + std::this_thread::sleep_for(std::chrono::milliseconds(600)); + + } +} \ No newline at end of file diff --git a/src/decoder/test_decoder.cpp b/src/decoder/test_decoder.cpp.dvpp index 7760ebf..7760ebf 100644 --- a/src/decoder/test_decoder.cpp +++ b/src/decoder/test_decoder.cpp.dvpp diff --git a/src/demo/demo.cpp b/src/demo/demo.cpp index 481e446..846e90b 100755 --- a/src/demo/demo.cpp +++ b/src/demo/demo.cpp @@ -1147,8 +1147,18 @@ void test_gpu(int gpuID){ // } - createTask(handle, algor_vec2, 8, false); - createTask(handle, algor_vec2, 27, false); + createTask(handle, algor_vec2, 0, false); + createTask(handle, algor_vec2, 2, false); + createTask(handle, algor_vec2, 0, false); + createTask(handle, algor_vec2, 2, false); + createTask(handle, algor_vec2, 0, false); + createTask(handle, algor_vec2, 2, false); + createTask(handle, algor_vec2, 0, false); + createTask(handle, algor_vec2, 2, false); + createTask(handle, algor_vec2, 0, false); + createTask(handle, algor_vec2, 2, false); + createTask(handle, algor_vec2, 0, false); + createTask(handle, algor_vec2, 2, false); while (getchar() != 'q');