记一次onvif协议开发遇到的异常处理
在一次对接海康onvif协议设备时,调用getprotfiles 返回错误码4(SOAP_TYPE),意思是 :An XML Schema type mismatch 。
显然问题出在海康设备返回的数据格式不对,唯一能做的就是找到出错的数据,然后看看能不能修改一下soap源代码,让其流程继续进行下去。
采用非常暴力的排查方法,将返回SOAP_TYPE的地方全部打上断点,然后运行程序。后来定位到是在stdsoap2.cpp的一个转换成long的函数中,源码如下:
点击查看代码
#ifndef PALM_2
SOAP_FMAC1
int
SOAP_FMAC2
soap_s2long(struct soap *soap, const char *s, long *p)
{ if (s)
{ char *r;
#ifndef WITH_NOIO
#ifndef WITH_LEAN
soap_reset_errno;
#endif
#endif
*p = soap_strtol(s, &r, 10);
if (s == r || *r
#ifndef WITH_NOIO
#ifndef WITH_LEAN
|| soap_errno == SOAP_ERANGE
#endif
#endif
)
soap->error = SOAP_TYPE;
}
return soap->error;
}
#endif
当s="H265"时,soap_strtol处理失败,返回SOAP_TYPE。
于是将soap_s2long函数的代码修改一下,让其不返回错误,问题暂时得到解决。
点击查看代码
#ifndef PALM_2
SOAP_FMAC1
int
SOAP_FMAC2
soap_s2long(struct soap *soap, const char *s, long *p)
{ if (s)
{ char *r;
#ifndef WITH_NOIO
#ifndef WITH_LEAN
soap_reset_errno;
#endif
#endif
long res = soap_strtol(s, &r, 10);
if( 0 == res)
{
*p = 0;
return soap->error;
}
*p = soap_strtol(s, &r, 10);
if (s == r || *r
#ifndef WITH_NOIO
#ifndef WITH_LEAN
|| soap_errno == SOAP_ERANGE
#endif
#endif
)
soap->error = SOAP_TYPE;
}
return soap->error;
}
#endif
后来,用onvif device test tool 重新对 该流媒体进行了测试分析,发现其出错的地方是在
tt:EncodingH265</tt:Encoding> 这一处。至于为什么soap库要将其解析为long还不得而知。
点击查看代码
<tt:VideoEncoderConfiguration token="VideoEncoderToken_2">
<tt:Name>VideoEncoder_2</tt:Name>
<tt:UseCount>1</tt:UseCount>
<tt:Encoding>H265</tt:Encoding>
<tt:Resolution>
<tt:Width>352</tt:Width>
<tt:Height>288</tt:Height>
</tt:Resolution>
<tt:Quality>3.000000</tt:Quality>
<tt:RateControl>
<tt:FrameRateLimit>8</tt:FrameRateLimit>
<tt:EncodingInterval>1</tt:EncodingInterval>
<tt:BitrateLimit>128</tt:BitrateLimit>
</tt:RateControl>
<tt:Multicast>
<tt:Address>
<tt:Type>IPv4</tt:Type>
<tt:IPv4Address>239.255.2.15</tt:IPv4Address>
</tt:Address>
<tt:Port>8866</tt:Port>
<tt:TTL>128</tt:TTL>
<tt:AutoStart>false</tt:AutoStart>
</tt:Multicast>
<tt:SessionTimeout>PT5S</tt:SessionTimeout>
</tt:VideoEncoderConfiguration>