熟悉了gsoap之后,开始做onvif的第一步:discovery
源码路径:http://download.csdn.net/detail/lishuanglin131/4758455
1、生成头文件。
执行wsdl中“gen-h - 副本.bat”,可以得到onvif.h文件。
执行wsdl中“gen-c - 副本.bat”,可以得到相关的.c、xml等文件。
2、编写discoveryServer.c
#include "onvif.nsmap" #include "soapH.h" #include "soapStub.h" ////////////////////////////////////////////////////////////////////////////////////////////////////// //主函数 int main(int argc,char ** argv) { struct soap ServerSoap; struct ip_mreq mcast; int count = 0; //初始话运行时环境 //soap_init2(&ServerSoap, SOAP_IO_UDP | SOAP_IO_FLUSH | SOAP_IO_LENGTH, SOAP_IO_UDP | SOAP_IO_FLUSH | SOAP_IO_LENGTH); soap_init1(&ServerSoap, SOAP_IO_UDP | SOAP_XML_IGNORENS); // ServerSoap.version = 2; // soap_init(&ServerSoap); // ServerSoap.accept_timeout = 10; // ServerSoap.recv_timeout = 10; soap_set_namespaces(&ServerSoap, namespaces); if(!soap_valid_socket(soap_bind(&ServerSoap, NULL, 3702, 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("Accepted 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; }
#include#include #include #include #include #include #include #include #include #include #include #include #include #include #include "soapH.h" #include "soapStub.h" static char szDevXAddr[1024]; static char szEndpointReference[1024]; static char tmpBuf[1024]; static struct d__ScopesType scopes; #define METADATA_VERSION 1 #define ONVIF_SERVER_CALL() printf("onvifs: call %s, path=%s\r\n", __FUNCTION__, soap->path) #define ONVIF_RETURN_OK(soap, namespaces) \ ONVIF_SERVER_CALL(); \ if(namespaces!=NULL) soap_set_namespaces(soap, namespaces); \ return SOAP_OK; static inline int onvif_receiver_fault_subcode_oom(struct soap *soap) { return soap_receiver_fault_subcode(soap, "ter:OutofMemory", "Out of Memory", "The device does not have sufficient memory to complete the action."); } /****************************** 具体服务方法 ******************************/ SOAP_FMAC5 int SOAP_FMAC6 __dndl__Probe(struct soap* soap, struct d__ProbeType *d__Probe, struct d__ProbeMatchesType *d__ProbeMatches) { char MessageID[128] = {0}; int MatchingRuleNotSupported = 0; printf("__dndl__Probe %s from %s\n", d__Probe->Types?d__Probe->Types:"Any types", inet_ntoa(soap->peer.sin_addr)); if (soap->header) { #if 0 uuid_t uuid; uuid_generate(uuid); strcpy(MessageID, "urn:uuid:"); uuid_unparse(uuid, MessageID+9); #else unsigned char mac[6] = {0}; netGetMac("eth3", mac); struct timeval tv, tv1; gettimeofday(&tv, NULL); usleep(1); gettimeofday(&tv1, NULL); sprintf(MessageID, "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", (int)tv.tv_usec, (int)(tv.tv_usec&0xFFFF), (int)(tv1.tv_usec&0xFFFF), (int)(tv.tv_usec&0xFF), (int)(tv1.tv_usec&0xFF), mac[0]&0xFF, mac[1]&0xFF, mac[2]&0xFF, mac[3]&0xFF, mac[4]&0xFF, mac[5]&0xFF); #endif if(soap->header->wsa__MessageID) { printf("remote wsa__MessageID : %s\n",soap->header->wsa__MessageID); soap->header->wsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship)); if(soap->header->wsa__RelatesTo==NULL) return onvif_receiver_fault_subcode_oom(soap); soap_default__wsa__RelatesTo(soap, soap->header->wsa__RelatesTo); soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID; soap->header->wsa__MessageID = soap_strdup(soap, MessageID); soap->header->wsa__To = (char*)"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"; if(MatchingRuleNotSupported) soap->header->wsa__Action = (char*)"http://schemas.xmlsoap.org/ws/2005/04/discovery/fault"; else soap->header->wsa__Action = (char*)"http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches"; } } d__ProbeMatches->__sizeProbeMatch = 1; d__ProbeMatches->ProbeMatch = (struct d__ProbeMatchType*)soap_malloc(soap, sizeof(struct d__ProbeMatchType)); if(d__ProbeMatches->ProbeMatch) { unsigned int localIp = 0; netGetIp("eth3", &localIp); sprintf(szDevXAddr, "http://%s/onvif/device_service", inet_ntoa(*((struct in_addr *)&localIp))); soap_default_d__ScopesType(soap, &scopes); sprintf(tmpBuf, "%s", "onvif://www.onvif.org/type/video_encoder onvif://www.onvif.org/type/audio_encoder onvif://www.onvif.org/hardware/IPC-model onvif://www.onvif.org/name/IPC-model"); scopes.__item = tmpBuf; soap_default_d__ProbeMatchType(soap, d__ProbeMatches->ProbeMatch); sprintf(szEndpointReference, MessageID);//"urn:uuid:11223344-5566-7788-99aa-000c29ebd542"); d__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address = szEndpointReference;//"urn:uuid:464A4854-4656-5242-4530-313035394100"; d__ProbeMatches->ProbeMatch->Types = (char*)"dn:NetworkVideoTransmitter"; d__ProbeMatches->ProbeMatch->Scopes = &scopes; d__ProbeMatches->ProbeMatch->XAddrs = szDevXAddr;//"http://192.168.7.98/onvif/device_service"; d__ProbeMatches->ProbeMatch->MetadataVersion = METADATA_VERSION; return SOAP_OK; } else { return onvif_receiver_fault_subcode_oom(soap); } } SOAP_FMAC5 int SOAP_FMAC6 __dnrd__Hello(struct soap* soap, struct d__HelloType *d__Hello, struct d__ResolveType *dn__HelloResponse) { ONVIF_RETURN_OK(soap, NULL); } SOAP_FMAC5 int SOAP_FMAC6 __dnrd__Bye(struct soap* soap, struct d__ByeType *d__Bye, struct d__ResolveType *dn__ByeResponse) { ONVIF_RETURN_OK(soap, NULL); } int netGetMac(char *pInterface, unsigned char *pMac) { struct ifreq ifreq; int sockfd = 0; unsigned char mac[6] = {0}; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <0) {/*创建套接口,后用于获取mac地址*/ perror("netGetMac socket"); return -1; } strcpy(ifreq.ifr_name, pInterface); if(ioctl(sockfd, SIOCGIFHWADDR, &ifreq) <0) {/*获取mac地址*/ perror("netGetMac ioctl"); close(sockfd); return -2; } memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);/*复制mac地址到mac*/ printf("MAC:%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); if(pMac != NULL) { memcpy(pMac, mac, 6); } close(sockfd); return 0; } /* 获取Ip */ int netGetIp(char *pInterface, unsigned int *ip) { int sock = 0; struct ifreq ifr; if((pInterface == NULL) || (*pInterface == '\0')) { printf("get ip: pInterface == NULL\r\n"); return -1; } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, pInterface, IFNAMSIZ); sock = socket(AF_INET, SOCK_DGRAM, 0); if(sock <= 0) { printf("get ip: sock error, %s\r\n", strerror(errno)); return -1; } ((struct sockaddr_in*)&ifr.ifr_addr)->sin_family = PF_INET; if(ioctl(sock, SIOCGIFADDR, &ifr) <0) { printf("get ip error: %s\r\n", strerror(errno)); close(sock); return -1; } else { *ip = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr; printf("get ip(%d:%d:%d:%d) success!\r\n", (*ip)&0xff, (*ip>>8)&0xff, (*ip>>16)&0xff, (*ip>>24)&0xff); } close(sock); return 0; }
#include#include #include #include #include "onvif.nsmap" #include "soapH.h" #include "soapStub.h" int main() { struct soap *soap; int result = 0; struct d__ProbeType req; struct d__ProbeMatchesType resp; struct d__ScopesType sScope; struct SOAP_ENV__Header header; int count = 0; // char guid_string[100]; // uuid_t uuid; soap = soap_new(); if(soap == NULL) { printf("sopa new error\r\n"); return -1; } /* discovery test */ // uuid_generate(uuid); // uuid_unparse(uuid, guid_string); soap_set_namespaces(soap, namespaces); //超过5秒钟没有数据就退出 soap->recv_timeout = 5; soap_default_SOAP_ENV__Header(soap, &header); #if 0 header.wsa__MessageID = guid_string; header.wsa__To = "urn:schemas-xmlsoap-org:ws:2005:04:discovery"; header.wsa__Action = "http://schemas.xmllocal_soap.org/ws/2005/04/discovery/Probe"; #endif soap->header = &header; soap_default_d__ScopesType(soap, &sScope); sScope.__item = ""; soap_default_d__ProbeType(soap, &req); req.Scopes = &sScope; req.Types =NULL; int i = 0; do { soap_call___dndl__Probe(soap, "soap.udp://239.255.255.250:3702/datagram", NULL, &req, &resp); printf("002.1 \n"); if (soap->error) { printf("soap error: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap)); result = soap->error; break; } else { //printf("soap_call___dndl__Probe __sizeProbeMatch=%d\r\n",resp.__sizeProbeMatch); // while(1) { printf("Target EP Address : %s\r\n", resp.ProbeMatch[i].wsa__EndpointReference.Address); printf("Target Type : %s\r\n", resp.ProbeMatch[i].Types); printf("Target Service Address : %s\r\n", resp.ProbeMatch[i].XAddrs); i++; } //printf("Target Metadata Version : %d\r\n", resp.ProbeMatch[0].ns2__MetadataVersion); //printf("Target Scopes Address : %s\r\n", resp.ProbeMatch[0].ns2__Scopes->__item); } }while(0); soap_destroy(soap); // remove deserialized class instances (C++ only) soap_end(soap); // clean up and remove deserialized data //////////////////////////////////////////////////////////////////////////// failed: soap_free(soap);//detach and free runtime context soap_done(soap); // detach context (last use and no longer in scope) return result; }
GSOAP_ROOT = /mnt/hgfs/work/onvif/gsoap-2.8/gsoap CC = gcc -g -O2 #-DWITH_OPENSSL -DHAVE_PTHREAD_H INCLUDE = -I$(GSOAP_ROOT) SERVER_OBJS = soapC.o soapServer.o stdsoap2.o function.o webServer.o SERVER_SSL_OBJS = soapC.o soapServer.o stdsoap2.o function.o webServerSsl.o DISCOVER_SERVER_OBJS = soapC.o soapServer.o stdsoap2.o function.o discoveryServer.o DISCOVER_CLIENT_OBJS = soapC.o soapClient.o stdsoap2.o function.o discoveryClient.o all: discoverServer discoverClient server discoverServer: $(DISCOVER_SERVER_OBJS) $(CC) -o discoveryServer $(DISCOVER_SERVER_OBJS) $(INCLUDE) -lpthread -lssl -lcrypto discoverClient: $(DISCOVER_CLIENT_OBJS) $(CC) -o discoveryClient $(DISCOVER_CLIENT_OBJS) $(INCLUDE) -lpthread -lssl -lcrypto server: $(SERVER_OBJS) $(CC) -o webServer $(SERVER_OBJS) $(INCLUDE) -lpthread -lssl -lcrypto serverSsl: $(SERVER_SSL_OBJS) $(CC) -o webServerSsl $(SERVER_SSL_OBJS) $(INCLUDE) -lpthread -lssl -lcrypto clean: rm -f *.o *.a discoveryServer discoveryClient webServer webServerSsl