使用gsoap生成onvif协议工程

简介

gsop工具gsop定义为一个工具,他的作用是根据xml等的配置文件生成符合onvif协议的webserver的c/c++源代码

The gSOAP toolkit is a C and C++ software development toolkit for SOAP and REST XML Web services and generic C/C++ XML data bindings. The toolkit analyzes WSDLs and XML schemas (separately or as a combined set) and maps the XML schema types and the SOAP/REST XML messaging protocols to easy-to-use and efficient C and C++ code. It also supports exposing (legacy) C and C++ applications as XML Web services by auto-generating XML serialization code and WSDL specifications. Or you can simply use it to automatically convert XML to/from C and C++ data. The toolkit supports options to generate pure ANSI C or C++ with or without STL.

gsoap使用

gsoap的主要用途是生产onvif协议的平台无关c代码,首先来一张使用原理图:
使用gsoap生成onvif协议工程_第1张图片分析图片,用户输入WSDL ,gsoap自动生成C/C++ Source Code Files,而wsdl文件就是符合onvif协议的配置文件,可以使用下面的wsdl资源来在线生成。
gsoap如何根据WSDL生成c代码?
gsoap提供两个编译工具

  • wsdl2h:WSDL文件解析工具,可以将WSDL/XSD文件转换为c语言头文件,里面包含onvif标准的函数声明
  • soapcpp2:框架编译器,这个工具根据c代码来生成RPC代码和XML文件
    The ‘wsdl2h’ parser converts WSDL into gSOAP header file specifications of Web services. This specification gives a C/C++ transparent view of the server’s functionality. The header file is processed by ‘soapcpp2’ to generate the source code stubs and skeletons to invoke the service or build a new service based on the WSDL.
    译:wsdl2h 将WSDL转换为符合onvif协议的带有函数申明h头文件,然后在利用soapcpp2工具,将h头文件生成所需的c源代码。
wsdl2h -o outfile.h infile.wsdl
wsdl2h -o XMethodsQuery.h http://www.xmethods.net/wsdl/query.wsdl

wsdl->h有两种方式,在线和离线,任选其一

soapcpp2 -c outfile.h

在使用soapcpp2工具,即可生成对应的webserver代码

wsdl资源

http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl
http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl
http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl
http://www.onvif.org/onvif/ver10/recording.wsdl
http://www.onvif.org/onvif/ver10/display.wsdl
http://www.onvif.org/onvi f/ver10/receiver.wsdl
http://www.onvif.org/onvif/ver10/deviceio.wsdl
http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl
http://www.onvif.org/onvif/ver10/search.wsdl
http://www.onvif.org/onvif/ver10/schema/onvif.xsd
https://www.onvif.org/ver20/media/wsdl/media.wsdl

实践

1.下载gsoap源码
2.编译gsoap工具

cd gsoap
./configure
make
make install

3.生成discover的onvif.h

root@zjy-T440:~/software/gsoap-2.8/mydiscover# ../gsoap/wsdl/wsdl2h -o onvif.h -c -s -k -t ./typemap.dat https://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
Saving onvif.h


**  The gSOAP WSDL/WADL/XSD processor for C and C++, wsdl2h release 2.8.96
**  Copyright (C) 2000-2019 Robert van Engelen, Genivia Inc.
**  All Rights Reserved. This product is provided "as is", without any warranty.
**  The wsdl2h tool and its generated software are released under the GPL.
**  ----------------------------------------------------------------------------
**  A commercial use license is available from Genivia Inc., [email protected]
**  ----------------------------------------------------------------------------

Reading type definitions from type map "./typemap.dat"
Connecting to 'https://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl' to retrieve WSDL/WADL or XSD...
 connected, receiving...
Done reading 'https://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl'

Warning: 2 service bindings found, but collected as one service (use option -Nname to produce a separate service for each binding)

To finalize code generation, execute:
> soapcpp2 onvif.h

root@zjy-T440:~/software/gsoap-2.8/mydiscover# 

4.根据onvif.h生成源码框架

root@zjy-T440:~/software/gsoap-2.8/mydiscover# ../gsoap/src/soapcpp2 -c onvif.h -x  -d ./ -I ../gsoap/import -I ../gsoap/

