Hardware is DM368, software is Appro IPNC SDK 4.x.
We are trying to get the blessed thing to pass ONVIF compliance test and include PTZ controls, it looks like we need to add to the list of services returned to Onvif "GetServices" request (in onvif.c) but I can't see the correct way to insert items on the Services / Capabilities list. The existing code is:
int __tds__GetServices(struct soap* soap, struct _tds__GetServices *tds__GetServices, struct _tds__GetServicesResponse *tds__GetServicesResponse)
{
char _IPAddr[URI_LENGTH];
int i = 0;
NET_IPV4 ip;
ip.int32 = net_get_ifaddr(ETH_NAME);
sprintf(_IPAddr, "http://%d.%d.%d.%d/onvif/services", ip.str[0], ip.str[1], ip.str[2], ip.str[3]);
tds__GetServicesResponse->__sizeService = 1;
if(!tds__GetServices->IncludeCapability)
{
tds__GetServicesResponse->Service = (struct tds__Service *)soap_malloc(soap, sizeof(struct tds__Service));
tds__GetServicesResponse->__sizeService = 1; // There are <n> tds__Service structs in tds__GetServicesResponse->Service
tds__GetServicesResponse->Service[0].XAddr = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
tds__GetServicesResponse->Service[0].Namespace = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
strcpy(tds__GetServicesResponse->Service[0].Namespace, "http://www.onvif.org/ver10/events/wsdl");
strcpy(tds__GetServicesResponse->Service[0].XAddr, _IPAddr);
tds__GetServicesResponse->Service[0].Capabilities = NULL;
tds__GetServicesResponse->Service[0].Version = (struct ns2__OnvifVersion *)soap_malloc(soap, sizeof(struct ns2__OnvifVersion));
tds__GetServicesResponse->Service[0].Version->Major = 0;
tds__GetServicesResponse->Service[0].Version->Minor = 3;
tds__GetServicesResponse->Service[0].__any = (char **)soap_malloc(soap, 2*sizeof(char *)); // Malloc Double the size of a pointer to char
tds__GetServicesResponse->Service[0].__any[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
strcpy(tds__GetServicesResponse->Service[0].__any[0],"Face Detection ");
tds__GetServicesResponse->Service[0].__any[1] = (char *)soap_malloc(soap,sizeof(char) * INFO_LENGTH);
strcpy(tds__GetServicesResponse->Service[0].__any[1],"Motion Detection ");
tds__GetServicesResponse->Service[0].__size = NULL;
tds__GetServicesResponse->Service[0].__anyAttribute = NULL;
return SOAP_OK;
}
else
{
tds__GetServicesResponse->Service = (struct tds__Service *)soap_malloc(soap, sizeof(struct tds__Service));
tds__GetServicesResponse->__sizeService = 1;
tds__GetServicesResponse->Service[0].Namespace = NULL;
tds__GetServicesResponse->Service[0].XAddr = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
strcpy(tds__GetServicesResponse->Service[0].XAddr, _IPAddr);
tds__GetServicesResponse->Service[0].Capabilities = NULL;
tds__GetServicesResponse->Service[0].Version = (struct ns2__OnvifVersion *)soap_malloc(soap, sizeof(struct ns2__OnvifVersion));
tds__GetServicesResponse->Service[0].Version->Major = 0;
tds__GetServicesResponse->Service[0].Version->Minor = 3;
tds__GetServicesResponse->Service[0].__size = NULL;
tds__GetServicesResponse->Service[0].__any = NULL;
tds__GetServicesResponse->Service[0].__anyAttribute = NULL;
return SOAP_OK;
}
}
Now, I have spent a while reading through the code and thought this looked like a reasonable way to go about things, but it just SEGFAULTs as soon as it gets the request:
int __tds__GetServices(struct soap* soap, struct _tds__GetServices *tds__GetServices, struct _tds__GetServicesResponse *tds__GetServicesResponse)
{
char _IPAddr[URI_LENGTH];
int i = 0;
NET_IPV4 ip;
ip.int32 = net_get_ifaddr(ETH_NAME);
sprintf(_IPAddr, "http://%d.%d.%d.%d/onvif/services", ip.str[0], ip.str[1], ip.str[2], ip.str[3]);
tds__GetServicesResponse->__sizeService = 2; // There are <n> tds__Service structs in tds__GetServicesResponse->Service
tds__GetServicesResponse->Service = (struct tds__Service *)soap_malloc(soap, 2 * sizeof(struct tds__Service));
tds__GetServicesResponse->Service[0].XAddr = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
tds__GetServicesResponse->Service[0].Namespace = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
strcpy(tds__GetServicesResponse->Service[0].Namespace, "http://www.onvif.org/ver10/events/wsdl");
strcpy(tds__GetServicesResponse->Service[0].XAddr, _IPAddr);
tds__GetServicesResponse->Service[0].Capabilities = NULL;
tds__GetServicesResponse->Service[0].Version = (struct ns2__OnvifVersion *)soap_malloc(soap, sizeof(struct ns2__OnvifVersion));
tds__GetServicesResponse->Service[0].Version->Major = 1;
tds__GetServicesResponse->Service[0].Version->Minor = 0;
tds__GetServicesResponse->Service[0].__size = NULL;
tds__GetServicesResponse->Service[0].__any = NULL;
tds__GetServicesResponse->Service[0].__anyAttribute = NULL;
/// Now the 2nd service
tds__GetServicesResponse->Service[1].XAddr = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
tds__GetServicesResponse->Service[1].Namespace = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
strcpy(tds__GetServicesResponse->Service[1].Namespace, "http://www.onvif.org/ver20/ptz/wsdl");
strcpy(tds__GetServicesResponse->Service[1].XAddr, _IPAddr);
tds__GetServicesResponse->Service[1].Capabilities = (char *)soap_malloc(soap, sizeof(char) * URI_LENGTH);
strcpy(tds__GetServicesResponse->Service[1].Capabilities, "<tptz:Capabilities xmlns:tptz=\"http://www.onvif.org/ver20/ptz/wsdl\" EFlip=\"false\" Reverse=\"false\" />");
tds__GetServicesResponse->Service[1].Version = (struct ns2__OnvifVersion *)soap_malloc(soap, sizeof(struct ns2__OnvifVersion));
tds__GetServicesResponse->Service[1].Version->Major = 2;
tds__GetServicesResponse->Service[1].Version->Minor = 20;
tds__GetServicesResponse->Service[1].__size = NULL;
tds__GetServicesResponse->Service[1].__any = NULL;
tds__GetServicesResponse->Service[1].__anyAttribute = NULL;
return SOAP_OK;
}
The sort of response we are looking for has more than one entry, like this example from the Onvif Core Spec document:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:enc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema">
<env:Header>
</env:Header>
<env:Body>
<tds:GetServicesResponse>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/device/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.10/onvif/device_service</tds:XAddr>
<tds:Capabilities>
<tds:Capabilities>
<tds:Network IPFilter="false" ZeroConfiguration="true" IPVersion6="false" DynDNS="false" Dot11Configuration="false" HostnameFromDHCP="false" NTP="0" />
<tds:Security TLS1.0="false" TLS1.1="false" TLS1.2="false" OnboardKeyGeneration="false" AccessPolicyConfig="false" DefaultAccessPolicy="false" Dot1X="false" RemoteUserHandling="false" X.509Token="false" SAMLToken="false" KerberosToken="false" UsernameToken="false" HttpDigest="false" RELToken="false" />
<tds:System DiscoveryResolve="true" DiscoveryBye="true" RemoteDiscovery="false" SystemBackup="false" SystemLogging="false" FirmwareUpgrade="true" HttpFirmwareUpgrade="false" HttpSystemBackup="false" HttpSystemLogging="false" HttpSupportInformation="false" />
<tds:MiscCapabilities AuxiliaryCommands="" />
</tds:Capabilities>
</tds:Capabilities>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>20</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/media/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.10/onvif</tds:XAddr>
<tds:Capabilities>
<trt:Capabilities xmlns:trt="http://www.onvif.org/ver10/media/wsdl" SnapshotUri="true" Rotation="false">
<trt:ProfileCapabilities MaximumNumberOfProfiles="10" />
<trt:StreamingCapabilities RTPMulticast="true" RTP_TCP="false" RTP_RTSP_TCP="true" NonAggregateControl="true" />
</trt:Capabilities>
</tds:Capabilities>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>20</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver20/ptz/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.10/onvif</tds:XAddr>
<tds:Capabilities>
<tptz:Capabilities xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" EFlip="false" Reverse="false" />
</tds:Capabilities>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>20</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/events/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.10/onvif</tds:XAddr>
<tds:Capabilities>
<tev:Capabilities xmlns:tev="http://www.onvif.org/ver10/events/wsdl" WSSubscriptionPolicySupport="false" WSPullPointSupport="false" WSPausableSubscription="false" />
</tds:Capabilities>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>20</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver20/imaging/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.10/onvif</tds:XAddr>
<tds:Capabilities>
<timg:Capabilities xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" ImageStabilization="false" />
</tds:Capabilities>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>20</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/deviceIO/wsdl</tds:Namespace>
<tds:XAddr>http://192.168.0.10/onvif</tds:XAddr>
<tds:Capabilities>
<tmd:Capabilities xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" VideoSources="1" VideoOutputs="0" AudioSources="1" AudioOutputs="1" RelayOutputs="0" SerialPorts="0" DigitalInputs="0" />
</tds:Capabilities>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>20</tt:Minor>
</tds:Version>
</tds:Service>
</tds:GetServicesResponse>
</env:Body>
</env:Envelope>
Can anyone help with the correct way to add multiple services into that code?