$ ./configure --disable-opensslotherwise execute:
$ ./configure
set HAVE_REALLOC 1 comment out: /* #define realloc rpl_realloc */Also make sure that in config.h:
#define HAVE_STRTOLL 0 #define HAVE_STRTOULL 0Then execute:
$ makeThere will be errors when building the tests, but ignore these
LEXLIB = /usr/local/lib/libfl.aand rebuild:
$ make
cd ../wsdlEdit Makefile:
wsdl2h_DEPENDENCIES = wsdlC.cpp $(top_builddir)/gsoap/stdsoap2.cpp AM_LDFLAGS = $(INCLUDES) -DWITH_OPENSSL -L$(srcdir) SOAP_CCP_LIB_SSL = $(top_builddir)/gsoap/stdsoap2.cppand execute:
$ make $ cd ../.. $ make install-execnow we have soapcpp2 and wsdl2h installed
$ make install
cd gsoap/src; make -f MakefileManual cd gsoap/wsdl; make -f MakefileManualIn your projects use gsoap/stdsoap2.h and gsoap/stdsoap2.c (or gsoap/stdsoap2.cpp) directly instead of the libgsoap library (which is built from stdsoap2.c/.cpp). If stdsoap2.c/.cpp do not compile, modify stdsoap2.h for portability. For example, if socklen_t is not defined, change it to an int as in:
#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) || defined(__QNX__) || defined(QNX) || defined(OS390) || defined(HP_UX)# define SOAP_SOCKLEN_T socklen_tTo:
#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) || defined(__QNX__) || defined(QNX) || defined(OS390) || defined(HP_UX)# define SOAP_SOCKLEN_T int
warning C4005: 'AF_IPX' : macro redefinitionthen try arrange your include list such that <windows.h> is included after "stdsoap2.h". Or define _WINSOCKAPI_ first:
#define _WINSOCKAPI_ // stops windows.h including winsock.h #include <windows.h> ... #include "soapH.h" // also includes "stdsoap2.h"The stdsoap2.h code includes winsock2.h, which clashes with winsock.h included by windows.h. Similar problems may occur when stdafx.h is included.
If all else fails, revert back to older winsock.h by changing in stdsoap2.h:
#include <winsock.h> // was: <winsock2.h>
automake --ignore-deps && ./configure CFLAGS="-arch ppc -arch i386" LDFLAGS="-arch ppc -arch i386" && make clean && make
lib_LTLIBRARIES = libgsoap.la libgsoap++.la libgsoapck.la libgsoapck++.la libgsoapssl.la libgsoapssl++.la libgsoap_la_SOURCES = stdsoap2.c libgsoap_la_CFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) libgsoap___la_SOURCES = stdsoap2_cpp.cpp libgsoap___la_CXXFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) libgsoapck_la_SOURCES = stdsoap2_ck.c libgsoapck_la_CFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_COOKIES libgsoapck___la_SOURCES = stdsoap2_ck_cpp.cpp libgsoapck___la_CXXFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_COOKIES libgsoapssl_la_SOURCES = stdsoap2_ssl.c libgsoapssl_la_CFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_OPENSSL -DWITH_DOM -DWITH_GZIP libgsoapssl___la_SOURCES = stdsoap2_ssl_cpp.cpp libgsoapssl___la_CXXFLAGS = $(SOAPCPP2_DEBUG) $(SOAPCPP2_NONAMESPACES) -D$(platform) -DWITH_OPENSSL -DWITH_DOM -DWITH_GZIPAfter the modifications run
autoconf -f -i -v configure make make install
//gsoap ns schema elementForm: qualifiedLikewise, when the default is unqualified, you will find
//gsoap ns schema elementForm: unqualifiedWhen an element form is qualified by default, elements in XML instances of the schema are required to be namespace qualified. Without going into too much detail, the XML basically looks like:
<x:foo xmlns:x="urn:foobar"> <x:bar>bar is qualified</x:bar> </x:foo>or:
<foo xmlns="urn:foobar"> <bar>bar is qualified</bar> </foo>When the element form is unqualified (as in SOAP RPC encoding), we would have:
<x:foo xmlns:x="urn:foobar"> <bar>bar is unqualified</bar> </x:foo>Note that sometime we can have multiple namespaces as in:
<x:foo xmlns:x="urn:foo"> <y:bar xmlns:y="urn:bar"></y:bar> </x:foo>or:
<x:foo xmlns:x="urn:foo" xmlns="urn:bar"> <bar></bar> </x:foo>In the last example the bar element belongs to the "urn:bar" namespace, because the default namespace is "urn:bar". With Visual Studio .NET 2003 WSDL import, we could not successfully deserialize data from a multi-namespace situation when a response element contains an element of struct type in a second namespace. The individual members of the struct were ignored on the .NET side until the element form default 'qualified' was defined.
The TIME_WAIT state is used to deal with possible problems related to unreliable or delayed packet delivery. TCP holds connections for a temporary waiting period (TIME_WAIT) to ensure that any delayed packets are caught and not treated as new connection requests. The size of TIME_WAIT is supposed to be twice the maximum segment lifetime or twice the time a packet can remain alive on a particular IP network. For some operating systems, this can be as high as 4 minutes. On busy systems, this can lead to a depleation of TCP port resources. Low throughput may occur due to many connections sitting in TIME_WAIT state.
Set the soap.accept_flags |= SO_LINGER and soap.linger_time = n with integer n before calling soap_accept(). This works on most systems, but zapping the TIME_WAIT state is not always encouraged!
If that does not work, then reduce the operating system setting for TIME_WAIT substantially to the operating system minimum of 15 or 30 seconds (depending on OS).
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TcpIp\ParametersSet it to a decimal value of 30 which is for 30 seconds - the minimum.
/usr/sbin/no a | grep tcp_timewaitTo set the TCP_TIMEWAIT values to 15 seconds, run the following command:
/usr/sbin/no o tcp_timewait =1The tcp_timewait option is used to configure how long connections are kept in the timewait state. It is given in 15-second intervals, and the default is 1.
/sbin/sysctl -w net.ipv4.vs.timeout_timewait=30This will set TME_WAIT for 30 seconds.
/usr/sbin/ndd -set /dev/tcp tcp_time_wait_interval 30000
soapcpp2 -a -L -S -I $GSOAPHOME -I $GSOAPHOME/import myprog.h g++ -I $GSOAPHOME -o myprog myprog.cpp plugin/wsaapi.c plugin/wsrmapi.c custom/duration.c soapC.cpp soapClient.cpp -lgsoap++Thus, you must use g++ to compile all C and C++ source code files to force C++ linking rules, as shown above.
soap.accept_flags = SO_NOSIGPIPE; /* some systems accept this */ soap.socket_flags = MSG_NOSIGNAL; /* others need this */ signal(SIGPIPE, sigpipe_handler); /* and when the above are not supported, we use a sigpipe handler */where the sigpipe_handler is defined as a no-op function:
void sigpipe_handler(int x) { }
void *soap_malloc(size_t n); // gSOAP 1.X void *soap_malloc(struct soap *soap, size_t n); // gSOAP 2.XThese functions allocate memory on the heap that will be released upon calling soap_end() after soap_serve(). For example, in a gSOAP service:
main()
{ ...
soap_serve(&soap);
soap_end(&soap);
...
}
An example remote method that allocates a temporary string is:
int ns__itoa(struct soap *soap, int i, char **a)
{ *a = (char*)soap_malloc(soap, 11);
sprintf(*a, "%d", i);
return SOAP_OK;
}
Note that you don't want to use local function variables to store values such as strings,
because the values are allocated on the stack and deallocated when the function returns while serialization of the values takes
place after return.
This allocation with soap_malloc() can also be used to allocate strings for the SOAP Fault data structure, for example:
int ns__mymethod(struct soap *soap, ...)
{ ...
if (exception)
{ char *message = (char*)soap_malloc(soap, 1024);
char *details = (char*)soap_malloc(soap, 1024);
sprintf(message, ...);
sprintf(details, ...);
return soap_receiver_fault(soap, message, details);
}
...
}
{ struct soap soap;
soap_init(&soap);
soap.fignore = mustmatch; // overwrite default callback
...
soap_done(&soap); // reset callbacks
}
int mustmatch(struct soap *soap, const char *tag)
{ return SOAP_TAG_MISMATCH; // every tag must be handled
}
The tag parameter contains the offending tag name. You can also selectively return a fault:
int mustmatch(struct soap *soap, const char *tag)
{ if (soap_match_tag(soap, tag, "ns:login*")) // all tags in namespace "ns" that start with "login" are optional
return SOAP_OK;
return SOAP_TAG_MISMATCH; // every other tag must be understood (handled)
}
int ns__mymethod(..., int *_return); // single anonymous output parameterand
int ns__mymethod(..., struct ns__mymethodResponse{int _return1; char *_return2; ...} *result); // multiple output paramers
extern class ostream; // can't be (de)serialized so must be declared a transient type
class ns__foo
{ public:
char *s;
struct soap *soap; // special field: already transient
ns__foo();
[ ns__foo(const char *t); // transient constructor
print(ostream &s); // transient method
]
};
with e.g. the following implementation of ns__foo:
ns__foo::ns__foo(const char *t)
{ s = (char*)soap_malloc(soap, strlen(t)+1);
strcpy(s, t);
}
The 'struct soap* soap' field in this class is a special field set by gSOAP's deserializers and the gSOAP-generated soap_new_ns__foo() function.
struct ns__data { ... };
int ns__example(..., struct ns__data *out);
where the ns__data struct contains the result parameters of the
method. The struct is translated into an element definition in the generated WSDL to
support doc/lit style messaging. As you can see, this means that ns__data cannot be
used as a type anywhere else in your header file. To work around this problem,
use:
struct ns__data { ... };
int ns__example(..., struct ns__exampleResponse { struct ns__data out; } *out);
Now we have a type ns__data and a response struct for the method
results.
typedef char *XML;or
typedef wchar_t *XML;and use either XML type for mixed-content strings (strings that contain XML).
# ONVIF recommended prefixes
tds = "http://www.onvif.org/ver10/device/wsdl"
tev = "http://www.onvif.org/ver10/events/wsdl"
tls = "http://www.onvif.org/ver10/display/wsdl"
tmd = "http://www.onvif.org/ver10/deviceIO/wsdl"
timg = "http://www.onvif.org/ver20/imaging/wsdl"
trt = "http://www.onvif.org/ver10/media/wsdl"
tptz = "http://www.onvif.org/ver20/ptz/wsdl"
trv = "http://www.onvif.org/ver10/receiver/wsdl"
trc = "http://www.onvif.org/ver10/recording/wsdl"
tse = "http://www.onvif.org/ver10/search/wsdl"
trp = "http://www.onvif.org/ver10/replay/wsdl"
tan = "http://www.onvif.org/ver20/analytics/wsdl"
tad = "http://www.onvif.org/ver10/analyticsdevice/wsdl"
tdn = "http://www.onvif.org/ver10/network/wsdl"
tt = "http://www.onvif.org/ver10/schema"
# OASIS recommended prefixes
wsnt = "http://docs.oasis-open.org/wsn/b-2"
wsntw = "http://docs.oasis-open.org/wsn/bw-2"
wsrfbf = "http://docs.oasis-open.org/wsrf/bf-2"
wsrfr = "http://docs.oasis-open.org/wsrf/r-2"
wsrfrw = "http://docs.oasis-open.org/wsrf/rw-2"
wstop = "http://docs.oasis-open.org/wsn/t-1"
# WS-Discovery 1.0 remapping
wsdd10__HelloType = | wsdd__HelloType
wsdd10__ByeType = | wsdd__ByeType
wsdd10__ProbeType = | wsdd__ProbeType
wsdd10__ProbeMatchesType = | wsdd__ProbeMatchesType
wsdd10__ProbeMatchType = | wsdd__ProbeMatchType
wsdd10__ResolveType = | wsdd__ResolveType
wsdd10__ResolveMatchesType = | wsdd__ResolveMatchesType
wsdd10__ResolveMatchType = | wsdd__ResolveMatchType
# SOAP-ENV mapping
SOAP_ENV__Envelope = struct SOAP_ENV__Envelope { struct SOAP_ENV__Header *SOAP_ENV__Header; _XML SOAP_ENV__Body; }; | struct SOAP_ENV__Envelope
SOAP_ENV__Header = | struct SOAP_ENV__Header
SOAP_ENV__Fault = | struct SOAP_ENV__Fault
SOAP_ENV__Detail = | struct SOAP_ENV__Detail
SOAP_ENV__Code = | struct SOAP_ENV__Code
SOAP_ENV__Subcode = | struct SOAP_ENV__Subcode
SOAP_ENV__Reason = | struct SOAP_ENV__Reason
At the command line prompt, run wsdl2h on the ONVIF WSDLs. For example, the
device management and event specifications:
$ wsdl2h -P -x -o onvif.h http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl $ soapcpp2 -I import onvif.hNote that the specifications are substantial in size. Option wsdl2h -P removes unnecessary class hierarchy dependences on the root type xsd__anyType. This option will reduce the code size. Option -x removes extensibility elements (xsd:anyAttribute attributes and xsd:any elements). If attribute and element extensions to a complexType are needed, then use the typemap.dat file to add these as additional optional members. For example, to extend tt__AudioDecoderConfigurationOptionsExtension complexType class with an element Address of type tt:IPAddress, add to typemap.dat:
tt__AudioDecoderConfigurationOptionsExtension = $ tt__IPAddress Address;Note that wsdl2h 2.8.10 and earlier versions generate ns1, ns2, ns3, etc prefixes when multiple service bindings are given for service operations. This will be changed in gSOAP 2.8.11 and up. The change can be made in 2.8.10 and earlier versions by modifying gsoap/wsdl/service.cpp:70
void Definitions::analyze(const wsdl__definitions &definitions)
{ // Analyze WSDL and build Service information
int binding_count = 0;
// Determine number of relevant SOAP service bindings
if (service_prefix)
{ for (vector::const_iterator i =
definitions.binding.begin(); i != definitions.binding.end(); ++i)
{ for (vector::const_iterator j =
(*i).operation.begin(); j != (*i).operation.end(); ++j)
{ if ((*j).operationPtr() && (*j).input && (*j).input->soap__body_)
{ binding_count++;
break;
}
}
}
}
else
binding_count = 1; // Put all operations under a single binding
...
then rebuild wsdl2h. With this change, option wsdl2h -Nns reverts back to the old behavior.