**  The gSOAP code generator for C and C++, soapcpp2 release 2.8.96
**  Copyright (C) 2000-2019, Robert van Engelen, Genivia Inc.
**  All Rights Reserved. This product is provided "as is", without any warranty.
**  The soapcpp2 tool and its generated software are released under the GPL.
**  ----------------------------------------------------------------------------
**  A commercial use license is available from Genivia Inc., [email protected]
**  ----------------------------------------------------------------------------

Using project directory path: ./
Saving ./soapStub.h annotated copy of the source interface header file
Saving ./soapH.h serialization functions to #include in projects
Using wsdd service name: wsdd
Using wsdd service style: document
Using wsdd service encoding: literal
Using wsdd schema import namespace: http://schemas.xmlsoap.org/ws/2005/04/discovery
Saving ./wsdd.nsmap namespace mapping table
Using tdn service name: RemoteDiscoveryBinding
Using tdn service style: document
Using tdn service encoding: literal
Using tdn schema namespace: http://www.onvif.org/ver10/network/wsdl
Saving ./RemoteDiscoveryBinding.nsmap namespace mapping table
Saving ./soapClient.c client call stub functions
Saving ./soapClientLib.c client stubs with serializers (use only for libs)
Saving ./soapServer.c server request dispatcher
Saving ./soapServerLib.c server request dispatcher with serializers (use only for libs)
Saving ./soapC.c serialization functions

Compilation successful 

root@zjy-T440:~/software/gsoap-2.8/mydiscover# 
root@zjy-T440:~/software/gsoap-2.8/mydiscover# ls
onvif.h                       soapC.c       soapClientLib.c  soapServer.c     soapStub.h   wsdd.nsmap
RemoteDiscoveryBinding.nsmap  soapClient.c  soapH.h          soapServerLib.c  typemap.dat
root@zjy-T440:~/software/gsoap-2.8/mydiscover# 

5.拷贝相关代码到工程
一些框架代码可能会用得到

root@zjy-T440:~/software/gsoap-2.8/mydiscover# ls ../gsoap
bin          libgsoap.a                   libgsoapck_a-dom.o                  Makefile     stdsoap2_ck.c         typemap.dat
custom       libgsoap++.a                 libgsoapck___a-stdsoap2_ck_cpp.o    Makefile.am  stdsoap2_ck_cpp.cpp   uddi2
doc          libgsoap___a-dom_cpp.o       libgsoapck_a-stdsoap2_ck.o          Makefile.in  stdsoap2.cpp          VisualStudio2005
dom.c        libgsoap_a-dom.o             libgsoapssl.a                       mod_gsoap    stdsoap2_cpp.cpp      WS
dom.cpp      libgsoap___a-stdsoap2_cpp.o  libgsoapssl++.a                     Palm         stdsoap2.h            wsdl
dom_cpp.cpp  libgsoap_a-stdsoap2.o        libgsoapssl___a-dom_cpp.o           plugin       stdsoap2_ssl.c
extras       libgsoapck.a                 libgsoapssl_a-dom.o                 samples      stdsoap2_ssl_cpp.cpp
import       libgsoapck++.a               libgsoapssl___a-stdsoap2_ssl_cpp.o  src          Symbian
ios_plugin   libgsoapck___a-dom_cpp.o     libgsoapssl_a-stdsoap2_ssl.o        stdsoap2.c   TandemNonStop
root@zjy-T440:~/software/gsoap-2.8/mydiscover# 
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/dom.c ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/stdsoap2.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/custom/duration. ./
duration.c  duration.h  
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/custom/duration.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/plugin/mecevp.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/plugin/smdevp.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/plugin/threads.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/plugin/wsaapi.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/plugin/wsseapi.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# cp ../gsoap/plugin/wsddapi.* ./
root@zjy-T440:~/software/gsoap-2.8/mydiscover# 

6、生成main.c 文件

#include 
#include 
#include 

#include "soapH.h"
#include "wsdd.nsmap"
#include "soapStub.h"

