2013年9月18日 星期三

ONVIF -- WS-Discovery implementation

Here is a guide to teach you how to implement WS-Discovery by gSOAP. You can also find sample code here.

1. Xml Schema of WS-Discovery 

Use the typemap.dat file located in "\gsoap-2.8\gsoap\wsdl\".
WS-Discovery is already defined in typemap.dat.
 1 # WS-Discovery 1.1 and 1.0
 2 
 3 wsdd = <http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01>
 4 wsdd10 = <http://schemas.xmlsoap.org/ws/2005/04/discovery>
 5 
 6 wsdd10__HelloType  = | wsdd__HelloType
 7 wsdd10__ByeType   = | wsdd__ByeType
 8 wsdd10__ProbeType  = | wsdd__ProbeType
 9 wsdd10__ProbeMatchesType = | wsdd__ProbeMatchesType
10 wsdd10__ProbeMatchType  = | wsdd__ProbeMatchType
11 wsdd10__ResolveType  = | wsdd__ResolveType
12 wsdd10__ResolveMatchesType = | wsdd__ResolveMatchesType
13 wsdd10__ResolveMatchType = | wsdd__ResolveMatchType
14 wsdd10__ScopesType  = | wsdd__ScopesType
15 wsdd10__SecurityType  = | wsdd__SecurityType
16 wsdd10__SigType   = | wsdd__SigType
17 wsdd10__AppSequenceType  = | wsdd__AppSequenceType


2. Code Generation

Generate header file for WS-Discovery
./wsdl2h -cegxy -o wsdiscovery.h -t ../../WS/WS-typemap.dat http://docs.oasis-open.org/ws-dd/discovery/1.1/os/wsdd-discovery-1.1-wsdl-os.wsdl 
Generate source code
soapcpp2 -S -I ../../import wsdiscovery.h 
After code generation, you will have following files
  • soapC.c  
  • soapServer.c  
  • soapStub.h  
  • soapH.h   
  • soapServerLib.c  

3. Implement callback functions in soapStub.h

 1 SOAP_FMAC5 int SOAP_FMAC6 SOAP_ENV__Fault(struct soap*, char *faultcode, char *faultstring, char *faultactor, struct SOAP_ENV__Detail *detail, struct SOAP_ENV__Code *SOAP_ENV__Code, struct SOAP_ENV__Reason *SOAP_ENV__Reason, char *SOAP_ENV__Node, char *SOAP_ENV__Role, struct SOAP_ENV__Detail *SOAP_ENV__Detail);
 2 SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Hello(struct soap*, struct wsdd__HelloType *wsdd__Hello);
 3 SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Bye(struct soap*, struct wsdd__ByeType *wsdd__Bye);
 4 SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Probe(struct soap*, struct wsdd__ProbeType *wsdd__Probe);
 5 SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ProbeMatches(struct soap*, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches);
 6 SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Resolve(struct soap*, struct wsdd__ResolveType *wsdd__Resolve);
 7 SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ResolveMatches(struct soap*, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches);

4. Write Makefile

here is a simple example
 1 STRIP = strip
 2 wsdiscovery: main.o soapC.o soapServer.o stdsoap2.o 
 3  $(CC) soapC.o soapServer.o stdsoap2.o main.o  -lpthread -o wsdiscovery
 4  $(STRIP) wsdiscovery
 5 clean: 
 6  rm *.o;rm wsdiscovery
NOTE: stdsoap2.c stdsoap2.h can be found in \gsoap-2.8\gsoap\src

5. Implement the main function to send/receive message

The source code can be referenced from  https://github.com/alb423/wsdiscovery/
I already write both Client and Server program, so you can test it without any modification. For example
  • Server side 
./ws-server
  • Client: 
./ws-client 2  
Here, I list some important point about gSoap usage
  • We need set SOAP_IO_UDP flag, for example: soap_init1(pSoap,SOAP_IO_UDP); So that the sending data will omit http header, and pSoap->peer will be filled when receive a multicast packet. We can response with unicast by using the address and port information in pSoap->peer.
Note: you can use the callback function in wsddapi.c and wsddapi.h located in /gsoap/plugin rather than implemented yourself.

Reference: