这篇文章不是对onvif device端开发的步骤和基本知识的说明,而是我在开发过程中遇到的一些问题。
很多问题,比如序列化、比如内存管理都在user guide中详细说明了,因此多看文档还是比较重要的。
关于wsdl2h和soapcpp2的使用还是比较重要的,其中我遇到的最重要的一个实际问题是:如何把生成的多个服务端的类联系起来,去监听同一个端口,
接收并分发同一份消息。gSOAP User Guide7.2.8就讲到了这个问题,因此建议soapcpp2使用-j选项:
DeviceBindingService *pDeviceBindingServiceObj = new DeviceBindingService(pSoap);
MediaBindingService *pMediaBindingServiceObj = new MediaBindingService(pSoap);
AdvancedSecurityServiceBindingService *pAdvancedSecurityBindingServiceObj = new AdvancedSecurityServiceBindingService(pSoap);
while(m_bBindingServiceRun)
{
if (soap_valid_socket(soap_accept(pSoap)))
{
if (soap_begin_serve(pSoap))
{
}
if (pDeviceBindingServiceObj->dispatch() == SOAP_NO_METHOD)
{
if (pMediaBindingServiceObj->dispatch() == SOAP_NO_METHOD)
{
if (pAdvancedSecurityBindingServiceObj->dispatch() == SOAP_NO_METHOD)
{
soap_send_fault(pSoap);
}
}
}
}
soap_destroy(pSoap);
soap_end(pSoap);
}
使用gsoap生产了onvif服务端的一些借口文件,产生了一大堆的接口函数,这些函数只有声明没有定义,于是新建一个cpp文件,把所有的函数声明拷贝进去。
这些函数太多了,有些也用不到,如果一个个的添加函数体太费体力了,于是把文件放在linux环境下,敲入命令:
sed -i 's/;/\r\n{\r\n\r\nreturn SOAP_OK;\r\n}/g' ServerSideOperation.cpp
搞定。把所有的声明,都变成了实现,即把";"都改成了"" 然后用到的接口再一个个改吧。
开发的过程中遇到了几个问题:
1 注意到soapStub.h中的结构体,大部分都只是指针,那么如果去分配空间并很好的释放呢?
这里参见gSoap user guide, gSoap中针对基本类型的数据都可以用soap_malloc来分配空间,对于class或者其他非基本数据都可以用"soap_new_CLASS"来分配,
比如要分配tt__Scope类型的空间,使用soap_new_tt__Scope就行了,最后统一使用soap_destroy; soap_end来释放空间。
2 在使用onvif device manager工具测试的时候,device list中显示的一些device信息竟然会一闪而过,然后就不显示了。
device list中显示的信息很多都在GetDeviceInformation中填写,也有需要在GetSopes中填写的数据,注意到这个scope最好和设备发现中,
也就是发送的proe_match中的消息一样。
3 明明是使用了soap_destroy和soap_end来释放临时资源,为什么还出现了内存泄露
原来是在分配这种tds__Service **Service结构体的内存时,错误地少分配了空间,导致gSoap没检测到,出现内存泄露的地方也很怪:
tds__GetServicesResponse->Service = (tds__Service**)soap_malloc(soap, sizeof(void*) );//err
tds__GetServicesResponse->Service = (tds__Service**)soap_malloc(soap, sizeof(void*) * tds__GetServicesResponse->__sizeService);
这种大意的问题找起来还是很吃力的。。
4 添加wsse认证
onvif.h文件是通过指定typemap文件和wsdl文件生成的,很奇怪的是wsse的内容需要手动添加import "wsse.h"来实现,
可能还有很多细节不了解吧。然后其他都一样了,注意到soap.header里面,也就是SOAP_ENV__Header中多了个结构体:_wsse__Security