SOAP_FMAC5 int SOAP_FMAC6 soap_send___wsdd__ProbeMatches(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
{	struct __wsdd__ProbeMatches soap_tmp___wsdd__ProbeMatches;
	if (soap_action == NULL)
		soap_action = "http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/ProbeMatches";
	soap_tmp___wsdd__ProbeMatches.wsdd__ProbeMatches = wsdd__ProbeMatches;
	soap_begin(soap);
	soap->encodingStyle = NULL; /* use SOAP literal style */
	soap_serializeheader(soap);
	soap_serialize___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches);
	if (soap_begin_count(soap))
		return soap->error;
	if ((soap->mode & SOAP_IO_LENGTH))
	{	if (soap_envelope_begin_out(soap)
		 || soap_putheader(soap)
		 || soap_body_begin_out(soap)
		 || soap_put___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches, "-wsdd:ProbeMatches", "")
		 || soap_body_end_out(soap)
		 || soap_envelope_end_out(soap))
			 return soap->error;
	}
	if (soap_end_count(soap))
		return soap->error;
	if (soap_connect(soap, soap_endpoint, soap_action)
	 || soap_envelope_begin_out(soap)
	 || soap_putheader(soap)
	 || soap_body_begin_out(soap)
	 || soap_put___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches, "-wsdd:ProbeMatches", "")
	 || soap_body_end_out(soap)
	 || soap_envelope_end_out(soap)
	 || soap_end_send(soap))
		return soap_closesock(soap);
	return SOAP_OK;
}

SOAP_FMAC5 int SOAP_FMAC6 SOAP_ENV__Fault(struct soap* 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)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Hello(struct soap* soap, struct wsdd__HelloType *wsdd__Hello)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Bye(struct soap* soap, struct wsdd__ByeType *wsdd__Bye)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ProbeMatches(struct soap* soap, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Resolve(struct soap* soap, struct wsdd__ResolveType *wsdd__Resolve)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ResolveMatches(struct soap* soap, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __tdn__Hello(struct soap* soap, struct wsdd__HelloType tdn__Hello, struct wsdd__ResolveType *tdn__HelloResponse)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __tdn__Bye(struct soap* soap, struct wsdd__ByeType tdn__Bye, struct wsdd__ResolveType *tdn__ByeResponse)
{

	return 0;
}

SOAP_FMAC5 int SOAP_FMAC6 __tdn__Probe(struct soap* soap, struct wsdd__ProbeType tdn__Probe, struct wsdd__ProbeMatchesType *tdn__ProbeResponse)
{

	return 0;
}

#define IP "192.168.1.125"			//服务器IP
#define ONVIF_TCP_PORT 8554 			//服务器访问端口(随意设置)


SOAP_FMAC5 int SOAP_FMAC6  __wsdd__Probe(struct soap* soap, struct wsdd__ProbeType *wsdd__Probe)
{
	char scopes_message[] =
		"onvif://www.onvif.org/type/NetworkVideoTransmitter\r\n"
		"onvif://www.onvif.org/Profile/Streaming\r\n"
		"onvif://www.onvif.org/Profile/Q/Operational\r\n"
		"onvif://www.onvif.org/hardware/HD1080P\r\n"
		"onvif://www.onvif.org/name/discover_test\r\n"
		"onvif://www.onvif.org/location/city/GuangZhou\r\n"
		"onvif://www.onvif.org/location/country/China\r\n";

	// response ProbeMatches
	struct wsdd__ProbeMatchesType   wsdd__ProbeMatches = {0};
	struct wsdd__ProbeMatchType     *pProbeMatchType = NULL;
	struct wsa__Relationship        *pWsa__RelatesTo = NULL;

	pProbeMatchType = (struct wsdd__ProbeMatchType*)soap_malloc(soap, sizeof(struct wsdd__ProbeMatchType));
	soap_default_wsdd__ProbeMatchType(soap, pProbeMatchType);

	char str_tmp[256] = {0};
	//sprintf(str_tmp, "http://%s:%d/onvif/device_service", IP, ONVIF_TCP_PORT);
	sprintf(str_tmp, "rtsp://%s:%d/live.ts", IP, ONVIF_TCP_PORT);
	pProbeMatchType->XAddrs = soap_strdup(soap, str_tmp);
	if( wsdd__Probe->Types && strlen(wsdd__Probe->Types) )
		pProbeMatchType->Types  = soap_strdup(soap, wsdd__Probe->Types);
	else
		pProbeMatchType->Types  = soap_strdup(soap, "dn:NetworkVideoTransmitter tds:Device");

	pProbeMatchType->MetadataVersion = 1;

	// Build Scopes Message
	struct wsdd__ScopesType *pScopes = NULL;
	pScopes = (struct wsdd__ScopesType *)soap_malloc(soap, sizeof(struct wsdd__ScopesType));
	soap_default_wsdd__ScopesType(soap, pScopes);
	pScopes->MatchBy = NULL;
	pScopes->__item  = soap_strdup(soap, scopes_message);
	pProbeMatchType->Scopes = pScopes;

	char g_uuid[64];
	//snprintf(g_uuid, 64, "%s", soap_wsa_rand_uuid(soap));
	//pProbeMatchType->wsa__EndpointReference.Address = soap_strdup(soap, g_uuid);

	wsdd__ProbeMatches.__sizeProbeMatch = 1;
	wsdd__ProbeMatches.ProbeMatch       = pProbeMatchType;

	// Build SOAP Header
	pWsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));
	soap_default__wsa__RelatesTo(soap, pWsa__RelatesTo);
	pWsa__RelatesTo->__item = soap->header->wsa__MessageID;
	soap->header->wsa__RelatesTo = pWsa__RelatesTo;
	soap->header->wsa__Action      = soap_strdup(soap, "http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches");
	soap->header->wsa__To          = soap_strdup(soap, "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous");

	soap_send___wsdd__ProbeMatches(soap, "http://", NULL, &wsdd__ProbeMatches);

	return SOAP_OK;
}



