便于调用gsoap onvif接口
#pragma once
#include
#include "soapStub.h"
#include "wsseapi.h"
#include "wsddapi.h"
#include "httpda.h"
extern SOAP_NMAC struct Namespace discoveryNamespaces[];
extern SOAP_NMAC struct Namespace mediaNamespaces[];
namespace ONVIF
{
using cstrRef = const std::string&;
template <class T, class U >
class SoapHelper
{
public:
using _soap_call_ = int(*)(struct soap*, const char*, const char*, T*, U&);
public:
SoapHelper(
cstrRef url,
cstrRef user,
cstrRef pwd,
T& req,
_soap_call_ call,
int timeout = 5)
: _url(url)
, _user(user)
, _pwd(pwd)
, _req(req)
, _call(call)
{
_soap = soap_new1(SOAP_IO_DEFAULT | SOAP_C_UTFSTRING);
_soap->send_timeout = timeout;
_soap->recv_timeout = timeout;
_soap->connect_timeout = timeout;
soap_wsse_add_UsernameTokenDigest(_soap, NULL, user.c_str(), pwd.c_str());
}
SoapHelper(
struct soap* soap,
cstrRef url,
cstrRef user,
cstrRef pwd,
T& req,
_soap_call_ call,
int timeout = 5)
: _soap(soap)
, _url(url)
, _user(user)
, _pwd(pwd)
, _req(req)
, _call(call)
{
_soap->send_timeout = timeout;
_soap->recv_timeout = timeout;
_soap->connect_timeout = timeout;
soap_wsse_add_UsernameTokenDigest(_soap, NULL, user.c_str(), pwd.c_str());
}
~SoapHelper()
{
soap_destroy(_soap); // delete managed objects
soap_end(_soap); // delete managed data and temporaries
soap_free(_soap); // finalize and delete the context
}
U& Rsp()
{
return _rsp;
}
int Call()
{
// make a copy for soap_header;
auto header = _soap->header;
// make a copy for wsse security;
auto wsse = header->wsse__Security;
auto ret = _call(_soap, _url.c_str(), NULL, &_req, _rsp);
if (ret != SOAP_OK)
{
// retry with digest authorization
if (_soap->error == 401 || _soap->status == 400)
{
// clear wsse
header->wsse__Security = nullptr;
// regist http digest plugin
soap_register_plugin(_soap, http_da);
struct http_da_info info;
// set header
_soap->header = header;
ret = _call(_soap, _url.c_str(), NULL, &_req, _rsp);
if (_soap->error == 401) // HTTP authentication is required
{
http_da_save(_soap, &info, _soap->authrealm, _user.c_str(), _pwd.c_str());
// set header
_soap->header = header;
ret = _call(_soap, _url.c_str(), NULL, &_req, _rsp);// make a call with authentication
http_da_release(_soap, &info); // release
}
}
}
// restore wsse security, soap will free that
header->wsse__Security = wsse;
return ret;
}
bool Ok()
{
return _soap->error == SOAP_OK ? true : false;
}
protected:
cstrRef _url;
cstrRef _user;
cstrRef _pwd;
T& _req;
U _rsp;
_soap_call_ _call;
private:
struct soap* _soap;
};
// 由用户传入时间,若出错,返回int
#define soapcalli_t(addr, usr, pwd, req, x, t) \
using ReqType = x;\
using RspType = x##Response;\
auto callFunc = soap_call__##x;\
SoapHelper<ReqType, RspType>\
rsp(addr, usr, pwd, req, callFunc, t);\
auto ret = rsp.Call();\
if (ret != SOAP_OK)\
{\
LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
string(__FUNCTION__), std::string(#x), ret, addr);\
return SoapCodeToJxCode(ret);\
}
// 默认5秒超时,若出错,返回int
#define soapcalli(addr, usr, pwd, req, x) soapcalli_t(addr, usr, pwd, req, x, 5)
// 由用户传入时间,若出错,返回void
#define soapcallv_t(addr, usr, pwd, req, x, t) \
using ReqType = x;\
using RspType = x##Response;\
auto callFunc = soap_call__##x;\
SoapHelper<ReqType, RspType>\
rsp(addr, usr, pwd, req, callFunc, t);\
auto ret = rsp.Call();\
if (ret != SOAP_OK)\
{\
LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
string(__FUNCTION__), std::string(#x), ret, addr);\
return;\
}
// 默认5秒超时,若出错,返回void
#define soapcallv(addr, usr, pwd, req, x) soapcallv_t(addr, usr, pwd, req, x, 5)
// 由用户传入时间,无论是否出错,均不返回
#define soapcalln_t(addr, usr, pwd, req, x, t) \
using ReqType = x;\
using RspType = x##Response;\
auto callFunc = soap_call__##x;\
SoapHelper<ReqType, RspType>\
rsp(addr, usr, pwd, req, callFunc, t);\
auto ret = rsp.Call();\
if (ret != SOAP_OK)\
{\
LOG_WARNING(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
string(__FUNCTION__), std::string(#x), ret, addr);\
}
// 默认5秒超时,无论是否出错,均不返回
#define soapcalln(addr, usr, pwd, req, x) soapcalln_t(addr, usr, pwd, req, x, 5)
// 由用户传入soap、时间,若出错,返回int
#define soapcalli_s_t(soap, addr, usr, pwd, req, x, t) \
using ReqType = x;\
using RspType = x##Response;\
auto callFunc = soap_call__##x;\
SoapHelper<ReqType, RspType>\
rsp(soap, addr, usr, pwd, req, callFunc, t);\
auto ret = rsp.Call();\
if (ret != SOAP_OK)\
{\
LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
string(__FUNCTION__), std::string(#x), ret, addr);\
return SoapCodeToJxCode(ret);\
}
// 由用户传入soap,默认5s超时,若出错,返回int
#define soapcalli_s(soap, addr, usr, pwd, req, x) soapcalli_s_t(soap, addr, usr, pwd, req, x, 5)
// 由用户传入传入soap、时间,若出错,返回void
#define soapcallv_s_t(soap, addr, usr, pwd, req, x, t) \
using ReqType = x;\
using RspType = x##Response;\
auto callFunc = soap_call__##x;\
SoapHelper<ReqType, RspType>\
rsp(soap, addr, usr, pwd, req, callFunc, t);\
auto ret = rsp.Call();\
if (ret != SOAP_OK)\
{\
LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
string(__FUNCTION__), std::string(#x), ret, addr);\
return;\
}
// 由用户传入传入soap、默认5s超时,若出错,返回void
#define soapcallv_s(soap, addr, usr, pwd, req, x) soapcallv_s_t(soap, addr, usr, pwd, req, x, 5)
// 由用户传入传入soap、时间,无论是否出错,均不返回
#define soapcalln_s_t(soap, addr, usr, pwd, req, x, t) \
using ReqType = x;\
using RspType = x##Response;\
auto callFunc = soap_call__##x;\
SoapHelper<ReqType, RspType>\
rsp(soap, addr, usr, pwd, req, callFunc, t);\
auto ret = rsp.Call();\
if (ret != SOAP_OK)\
{\
LOG_WARNING(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
string(__FUNCTION__), std::string(#x), ret, addr);\
}
// 由用户传入传入soap、默认5s超时,无论是否出错,均不返回
#define soapcalln_s(soap, addr, usr, pwd, req, x) soapcalln_s_t(soap, addr, usr, pwd, req, x, 5)
// 若指针为空,返回void
#define CHECK_POINTER_V(p) \
if (p == nullptr) \
{ \
LOG_ERROR(*context_onvif->pLogger, "<%s>: null pointer: %s", string(__FUNCTION__), std::string(#p)); \
return; \
}
// 若指针为空,返回int
#define CHECK_POINTER_I(p) \
if (p == nullptr) \
{ \
LOG_ERROR(*context_onvif->pLogger, "<%s>: null pointer: %s", string(__FUNCTION__), std::string(#p)); \
return EC_NULL_POINTERER; \
}
//若指针为空,跳出当前迭代
#define CHECK_POINTER_C(p) \
if (p == nullptr) \
{ \
LOG_WARNING(*context_onvif->pLogger, "<%s>: null pointer: %s", string(__FUNCTION__), std::string(#p)); \
continue; \
}
#define SOAP_FREE_FOR_NEW(soap)\
soap_destroy(soap); \
soap_end(soap); \
soap_free(soap);
}
调用举例
// 调用举例
int main(int argc, char* argv[])
{
// 1
_trt__GetProfiles req;
soapcalli(_devAddrs[t_media], _strUserName, _strPassword, req, _trt__GetProfiles);
// 2
struct soap* soap = soap_new();
_tr2__GetProfiles req;
req.soap_default(soap);
req.Token = (std::string*)&profileToken;
req.Type.push_back(soap_tr2__ConfigurationEnumeration2s(soap, tr2__ConfigurationEnumeration__VideoEncoder));
req.Type.push_back(soap_tr2__ConfigurationEnumeration2s(soap, tr2__ConfigurationEnumeration__AudioEncoder));
soapcalli_s(soap, _devAddrs[t_media2], _strUserName, _strPassword, req, _tr2__GetProfiles);
// 3
_tds__GetDeviceInformation req;
soapcalli(_strDevAddr, _strUserName, _strPassword, req, _tds__GetDeviceInformation);
// save device info
_deviceInfo.strManufacturer = rsp.Rsp().Manufacturer;
_deviceInfo.strModel = rsp.Rsp().Model;
_deviceInfo.strFireware = rsp.Rsp().FirmwareVersion;
}