GetProfiles Issue When Accessing Hikvision Cameras Programmatically Via ONVIF - soap

PROBLEM:
I have a number of test cameras that I'm using in development of a Cocoa ONVIF driver. I have AXIS, Dahua and Hikvision (so far -more will be coming).
All of the cameras claim conformance to Profile S and Profile G.
The AXIS cameras are the only ones that are behaving as expected.
Most can return RTSP image data if I send a direct URI to them (which, I see, is how most "ONVIF" apps seem to work).
What I am trying to do, is use the "proper channels" to access these devices.
That means running the MANDATORY GetProfiles query, like so:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:trt="http://www.onvif.org/ver10/media/wsdl">
<soap:Body>
<trt:GetProfiles/>
</soap:Body>
</soap:Envelope>
That's textbook. Straight out of the ONVIF application programming guide. I'm using a REST injection app to test this, using POST. I have set up authentication as Basic, using a full admin user.
The issue is that Hikvision cameras consistently return an "Optional Action Not Implemented" fault, which is their way of saying "We don't like what you sent".
I should note that the Core commands, like "GetServices" and "GetCapabilities" work just fine.
There is precious little lessons learned stuff out there on ONVIF. I think it's a standard that is still struggling to stand up on its own.
The only thing I've seen out there is this post.
That does not apply to me. The same issue happens when I use either WSDL version.
When I Wireshark the apps that can connect to the camera, all I see is that they directly send an RTSP URI. No mention of "GetProfiles".
My question is this an issue that anyone else has encountered?
If so, how was it solved? I am learning to loathe the ONVIF spec, as it gets real hard to find detailed packet descriptions.

It seems that you are posting all the requests to the same URI. GetServices and GetCapabilities belong to the Device management Service, while GetProfiles belongs to the Media Service, which could have a different URI (this is something you must verify with GetServices).
The ONVIF specs are abundant, I suggest you to start from the ONVIF Application Programming Guide. It gives you an idea about how to structure your application.

Related

I need help putting together a POST/PUT/GET request for my ESP32