int main(int argc,char ** argv)
{
#define ONVIF_LISTEN_PORT 3702
	printf("[%s][%d][%s][%s] start \n", __FILE__, __LINE__, __TIME__, __func__);

	int count = 0;
	struct soap ServerSoap;
	struct ip_mreq mcast;

	soap_init1(&ServerSoap, SOAP_IO_UDP | SOAP_XML_IGNORENS);
	soap_set_namespaces(&ServerSoap,  namespaces);

	printf("[%s][%d][%s][%s] ServerSoap.version = %d \n", __FILE__, __LINE__, __TIME__, __func__, ServerSoap.version);

	if(!soap_valid_socket(soap_bind(&ServerSoap, NULL, ONVIF_LISTEN_PORT, 10)))
	{
		soap_print_fault(&ServerSoap, stderr);
		exit(1);
	}

	mcast.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
	mcast.imr_interface.s_addr = htonl(INADDR_ANY);

	if(setsockopt(ServerSoap.master, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mcast, sizeof(mcast)) < 0)
	{
		printf("setsockopt error! error code = %d,err string = %s\n",errno,strerror(errno));
		return 0;
	}

	for(;;)
	{
		if(soap_serve(&ServerSoap))
		{
			soap_print_fault(&ServerSoap, stderr);
		}

		soap_destroy(&ServerSoap);
		soap_end(&ServerSoap);

		//客户端的IP地址
		printf("RECEIVE count %d, connection from IP = %lu.%lu.%lu.%lu socket = %d \r\n", count, ((ServerSoap.ip)>>24)&0xFF, ((ServerSoap.ip)>>16)&0xFF, ((ServerSoap.ip)>>8)&0xFF,(ServerSoap.ip)&0xFF, (ServerSoap.socket));
		count++;
	}

	//分离运行时的环境
	soap_done(&ServerSoap);

	return 0;
}

7、生成Makefile

PWD := $(shell pwd)
CPP=gcc
#CFLAGS=-Wall -g -I../gsoap/plugin/
CFLAGS=-Wall
TARGET1 = $(PWD)/server

all: $(TARGET1)
$(TARGET1):$(OBJ)
	$(CPP) $(CFLAGS) -o $@ main.c soapC.c soapServer.c stdsoap2.c wsaapi.c
clean:
	rm $(TARGET1)

8、编译运行测试
测试onvif的发现设备的方法:

  • 运行server
  • 在同一网段的windowsPC上运行ONVIF Device Test
  • 在ONVIF Device Test 工具中选择对应的NIC 点击Discoverevice即可发现设备

使用gsoap生成onvif协议工程_第2张图片

你可能感兴趣的:(音视频,c++,linux,物联网)