Can someone post an example code for sending data in a URL using HTTPClient on a ESP32 (I'm using dweet as an example, I have a different site)?
Say I have a sensor data of temperature (24'C - nevermind the "'C", sensor only shows the number which is what I want) and humidity (30%) and want to send those as URL like this: http://dweet.io/sensor.php?temperature=24&humidity=30
I guess header should be "HTTP/1.0".
Ways to send over HTTPS without CA or fingerprint would also be helpful.
Practices to avoid memory leaks and to prevent errors or crashes would be a delightful bonus. :-)
You might find the protocol examples provided by ESP-IDF to be very helpful. And there are some tutorials that help with writing those requests as well.
If you do not want to use a CA and just want to have https for testing purposes, then I have found the https-mbedtls example provided by ESP-IDF to be very helpful here, as there is an option to optionally verify the certificate. MBEDTLS_SSL_VERIFY_OPTIONAL can be set to MBEDTLS_SSL_VERIFY_NONE in the https_mbedtls_example_main.c file meaning that you can use self-signed certificates without receiving an error.

Proper way to distinguish between multiple services using zeroconf

I'm writing a piece of software that will run on computers as well as phones.
The service uses an HTTP API for communication and will be published over the local network using Zeroconf.
Initially I published my service using _http._tcp. as the service type but I quickly discovered that both my NAS and my music receiver(!) also broadcasts themselves with that exact service type.
So the question now arises how to differentiate between my service and other services that are using HTTP.
Alternatives
Using a different service type
The is certainly the most certainly the easiest way and (almost) guarantees no other services will be picked up.
However, according to Apple1 new services should be registered with IANA. This is obviously not required but seeing as they recommend it it feels like it would be the wrong way to do it
Using the TXT record
Apple2 describes the TXT record like this:
When a service is registered, three related DNS records are created: a service (SRV) record, a pointer (PTR) record, and a text (TXT) record. The TXT record contains additional data needed to resolve or use the service, although it is also often empty.
The certainly feels like it could be the right way to do it, but I'm still not sure and it's hard to find a description of what the field should contain.
My first though would be to put something like <service_name>-<version> which will then be parsed to see which service it actually is.
My NAS seems to use this for identifying model and version numbers.
Try talking to the service
After finding a service one could always perform a HEAD request on a known endpoint and look for a known header set by the service.
This feels like a fairly slow approach and who knows what making a HEAD request to my receiver will do.
And just to be clear, this question has nothing to do with a specific language or framework, it's about the concepts of zeroconf.
I could show some code but I don't see how that would help.
First, does the service you're advertising actually meet the qualifications for _http as defined by RFC 2782. Specifically- is it not just using HTTP for a transport but is also:
can be displayed by "typical" web browser client software, and
is intended primarily to be viewed by a human user.
If no, register your own service type (there are a couple other services that use HTTP as a transport but don't meet those qualifications so they have -http as a suffix to the service name, see pgpkey-http, senteo-http, xul-http).
If yes, there are a couple ways to go depending on how strict one's interpretation of the RFC is. The least strict being just adding a TXT record as you've already noted in your question. iTunes registers itself with a TXT record in the format iTSh Version=196618.
If you're feeling a little more strict, the RFC only explicitly states that the u=, p= and path= TXT records exist for HTTP. Perhaps someone can chime in on this, but I haven't seen much discussion on whether adding TXT records to already existing entries is frowned upon or not. So with that, the other way is to just an algorithmic instance name. For example, adding the suffix "-NicklasAService" to the device name. Hopefully giving it a unique name to the local network but still making it so that the service can be easily picked out by the PTR record by just looking for the suffix.

Blackberry ksoap2 request issues

First time posting a question. I'm trying to call some SOAP webservices from inside a blackberry app using the ksoap2 library. I've successfully managed to get a response from the one service, which uses an HTTP url, but now that I'm trying to get response from a (different) HTTPS url, I've run up against a brick wall.
The response dump I'm getting has the following fault message:
"An error occurred while routing the message for element value : (country option I specified in my request). Keep-Alive and Close may not be set using this property. Parameter name: value."
The weird thing is that using Oxygen XML's SOAP tools with the XML request dump works just fine. Any ideas where to start looking? This has taken up a full day already.
Update:
Responding to your comment below - it turns out the double quoting is part of the SOAP spec. Some servers are more relaxed in their implementation, and will work without the quotes.
ksoap2 doesn't force the quotes onto your actions - you may want to patch your ksoap2 library to ensure the quotes are always there.
ymmv
Original:
I don't think this is a SOAP related problem, nor with BlackBerry.
I think the problem lies on the server side, since that error string is not a common error (just google it to see no hits on the whole internet other than this question).
Looks like this is a job for the network guy on the server side to tell you what he's seeing on his end.
Only other thing I can think of is to make the call using HTTP instead of HTTPS. You can then use some network sniffer to see what the difference between the messages is. Alternatively, install an SSL proxy with something like "Charles" and sniff the packets like that.

SOP issue behind reverse proxy

I've spent the last 5 months developing a gwt app, and it's now become time for third party people to start using it. In preparation for this one of them has set up my app behind a reverse proxy, and this immediately resulted in problems with the browser's same origin policy. I guess there's a problem in the response headers, but I can't seem to rewrite them in any way to make the problem go away. I've tried this
response.setHeader("Server", request.getRemoteAddress());
in some sort of naive attempt to mimic the behaviour I want. Didn't work (to the surprise of no-one).
Anyone knowing anything about this will most likely snicker and shake their heads when reading this, and I do not blame them. I would snicker too, if it was me... I know nothing at all about this, and that naturally makes this problem awfully hard to solve. Any help at all will be greatly appreciated.
How can I get the header rewrite to work and get away from the SOP issues I'm dealing with?
Edit: The exact problem I'm getting is a pop-up saying:
"SmartClient can't directly contact
URL
'https://localhost/app/resource?action='doStuffs'"
due to browser same-origin policy.
Remove the host and port number (even
if localhost) to avoid this problem,
or use XJSONDataSource protocol (which
allows cross-site calls), or use the
server-side HttpProxy included with
SmartClient Server."
But I shouldn't need the smartclient HttpProxy, since I have a proxy on top of the server, should I? I've gotten no indications that this could be a serialisation problem, but maybe this message is hiding the real issue...
Solution
chris_l and saret both helped to find the solution, but since I can only mark one I marked the answer from chris_l. Readers are encouraged to bump them both up, they really came through for me here. The solution was quite simple, just remove any absolute paths to your server and use only relative ones, that did the trick for me. Thanks guys!
The SOP (for AJAX requests) applies, when the URL of the HTML page, and the URL of the AJAX requests differ in their "origin". The origin includes host, port and protocol.
So if the page is http://www.example.com/index.html, your AJAX request must also point to something under http://www.example.com. For the SOP, it doesn't matter, if there is a reverse proxy - just make sure, that the URL - as it appears to the browser (including port and protocol) - isn't different. The URL you use internally is irrelevant - but don't use that internal URL in your GWT app!
Note: The solution in the special case of SmartClient turned out to be using relative URLs (instead of absolute URLs to the same origin). Since relative URLs aren't an SOP requirement in browsers, I'd say that's a bug in SmartClient.
What issue are you having exactly?
Having previously had to write a reverseproxy for a GWT app I can't remember hitting any SOP issues, one thing you need to do though is make sure response headers and uri's are rewritten to the reverseproxies url - this includes ajax callback urls.
One issue I hit (which you might also experience) when running behind a reverseproxy was with the serialization policy of GWT server.
Fixing this required writing an implementation of RemoteServiceServlet. While this was in early/mid 2009, it seems the issue still exists.
Seems like others have hit this as well - see this for further details (the answer by Michele Renda in particular)

Deploying a web service to my Google App Engine application

We made a simple application and using GoogleAppEngineLauncher (GAEL) ran that locally. Then we deployed, using GAEL again, to our appid. It works fine.
Now, we made a web service. We ran that locally using GAEL and a very thin local python client. It works fine.
We deployed that, and we get this message when we try to visit our default page:
"Move along people, there is nothing to see here"
We modified our local client and tried to run that against our google site and we got an error that looked like:
Response is "text/plain", not "text/xml"
Any ideas where we are falling down in our deployment or config for using a web service with google app engine?
Any help appreciated!
Thanks // :)
Looks like you're not setting the Content-Type header correctly in your service (assuming you ARE actually trying to send XML -- e.g. SOAP, XML-RPC, &c). What code are you using to set that header? Without some indication about what protocol you're implementing and via what framework, it's impossible to help in detail...!
Looks like we aren't going to get to the bottom of this one. Just not enough information available at debug time. We've managed to affect a fix on the service, although I hate ot admit it we never found out what was causing this bug.