$ wsdl2h -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl |
$ wsdl2h -s -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl |
$ wsdl2h -c -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl |
$ soapcpp2 -i -C -Iimport calc.h |
#include "soapcalcProxy.h" #include "calc.nsmap" main() { calcProxy service; double result; if (service.add(1.0, 2.0, result) == SOAP_OK) std::cout << "The sum of 1.0 and 2.0 is " << result << std::endl; else service.soap_stream_fault(std::cerr); } |
#include "soapH.h" #include "calc.nsmap" main() { struct soap *soap = soap_new(); double result; if (soap_call_ns__add(soap, 1.0, 2.0, &result) == SOAP_OK) printf("The sum of 1.0 and 2.0 is %g n", result); else soap_print_fault(soap, stderr); soap_end(soap); soap_free(soap); } |
// File: currentTime.h //gsoap ns service name: currentTime //gsoap ns service namespace: urn:currentTime //gsoap ns service location: http://www.yourdomain.com/currentTime.cgi int ns__currentTime(time_t& response); |
// File: currentTime.cpp main() { // create soap context and serve one CGI-based request: soap_serve(soap_new()); } int ns__currentTime(struct soap *soap, time_t& response) { response = time(0); return SOAP_OK; } |
$ soapcpp2 -S currentTime.h |
$ c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapServer.cpp stdsoap2.cpp |
<book isbn="1234567890"> <title>Farewell John Doe</title> <publisher>ABC's is our Name</publisher> </book> |
class book { @ULONG64 isbn; std::string title; std::string publisher; } |
<schema ...> <element name="book"> <complexType> <sequence> <element name="title" type="string" minOccurs="1"/> <element name="publisher" type="string" minOccurs="1"/> </sequence> <attribute name="isbn" type="unsignedLong" use="required"/> </complexType> </element> </schema> |
soap *ctx = soap_new1(SOAP_XML_INDENT); // new context with option book bk; bk.isbn = 1234567890; bk.title = "Farewell John Doe"; bk.publisher = "ABC's is our Name"; soap_begin_send(ctx); bk.soap_put(ctx, "book", NULL); soap_end_send(ctx); soap_end(ctx); // clean up allocated temporaries soap_free(ctx); // delete context |
soap *ctx = soap_new1(SOAP_XML_STRICT); // new context with option book bk; soap_begin_recv(ctx); bk.soap_get(ctx, "book", NULL); if (ctx->error == SOAP_OK) cout << bk.isbn << ", " << bk.title << ", " << bk.publisher << endl; ... further use of bk ... soap_end_recv(ctx); soap_destroy(ctx); // delete deserialized objects soap_end(ctx); // delete temporaries soap_free(ctx); // delete context |
|
|
int main() { struct soap soap; ... soap_init(&soap); // initialize runtime environment ... soap_call_ns__method1(&soap, ...); // make a remote call ... soap_call_ns__method2(&soap, ...); // make another remote call ... soap_destroy(&soap); // remove deserialized class instances (C++ only) soap_end(&soap); // clean up and remove deserialized data soap_done(&soap); // detach environment (last use and no longer in scope) ... } |
int main() { struct soap *soap; ... soap = soap_new(); // allocate and initialize runtime environment if (!soap) // couldn't allocate: stop ... soap_call_ns__method1(soap, ...); // make a remote call ... soap_call_ns__method2(soap, ...); // make another remote call ... soap_destroy(soap); // remove deserialized class instances (C++ only) soap_end(soap); // clean up and remove deserialized data soap_free(soap); // detach and free runtime environment } |
int main() { struct soap soap; soap_init(&soap); soap_serve(&soap); } |
int main() { soap_serve(soap_new()); } |
int main() { struct soap soap1, soap2; pthread_t tid; ... soap_init(&soap1); if (soap_bind(&soap1, host, port, backlog) < 0) exit(1); if (soap_accept(&soap1) < 0) exit(1); pthread_create(&tid, NULL, (void*(*)(void*))soap_serve, (void*)&soap1); ... soap_init(&soap2); soap_call_ns__method(&soap2, ...); // make a remote call ... soap_end(&soap2); ... pthread_join(tid, NULL); // wait for thread to terminate soap_end(&soap1); // release its data } |
$ wsdl2h -o quote.h http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl |
$ wsdl2h -c -o quote.h http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl |
|
//gsoap ns1 service name: net_DOTxmethods_DOTservices_DOTstockquote_DOTStockQuoteBinding //gsoap ns1 service type: net_DOTxmethods_DOTservices_DOTstockquote_DOTStockQuotePortType //gsoap ns1 service port: http://66.28.98.121:9090/soap //gsoap ns1 service namespace: urn:xmethods-delayed-quotes //gsoap ns1 service documentation: Definitions generated by the gSOAP WSDL parser 1.0 // Service net.xmethods.services.stockquote.StockQuoteService : net.xmethods.services.stockquote.StockQuote web service //gsoap ns1 service method-style: getQuote rpc //gsoap ns1 service method-encoding: getQuote http://schemas.xmlsoap.org/soap/encoding/ //gsoap ns1 service method-action: getQuote urn:xmethods-delayed-quotes#getQuote int ns1__getQuote(char *symbol, float &Result); |
soapcpp2 getQuote.h |
int soap_call_ns1__getQuote(struct soap *soap, char *URL, char *action, char *symbol, float &Result); |
#include "soapH.h" // obtain the generated stub #include "net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding.nsmap" // obtain the namespace mapping table int main() { struct soap soap; // gSOAP runtime environment float quote; soap_init(&soap); // initialize runtime environment (only once) if (soap_call_ns1__getQuote(&soap, NULL, NULL, "IBM", "e) == SOAP_OK) std::cout << "Current IBM Stock Quote = " << quote << std::endl; else // an error occurred soap_print_fault(&soap, stderr); // display the SOAP fault message on the stderr stream soap_destroy(&soap); // delete deserialized class instances (for C++ only) soap_end(&soap); // remove deserialized data and clean up soap_done(&soap); // detach the gSOAP environment return 0; } |
#include "soapnet_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBindingProxy.h" // get proxy #include "net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding.nsmap" // obtain the namespace mapping table int main() { net q; // "net" is the proxy class with a name that is the short name of the service float r; if (q.ns1__getQuote("IBM", r) == SOAP_OK) std::cout << r << std::endl; else soap_print_fault(q.soap, stderr); return 0; } |
//gsoap ns1 service name: net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding |
|
POST /soap HTTP/1.1 Host: services.xmethods.net Content-Type: text/xml Content-Length: 529 SOAPAction: "" <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:xmethods-delayed-quotes" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:getQuote> <symbol>IBM</symbol> </ns1:getQuote> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
HTTP/1.1 200 OK Date: Sat, 25 Aug 2001 19:28:59 GMT Content-Type: text/xml Server: Electric/1.0 Connection: Keep-Alive Content-Length: 491 <?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/» <soap:Body> <n:getQuoteResponse xmlns:n="urn:xmethods-delayed-quotes» <Result xsi:type="xsd:float»41.81</Result> </n:getQuoteResponse> </soap:Body> </soap:Envelope> |
... struct soap soap; float quotes[3]; char *myportfolio[] = {"IBM", "MSDN"}; soap_init(&soap); // need to initialize only once for (int i = 0; i < 3; i++) if (soap_call_ns1__getQuote(&soap, "http://services.xmethods.net:80/soap", "", myportfolio[i], "es[i]) != SOAP_OK) break; if (soap.error) // an error occurred soap_print_fault(&soap, stderr); soap_end(&soap); // clean up all deserialized data ... |
struct Namespace namespaces[] = { // {"ns-prefix", "ns-name"} {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, // MUST be first {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, // MUST be second {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, // MUST be third {"xsd", "http://www.w3.org/2001/XMLSchema"}, // 2001 XML Schema {"ns1", "urn:xmethods-delayed-quotes"}, // given by the service description {NULL, NULL} // end of table }; |
... <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:xmethods-delayed-quotes" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> ... |
// Contents of file "getQuote.h": int ns1__getQuote(char *symbol, float &Result); int ns2__getQuote(char *ticker, char *"e); |
class e__Address // an electronic address { char *email; char *url; }; class s__Address // a street address { char *street; int number; char *city; }; |
<e:Address xsi:type="e:Address"> <email xsi:type="string">me@home</email> <url xsi:type="string">www.me.com</url> </e:Address> |
<s:Address xsi:type="s:Address"> <street xsi:type="string">Technology Drive</street> <number xsi:type="int">5</number> <city xsi:type="string">Softcity</city> </s:Address> |
struct Namespace namespaces[] = { ... {"e", "http://www.me.com/schemas/electronic-address"}, {"s", "http://www.me.com/schemas/street-address"}, ... |
// Content of file "getQuote.h": //gsoap ns1 service name: Quote //gsoap ns1 service location: http://services.xmethods.net/soap //gsoap ns1 service namespace: urn:xmethods-delayed-quotes //gsoap ns1 service style: rpc //gsoap ns1 service encoding: encoded //gsoap ns1 service method-action: getQuote "" int ns1__getQuote(char *symbol, float &Result); |
#include "soapH.h" class Quote { public: struct soap *soap; const char *endpoint; Quote() { soap = soap_new(); endpoint = "http://services.xmethods.net/soap"; }; ~Quote() { if (soap) { soap_destroy(soap); soap_end(soap); soap_free(soap); }}; int getQuote(char *symbol, float &Result) { return soap ? soap_call_ns1__getQuote(soap, endpoint, "", symbol, Result) : SOAP_EOM; }; }; |
#include "soapQuoteProxy.h" // get proxy #include "Quote.nsmap" // get namespace bindings int main() { Quote q; float r; if (q.ns1__getQuote("IBM", r) == SOAP_OK) std::cout << r << std::endl; else soap_print_fault(q.soap, stderr); return 0; } |
// Contents of header file: ... typedef char *xsd__string; // encode xsd__string value as the xsd:string schema type typedef char *xsd__anyURI; // encode xsd__anyURI value as the xsd:anyURI schema type typedef float xsd__float; // encode xsd__float value as the xsd:float schema type typedef long xsd__int; // encode xsd__int value as the xsd:int schema type typedef bool xsd__boolean; // encode xsd__boolean value as the xsd:boolean schema type typedef unsigned long long xsd__positiveInteger; // encode xsd__positiveInteger value as the xsd:positiveInteger schema type ... |
// Contents of file "getQuote.h": typedef char *xsd__string; typedef float xsd__float; int ns1__getQuote(xsd__string symbol, xsd__float &Result); |
int soap_call_ns1__getQuote(struct soap *soap, char *URL, char *action, char *symbol, float &Result); |
... <SOAP-ENV:Body> <ns1:getQuote><symbol xsi:type="xsd:string">IBM</symbol> </ns1:getQuote> </SOAP-ENV:Body> ... |
... <soap:Body> <n:getQuoteResponse xmlns:n="urn:xmethods-delayed-quotes» <Result xsi:type="xsd:float»41.81</Result> </n:getQuoteResponse> </soap:Body> ... |
// Contents of "getQuote.h": typedef char *xsd__string; typedef float xsd__float; struct ns1__getQuoteResponse {xsd__float Result;}; int ns1__getQuote(xsd__string symbol, struct ns1__getQuoteResponse &r); |
... <SOAP-ENV:Body> <ns1:getQuote><symbol xsi:type="xsd:string">IBM</symbol> </ns1:getQuote> </SOAP-ENV:Body> ... |
... <soap:Body> <n:getQuoteResponse xmlns:n='urn:xmethods-delayed-quotes'> <Result xsi:type='xsd:float'>41.81</Result> </n:getQuoteResponse> </soap:Body> ... |
// Contents of "getQuote.h": typedef char *xsd__string; typedef float xsd__float; int ns1__getQuote(xsd__string symbol, struct ns1__getQuoteResponse {xsd__float Result;} &r); |
// Contents of file "getNames.h": int ns3__getNames(char *SSN, struct ns3__getNamesResponse {char *first; char *last;} &r); |
... <SOAP-ENV:Envelope ... xmlns:ns3="urn:names" ...> ... <ns3:getNames> <SSN>999 99 9999</SSN> </ns3:getNames> ... |
... <m:getNamesResponse xmlns:m="urn:names"> <first>John</first> <last>Doe</last> </m:getNamesResponse> ... |
// Content of file "copy.h": int X_rox__copy_name(char *name, struct X_rox__copy_nameResponse {char *name;} &r); |
... <SOAP-ENV:Envelope ... xmlns:X-rox="urn:copy" ...> ... <X-rox:copy-name> <name>SOAP</name> </X-rox:copy-name> ... |
... <m:copy-nameResponse xmlns:m="urn:copy"> <name>SOAP</name> </m:copy-nameResponse> ... |
// Contents of file "flight.h": typedef char *xsd__string; class ns2__FlightInfo { public: xsd__string airline; xsd__string flightNumber; xsd__string altitude; xsd__string currentLocation; xsd__string equipment; xsd__string speed; }; struct ns1__getFlightInfoResponse {ns2__FlightInfo _return;}; int ns1__getFlightInfo(xsd__string param1, xsd__string param2, struct ns1__getFlightInfoResponse &r); |
struct soap soap; ... soap_init(&soap); ... soap_call_ns1__getFlightInfo(&soap, "testvger.objectspace.com/soap/servlet/rpcrouter", "urn:galdemo:flighttracker", "UAL", "184", r); ... struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema"}, {"ns1", "urn:galdemo:flighttracker"}, {"ns2", "http://galdemo.flighttracker.com"}, {NULL, NULL} }; |
POST /soap/servlet/rpcrouter HTTP/1.1 Host: testvger.objectspace.com Content-Type: text/xml Content-Length: 634 SOAPAction: "urn:galdemo:flighttracker" <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:galdemo:flighttracker" xmlns:ns2="http://galdemo.flighttracker.com" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:getFlightInfo xsi:type="ns1:getFlightInfo"> <param1 xsi:type="xsd:string">UAL</param1> <param2 xsi:type="xsd:string">184</param2> </ns1:getFlightInfo> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
HTTP/1.1 200 ok Date: Thu, 30 Aug 2001 00:34:17 GMT Server: IBM_HTTP_Server/1.3.12.3 Apache/1.3.12 (Win32) Set-Cookie: sesessionid=2GFVTOGC30D0LGRGU2L4HFA;Path=/ Cache-Control: no-cache="set-cookie,set-cookie2" Expires: Thu, 01 Dec 1994 16:00:00 GMT Content-Length: 861 Content-Type: text/xml; charset=utf-8 Content-Language: en <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:getFlightInfoResponse xmlns:ns1="urn:galdemo:flighttracker" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <return xmlns:ns2="http://galdemo.flighttracker.com" xsi:type="ns2:FlightInfo"> <equipment xsi:type="xsd:string">A320</equipment> <airline xsi:type="xsd:string">UAL</airline> <currentLocation xsi:type="xsd:string">188 mi W of Lincoln, NE</currentLocation> <altitude xsi:type="xsd:string">37000</altitude> <speed xsi:type="xsd:string">497</speed> <flightNumber xsi:type="xsd:string">184</flightNumber> </return> </ns1:getFlightInfoResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
cout << r.return_.equipment << " flight " << r.return_.airline << r.return_.flightNumber << " traveling " << r.return_.speed << " mph " << " at " << r.return_.altitude << " ft, is located " << r.return_.currentLocation << endl; |
A320 flight UAL184 traveling 497 mph at 37000 ft, is located 188 mi W of Lincoln, NE |
// Contents of "getQuote.h": typedef char *xsd__string; typedef float xsd__float; int ns1__getQuote(xsd__string, xsd__float&); |
// Contents of "getQuote.h": typedef char *xsd__string; typedef float xsd__float; int ns1__getQuote(xsd__string symbol, xsd__float &_return); |
// Contents of "getQuote.h": typedef char *xsd__string; typedef float xsd__float; struct ns1__getQuoteResponse {xsd__float _return;}; int ns1__getQuote(xsd__string symbol, struct ns1__getQuoteResponse &r); |
struct ns3__SOAPService { public: int ID; char *name; char *owner; char *description; char *homepageURL; char *endpoint; char *SOAPAction; char *methodNamespaceURI; char *serviceStatus; char *methodName; char *dateCreated; char *downloadURL; char *wsdlURL; char *instructions; char *contactEmail; char *serverImplementation; }; struct ArrayOfSOAPService {struct ns3__SOAPService *__ptr; int __size;}; int ns__getAllSOAPServices(void *_, struct ArrayOfSOAPService &_return); |
enum ns__event { off, on, stand_by }; int ns__signal(enum ns__event in, struct ns__signalResponse { } *out); |
// Contents of file "calc.h": typedef double xsd__double; int ns__add(xsd__double a, xsd__double b, xsd__double &result); int ns__sub(xsd__double a, xsd__double b, xsd__double &result); int ns__sqrt(xsd__double a, xsd__double &result); |
soapcpp2 calc.h |
// Contents of file "calc.cpp": #include "soapH.h" #include < math.h > // for sqrt() main() { soap_serve(soap_new()); // use the remote method request dispatcher } // Implementation of the "add" remote method: int ns__add(struct soap *soap, double a, double b, double &result) { result = a + b; return SOAP_OK; } // Implementation of the "sub" remote method: int ns__sub(struct soap *soap, double a, double b, double &result) { result = a - b; return SOAP_OK; } // Implementation of the "sqrt" remote method: int ns__sqrt(struct soap *soap, double a, double &result) { if (a > = 0) { result = sqrt(a); return SOAP_OK; } else return soap_receiver_fault(soap, "Square root of negative number", "I can only take the square root of a non-negative number"); } // As always, a namespace mapping table is needed: struct Namespace namespaces[] = { // {"ns-prefix", "ns-name"} {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema"}, {"ns", "urn:simple-calc"}, // bind "ns" namespace prefix {NULL, NULL} }; |
|
int main() { struct soap soap; int m, s; // master and slave sockets soap_init(&soap); m = soap_bind(&soap, "machine.cs.fsu.edu", 18083, 100); if (m < 0) soap_print_fault(&soap, stderr); else { fprintf(stderr, "Socket connection successful: master socket = %d\n", m); for (int i = 1; ; i++) { s = soap_accept(&soap); if (s < 0) { soap_print_fault(&soap, stderr); break; } fprintf(stderr, "%d: accepted connection from IP=%d.%d.%d.%d socket=%d", i, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s); if (soap_serve(&soap) != SOAP_OK) // process RPC request soap_print_fault(&soap, stderr); // print error fprintf(stderr, "request served\n"); soap_destroy(&soap); // clean up class instances soap_end(&soap); // clean up everything and close socket } } soap_done(&soap); // close master socket and detach environment } |
|
#include "soapH.h" #include < pthread.h > #define BACKLOG (100) // Max. request backlog int main(int argc, char **argv) { struct soap soap; soap_init(&soap); if (argc < 2) // no args: assume this is a CGI application { soap_serve(&soap); // serve request, one thread, CGI style soap_destroy(&soap); // dealloc C++ data soap_end(&soap); // dealloc data and clean up } else { soap.send_timeout = 60; // 60 seconds soap.recv_timeout = 60; // 60 seconds soap.accept_timeout = 3600; // server stops after 1 hour of inactivity soap.max_keep_alive = 100; // max keep-alive sequence void *process_request(void*); struct soap *tsoap; pthread_t tid; int port = atoi(argv[1]); // first command-line arg is port SOAP_SOCKET m, s; m = soap_bind(&soap, NULL, port, BACKLOG); if (!soap_valid_socket(m)) exit(1); fprintf(stderr, "Socket connection successful %d\n", m); for (;;) { s = soap_accept(&soap); if (!soap_valid_socket(s)) { if (soap.errnum) { soap_print_fault(&soap, stderr); exit(1); } fprintf(stderr, "server timed out\n"); break; } fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF); tsoap = soap_copy(&soap); // make a safe copy if (!tsoap) break; pthread_create(&tid, NULL, (void*(*)(void*))process_request, (void*)tsoap); } } soap_done(&soap); // detach soap struct return 0; } void *process_request(void *soap) { pthread_detach(pthread_self()); soap_serve((struct soap*)soap); soap_destroy((struct soap*)soap); // dealloc C++ data soap_end((struct soap*)soap); // dealloc data and clean up soap_done((struct soap*)soap); // detach soap struct free(soap); return NULL; } |
#include "soapH.h" #include < pthread.h > #define BACKLOG (100) // Max. request backlog #define MAX_THR (10) // Max. threads to serve requests int main(int argc, char **argv) { struct soap soap; soap_init(&soap); if (argc < 2) // no args: assume this is a CGI application { soap_serve(&soap); // serve request, one thread, CGI style soap_destroy(&soap); // dealloc C++ data soap_end(&soap); // dealloc data and clean up } else { struct soap *soap_thr[MAX_THR]; // each thread needs a runtime environment pthread_t tid[MAX_THR]; int port = atoi(argv[1]); // first command-line arg is port SOAP_SOCKET m, s; int i; m = soap_bind(&soap, NULL, port, BACKLOG); if (!soap_valid_socket(m)) exit(1); fprintf(stderr, "Socket connection successful %d\n", m); for (i = 0; i < MAX_THR; i++) soap_thr[i] = NULL; for (;;) { for (i = 0; i < MAX_THR; i++) { s = soap_accept(&soap); if (!soap_valid_socket(s)) { if (soap.errnum) { soap_print_fault(&soap, stderr); continue; // retry } else { fprintf(stderr, "Server timed out\n"); break; } } fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF); if (!soap_thr[i]) // first time around { soap_thr[i] = soap_copy(&soap); if (!soap_thr[i]) exit(1); // could not allocate } else// recycle soap environment { pthread_join(tid[i], NULL); fprintf(stderr, "Thread %d completed\n", i); soap_destroy(soap_thr[i]); // deallocate C++ data of old thread soap_end(soap_thr[i]); // deallocate data of old thread } soap_thr[i]->socket = s; // new socket fd pthread_create(&tid[i], NULL, (void*(*)(void*))soap_serve, (void*)soap_thr[i]); } } for (i = 0; i < MAX_THR; i++) if (soap_thr[i]) { soap_done(soap_thr[i]); // detach context free(soap_thr[i]); // free up } } return 0; } |
|
#include "soapH.h" #include < pthread.h > #define BACKLOG (100) // Max. request backlog #define MAX_THR (10) // Size of thread pool #define MAX_QUEUE (1000) // Max. size of request queue SOAP_SOCKET queue[MAX_QUEUE]; // The global request queue of sockets int head = 0, tail = 0; // Queue head and tail void *process_queue(void*); int enqueue(SOAP_SOCKET); SOAP_SOCKET dequeue(); pthread_mutex_t queue_cs; pthread_cond_t queue_cv; int main(int argc, char **argv) { struct soap soap; soap_init(&soap); if (argc < 2) // no args: assume this is a CGI application { soap_serve(&soap); // serve request, one thread, CGI style soap_destroy(&soap); // dealloc C++ data soap_end(&soap); // dealloc data and clean up } else { struct soap *soap_thr[MAX_THR]; // each thread needs a runtime environment pthread_t tid[MAX_THR]; int port = atoi(argv[1]); // first command-line arg is port SOAP_SOCKET m, s; int i; m = soap_bind(&soap, NULL, port, BACKLOG); if (!soap_valid_socket(m)) exit(1); fprintf(stderr, "Socket connection successful %d\n", m); pthread_mutex_init(&queue_cs, NULL); pthread_cond_init(&queue_cv, NULL); for (i = 0; i < MAX_THR; i++) { soap_thr[i] = soap_copy(&soap); fprintf(stderr, "Starting thread %d\n", i); pthread_create(&tid[i], NULL, (void*(*)(void*))process_queue, (void*)soap_thr[i]); } for (;;) { s = soap_accept(&soap); if (!soap_valid_socket(s)) { if (soap.errnum) { soap_print_fault(&soap, stderr); continue; // retry } else { fprintf(stderr, "Server timed out\n"); break; } } fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF); while (enqueue(s) == SOAP_EOM) sleep(1); } for (i = 0; i < MAX_THR; i++) { while (enqueue(SOAP_INVALID_SOCKET) == SOAP_EOM) sleep(1); } for (i = 0; i < MAX_THR; i++) { fprintf(stderr, "Waiting for thread %d to terminate... ", i); pthread_join(tid[i], NULL); fprintf(stderr, "terminated\n"); soap_done(soap_thr[i]); free(soap_thr[i]); } pthread_mutex_destroy(&queue_cs); pthread_cond_destroy(&queue_cv); } soap_done(&soap); return 0; } void *process_queue(void *soap) { struct soap *tsoap = (struct soap*)soap; for (;;) { tsoap->socket = dequeue(); if (!soap_valid_socket(tsoap->socket)) break; soap_serve(tsoap); soap_destroy(tsoap); soap_end(tsoap); fprintf(stderr, "served\n"); } return NULL; } int enqueue(SOAP_SOCKET sock) { int status = SOAP_OK; int next; pthread_mutex_lock(&queue_cs); next = tail + 1; if (next > = MAX_QUEUE) next = 0; if (next == head) status = SOAP_EOM; else { queue[tail] = sock; tail = next; } pthread_cond_signal(&queue_cv); pthread_mutex_unlock(&queue_cs); return status; } SOAP_SOCKET dequeue() { SOAP_SOCKET sock; pthread_mutex_lock(&queue_cs); while (head == tail) pthread_cond_wait(&queue_cv, &queue_cs); sock = queue[head++]; if (head > = MAX_QUEUE) head = 0; pthread_mutex_unlock(&queue_cs); return sock; } |
{ ... struct soap soap; database_handle_type database_handle; soap_init(&soap); soap.user = (void*)database_handle; ... soap_serve(&soap); // call the remove method dispatcher to handle request ... } int ns__myMethod(struct soap *soap, ...) { ... fetch((database_handle_type*)soap->user); // get data ... return SOAP_OK; } |
// Content of file "calc.h": //gsoap ns service name: Calculator //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service location: http://www.cs.fsu.edu/~engelen/calc.cgi //gsoap ns schema namespace: urn:calc //gsoap ns service method-action: add "" int ns__add(double a, double b, double &result); int ns__sub(double a, double b, double &result); int ns__mul(double a, double b, double &result); int ns__div(double a, double b, double &result); |
#include "soapH.h" class CalculatorObject : public soap { public: Calculator() { ... }; ~Calculator() { ... }}; int serve() { return soap_serve(this); }; }; |
#include "soapCalculatorObject.h" // get server object #include "Calculator.nsmap" // get namespace bindings int main() { CalculatorObject c; return c.serve(); // calls soap_serve to serve as CGI application (using stdin/out) } int ns__add(double a, double b, double &result) { result = a + b; return SOAP_OK; } ... sub(), mul(), and div() implementations ... |
struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance", \"http://www.w3.org/*/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema", \"http://www.w3.org/*/XMLSchema"}, {"ns", "http://tempuri.org"}, {NULL, NULL} }; |
typedef double xsd__double; int ns__add(xsd__double a, xsd__double b, xsd__double &result); int ns__sub(xsd__double a, xsd__double b, xsd__double &result); int ns__sqrt(xsd__double a, xsd__double &result); |
<?xml version="1.0" encoding="UTF-8"?> <definitions name="Service" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://location/Service.wsdl" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" xmlns:tns="http://location/Service.wsdl" xmlns:ns="http://tempuri.org"> <types> <schema xmlns="http://www.w3.org/2000/10/XMLSchema" targetNamespace="http://tempuri.org" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> <complexType name="addResponse"> <all> <element name="result" type="double" minOccurs="0" maxOccurs="1"/> </all> <anyAttribute namespace="##other"/> </complexType> <complexType name="subResponse"> <all> <element name="result" type="double" minOccurs="0" maxOccurs="1"/> </all> <anyAttribute namespace="##other"/> </complexType> <complexType name="sqrtResponse"> <all> <element name="result" type="double" minOccurs="0" maxOccurs="1"/> </all> <anyAttribute namespace="##other"/> </complexType> </schema> </types> <message name="addRequest"> <part name="a" type="xsd:double"/> <part name="b" type="xsd:double"/> </message> <message name="addResponse"> <part name="result" type="xsd:double"/> </message> <message name="subRequest"> <part name="a" type="xsd:double"/> <part name="b" type="xsd:double"/> </message> <message name="subResponse"> <part name="result" type="xsd:double"/> </message> <message name="sqrtRequest"> <part name="a" type="xsd:double"/> </message> <message name="sqrtResponse"> <part name="result" type="xsd:double"/> </message> <portType name="ServicePortType"> <operation name="add"> <input message="tns:addRequest"/> <output message="tns:addResponse"/> </operation> <operation name="sub"> <input message="tns:subRequest"/> <output message="tns:subResponse"/> </operation> <operation name="sqrt"> <input message="tns:sqrtRequest"/> <output message="tns:sqrtResponse"/> </operation> </portType> <binding name="ServiceBinding" type="tns:ServicePortType"> <SOAP:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="add"> <SOAP:operation soapAction="http://tempuri.org#add"/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="sub"> <SOAP:operation soapAction="http://tempuri.org#sub"/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="sqrt"> <SOAP:operation soapAction="http://tempuri.org#sqrt"/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <service name="Service"> <port name="ServicePort" binding="tns:ServiceBinding"> <SOAP:address location="http://location/Service.cgi"/> </port> </service> </definitions> |
$ wsdl2h -o calc.h http://www.cs.fsu.edu/~engelen/calc.wsdl ... $ soapcpp2 -i -Iimport calc.h |
|
# This file contains custom definitions of the XML Schema types and # C/C++ types for your project, and XML namespace prefix definitions. # The wsdl2h WSDL importer consults this file to determine bindings. [ // This comment will be included in the generated .h file // You can include any additional declarations, includes, imports, etc. // within [ ] sections. The brackets MUST appear at the start of a line ] # XML namespace prefix definitions can be provided to override the # default choice of ns1, ns2, ... prefixes. For example: i = "http://www.soapinterop.org/" s = "http://www.soapinterop.org/xsd" # Type definitions are of the form: # type = declaration | use | pointer-use # where # type is the XML Schema type (or an application type in a namespace # that has a prefix definition given as above). # declaration is an optional C/C++ type declaration # use is how the type is referred to in code # pointer-use is how the type should be referred to as a pointer (opt) # Example XML Schema and C/C++ type bindings: xsd__int = | int xsd__string = | char* | char* xsd__boolean = enum xsd__boolean false_, true_ ; | enum xsd__boolean xsd__base64Binary = class xsd__base64Binary unsigned char *__ptr; int __size; ; | xsd__base64Binary | xsd__base64Binary # You can extend structs and classes with member data and functions. # For example, adding a constructor to ns__myClass: ns__myClass = $ ns__myClass(); # The general form is # class_name = $ member; |
// Contents of file "quotex.h": int ns1__getQuote(char *symbol, float &result); // XMethods delayed stock quote service remote method int ns2__getRate(char *country1, char *country2, float &result); // XMethods currency-exchange service remote method int ns3__getQuote(char *symbol, char *country, float &result); // the new currency-converted stock quote service |
// Contents of file "quotex.cpp": #include "soapH.h" // include generated proxy and SOAP support int main(int argc, char **argv) { struct soap soap; float q; soap_init(&soap); if (argc < = 2) soap_serve(&soap); else if (soap_call_ns3__getQuote(&soap, "http://www.cs.fsu.edu/\symbol{126}engelen/quotex.cgi", "", argv[1], argv[2], q)) soap_print_fault(&soap, stderr); else printf("\nCompany %s: %f (%s)\n", argv[1], q, argv[2]); return 0; } int ns3__getQuote(struct soap *soap, char *symbol, char *country, float &result) { float q, r; int socket = soap->socket; // save socket (stand-alone service only, does not support keep-alive) if (soap_call_ns1__getQuote(soap, "http://services.xmethods.net/soap", "", symbol, &q) == 0 && soap_call_ns2__getRate(soap, "http://services.xmethods.net/soap", NULL, "us", country, &r) == 0) { result = q*r; soap->socket = socket; return SOAP_OK; } soap->socket = socket; return SOAP_FAULT; // pass soap fault messages on to the client of this app } /* Since this app is a combined client-server, it is put together with * one header file that describes all remote methods. However, as a consequence we * have to implement the methods that are not ours. Since these implementations are * never called (this code is client-side), we can make them dummies as below. */ int ns1__getQuote(struct soap *soap, char *symbol, float &result) { return SOAP_NO_METHOD; } // dummy: will never be called int ns2__getRate(struct soap *soap, char *country1, char *country2, float &result) { return SOAP_NO_METHOD; } // dummy: will never be called struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"}, {"ns1", "urn:xmethods-delayed-quotes"}, {"ns2", "urn:xmethods-CurrencyExchange"}, {"ns3", "urn:quotex"}, {NULL, NULL} }; |
soapcpp2 quotex.h g++ -o quotex.cgi quotex.cpp soapC.cpp soapClient.cpp soapServer.cpp stdsoap2.cpp -lsocket -lxnet -lnsl |
quotex.cgi IBM uk |
int ns__event(int eventNo, void); |
int soap_send_ns__event(struct soap *soap, const char URL, const char action, int event); int soap_recv_ns__event(struct soap *soap, struct ns__event *dummy); |
struct ns__event { int eventNo; } |
int soap_serve_ns__event(struct soap *soap); |
main() { soap_serve(soap_new()); } int ns__event(struct soap *soap, int eventNo) { ... // handle event return SOAP_OK; } |
int ns__event(struct soap *soap, int eventNo) { ... // handle event return soap_send_empty_response(soap, SOAP_OK); // SOAP_OK: return HTTP 202 ACCEPTED } |
if (soap_send_ns__event(soap, eventNo) != SOAP_OK || soap_recv_empty_response(soap) != SOAP_OK) soap_print_fault(soap, stderr); ... |
|
|
|
struct ns__Person { char *name; } *p; |
soap_serialize_PointerTons__Person(&soap, &p); |
soap_begin_send(&soap); soap_put_PointerTons__Person(&soap, &p, "ns:element-name", "ns:type-name"); soap_end_send(&soap); |
<ns:element-name xmlns:SOAP-ENV="..." xmlns:SOAP-ENC="..." xmlns:ns="..." ... xsi:type="ns:type-name"> <name xsi:type="xsd:string">...</name> </ns:element-name> |
soap.sendfd = open(file, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR); soap_serialize_PointerTons__Person(&soap, &p); soap_begin_send(&soap); soap_put_PointerTons__Person(&soap, &p, "ns:element-name", "ns:type-name"); soap_end_send(&soap); |
T1 var1; T2 var2; struct soap soap; ... soap_init(&soap); // initialize [soap_omode(&soap, flags);] // set output-mode flags (e.g. SOAP_ENC_XML|SOAP_ENC_ZLIB) soap_begin(&soap); // start new (de)serialization phase soap_set_omode(&soap, SOAP_XML_GRAPH); soap_serialize_Type1(&soap, &var1); soap_serialize_Type2(&soap, &var2); ... [soap.socket = a_socket_file_descriptor;] // when using sockets [soap.os = an_output_stream;] // C++ [soap.sendfd = an_output_file_descriptor;] // C soap_begin_send(&soap); soap_put_Type1(&soap, &var1, "[namespace-prefix:]element-name1", "[namespace-prefix:]type-name1"); soap_put_Type2(&soap, &var2, "[namespace-prefix:]element-name2", "[namespace-prefix:]type-name2"); ... soap_end_send(&soap); // flush soap_destroy(&soap); // remove deserialized C++ objects soap_end(&soap); // remove deserialized data structures soap_done(&soap); // finalize last use of this environment ... |
struct soap soap; myClass obj; soap_init(&soap); // initialize soap_begin(&soap); // start new (de)serialization phase soap_set_omode(&soap, SOAP_XML_GRAPH); obj.serialize(&soap); soap.os = cout; // send to cout soap_begin_send(&soap); obj.put(&soap, "[namespace-prefix:]element-name1", "[namespace-prefix:]type-name1"); ... soap_end_send(&soap); // flush soap_destroy(&soap); // remove deserialized C++ objects soap_end(&soap); // remove deserialized data soap_done(&soap); // finalize last use of this environment |
ostream &operator<<(ostream &o, const myClass &e) { if (!e.soap) ... error: need a soap struct to serialize (could use global struct) ... else { ostream *os = e.soap->os; e.soap->os = &o; soap_set_omode(e.soap, SOAP_XML_GRAPH); e.serialize(e.soap); soap_begin_send(e.soap); e.put(e.soap, "myClass", NULL); soap_end_send(e.soap); e.soap->os = os; soap_clr_omode(e.soap, SOAP_XML_GRAPH); } return o; } |
// Contents of file "tricky.h": struct Tricky { int *p; int n; int *q; }; |
struct soap soap; struct Tricky X; X.n = 1; X.p = &X.n; X.q = &X.n; soap_init(&soap); soap_begin(&soap); soap_serialize_Tricky(&soap, &X); soap_put_Tricky(&soap, &X, "Tricky", NULL); soap_end(&soap); // Clean up temporary data used by the serializer |
<Tricky xsi:type="Tricky"> <p href="#2"/> <n xsi:type="int">1</n> <q href="#2"/> <r xsi:type="int">2</r> </Tricky> <id id="2" xsi:type="int">1</id> |
<Tricky xsi:type="Tricky"> <p href="#2"/> <n id="2" xsi:type="int">1</n> <q href="#2"/> </Tricky> |
T1 var1; T2 var2; struct soap soap; ... soap_init(&soap); // initialize at least once [soap_imode(&soap, flags);] // set input-mode flags soap_begin(&soap); // begin new decoding phase [soap.is = an_input_stream;] // C++ [soap.recvfd = an_input_file_desriptpr;] // C soap_begin_recv(&soap); // if HTTP/MIME/DIME/GZIP headers are present, parse them if (!soap_get_Type1(&soap, &var1, "[namespace-prefix:]element-name1", "[namespace-prefix:]type-name1")) ... error ... if (!soap_get_Type2(&soap, &var2, "[namespace-prefix:]element-name2", "[namespace-prefix:]type-name1")) ... error ... ... soap_end_recv(&soap); // check consistency of id/hrefs soap_destroy(&soap); // remove deserialized C++ objects soap_end(&soap); // remove deserialized data soap_done(&soap); // finalize last use of the environment |
myClass obj; struct soap soap; soap_init(&soap); // initialize soap_begin(&soap); // begin new decoding phase soap.is = cin; // read from cin soap_begin_recv(&soap); // if HTTP header is present, parse it if (!obj.get(&soap, "myClass", NULL) ... error ... soap_end_recv(&soap); // check consistency of id/hrefs ... soap_destroy(&soap); // remove deserialized C++ objects soap_end(&soap); // remove deserialized data soap_done(&soap); // finalize last use of the environment |
istream &operator>>(istream &i, myClass &e) { if (!e.soap) ... error: need soap struct to deserialize (could use global struct)... istream *is = e.soap->is; e.soap->is = &i; if (soap_begin_recv(e.soap) || !e.soap_in(e.soap, NULL, NULL) || soap_end_recv(e.soap)) ... error ... e.soap->is = is; return i; } |
// Contents of file "person.h": typedef char *xsd__string; typedef char *xsd__Name; typedef unsigned int xsd__unsignedInt; enum ns__Gender {male, female}; class ns__Address { public: xsd__string street; xsd__unsignedInt number; xsd__string city; }; class ns__Person { public: xsd__Name name; enum ns__Gender gender; ns__Address address; ns__Person *mother; ns__Person *father; }; |
// Contents of file "person.cpp": #include "soapH.h" int main() { struct soap soap; ns__Person mother, father, john; mother.name = "Mary"; mother.gender = female; mother.address.street = "Downing st."; mother.address.number = 10; mother.address.city = "London"; mother.mother = NULL; mother.father = NULL; father.name = "Stuart"; father.gender = male; father.address.street = "Main st."; father.address.number = 5; father.address.city = "London"; father.mother = NULL; father.father = NULL; john.name = "John"; john.gender = male; john.address = mother.address; john.mother = &mother; john.father = &father; soap_init(&soap); soap_omode(&soap, SOAP_ENC_ZLIB | SOAP_XML_GRAPH); // see 8.12 soap_begin(&soap); soap_begin_send(&soap); john.soap_serialize(&soap); john.soap_put(&soap, "johnnie", NULL); soap_end_send(&soap); soap_destroy(&soap); soap_end(&soap); soap_done(&soap); } struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema"}, {"ns", "urn:person"}, // Namespace URI of the "Person" data type {NULL, NULL} }; |
soapcpp2 person.h g++ -DWITH_GZIP -o person person.cpp soapC.cpp stdsoap2.cpp -lsocket -lxnet -lnsl -lz |
<johnnie xsi:type="ns:Person" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="urn:person" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <name xsi:type="xsd:Name">John</name> <gender xsi:type="ns:Gender">male</gender> <address xsi:type="ns:Address"> <street id="3" xsi:type="xsd:string">Dowling st.</street> <number xsi:type="unsignedInt">10</number> <city id="4" xsi:type="xsd:string">London</city> </address> <mother xsi:type="ns:Person"> <name xsi:type="xsd:Name">Mary</name> <gender xsi:type="ns:Gender">female</gender> <address xsi:type="ns:Address"> <street href="#3"/> <number xsi:type="unsignedInt">5</number> <city href="#4"/> </address> </mother> <father xsi:type="ns:Person"> <name xsi:type="xsd:Name">Stuart</name> <gender xsi:type="ns:Gender">male</gender> <address xsi:type="ns:Address"> <street xsi:type="xsd:string">Main st.</street> <number xsi:type="unsignedInt">13</number> <city href="#4"/> </address> </father> </johnnie> |
#include "soapH.h" int main() { struct soap soap; ns__Person *mother, *father, *john = NULL; soap_init(&soap); soap_imode(&soap, SOAP_ENC_ZLIB); // optional: gzip is detected automatically soap_begin(&soap); soap_begin_recv(&soap); if (soap_get_ns__Person(&soap, john, "johnnie", NULL) == NULL) ... error ... mother = john->mother; father = john->father; ... soap_end_recv(&soap); soap_free_temp(&soap); // Clean up temporary data but keep deserialized data } struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema"}, {"ns", "urn:person"}, // Namespace URI of the "Person" data type {NULL, NULL} }; |
john = soap_get_ns__Person(&soap, NULL, "johnnie", NULL); |
#include "soapH.h" main() { struct soap soap; ns__Person *mother, *father, john; soap_init(&soap); soap_imode(&soap, SOAP_ENC_ZLIB); // optional soap_begin(&soap); soap_begin_recv(&soap); soap_default_ns__Person(&soap, &john); if (soap_get_ns__Person(&soap, &john, "johnnie", NULL) == NULL) ... error ... ... } struct Namespace namespaces[] = ... |
class ns__person { public: char *name; struct soap *soap; // we need this, see below ns__person(); ~ns__person(); }; |
soapcpp2 person.h |
#include "soapH.h" #include "ns.nsmap" ... struct soap *soap = soap_new(); ns__person *p = soap_new_ns__person(soap, -1); ... cout << p; // serialize p in XML ... in >> p; // parse XML and deserialize p ... soap_destroy(soap); // deletes p too soap_end(soap); soap_done(soap); |
ostream &operator<<(ostream &o, const ns__person &p) { if (!p.soap) return o; // need a gSOAP environment to serialize p.soap->os = &o; soap_omode(p.soap, SOAP_XML_GRAPH); // XML tree or graph p.soap_serialize(p.soap); soap_begin_send(p.soap); if (p.soap_put(p.soap, "person", NULL) | | soap_end_send(p.soap)) ; // handle I/O error return o; } istream &operator>>(istream &i, ns__person &p) { if (!p.soap) return o; // need a gSOAP environment to parse XML and deserialize p.soap->is = &i; if (soap_begin_recv(p.soap) | | p.soap_in(p.soap, NULL, NULL) | | soap_end_recv(p.soap)) ; // handle I/O error return i; } |
#define SOAP_DEFAULT_bool #define SOAP_DEFAULT_byte #define SOAP_DEFAULT_double #define SOAP_DEFAULT_float #define SOAP_DEFAULT_int #define SOAP_DEFAULT_long #define SOAP_DEFAULT_LONG64 #define SOAP_DEFAULT_short #define SOAP_DEFAULT_string #define SOAP_DEFAULT_time #define SOAP_DEFAULT_unsignedByte #define SOAP_DEFAULT_unsignedInt #define SOAP_DEFAULT_unsignedLong #define SOAP_DEFAULT_unsignedLONG64 #define SOAP_DEFAULT_unsignedShort #define SOAP_DEFAULT_wstring |
struct MyRecord { char *name = "Unknown"; int value = 9999; enum Status { active, passive } status = passive; } |
int ns__login(char *uid = "anonymous", char *pwd = "guest", bool granted); |
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="http://tempuri.org"> <SOAP-ENV:Body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <ns:login> </ns:login> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
soapcpp2 [aheaderfile.h] |
|
|
|
soapcpp2 -cd '../projects' -pmy file.h |
../projects/myH.h ../projects/myC.c ../projects/myClient.c ../projects/myServer.c ../projects/myStub.h |
soapcpp2 /cd '..\projects' /pmy file.h |
// Generate pure C and do not produce WSDL output: //gsoapopt cw int ns__myMethod(char*,char**); // takes a string and returns a string |
struct Namespace namespaces[] = { {"SOAP-ENV", "http://www.w3.org/2002/06/soap-envelope"}, {"SOAP-ENC", "http://www.w3.org/2002/06/soap-encoding"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"}, ... } |
struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/2002/06/soap-encoding"}, {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/2002/06/soap-envelope"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"}, ... } |
g++ -DWITH_SOAPDEFS_H -c stdsoap2.cpp |
// Contents of soapdefs.h #include < ostream > #define SOAP_BUFLEN 20480 // use large send/recv buffer |
extern class ostream; // ostream can't be (de)serialized, but need to be declared to make it visible to gSOAP class ns__myClass { ... virtual void print(ostream &s) const; // need ostream here ... }; |
#module "name" |
#module "name" "fullname" |
/* Contents of module.h */ #module "test" long; char*; struct ns__S { ... } |
#import "mydefs.gsoap" int ns__mymethod(xsd__string in, xsd__int *out); |
typedef char *xsd__string; typedef int xsd__int; |
#include < ostream > #define WITH_COOKIES // use HTTP cookie support (you must compile stdsoap2.cpp with -DWITH_COOKIES) #define WITH_OPENSSL // enable HTTPS (SSL) support (you must compile stdsoap2.cpp with -DWITH_OPENSSL) #define SOAP_DEFAULT_float FLT_NAN // use NaN instead of 0.0 extern class ostream; // ostream can't be (de)serialized, but need to be declared to make it visible to gSOAP class ns__myClass { ... virtual void print(ostream &s) const; // need ostream here ... }; |
g++ -o myclient myclient.cpp stdsoap2.cpp soapC.cpp soapClient.cpp |
g++ -o myclient myclient.cpp stdsoap2.cpp soapC.cpp soapClient.cpp -lsocket -lxnet -lnsl |
// Contents of file "myclient.cpp" #include "soapH.h"; ... // A remote method invocation: soap_call_some_remote_method(...); ... struct Namespace namespaces[] = { // {"ns-prefix", "ns-name"} {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema"}, {"ns1", "urn:my-remote-method"}, {NULL, NULL} }; ... |
g++ -o myserver myserver.cpp stdsoap2.cpp soapC.cpp soapServer.cpp |
g++ -o myserver myserver.cpp stdsoap2.cpp soapC.cpp soapServer.cpp -lsocket -lxnet -lnsl |
// Contents of file "myserver.cpp" #include "soapH.h"; int main() { soap_serve(soap_new()); } ... // Implementations of the remote methods as C++ functions ... struct Namespace namespaces[] = { // {"ns-prefix", "ns-name"} {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema"}, {"ns1", "urn:my-remote-method"}, {NULL, NULL} }; ... |
soapcpp2 -c quote.h gcc -o quote quote.c stdsoap2.c soapC.c soapClient.c |
|
soap_set_imode(soap, inflag); soap_clr_imode(soap, inflag); |
soap_set_omode(soap, outflag); soap_clr_imode(soap, outflag); |
soap_new2(soap, inflag, outflag); |
soap_init2(soap, inflag, outflag); |
|
|
struct soap soap; soap_init2(&soap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE | SOAP_ENC_ZLIB | SOAP_XML_TREE | SOAP_XML_CANONICAL); if (soap_call_ns__myMethod(&soap, ...)) ... |
|
class X { ... }; ns__remoteMethod(X *in, ...); |
class X { ... }; class ns__remoteMethodResponse { ... }; ns__remoteMethod(X *in, ns__remoteMethodResponse &out); |
typedef int xsd__int; class X { ... }; class ArrayOfint { xsd__int *__ptr; int __size; }; ns__remoteMethod(X *in, ArrayOfint *out); |
typedef int xsd__int; class X { ... }; class ArrayOfint { xsd__int *__ptr; int __size; }; ns__remoteMethod(X *in, ArrayOfint *&out); |
|
int main() { ... struct soap soap; soap_init(&soap); soap_serve(&soap); soap_end(&soap); ... } |
int ns__itoa(struct soap *soap, int i, char **a) { *a = (char*)soap_malloc(soap, 11); sprintf(*a, "%d", i); return SOAP_OK; } |
int ns__mymethod(...) { ... if (exception) { char *msg = (char*)soap_malloc(soap, 1024); // allocate temporary space for detailed message sprintf(msg, "...", ...); // produce the detailed message return soap_receiver_fault(soap, Än exception occurred", msg); // return the server-side fault } ... } |
char *soap_strdup(struct soap *soap, const char *s) |
class Sample { public: struct soap *soap; // reference to gSOAP's run-time ... Sample(); ~Sample(); }; |
Sample::Sample() { this->soap = NULL; } Sample::~Sample() { soap_unlink(this->soap, this); } |
struct soap *soap = soap_new(); // new gSOAP runtime Sample *obj = soap_new_Sample(soap, -1); // new Sample object with obj->soap set to runtime ... delete obj; // also calls soap_unlink to remove obj from the deallocation chain soap_destroy(soap); // deallocate all (other) class instances soap_end(soap); // clean up |
class ns__myClass { ... struct soap *soap; // set by soap_new_ns__myClass() char *name; void setName(const char *s); ... }; |
int ns__myMethod(struct soap *soap, ...) { ns__myClass *p = soap_new_ns__myClass(soap, -1); p->setName("SOAP"); return SOAP_OK; } void ns__myClass::ns__setName(const char *s) { if (soap) name = (char*)soap_malloc(soap, strlen(s)+1); else name = (char*)malloc(strlen(s)+1); strcpy(name, s); } ns__myClass::ns__myClass() { soap = NULL; name = NULL; } ns__myClass::~ns__myClass() { if (!soap && name) free(name); soap_unlink(soap, this); } |
|
myservice.cgi < SENT.tst |
struct soap soap; soap_init(&soap); ... soap_set_recv_logfile(&soap, "logs/recv/service12.log"); // append all messages received in /logs/recv/service12.log soap_set_sent_logfile(&soap, "logs/sent/service12.log"); // append all messages sent in /logs/sent/service12.log soap_set_test_logfile(&soap, NULL); // no file name: do not save debug messages ... soap_serve(&soap); ... |
g++ -o myclient myclient.cpp stdsoap2.cpp soapC.cpp soapClient.cpp -lsocket -lxnet -lnsl |
g++ -o myclient myclient.cpp stdsoap2.cpp soapC.cpp soapClient.cpp -lsocket -lxnet -lnsl |
[int] [namespace_prefix__]method_name([inparam1, inparam2, ...,] outparam); |
<[namespace-prefix:]method_name xsi:type="[namespace-prefix:]method_name> <inparam-name1 xsi:type="...">...</inparam-name1> <inparam-name2 xsi:type="...">...</inparam-name2> ... </[namespace-prefix:]method_name> |
<[namespace-prefix:]method-nameResponse xsi:type="[namespace-prefix:]method-nameResponse> <outparam-name xsi:type="...">...</outparam-name> </[namespace-prefix:]method-nameResponse> |
int soap_call_[namespace_prefix__]method_name(struct soap *soap, char *URL, char *action, [inparam1, inparam2, ...,] outparam); |
int soap_serve_[namespace_prefix__]method_name(struct soap *soap); |
struct [namespace_prefix__]response_element_name { outparam1; outparam2; ... }; |
[int] [namespace_prefix__]method_name([inparam1, inparam2, ...,] struct [namespace_prefix__]response_element_name {outparam1[, outparam2, ...]} &anyparam); |
<[namespace-prefix:]method-name xsi:type="[namespace-prefix:]method-name> <inparam-name1 xsi:type="...">...</inparam-name1> <inparam-name2 xsi:type="...">...</inparam-name2> ... </[namespace-prefix:]method-name> |
<[namespace-prefix:]response-element-name xsi:type="[namespace-prefix:]response-element-name> <outparam-name1 xsi:type="...">...</outparam-name1> <outparam-name2 xsi:type="...">...</outparam-name2> ... </[namespace-prefix:]response-element-name> |
|
|
[namespace_prefix__]element_name |
<[namespace-prefix:]element-name ...> |
class n_s__biz_DOTcom { char *n_s__biz_USCOREname; }; |
<n-s:biz.com xsi:type="n-s:biz.com"> <n-s:biz_name xsi:type="string">Bizybiz</n-s:biz_name> </n-s:biz.com> |
struct Namespace namespaces[] = { // {"ns-prefix", "ns-name"} {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, // MUST be first {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, // MUST be second {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, // MUST be third {"xsd", "http://www.w3.org/2001/XMLSchema"}, // Required for XML Schema types {"ns1", "urn:my-service-URI"}, // The namespace URI of the remote methods {NULL, NULL} // end of table }; |
struct Namespace namespaces[] = { // {"ns-prefix", "ns-name", "ns-name validation pattern"} ... {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/----/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/----/XMLSchema"}, ... |
struct Namespace namespaces[] = { // {"ns-prefix", "ns-name", "ns-name validation pattern"} ... {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"}, ... |
struct a__elt { ... }; struct b__elt { ... }; struct k__elt { ... }; |
struct Namespace namespaces[] = { // {"ns-prefix", "ns-name", "ns-name validation pattern"} ... {"a", "some uri"}, {"b", "other uri"}, {"c", "his uri", "* uri"}, ... |
<n:elt xmlns:n="some URI"> matches the struct name a__elt ... <m:elt xmlns:m="other URI"> matches the struct name b__elt ... <k:elt xmlns:k="my URI"> matches the struct name c__elt ... |
struct Namespace namespacesTable1[] = { ... }; struct Namespace namespacesTable2[] = { ... }; struct Namespace namespacesTable3[] = { ... }; struct Namespace *namespaces; ... struct soap soap; ... soap_init(&soap); soap_set_namespaces(&soap, namespaceTable1); soap_call_remote_method(&soap, URL, Action, ...); ... |
|
typedef unsigned int xsd__positiveInteger; |
<positiveInteger xsi:type="xsd:positiveInteger">3</positiveInteger> |
typedef char *xsd__anyURI; |
typedef char *xsd__base64Binary; |
typedef bool xsd__boolean; |
<xsd:boolean xsi:type="xsd:boolean">...</xsd:boolean> |
typedef char xsd__byte; |
<xsd:byte xsi:type="xsd:byte">...</xsd:byte> |
typedef time_t xsd__dateTime; |
typedef char *xsd__dateTime; |
typedef char *xsd__date; |
typedef double xsd__decimal; |
<xsd:double xsi:type="xsd:decimal">...</xsd:double> |
typedef double xsd__double; |
<xsd:double xsi:type="xsd:double">...</xsd:double> |
typedef char *xsd__duration; |
typedef float xsd__float; |
<xsd:float xsi:type="xsd:float">...</xsd:float> |
typedef char *xsd__hexBinary; |
typedef int xsd__int; |
typedef long xsd__int; |
<xsd:int xsi:type="xsd:int">...</xsd:int> |
typedef long long xsd__integer; |
<xsd:integer xsi:type="xsd:integer">...</xsd:integer> |
typedef long long xsd__long; |
typedef LONG64 xsd__long; |
<xsd:long xsi:type="xsd:long">...</xsd:long> |
typedef long long xsd__negativeInteger; |
<xsd:negativeInteger xsi:type="xsd:negativeInteger">...</xsd:negativeInteger> |
typedef unsigned long long xsd__nonNegativeInteger; |
<xsd:nonNegativeInteger xsi:type="xsd:nonNegativeInteger">...</xsd:nonNegativeInteger> |
typedef long long xsd__nonPositiveInteger; |
<xsd:nonPositiveInteger xsi:type="xsd:nonPositiveInteger">...</xsd:nonPositiveInteger> |
typedef char *xsd__normalizedString; |
<xsd:normalizedString xsi:type="xsd:normalizedString">...</xsd:normalizedString> |
typedef unsigned long long xsd__positiveInteger; |
<xsd:positiveInteger xsi:type="xsd:positiveInteger">...</xsd:positiveInteger> |
typedef short xsd__short; |
<xsd:short xsi:type="xsd:short">...</xsd:short> |
typedef char *xsd__string; |
<xsd:string xsi:type="xsd:string">...</xsd:string> |
typedef wchar_t *xsd__string; |
typedef wchar_t *xsd__string_; |
typedef char *xsd__time; |
typedef char *xsd__token; |
<xsd:token xsi:type="xsd:token">...</xsd:token> |
typedef unsigned char xsd__unsignedByte; |
<xsd:unsignedByte xsi:type="xsd:unsignedByte">...</xsd:unsignedByte> |
typedef unsigned int xsd__unsignedInt; |
typedef unsigned long xsd__unsignedInt; |
<xsd:unsignedInt xsi:type="xsd:unsignedInt">...</xsd:unsignedInt> |
typedef unsigned long long xsd__unsignedLong; |
typedef ULONG64 xsd__unsignedLong; |
<xsd:unsignedLong xsi:type="xsd:unsignedLong">...</xsd:unsignedLong> |
typedef unsigned short xsd__unsignedShort; |
<xsd:unsignedShort xsi:type="xsd:unsignedShort">...</xsd:unsignedShort> |
typedef char *xsd__string; typedef wchar_t *xsd__string_; |
class xsd__type_name: [public xsd__super_type_name] { public: Type __item; [public:] [private] [protected:] method1; method2; ... }; |
class xsd__anyType { }; class xsd__anySimpleType: public xsd__anyType { }; typedef char *xsd__anyURI; class xsd__anyURI_: public xsd__anySimpleType { public: xsd__anyURI __item; }; typedef bool xsd__boolean; class xsd__boolean_: public xsd__anySimpleType { public: xsd__boolean __item; }; typedef char *xsd__date; class xsd__date_: public xsd__anySimpleType { public: xsd__date __item; }; typedef time_t xsd__dateTime; class xsd__dateTime_: public xsd__anySimpleType { public: xsd__dateTime __item; }; typedef double xsd__double; class xsd__double_: public xsd__anySimpleType { public: xsd__double __item; }; typedef char *xsd__duration; class xsd__duration_: public xsd__anySimpleType { public: xsd__duration __item; }; typedef float xsd__float; class xsd__float_: public xsd__anySimpleType { public: xsd__float __item; }; typedef char *xsd__time; class xsd__time_: public xsd__anySimpleType { public: xsd__time __item; }; typedef char *xsd__decimal; class xsd__decimal_: public xsd__anySimpleType { public: xsd__decimal __item; }; typedef char *xsd__integer; class xsd__integer_: public xsd__decimal_ { public: xsd__integer __item; }; typedef LONG64 xsd__long; class xsd__long_: public xsd__integer_ { public: xsd__long __item; }; typedef long xsd__int; class xsd__int_: public xsd__long_ { public: xsd__int __item; }; typedef short xsd__short; class xsd__short_: public xsd__int_ { public: xsd__short __item; }; typedef char xsd__byte; class xsd__byte_: public xsd__short_ { public: xsd__byte __item; }; typedef char *xsd__nonPositiveInteger; class xsd__nonPositiveInteger_: public xsd__integer_ { public: xsd__nonPositiveInteger __item; }; typedef char *xsd__negativeInteger; class xsd__negativeInteger_: public xsd__nonPositiveInteger_ { public: xsd__negativeInteger __item; }; typedef char *xsd__nonNegativeInteger; class xsd__nonNegativeInteger_: public xsd__integer_ { public: xsd__nonNegativeInteger __item; }; typedef char *xsd__positiveInteger; class xsd__positiveInteger_: public xsd__nonNegativeInteger_ { public: xsd__positiveInteger __item; }; typedef ULONG64 xsd__unsignedLong; class xsd__unsignedLong_: public xsd__nonNegativeInteger_ { public: xsd__unsignedLong __item; }; typedef unsigned long xsd__unsignedInt; class xsd__unsignedInt_: public xsd__unsginedLong_ { public: xsd__unsignedInt __item; }; typedef unsigned short xsd__unsignedShort; class xsd__unsignedShort_: public xsd__unsignedInt_ { public: xsd__unsignedShort __item; }; typedef unsigned char xsd__unsignedByte; class xsd__unsignedByte_: public xsd__unsignedShort_ { public: xsd__unsignedByte __item; }; typedef char *xsd__string; class xsd__string_: public xsd__anySimpleType { public: xsd__string __item; }; typedef char *xsd__normalizedString; class xsd__normalizedString_: public xsd__string_ { public: xsd__normalizedString __item; }; typedef char *xsd__token; class xsd__token_: public xsd__normalizedString_ { public: xsd__token __item; }; |
class xsd__base64Binary: public xsd__anySimpleType { public: unsigned char *__ptr; int __size; }; class xsd__hexBinary: public xsd__anySimpleType { public: unsigned char *__ptr; int __size; }; |
|
|
typedef unsigned long long xsd__nonNegativeInteger; |
char *s = "hello", *t = s; |
<string id="123" xsi:type="string">hello</string> ... <string href="#123"/> |
typedef char *xsd__string; typedef char *xsd__anyURI; xsd__anyURI *s = "http://www.myservice.com"; xsd__string *t = s; |
// Contents of header file "getInfo.h": getInfo(char *detail); |
HTTP/1.1 200 OK Content-Type: text/xml Content-Length: nnn <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" <SOAP-ENV:Body> <getInfoResponse> <detail> <picture>Mona Lisa by <i>Leonardo da Vinci</i></picture> </detail> </getInfoResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
typedef std::string xsd__string; class ns__myClass { public: xsd__string s; // serialized with xsi:type="xsd:string" std::string t; // serialized without xsi:type ... }; |
struct soap soap; soap_init(&soap); // sets double_format = "%.18G" soap.double_format = "%e"; // redefine |
struct soap soap; soap_init(&soap); // sets float_format = "%.9G" soap.float_format = "%.4f"; // redefine |
#define FLT_NAN #define FLT_PINFTY #define FLT_NINFTY #define DBL_NAN #define DBL_PINFTY #define DBL_NINFTY |
enum weekday {Mon, Tue, Wed, Thu, Fri, Sat, Sun}; |
<weekday xsi:type="weekday">Mon</weekday> |
enum ns1__weekday {Mon, Tue, Wed, Thu, Fri, Sat, Sun}; |
<ns1:weekday xsi:type="ns1:weekday">Sat</ns1:weekday> |
<xsd:element name="weekday" type="tns:weekday"/> <xsd:simpleType name="weekday"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="Mon"/> <xsd:enumeration value="Tue"/> <xsd:enumeration value="Wed"/> <xsd:enumeration value="Thu"/> <xsd:enumeration value="Fri"/> <xsd:enumeration value="Sat"/> <xsd:enumeration value="Sun"/> </xsd:restriction> </xsd:simpleType> |
enum ns1__workday {Mon, Tue, Wed, Thu, Fri}; |
<ns1:workday xsi:type="ns1:workday">5</ns1:workday> |
enum ns1__nums { _1 = 1, _2 = 2, _3 = 3 }; |
enum ns1__relation {LESS = -1, EQUAL = 0, GREATER = 1}; |
enum ns1__workday {Mon, Tue, Wed, Thu, Fri}; enum ns1__weekday {Mon_, Tue_, Wed_, Thu_, Fri_, Sat_, Sun_}; |
enum ns1__workday {Mon, Tue, Wed, Thu, Fri}; enum ns1__weekday {Sat = 5, Sun = 6}; |
enum xsd__boolean {false_, true_}; |
<xsd:boolean xsi:type="xsd:boolean">false</xsd:boolean> |
enum SOAP_ENC__boolean {}; |
<SOAP-ENC:boolean xsi:type="SOAP-ENC:boolean">0<SOAP-ENC:boolean> |
enum * name { enum-constant, enum-constant, ... }; |
enum * ns__machineStatus { ON, BELT, VALVE, HATCH}; int ns__getMachineStatus(char *name, char *enum ns__machineStatus result); |
enum ns__machineStatus { ON=1, BELT=2, VALVE=4, HATCH=8}; |
int ns__getMachineStatus(struct soap *soap, char *name, enum ns__machineStatus result) { ... *result = BELT | HATCH; return SOAP_OK; } |
class [namespace_prefix__]class_name1 [:[public:] [private:] [protected:] [namespace_prefix__]class_name2] { [public:] [private:] [protected:] field1; field2; ... [public:] [private:] [protected:] method1; method2; ... }; |
<[namespace-prefix:]class-name xsi:type="[namespace-prefix:]class-name"> <basefield-name1 xsi:type="...">...</basefield-name1> <basefield-name2 xsi:type="...">...</basefield-name2> ... <field-name1 xsi:type="...">...</field-name1> <field-name2 xsi:type="...">...</field-name2> ... </[namespace-prefix:]class-name> |
// Contents of file "shape.h": class ns__Object { public: char *name; }; class ns__Shape : public ns__Object { public: int sides; enum ns__Color {Red, Green, Blue} color; ns__Shape(); ns__Shape(int sides, enum ns__Green color); ~ns__Shape(); }; |
<ns:Shape xsi:type="ns:Shape"> <name xsi:type="string">Triangle</name> <sides xsi:type="int">3</sides> <color xsi:type="ns:Color">Green</color> </ns:shape> |
// Contents of file "triangle.h": class ns__Triangle : public ns__Object { public: int size; static const int sides = 3; }; |
<ns:Triangle xsi:type="ns:Triangle"> <name xsi:type="string">Triangle</name> <size xsi:type="int">15</size> <sides xsi:type="int">3>/sides> </ns:Triangle> |
[virtual] int get(struct soap *soap) [const]; [virtual] int set(struct soap *soap); |
class xsd__base64Binary { public: unsignedchar *__ptr; int__size; int get(struct soap *soap); int set(struct soap *soap); }; |
class update { public: time_t __item; int set(struct soap *soap); }; |
int update::set(struct soap *soap) { this->__item = time(NULL); return SOAP_OK; } |
class h__Authentication { public: char *id; int get(struct soap *soap); }; class SOAP_ENV__Header { public: h__Authentication *h__authentication; }; |
// Contents of file "derived.h" class Base { public: char *name; Base(); virtual void print(); }; class Derived : public Base { public: int num; Derived(); virtual void print(); }; int method(Base *in, struct methodResponse { Base *out; } &result); |
// Method implementations of the Base and Derived classes: #include "soapH.h" ... Base::Base() { cout << "created a Base class instance" << endl; } Derived::Derived() { cout << "created a Derived class instance" << endl; } Base::print() { cout << "print(): Base class instance " << name << endl; } Derived::print() { cout << "print(): Derived class instance " << name << " " << num << endl; } |
// CLIENT #include "soapH.h" int main() { struct soap soap; soap_init(&soap); Derived obj1; Base *obj2; struct methodResponse r; obj1.name = "X"; obj1.num = 3; soap_call_method(&soap, url, action, &obj1, r); r.obj2->print(); } ... |
// SERVER1 #include "soapH.h" int main() { soap_serve(soap_new()); } int method(struct soap *soap, Base *obj1, struct methodResponse &result) { obj1->print(); result.obj2 = obj1; return SOAP_OK; } ... |
CLIENT: created a Derived class instance SERVER1: created a Derived class instance SERVER1: print(): Derived class instance X 3 CLIENT: created a Derived class instance CLIENT: print(): Derived class instance X 3 |
// Contents of file "base.h": class Base { public: char *name; Base(); virtual void print(); }; int method(Base *in, Base *out); |
// Method implementations of the Base class: #include "soapH.h" ... Base::Base() { cout << "created a Base class instance" << endl; } Base::print() { cout << "print(): Base class instance " << name << endl; } |
// SERVER2 #include "soapH.h" int main() { soap_serve(soap_new()); } int method(struct soap *soap, Base *obj1, struct methodResponse &result) { obj1->print(); result.obj2 = obj1; return SOAP_OK; } ... |
CLIENT: created a Derived class instance SERVER2: created a Base class instance SERVER2: print(): Base class instance X CLIENT: created a Base class instance CLIENT: print(): Base class instance X |
typedef char *xsd__string; typedef bool *xsd__boolean; enum ns__state { _0, _1, _2 }; struct ns__myStruct { @xsd__string ns__type; // encode as XML attribute 'ns:type' of type 'xsd:string' @xsd__boolean ns__flag = false; // encode as XML attribute 'ns:flag' of type 'xsd:boolean' @enum ns__state ns__state = _2; // encode as XML attribute 'ns:state' of type 'ns:state' struct ns__myStruct *next; }; |
struct ns__myStruct { @int *a; // omitted when NULL }; |
int ns__myMethod(@char *ns__name, ...); |
struct xsd__string { char *__item; @xsd__boolean flag; }; |
struct xsd__base64Binary { unsigned char *__ptr; int __size; @xsd__boolean flag; }; |
typedef char *xsd__QName; struct ns__myStruct { xsd__QName elt = "ns:xyz"; // QName element with default value "ns:xyz" @xsd__QName att = "ns:abc"; // QName attribute with default value "ns:abc" }; |
struct ns__PO { ... }; struct ns__Invoice { ... }; union ns__PO_or_Invoice { struct ns__PO po; struct ns__Invoice invoice; }; struct ns__composite { char *name; int __union; union ns__PO_or_Invoice value; }; |
<complexType name="composite» <sequence> <element name="name" type="xsd:string"/> <choice> <element name="po" type="ns:PO"/> <element name="invoice" type="ns:Invoice"/> </choice> </sequence> </complexType> |
SOAP_UNION_union-name_field-name |
struct ns__composite { char *name; int __union 0; // <choice minOccurs="0» union ns__PO_or_Invoice value; }; |
struct ns__composite data; data.name = "..."; data.__union = SOAP_UNION_ns__PO_or_Invoice_po; // select PO data.value.po.number = ...; // populate the PO |
struct ns__composite { char *name; int __union_value; // added suffix "_value" union ns__PO_or_Invoice value; int __union_data; // added suffix "_data" union ns__Email_or_Fax data; }; |
typedef char *xsd__string; struct ns__list { xsd__string value; struct ns__list *next; }; |
<ns:list id="1" xsi:type="ns:list"> <value xsi:type="xsd:string">abc</value> <next xsi:type="ns:list"> <value xsi:type="xsd:string">def</value> <next href="#1"/> </next> </ns:list> |
typedef long xsd__int; struct ns__record { xsd__int *a; xsd__int *b; } P; struct ns__record { xsd__int a; xsd__int b; } R; ... P.a = &n; P.b = &n; ... |
<ns:record xsi:type="ns:record"> <a href="#1"/> <b href="#1"/> </ns:record> <id id="1" xsi:type="xsd:int">123</id> |
struct X { int *p; int **q; } |
<... id="123" xsi:nil="true"/> |
struct myStruct { int __type; // the SOAP_TYPE pointed to by p void *p; }; |
struct myStruct S; int n; S.p = &n; S.__type = SOAP_TYPE_int; |
struct myStruct S; S.p = (void*)"Hello"; S.__type = SOAP_TYPE_string; |
struct myStruct { int __typeOfp; // the SOAP_TYPE pointed to by p void *p; int __typeOfq; // the SOAP_TYPE pointed to by q void *q; }; |
typedef char *xsd__string; typedef int xsd__int; typedef float xsd__float; enum ns__status { on, off }; struct ns__widget { xsd__string name; xsd__int part; }; int ns__myMethod(int __type, void *data, struct ns__myMethodResponse { int __type; void *return_; } *out); |
// Contents of header file "fixed.h": struct Example { float a[2][3]; }; |
<a xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="float[][2]"> <SOAP-ENC:Array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="float[3]" <float xsi:type="float">...</float> <float xsi:type="float">...</float> <float xsi:type="float">...</float> </SOAP-ENC:Array> <SOAP-ENC:Array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="float[3]" <float xsi:type="float">...</float> <float xsi:type="float">...</float> <float xsi:type="float">...</float> </SOAP-ENC:Array> </a> |
struct some_name { Type *__ptr; // pointer to array int __size; // number of elements pointed to [[static const] int __offset [= ...];] // optional SOAP 1.1 array offset ... // anything that follows here will be ignored }; |
class some_name { public: Type *__ptr; int __size; [[static const] int __offset [= ...];] method1; method2; ... // any fields that follow will be ignored }; |
// Contents of file "listing.h": class ns3__SOAPService { public: int ID; char *name; char *owner; char *description; char *homepageURL; char *endpoint; char *SOAPAction; char *methodNamespaceURI; char *serviceStatus; char *methodName; char *dateCreated; char *downloadURL; char *wsdlURL; char *instructions; char *contactEmail; char *serverImplementation; }; class ServiceArray { public: ns3__SOAPService *__ptr; // points to array elements int __size; // number of elements pointed to ServiceArray(); ~ServiceArray(); void print(); }; int ns__getAllSOAPServices(ServiceArray &return_); |
#include "soapH.h"
... // ServiceArray class method implementations: ServiceArray::ServiceArray() { __ptr = NULL; __size = 0; } ServiceArray::~ServiceArray() { // destruction handled by gSOAP } void ServiceArray::print() { for (int i = 0; i < __size; i++) cout << __ptr[i].name << ": " << __ptr[i].homepage << endl; } ... // Request a service listing and display results: { struct soap soap; ServiceArray result; const char *endpoint = "www.xmethods.net:80/soap/servlet/rpcrouter"; const char *action = "urn:xmethodsServicesManager#getAllSOAPServices"; ... soap_init(&soap); soap_call_ns__getAllSOAPServices(&soap, endpoint, action, result); result.print(); ... soap_destroy(&soap); // dealloc class instances soap_end(&soap); // dealloc deserialized data soap_done(&soap); // cleanup and detach soap struct } |
// Contents of file "vector.h": typedef float xsd__float; class Vector { xsd__float *__ptr; int __size; int __offset; Vector(); Vector(int n); float& operator[](int i); } |
Vector::Vector() { __ptr = NULL; __size = 0; __offset = 1; } Vector::Vector(int n) { __ptr = (float*)malloc(n*sizeof(float)); __size = n; __offset = 1; } Vector::~Vector() { if (__ptr) free(__ptr); } float& Vector::operator[](int i) { return __ptr[i-__offset]; } |
struct soap soap; soap_init(&soap); Vector v(3); v[1] = 1.0; v[2] = 2.0; v[3] = 3.0; soap_begin(&soap); v.serialize(&soap); v.put("vec"); soap_end(&soap); |
<vec xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:float[4]" SOAP-ENC:offset="[1]"> <item xsi:type="xsd:float">1.0</item> <item xsi:type="xsd:float">2.0</item> <item xsi:type="xsd:float">3.0</item> </vec> |
// Contents of file "matrix.h": class Matrix { public: Vector *__ptr; int __size; int __offset; Matrix(); Matrix(int n, int m); ~Matrix(); Vector& operator[](int i); }; |
struct some_name { Type *__ptr; int __size[K]; int __offset[K]; ... // anything that follows here will be ignored }; |
class some_name { public: Type *__ptr; int __size[K]; int __offset[K]; method1; method2; ... // any fields that follow will be ignored }; |
typedef double xsd__double; class Matrix { public: xsd__double *__ptr; int __size[2]; int __offset[2]; }; |
struct ns__Map { struct ns__Binding {char *key; char *val;} *__ptr; int __size; }; |
<ns:Map xsi:type="ns:Map"> <ns:Binding xsi:type="ns:Binding"> <key>Joe</key> <val>555 77 1234</val> </ns:Binding> <ns:Binding xsi:type="ns:Binding"> <key>Susan</key> <val>555 12 6725</val> </ns:Binding> <ns:Binding xsi:type="ns:Binding"> <key>Pete</key> <val>555 99 4321</val> </ns:Binding> </ns:Map> |
struct ns__SomeStruct { ... int __sizename1; // number of elements pointed to Type1 *field1; // by this field ... int __sizename2; // number of elements pointed to Type2 *field2; // by this field ... }; |
struct ns__Contact { char *firstName; char *lastName; int __sizePhones; ULONG64 *phoneNumber; // array of phone numbers int __sizeEmails; char **emailAddress; // array of email addresses char *socSecNumber; }; |
<mycontact xsi:type="ns:Contact"> <firstName>Joe</firstName> <lastName>Smith</lastName> <phoneNumber>5551112222</phoneNumber> <phoneNumber>5551234567</phoneNumber> <phoneNumber>5552348901</phoneNumber> <emailAddress>Joe.Smith@mail.com</emailAddress> <emailAddress>Joe@Smith.com</emailAddress> <socSecNumber>999999999</socSecNumber> </mycontact> |
#import "stlvector.h" class ns__myClass { public: std::vector < int > *number; std::vector < xsd__string > *name; ... }; |
<complexType name="myClass» <sequence> <element name="number" type="xsd:int" minOccurs="1" maxOccurs="unbounded"/> <element name="name" type="xsd:string" minOccurs="1" maxOccurs="unbounded"/> ... </sequence> </complexType> |
// simpleVector.h template < class T > class simpleVector { public: typedef T value_type; typedef value_type * pointer; typedef const value_type * const_pointer; typedef value_type & reference; typedef const value_type & const_reference; typedef pointer iterator; typedef const_pointer const_iterator; protected: iterator start; iterator finish; size_t length; public: simpleVector() { clear(); } ~simpleVector() { delete[] start; } void\ clear() { start = finish = NULL; } iterator begin() { return start; } const_iterator begin() const\ { return start; } iterator end() { return finish; } const_iterator end() const\ { return finish; } size_t size() const\ { return finish-start; } iterator insert(iterator pos, const_reference val) { if (!start) start = finish = new value_type[length = 4]; else if (finish > = start + length) { iterator i = start; iterator j = new value_type[2 * length]; start = j; finish = start + length; length *= 2; if (pos) pos = j + (pos - i); while (i != finish) *j++ = *i++; } if (pos && pos != finish) { iterator i = finish; iterator j = i - 1; while (j != pos) *i- = *j-; } *finish++ = val; return pos; } }; |
#include "simpleVector.h" template < class T > class simpleVector; |
class ns__Object { public: ... }; class ns__Data: public ns__Object { public: ... }; class ArrayOfObject { public: ns__Object **__ptr; // pointer to array of pointers to Objects int __size; // number of Objects pointed to int __offset; // optional SOAP 1.1 array offset }; |
Type *__ptrarray_elt_name |
struct ArrayOfstring { xsd__string *__ptrstring; int __size; }; |
<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]» <string xsi:type="xsd:string»Hello</string> <string xsi:type="xsd:string»World</string> </array> |
struct xsd__base64Binary { unsigned char *__ptr; int __size; }; |
class xsd__base64Binary { public: unsigned char *__ptr; int __size; }; |
struct SOAP_ENC__base64 { unsigned char *__ptr; int __size; }; |
class SOAP_ENC__base64 { unsigned char *__ptr; int __size; }; |
class xsd__base64Binary { public: unsigned char *__ptr; int __size; xsd__base64Binary(); // Constructor xsd__base64Binary(struct soap *soap, int n); // Constructor ~xsd__base64Binary(); // Destructor unsigned char *location(); // returns the memory location int size(); // returns the number of bytes }; |
xsd__base64Binary::xsd__base64Binary() { __ptr = NULL; __size = 0; } xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n) { __ptr = (unsigned char*)soap_malloc(soap, n); __size = n; } xsd__base64Binary::~xsd__base64Binary() { } unsigned char *xsd__base64Binary::location() { return __ptr; } int xsd__base64Binary::size() { return __size; } |
... FILE *fd = fopen("image.jpg", "rb"); xsd__base64Binary image(&soap, filesize(fd)); fread(image.location(), image.size(), 1, fd); fclose(fd); soap_begin(&soap); image.soap_serialize(&soap); image.soap_put(&soap, "jpegimage", NULL); soap_end(&soap); ... |
... xsd__base64Binary image; soap_begin(&soap); image.get(&soap, "jpegimage"); soap_end(&soap); ... |
struct xsd__hexBinary { unsigned char *__ptr; int __size; }; |
class xsd__hexBinary { public: unsigned char *__ptr; int __size; }; |
//gsoap ns service encoding: encoded |
//gsoap ns service method-encoding: myMethod encoded int ns__myMethod(...) |
//gsoap ns service method-response-encoding: myMethod encoded int ns__myMethod(...) |
int LocalTimeByZipCode(char *ZipCode, char **LocalTimeByZipCodeResult); |
//gsoap ns service name: localtime //gsoap ns service encoding: literal //gsoap ns service namespace: http://alethea.net/webservices/ int ns__LocalTimeByZipCode(char *ZipCode, char **LocalTimeByZipCodeResult); |
#include "soapH.h" #include "localtime.nsmap" // include generated map file int main() { struct soap soap; char *t; soap_init(&soap); if (soap_call_ns__LocalTimeByZipCode(&soap, "http://alethea.net/webservices/LocalTime.asmx", "http://alethea.net/webservices/LocalTimeByZipCode", "32306", &t)) soap_print_fault(&soap, stderr); else printf("Time = %s\n", t); return 0; } |
#include "soapH.h" #include "localtime.nsmap" // include generated map file int main() { struct soap soap; char *t; soap_init(&soap); soap.encodingStyle = NULL; // don't use SOAP encoding soap_set_omode(&soap, SOAP_XML_TREE);" // don't produce multi-ref data (but can accept) if (soap_call_ns__LocalTimeByZipCode(&soap, "http://alethea.net/webservices/LocalTime.asmx", "http://alethea.net/webservices/LocalTimeByZipCode", "32306", &t)) soap_print_fault(&soap, stderr); else printf("Time = %s\n", t); return 0; } |
POST /webservices/LocalTime.asmx HTTP/1.0 Host: alethea.net Content-Type: text/xml; charset=utf-8 Content-Length: 479 SOAPAction: "http://alethea.net/webservices/LocalTimeByZipCode" <?xml version="1.0" encoding=ÜTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" <SOAP-ENV:Body> <LocalTimeByZipCode xmlns="http://alethea.net/webservices/"> <ZipCode>32306</ZipCode></LocalTimeByZipCode> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
typedef char *XML; |
typedef wchar_t *XML; |
typedef char *XML; ns__GetDocument(XML m__XMLDoc, XML &m__XMLDoc_); |
typedef char *XML; ns__GetDocument(XML m__XMLDoc, XML *m__XMLDoc_); |
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="http://my.org/" xmlns:m="http://my.org/mydoc.xsd" SOAP-ENV:encodingStyle=""> <SOAP-ENV:Body> <ns:GetDocument> <XMLDoc xmlns="http://my.org/mydoc.xsd"> ... </XMLDoc> </ns:Document> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
struct soap soap; soap_init(&soap); soap.encodingStyle = NULL; |
struct soap soap; soap_init(&soap); soap.encodingStyle = "http://xml.apache.org/xml-soap/literalxml"; |
typedef char *XML; struct ns__Data /* data in namespace 'ns' */ { int number; char *name; XML m__document; /* XML document in default namespace 'm' */ }; ns__Example(struct ns__Data data, struct ns__ExampleResponse { struct ns__Data data; } *out); |
struct SOAP_ENV__Fault { _QName faultcode; // _QName is builtin char *faultstring; char *faultactor; struct SOAP_ENV__Detail *detail; struct SOAP_ENV__Code *SOAP_ENV__Code; // MUST be a SOAP_ENV__Code struct defined below char *SOAP_ENV__Reason; char *SOAP_ENV__Node; char *SOAP_ENV__Role; struct SOAP_ENV__Detail SOAP_ENV__Detail; // SOAP 1.2 detail field }; struct SOAP_ENV__Code { _QName SOAP_ENV__Value; struct SOAP_ENV__Code *SOAP_ENV__Subcode; }; struct SOAP_ENV__Detail { int __type; // The SOAP_TYPE_ of the object serialized as Fault detail void *fault; // pointer to the fault object, or NULL char *__any; // any other detail element content (stored in XML format) }; |
int ns1__myMethod(struct soap *soap, ...) { ... return soap_receiver_fault(soap, "Resource temporarily unavailable", NULL); // return fault to sender } |
return soap_receiver_fault(soap, "Resource temporarily unavailable", " < errorcode xmlns='http://tempuri.org' > 123 < /errorcode > < errorinfo xmlns='http://tempuri.org' > abc < /errorinfo > "); |
soap_receiver_fault(soap, "Stack dump", NULL); if (soap->version == 2) // SOAP 1.2 is used { soap->fault->SOAP_ENV__Detail = (struct SOAP_ENV__Detail*)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail); soap->fault->SOAP_ENV__Detail->__type = SOAP_TYPE_ns1__myStackDataType; // stack type soap->fault->SOAP_ENV__Detail->fault = sp; // point to stack soap->fault->SOAP_ENV__Detail->__any = NULL; // no other XML data } else { soap->fault->detail = (struct SOAP_ENV__Detail*)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail); soap->fault->detail->__type = SOAP_TYPE_ns1__myStackDataType; // stack type soap->fault->detail->fault = sp; // point to stack soap->fault->detail->__any = NULL; // no other XML data } return SOAP_FAULT; // return from remote method call |
int main() { struct soap soap; soap_init(&soap); some initialization code if (initialization failed) { soap.error = soap_receiver_fault(&soap, "Init failed", NULL); // set the error condition (SOAP_FAULT) soap_send_fault(&soap); // Send SOAP Fault to client return 0; // Terminate } } |
struct SOAP_ENV__Header { }; |
struct SOAP_ENV__Header { char *t__transaction; }; |
struct soap soap; soap_init(&soap); ... soap.header = NULL; // do not use a SOAP Header for the request (as set with soap_init) soap.actor = NULL; // do not use an actor (receiver is actor) soap_call_method(&soap, ...); if (soap.header) // a SOAP Header was received cout << soap.header->t__transaction; // Can reset, modify, or set soap.header here before next call soap_call_method(&soap, ...); // reuse the SOAP Header of the service response for the request ... |
... <SOAP-ENV:Envelope ...> <SOAP-ENV:Header> <transaction xmlns="..." xsi:type="int">12345</transaction> </SOAP-ENV:Header> <SOAP-ENV:Body> ... </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
int main() { struct soap soap; soap.actor = NULL; // use this to accept all headers (default) soap.actor = "http://some/actor"; // accept headers destined for "http://some/actor" only soap_serve(&soap); } ... int method(struct soap *soap, ...) { if (soap->header) // a Header was received ... = soap->header->t__transaction; else soap->header = soap_malloc(sizeof(struct SOAP_ENV__Header)); // alloc new header ... soap->header->t__transaction = ...; return SOAP_OK; } |
struct SOAP_ENV__Header { char *t__transaction; mustUnderstand char *t__authentication; }; |
<SOAP-ENV:Envelope ...> <SOAP-ENV:Header> <transaction xmlns="...»5</transaction> <authentication xmlns="..." SOAP-ENV:actor="http://some/actor" SOAP-ENV:mustUnderstand="1">XX </authentication> </SOAP-ENV:Header> <SOAP-ENV:Body> ... </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
|
struct claim__form form1, form2; form1.href = "cid:claim061400a.tiff@claiming-it.com"; form2.href = "cid:claim061400a.jpeg@claiming-it.com"; /* initialize and enable MIME */ soap_set_mime(soap, "MIME_boundary", "<claim061400a.xml@claiming-it.com>"); /* add a base64 encoded tiff image (tiffImage points to base64 data) */ soap_set_mime_attachment(soap, tiffImage, tiffLen, SOAP_MIME_BASE64, "image/tiff", "<claim061400a.tiff@claiming-it.com>", NULL, NULL); /* add a raw binary jpeg image (jpegImage points to raw data) */ soap_set_mime_attachment(soap, jpegImage, jpegLen, SOAP_MIME_BINARY, "image/jpeg", "<claim061400a.jpeg@claiming-it.com>", NULL, NULL); /* send the forms as MIME attachments with this invocation */ if (soap_call_claim__insurance_claim_auto(soap, form1, form2, ...)) // an error occurred else // process response |
struct claim__form { @char *href; }; |
int claim__insurance_claim_auto(struct soap *soap, ...) { soap_set_mime(soap, NULL, NULL); // enable MIME // add a HTML document (htmlDoc points to data, where the HTML doc is stored in compliance with 7bit encoding RFC2045) if (soap_set_mime_attachment(soap, htmlDoc, strlen(htmlDoc), SOAP_MIME_7BIT, "text/html", "<claim061400a.html@claiming-it.com>", NULL, NULL)) { soap_clr_mime(soap); // don't want fault with attachments return soap->error; } return SOAP_OK; } |
struct soap_multipart *attachment; for (attachment = soap.mime.list; attachment; attachment = attachment->next) { printf("MIME attachment:\n"); printf("Memory=%p\n", (*attachment).ptr); printf("Size=%ul\n", (*attachment).size); printf("Encoding=%d\n", (int)(*attachment).encoding); printf("Type=%s\n", (*attachment).type?(*attachment).type:"null"); printf("ID=%s\n", (*attachment).id?(*attachment).id:"null"); printf("Location=%s\n", (*attachment).location?(*attachment).location:"null"); printf("Description=%s\n", (*attachment).description?(*attachment).description:"null"); } |
for (soap_multipart::iterator attachment = soap.mime.begin(); attachment != soap.mime.end(); ++attachment) { cout << "MIME attachment:" << endl; cout << "Memory=" << (void*)(*attachment).ptr << endl; cout << "Size=" << (*attachment).size << endl; cout << Ëncoding=" << (*attachment).encoding << endl; cout << "Type=" << ((*attachment).type?(*attachment).type:"null") << endl; cout << "ID=" << ((*attachment).id?(*attachment).id:"null") << endl; cout << "Location=" << ((*attachment).location?(*attachment).location:"null") << endl; cout << "Description=" << ((*attachment).description?(*attachment).description:"null") << endl; } |
|
struct soap_multipart *attachment; for (attachment = soap.dime.list; attachment; attachment = attachment->next) { printf("DIME attachment:\n"); printf("Memory=%p\n", (*attachment).ptr); printf("Size=%ul\n", (*attachment).size); printf("Type=%s\n", (*attachment).type?(*attachment).type:"null"); printf("ID=%s\n", (*attachment).id?(*attachment).id:"null"); } |
for (soap_multipart::iterator attachment = soap.dime.begin(); attachment != soap.dime.end(); ++attachment) { cout << "DIME attachment:" << endl; cout << "Memory=" << (void*)(*attachment).ptr << endl; cout << "Size=" << (*attachment).size << endl; cout << "Type=" << ((*attachment).type?(*attachment).type:"null") << endl; cout << "ID=" << ((*attachment).id?(*attachment).id:"null") << endl; } |
struct xsd__base64Binary { unsigned char *__ptr; // pointer to raw binary data int __size; // size of the block of data }; |
struct xsd__base64Binary { unsigned char *__ptr; int __size; char *id; char *type; char *options; }; |
char *soap_dime_option(struct soap *soap, unsigned short type, const char *option) |
struct xsd__base64Binary image; image.__ptr = ...; image.__size = ...; image.id = "uuid:09233523-345b-4351-b623-5dsf35sgs5d6"; image.type = "image/jpeg"; image.options = soap_dime_option(soap, 0, "My wedding picture"); |
struct ns__myBinaryDataType { unsigned char *__ptr; int __size; char *id; char *type; char *options; }; |
class xsd__base64Binary { unsigned char *__ptr; int __size; }; class ns__myBinaryDataType : xsd__base64Binary { char *id; char *type; char *options; }; |
//gsoap WSref schema import: http://schemas.xmlsoap.org/ws/2002/04/reference/ struct ns__myBinaryDataType { unsigned char *__ptr; int __size; char *id; char *type; char *options; @char *WSref__location; }; |
struct soap soap; soap_init(&soap); soap.dime_id_format = "uuid:09233523-345b-4351-b623-5dsf35sgs5d6-%x"; |
|
int main() { struct soap soap; struct xsd__base64Binary image; FILE *fd; struct stat sb; soap_init(&soap); if (!fstat(fileno(fd), &sb) && sb.st_size > 0) { // because we can get the length of the file, we can stream it soap.fdimereadopen = dime_read_open; soap.fdimereadclose = dime_read_close; soap.fdimeread = dime_read; image.__ptr = (unsigned char*)fd; // must set to non-NULL (this is our fd handle which we need in the callbacks) image.__size = sb.st_size; // must set size } else { // don't know the size, so buffer it size_t i; int c; image.__ptr = (unsigned char*)soap_malloc(&soap, MAX_FILE_SIZE); for (i = 0; i < MAX_FILE_SIZE; i++) { if ((c = fgetc(fd)) == EOF) break; image.__ptr[i] = c; } fclose(fd); image.__size = i; } image.type = "image/jpeg"; image.options = soap_dime_option(&soap, 0, "My picture"); soap_call_ns__method(&soap, ...); ... } void *dime_read_open(struct soap *soap, void *handle, const char *id, const char *type, const char *options) { return handle; } void dime_read_close(struct soap *soap, void *handle) { fclose((FILE*)handle); } size_t dime_read(struct soap *soap, void *handle, char *buf, size_t len) { return fread(buf, 1, len, (FILE*)handle); } |
int main() { struct soap soap; soap_init(&soap); soap.fdimewriteopen = dime_write_open; soap.fdimewriteclose = dime_write_close; soap.fdimewrite = dime_write; soap_call_ns__method(&soap, ...); ... } void *dime_write_open(struct soap *soap, const char *id, const char *type, const char *options) { FILE *handle = fopen("somefile", "wb"); if (!handle) { soap->error = SOAP_EOF; soap->errnum = errno; // get reason } return (void*)handle; } void dime_write_close(struct soap *soap, void *handle) { fclose((FILE*)handle); } int dime_write(struct soap *soap, void *handle, const char *buf, size_t len) { size_t nwritten; while (len) { nwritten = fwrite(buf, 1, len, (FILE*)handle); if (!nwritten) { soap->errnum = errno; // get reason return SOAP_EOF; } len -= nwritten; buf += nwritten; } return SOAP_OK; } |
//gsoap xop schema import: http://www.w3.org/2004/08/xop/include struct _xop__Include { unsigned char *__ptr; int __size; char *id; char *type; char *options; }; typedef struct _xop__Include _xop__Include; |
#import ïmport/soap12.h" /* alternatively, without the import above, use: //gsoap SOAP-ENV schema namespace: http://www.w3.org/2003/05/soap-envelope //gsoap SOAP-ENC schema namespace: http://www.w3.org/2003/05/soap-encoding */ #import ïmport/xop.h" #import ïmport/xmlmime.h" //gsoap x schema namespace: http://my.first.mtom.net struct x__myData { _xop__Include xop__Include; // attachment @char *xmlmime__contentType; // and its contentType }; int x__myMTOMtest(struct x__myData *in, struct x__myData *out); |
struct soap *soap = soap_new1(SOAP_ENC_MTOM); |
#import ïmport/soap12.h" #import ïmport/xop.h" #import ïmport/xmlmime.h" //gsoap x schema namespace: http://my.first.mtom.net struct x__myData { _xop__Include xop__Include; // attachment @char *xmlmime__contentType; // and its contentType }; //gsoap x service method-mime-type: myMTOMtest text/xml int x__myMTOMtest(struct x__myData *in, struct x__myData *out); |
xop = < http://www.w3.org/2004/08/xop/include > xmime = < http://www.w3.org/2004/06/xmlmime > xmlmime = < http://www.w3.org/2004/11/xmlmime > |
#import "xop.h" #import "xmlmime.h" |
#import "xop.h" #import "xmlmime.h" struct ns__Data { _xop__Include xop__Include; @char *xmlmime__contentType; }; |
int ns__echoData(struct ns__Data *in, struct ns__Data *out); |
struct soap *soap = soap_new1(SOAP_ENC_MTOM); struct ns__Data data; data.xop__Include.__ptr = (unsigned char*)"<b>Hello world!</b>"; data.xop__Include.__size = 20; data.xop__Include.id = NULL; // CID automatically generated by gSOAP engine data.xop__Include.type = "text/html"; // MIME type data.xop__Include.options = NULL; // no descriptive info added data.xmlmime__contentType = "text/html"; // MIME type if (soap_call_ns__echoData(soap, endpoint, action, &data, &data)) soap_print_fault(soap, stderr); else printf("Got data\n"); soap_destroy(soap); // remove deserialized class instances soap_end(soap); // remove temporary and deserialized data soap_free(soap); // detach and free context |
int ns__echoData(struct soap *soap, struct ns__Data *in, struct ns__data *out) { *out = *in; return SOAP_OK; } |
|
int main() { struct soap soap; struct xsd__base64Binary image; FILE *fd; struct stat sb; soap_init1(&soap, SOAP_ENC_MTOM); // mandatory to enable MTOM if (!fstat(fileno(fd), &sb) && sb.st_size > 0) { // because we can get the length of the file, we can stream it without chunking soap.fmimereadopen = mime_read_open; soap.fmimereadclose = mime_read_close; soap.fmimeread = mime_read; image.__ptr = (unsigned char*)fd; // must set to non-NULL (this is our fd handle which we need in the callbacks) image.__size = sb.st_size; // must set size } else { // don't know the size, so buffer it size_t i; int c; image.__ptr = (unsigned char*)soap_malloc(&soap, MAX_FILE_SIZE); for (i = 0; i < MAX_FILE_SIZE; i++) { if ((c = fgetc(fd)) == EOF) break; image.__ptr[i] = c; } fclose(fd); image.__size = i; } image.type = "image/jpeg"; // MIME type image.options = "This is my picture"; // description of object soap_call_ns__method(&soap, ...); ... } void *mime_read_open(struct soap *soap, void *handle, const char *id, const char *type, const char *description) { return handle; } void mime_read_close(struct soap *soap, void *handle) { fclose((FILE*)handle); } size_t mime_read(struct soap *soap, void *handle, char *buf, size_t len) { return fread(buf, 1, len, (FILE*)handle); } |
int main() { struct soap soap; soap_init(&soap); soap.fmimewriteopen = mime_write_open; soap.fmimewriteclose = mime_write_close; soap.fmimewrite = mime_write; soap_call_ns__method(&soap, ...); ... } void *mime_write_open(struct soap *soap, const char *id, const char *type, const char *description, enum soap_mime_encoding encoding) { FILE *handle = fopen("somefile", "wb"); // We ignore the MIME content transfer encoding here, but should check if (!handle) { soap->error = SOAP_EOF; soap->errnum = errno; // get reason } return (void*)handle; } void mime_write_close(struct soap *soap, void *handle) { fclose((FILE*)handle); } int mime_write(struct soap *soap, void *handle, const char *buf, size_t len) { size_t nwritten; while (len) { nwritten = fwrite(buf, 1, len, (FILE*)handle); if (!nwritten) { soap->errnum = errno; // get reason return SOAP_EOF; } len -= nwritten; buf += nwritten; } return SOAP_OK; } |
|
struct soap *soap = soap_new1(SOAP_ENC_MTOM); soap_post_check_mime_attachments(soap); ... if (soap_call_ns__myMethod(soap, ...)) soap_print_fault(soap, stderr); // an error occurred else { if (soap_check_mime_attachments(soap)) { // attachments are present, channel is still open { do { ... // get data 'handle' from SOAP response and pass to callbacks ... // set the fmime callbacks, if needed struct soap_multipart *content = soap_get_mime_attachment(soap, (void*)handle); printf("Received attachment with id=%s and type=%s\n", content->id?content->id:"", content->type?content->type:""); } while (content); if (soap->error) soap_print_fault(soap, stderr); } } } ... soap_destroy(soap); soap_end(soap); soap_free(soap); // detach and free context |
struct soap *soap = soap_new1(SOAP_ENC_MTOM); soap_post_check_mime_attachments(soap); ... soap_serve(soap); ... int ns__myMethod(struct soap *soap, ...) { ... // server-side processing logic if (soap_check_mime_attachments(soap)) { // attachments are present, channel is still open { do { ... // get data 'handle' from SOAP request and pass to callbacks ... // set the fmime callbacks, if needed struct soap_multipart *content = soap_get_mime_attachment(soap, (void*)handle); printf("Received attachment with id=%s and type=%s\n", content->id?content->id:"", content->type?content->type:""); } while (content); if (soap->error) return soap->error; } } ... // server-side processing logic return SOAP_OK; } |
Type fieldname [minOccurs[:maxOccurs]] [= value] |
struct ns__MyRecord { int n = 5; // element with default value 5, minOccurs=0, maxOccurs=1 int m 1; // element with minOccurs=1 int __size 0:10; // sequence <item> with minOccurs=0, maxOccurs=10 int *item; std::vector<double> nums 2; // sequence <nums> with minOccurs=2, maxOccurs=unbounded }; struct arrayOfint { int *__ptr 1:100; // minOccurs=1, maxOccurs=100 int size; }; |
struct ns__MyRecord { @int m 1; // required attribute (occurs at least once) @int n = 5; // optional attribute with default value 5 @int o 0; // optional attribute (may or may not occur) @int p 0:0; // prohibited attribute }; |
typedef int time__seconds; |
<simpleType name="seconds» <restriction base="xsd:int"/> </simpleType> |
struct time__date { char *__item; // some custom format date (restriction of string) @enum time__zone { EST, GMT, ... } zone; } |
<complexType name="date» <simpleContent> <extension base="xsd:string"/> </simpleContent> <attribute name="zone" type="time:zone" use="optional"/> </complexType> <simpleType name="zone» <restriction base="xsd:string» <enumeration value="EST"/> <enumeration value="GMT"/> ... </restriction> </simpleType> |
typedef char *ns__string256 0:256; // simpleType restriction of string with max length 256 characters typedef char *ns__string10 10:10; // simpleType restriction of string with length of 10 characters typedef std::string *ns__string8 8; // simpleType restriction of string with at least 8 characters struct ns__data { char *__item :256; // simpleContent with at most 256 characters @char *name 1; // required name attribute }; struct time__date { char *__item :100; @enum time__zone { EST, GMT, ... } zone = GMT; } |
typedef int time__second "[1-5]?[0-9]|60"; |
<simpleType name="second» <restriction base="xsd:int» <pattern value="[1-5]?[0-9]|60"/> </restriction base="xsd:int"/> </simpleType> |
#import "wsa.h" struct SOAP_ENV__Header { mustUnderstand _wsa__MessageID wsa__MessageID 0; mustUnderstand _wsa__RelatesTo *wsa__RelatesTo 0; mustUnderstand _wsa__From *wsa__From 0; mustUnderstand _wsa__ReplyTo *wsa__ReplyTo 0; mustUnderstand _wsa__FaultTo *wsa__FaultTo 0; mustUnderstand _wsa__To wsa__To 0; mustUnderstand _wsa__Action wsa__Action 0; }; |
//gsoap ns service method-header-part: sendString wsa__MessageID //gsoap ns service method-header-part: sendString wsa__To //gsoap ns service method-header-part: sendString wsa__Action int ns__sendString(char *str, void); |
//gsoap ns service method-header-part: echoString wsa__MessageID //gsoap ns service method-header-part: echoString wsa__To //gsoap ns service method-header-part: echoString wsa__Action //gsoap ns service method-input-header-part: sendString wsa__ReplyTo //gsoap ns service method-output-header-part: echoString wsa__RelatesTo int ns__echoString(char *str, char **res); |
struct soap soap; struct SOAP_ENV__Header header; // the SOAP Header soap_init(&soap); soap.send_timeout = 1; // 1s timeout soap_default_SOAP_ENV__Header(&soap, &header); // init SOAP Header header.wsa__MessageID = "message ID"; header.wsa__To = "server URL"; header.wsa__Action = "server action"; soap.header = &header; // bind the SOAP Header for transport // Send the message over UDP: if (soap_send_ns__echoString(&soap, "soap.udp://...", NULL, "hello world!")) soap_print_fault(&soap, stderr); // report error soap_end(&soap); // cleanup soap_destroy(&soap); // cleanup soap_done(&soap); // close connection (should not use soap struct after this) |
struct soap soap; struct SOAP_ENV__Header header; // the SOAP Header soap_init(&soap); soap.send_timeout = 1; // 1s timeout soap.connect_flags = SO_BROADCAST; // required for broadcast soap_default_SOAP_ENV__Header(&soap, &header); // init SOAP Header header.wsa__MessageID = "message ID"; header.wsa__To = "server URL"; header.wsa__Action = "server action"; soap.header = &header; // bind the SOAP Header for transport // Send the message over UDP to a broadcast address: if (soap_send_ns__echoString(&soap, "soap.udp://...", NULL, "hello world!")) soap_print_fault(&soap, stderr); // report error soap_destroy(&soap); // cleanup soap_end(&soap); // cleanup soap_done(&soap); // close connection (should not use soap struct after this) |
struct soap soap; struct SOAP_ENV__Header header; // the SOAP Header struct wsa__EndpointReferenceType replyTo; // (anonymous) reply address char *res; // server response soap_init(&soap); soap.send_timeout = 1; // 1s timeout soap.recv_timeout = 1; // 1s timeout soap_default_SOAP_ENV__Header(&soap, &header); // init SOAP Header soap_default_wsa__EndpointReferenceType(&soap, &replyTo); // init reply address replyTo.Address = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"; header.wsa__MessageID = "message ID"; header.wsa__To = "server URL"; header.wsa__Action = "server action"; header.wsa__ReplyTo = &replyTo; soap.header = &header; // bind the SOAP Header for transport // Send and receive messages over UDP: if (soap_call_ns__echoString(&soap, "soap.udp://...", NULL, "hello world!", &res)) { if (soap.error == SOAP_EOF && soap.errnum == 0) // Timeout: no response from server (message already delivered?) else soap_print_fault(&soap, stderr); } else // UDP server response is stored in 'res' // check SOAP header received, if applicable check_header(&soap.header); soap_destroy(&soap); // cleanup soap_end(&soap); // cleanup soap_done(&soap); // close connection (should not use soap struct after this) |
//gsoap ns service method-header-part: bcastString wsa__MessageID //gsoap ns service method-header-part: bcastString wsa__To //gsoap ns service method-header-part: bcastString wsa__Action //gsoap ns service method-header-part: bcastString wsa__ReplyTo int ns__bcastString(char *str, void); //gsoap ns service method-header-part: bcastStringResponse wsa__MessageID //gsoap ns service method-header-part: bcastStringResponse wsa__To //gsoap ns service method-header-part: bcastStringResponse wsa__Action //gsoap ns service method-header-part: bcastStringResponse wsa__RelatesTo int ns__bcastStringResponse(char *res, void); |
struct soap soap; struct SOAP_ENV__Header header; struct wsa__EndpointReferenceType replyTo; char *res; soap_init(&soap); soap.connect_flags = SO_BROADCAST; soap.send_timeout = 1; // 1s timeout soap.recv_timeout = 1; // 1s timeout soap_default_SOAP_ENV__Header(&soap, &header); soap.header = &header; soap_default_wsa__EndpointReferenceType(&soap, &replyTo); replyTo.Address = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"; header.wsa__MessageID = "message ID"; header.wsa__To = "server URL"; header.wsa__Action = "server action"; header.wsa__ReplyTo = &replyTo; if (soap_send_ns__bcastString(&soap, "soap.udp://...", NULL, "hello world!")) soap_print_fault(&soap, stderr); else { for (;;) { if (soap_recv_ns__bcastStringResponse(&soap, &res)) break; // Got response 'res' from a server } if (soap.error == SOAP_EOF && soap.errnum == 0) // Timeout: no more messages received else soap_print_fault(&soap, stderr); } soap_destroy(&soap); // cleanup soap_end(&soap); // cleanup soap_done(&soap); // close connection (should not use soap struct after this) |
main() { struct soap soap; soap_init1(&soap, SOAP_IO_UDP); // must set UDP flag // bind to host (NULL=current host) and port: if (!soap_valid_socket(soap_bind(&soap, host, port, 100))) { soap_print_fault(&soap, stderr); exit(1); } for (;;) { if (soap_serve(&soap)) soap_print_fault(&soap, stderr); // report the problem soap_destroy(&soap); soap_end(&soap); } soap_done(&soap); // close connection } int ns__echoString(struct soap *soap, char *str, char **res) { if (!soap->header) return soap_sender_fault(soap, "No SOAP header", NULL); if (!soap->header->wsa__MessageID) return soap_sender_fault(soap, "No WS-Addressing MessageID", NULL); soap->header->wsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship)); soap_default_wsa__Relationship(soap, soap->header->wsa__RelatesTo); soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID; // must check for duplicate messages if (check_received(soap->header->wsa__MessageID)) { // Request message already received return SOAP_STOP; // don't return response } if (!soap->header->wsa__ReplyTo || !soap->header->wsa__ReplyTo->Address) return soap_sender_fault(soap, "No WS-Addressing ReplyTo address", NULL); soap->header->wsa__To = soap->header->wsa__ReplyTo->Address; soap->header->wsa__MessageID = soap_strdup(soap, soap_int2s(soap, id_count++)) ; soap->header->wsa__Action = "http://genivia.com/udp/echoStringResponse"; *res = str; return SOAP_OK; } int ns__sendString(struct soap *soap, char *str) { if (!soap->header) return SOAP_STOP; if (!soap->header->wsa__MessageID) return SOAP_STOP; // must check for duplicate messages if (check_received(soap->header->wsa__MessageID)) return SOAP_STOP; return SOAP_OK; } int ns__sendStringResponse(struct soap *soap, char *res) { return SOAP_NO_METHOD; } // we don't expect to serve this message |
typedef wchar_t *xsd__string; ... int ns__myMethod(xsd__string input, xsd__string *output); |
typedef wchar_t *xsd__string; typedef char *xsd__string_; // trailing '_' avoids name clash ... int ns__myMethod(xsd__string input, xsd__string_ *output); |
//gsoap namespace-prefix service name: service-name |
//gsoap namespace-prefix service definitions: definitions-name |
//gsoap namespace-prefix service documentation: text |
//gsoap namespace-prefix service portType: portType-name |
//gsoap namespace-prefix service type: portType-name |
//gsoap namespace-prefix service portName: port-name |
//gsoap namespace-prefix service binding: binding-name |
//gsoap namespace-prefix service transport: transport-URL |
//gsoap namespace-prefix service location: URL |
//gsoap namespace-prefix service port: URL |
//gsoap namespace-prefix service executable: executable-name |
//gsoap namespace-prefix service encoding: literal |
//gsoap namespace-prefix service encoding: encoding-style |
//gsoap namespace-prefix service namespace: namespace-URI |
//gsoap namespace-prefix schema namespace: namespace-URI |
//gsoap namespace-prefix schema import: namespace-URI |
//gsoap namespace-prefix schema namespace: namespace-URI //gsoap namespace-prefix schema import: schema-location |
//gsoap namespace-prefix schema elementForm: qualified //gsoap namespace-prefix schema attributeForm: qualified |
//gsoap namespace-prefix schema elementForm: unqualified //gsoap namespace-prefix schema attributeForm: unqualified |
//gsoap namespace-prefix schema form: qualified |
//gsoap namespace-prefix schema form: unqualified |
//gsoap namespace-prefix schema type-documentation: type-name //text |
//gsoap ns schema type-documentation: tdata stores <a href="transaction.html">transaction</a> data class ns__tdata { ... } |
//gsoap namespace-prefix service method-documentation: method-name //text |
//gsoap ns service method-documentation: getQuote returns a <i>stock quote</i> int ns__getQuote(char *symbol, float &_result); |
//gsoap namespace-prefix service method-action: method-name action |
//gsoap ns service method-action: getQuote "" int ns__getQuote(char *symbol, float &_result); |
//gsoap namespace-prefix service method-style: method-name document |
//gsoap namespace-prefix service method-encoding: method-name encoded |
//gsoap namespace-prefix service method-encoding: method-name literal |
//gsoap namespace-prefix service method-encoding: method-name encoding-style |
//gsoap namespace-prefix service method-response-encoding: method-name encoded |
//gsoap namespace-prefix service method-response-encoding: method-name literal |
//gsoap namespace-prefix service method-response-encoding: method-name encoding-style |
//gsoap namespace-prefix service method-header-part: method-name header-part |
struct SOAP_ENV__Header { char *h__transaction; struct UserAuth *h__authentication; }; |
//gsoap ns service method-header-part: login h__transaction //gsoap ns service method-header-part: login h__authentication int ns__login(...); |
//gsoap ns service method-header-part: search h__transaction int ns__search(...); |
//gsoap namespace-prefix service method-input-header-part: method-name header-part |
//gsoap namespace-prefix service method-output-header-part: method-name header-part |
struct SOAP_ENV__Header { char *h__transaction; struct UserAuth *h__authentication; }; //gsoap ns service method-input-header-part: login h__authentication //gsoap ns service method-input-header-part: login h__transaction //gsoap ns service method-output-header-part: login h__transaction int ns__login(...); |
//gsoap namespace-prefix service method-mime-type: method-name mime-type |
//gsoap namespace-prefix service method-input-mime-type: method-name mime-type |
//gsoap namespace-prefix service method-output-mime-type: method-name mime-type |
//gsoap ns1 service namespace: urn:xmethods-delayed-quotes int ns1__getQuote(char *symbol, float &result); //gsoap ns2 service namespace: urn:xmethods-CurrencyExchange int ns2__getRate(char *country1, char *country2, float &result); //gsoap ns3 service name: quotex //gsoap ns3 service style: rpc //gsoap ns3 service encoding: encoded //gsoap ns3 service location: http://www.cs.fsu.edu/~engelen //gsoap ns3 service namespace: urn:quotex int ns3__getQuote(char *symbol, char *country, float &result); |
soapcpp2 quotex.h |
#include "quotex.nsmap" |
extern class ostream; // ostream can't be (de)serialized, but need to be declared to make it visible to gSOAP class ns__myClass { ... virtual void print(ostream &s) const; // need ostream here ... }; |
[ class myBase // base class need not be (de)serialized { ... }; ] class ns__myDerived : myBase { ... }; |
[ typedef int transientInt; ] class ns__myClass { int a; // will be (de)serialized [ int b; // transient field char s[256]; // transient field ] extern float d; // transient field char *t; // will be (de)serialized transientInt *n; // transient field [ virtual void method(char buf[1024]); // does not create a char[1024] (de)serializer ] }; |
volatile struct tm { int tm_sec; /* seconds (0 - 60) */ int tm_min; /* minutes (0 - 59) */ int tm_hour; /* hours (0 - 23) */ int tm_mday; /* day of month (1 - 31) */ int tm_mon; /* month of year (0 - 11) */ int tm_year; /* year - 1900 */ int tm_wday; /* day of week (Sunday = 0) */ int tm_yday; /* day of year (0 - 365) */ int tm_isdst; /* is summer time in effect? */ char *tm_zone; /* abbreviation of timezone name */ long tm_gmtoff; /* offset from UTC in seconds */ }; |
struct soap *soap = soap_new(); ... time_t T = time(NULL); struct tm *t = localtime(&T); struct soap *soap = soap_new(); soap_set_omode(soap, SOAP_XML_GRAPH); // good habit to use this soap_begin_send(soap); soap_put_tm(soap, t, "myLocalTime", NULL); soap_end_send(soap); soap_destroy(soap); soap_end(soap); soap_free(soap); // detach and free context |
typedef struct tm time__struct_tm; |
extern typedef char *MyData; struct Sample { MyData s; // use user-defined (de)serializer for this field char *t; // use gSOAP (de)serializer for this field }; |
void soap_serialize_T(struct soap *soap, const T *a) void soap_default_T(struct soap *soap, T *a) void soap_out_T(struct soap *soap, const char *tag, int id, const T *a, const char *type) T *soap_in_T(struct soap *soap, const char *tag, T *a, const char *type) |
void soap_serialize_MyData(struct soap *soap, MyData *const*a) { } // no need to mark this node (for multi-ref and cycle detection) void soap_default_MyData(&soap, MyData **a) { *a = NULL } void soap_out_MyData(struct soap *soap, const char *tag, int id, MyData *const*a, const char *type) { soap_element_begin_out(soap, tag, id, type); // print XML beginning tag soap_send(soap, *a); // just print the string (no XML conversion) soap_element_end_out(soap, tag); // print XML ending tag } MyData **soap_in_MyData(struct soap *soap, const char *tag, MyData **a, const char *type) { if (soap_element_begin_in(soap, tag)) return NULL; if (!a) a = (MyData**)soap_malloc(soap, sizeof(MyData*)); if (soap->null) *a = NULL; // xsi:nil element if (*soap->type && soap_match_tag(soap, soap->type, type)) { soap->error = SOAP_TYPE; return NULL; // type mismatch } if (*soap->href) a = (MyData**)soap_id_forward(soap, soap->href, a, SOAP_MyData, sizeof(MyData*)) else if (soap->body) { char *s = soap_value(soap); // fill buffer *a = (char*)soap_malloc(soap, strlen(s)+1); strcpy(*a, s); } if (soap->body && soap_element_end_in(soap, tag)) return NULL; return a; |
typedef char *_xsd__date; |
struct _ns__myStruct { ... }; |
|
|
|
char buf[10000]; // XML buffer int len1 = 0; // #chars written int len2 = 0; // #chars read // mysend: put XML in buf[] int mysend(struct soap *soap, const char *s, size_t n) { if (len1 + n > sizeof(buf)) return SOAP_EOF; strcpy(buf + len1, s); len1 += n; return SOAP_OK; } // myrecv: get XML from buf[] size_t myrecv(struct soap *soap, char *s, size_t n) { if (len2 + n > len1) n = len1 - len2; strncpy(s, buf + len2, n); len2 += n; return n; } main() { struct soap soap; struct ns__person p; soap_init(&soap); len1 = len2 = 0; // reset buffer pointers p.name = "John Doe"; p.age = 25; soap.fsend = mysend; // assign callback soap.frecv = myrecv; // assign callback soap_begin(&soap); soap_set_omode(&soap, SOAP_XML_GRAPH); soap_serialize_ns__person(&soap, &p); soap_put_ns__person(&soap, &p, "ns:person", NULL); if (soap.error) { soap_print_fault(&soap, stdout); exit(1); } soap_end(&soap); soap_begin(&soap); soap_get_ns__person(&soap, &p, "ns:person", NULL); if (soap.error) { soap_print_fault(&soap, stdout); exit(1); } soap_destroy(&soap); soap_end(&soap); soap_done(&soap); // disable callbacks } |
//gsoap ns service name: callback //gsoap ns service namespace: urn:callback struct ns__person { char *name; int age; }; int ns__test(struct ns__person in, struct ns__test &out); |
#include "soapH.h" ... SOAP_SOCKET myopen(struct soap *soap, const char *endpoint, const char *host, int port) { if (strncmp(endpoint, "file:", 5)) { printf("File name expected\n"); return SOAP_INVALID_SOCKET; } if ((soap->sendfd = soap->recvfd = open(host, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR)) < 0) return SOAP_INVALID_SOCKET; return soap->sendfd; } void myclose(struct soap *soap) { if (soap->sendfd > 2) // still open? close(soap->sendfd); // then close it soap->recvfd = 0; // set back to stdin soap->sendfd = 1; // set back to stdout } int mypost(struct soap *soap, const char *endpoint, const char *host, const char *path, const char *action, size_t count) { return soap_send(soap, "Custom-generated file\n"); // writes to soap->sendfd } int myparse(struct soap *soap) { char buf[256]; if (lseek(soap->recvfd, 0, SEEK_SET) < 0 || soap_getline(soap, buf, 256)) // go to begin and skip custom header return SOAP_EOF; return SOAP_OK; } main() { struct soap soap; struct ns__test r; struct ns__person p; soap_init(&soap); // reset p.name = "John Doe"; p.age = 99; soap.fopen = myopen; // use custom open soap.fpost = mypost; // use custom post soap.fparse = myparse; // use custom response parser soap.fclose = myclose; // use custom close soap_call_ns__test(&soap, "file://test.xml", "", p, r); if (soap.error) { soap_print_fault(&soap, stdout); exit(1); } soap_end(&soap); soap_init(&soap); // reset to default callbacks } |
int myignore(struct soap *soap, const char *tag) { return SOAP_MUSTUNDERSTAND; // never skip elements (secure) } ... soap.fignore = myignore; soap_call_ns__method(&soap, ...); // or soap_serve(&soap); |
int myignore(struct soap *soap, const char *tag) { if (soap_match_tag(soap, tag, "ns:xyz") != SOAP_OK) return SOAP_MUSTUNDERSTAND; return SOAP_OK; } ... soap.fignore = myignore; soap_call_ns__method(&soap, ...); // or soap_serve(&soap) ... struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "http://www.w3.org/2001/XMLSchema"}, {"ns", "some-URI"}, // the namespace of element ns:xyz {NULL, NULL} |
struct Unknown { char *tag; struct Unknown *next; }; int myignore(struct soap *soap, const char *tag) { char *s = (char*)soap_malloc(soap, strlen(tag)+1); struct Unknown *u = (struct Unknown*)soap_malloc(soap, sizeof(struct Unknown)); if (s && u) { strcpy(s, tag); u->tag = s; u->next = ulist; ulist = u; } } ... struct soap *soap; struct Unknown *ulist = NULL; soap_init(&soap); soap.fignore = myignore; soap_call_ns__method(&soap, ...); // or soap_serve(&soap) // print the list of unknown elements soap_end(&soap); // clean up |
struct soap soap; soap_init(&soap); ... soap.http_version = "1.0"; |
char *endpoint = NULL; // use default endpoint given in WSDL (or add another one here) int n = 10; // max redirect count while (n-) { if (soap_call_ns1__myMethod(soap, endpoint, ...)) { if ((soap->error >= 301 && soap->error <= 303) || soap->error == 307) endpoint = soap->endpoint; // endpoint from HTTP 301, 302, 303, 307 Location header else { ... report and handle error break; } } else break; } |
struct soap *soap = soap_new(); soap->fget = http_get(); ... soap_serve(soap); ... int http_get(struct soap *soap) { soap_response(soap, SOAP_HTML); // HTTP response header with text/html soap_send(soap, "<HTML>My Web server is operational.</HTML>"); soap_end_send(soap); return SOAP_OK; } |
int http_get(struct soap *soap) { char *s = strchr(soap->path, '?'); if (!s || strcmp(s, "?wsdl")) return SOAP_GET_METHOD; fd = fopen("myservice.wsdl", "rb"); // open WSDL file to copy if (!fd) return 404; // return HTTP not found error soap->http_content = "text/xml"; // HTTP header with text/xml content soap_response(soap, SOAP_FILE); for (;;) { r = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd); if (!r) break; if (soap_send_raw(soap, soap->tmpbuf, r)) break; // can't send, but little we can do about that } fclose(fd); soap_end_send(soap); return SOAP_OK; } |
int http_get(struct soap *soap) { if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK) soap_set_omode(soap, SOAP_IO_STORE); // if not chunking we MUST buffer entire content to determine content length soap_response(soap, SOAP_OK); return soap_send_ns1__mySendMethodResponse(soap, "", NULL, ... params ...); } |
int ns1__mySendMethodResponse(... params ..., void); |
struct soap soap; soap_init2(&soap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE); |
signal(SIGPIPE, sigpipe_handle); |
void sigpipe_handle(int x) { } |
soap.socket_flags = MSG_NOSIGNAL; |
int main(int argc, char **argv) { struct soap soap, *tsoap; pthread_t tid; int m, s; soap_init2(&soap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE); soap.max_keep_alive = 100; // at most 100 calls per keep-alive session soap.accept_timeout = 600; // optional: let server time out after ten minutes of inactivity m = soap_bind(&soap, NULL, 18000, BACKLOG); // use port 18000 on the current machine if (m < 0) { soap_print_fault(&soap, stderr); exit(1); } fprintf(stderr, "Socket connection successful %d\n", m); for (count = 0; count > = 0; count++) { soap.socket_flags = MSG_NOSIGNAL; // use this soap.accept_flags = SO_NOSIGPIPE; // or this to prevent sigpipe s = soap_accept(&soap); if (s < 0) { if (soap.errnum) soap_print_fault(&soap, stderr); else fprintf(stderr, "Server timed out\n"); // Assume timeout is long enough for threads to complete serving requests break; } fprintf(stderr, "Accepts socket %d connection from IP %d.%d.%d.%d\n", s, (int)(soap.ip >> 24)&0xFF, (int)(soap.ip >> 16)&0xFF, (int)(soap.ip >> 8)&0xFF, (int)soap.ip&0xFF); tsoap = soap_copy(&soap); pthread_create(&tid, NULL, (void*(*)(void*))process_request, (void*)tsoap); } return 0; } void *process_request(void *soap) { pthread_detach(pthread_self()); ((struct soap*)soap)->recv_timeout = 300; // Timeout after 5 minutes stall on recv ((struct soap*)soap)->send_timeout = 60; // Timeout after 1 minute stall on send soap_serve((struct soap*)soap); soap_destroy((struct soap*)soap); soap_end((struct soap*)soap); soap_free((struct soap*)soap); return NULL; } |
struct soap soap; soap_init(&soap); soap.userid = "guest"; soap.passwd = "visit"; ... |
POST /XXX HTTP/1.0 Host: YYY User-Agent: gSOAP/2.2 Content-Type: text/xml; charset=utf-8 Content-Length: nnn Authorization: Basic Z3Vlc3Q6Z3Vlc3Q= ... |
int ns__method(struct soap *soap, ...) { if (!soap->.userid || !soap->.passwd || strcmp(soap->.userid, "guest") || strcmp(soap->.passwd, "visit")) return 401; ... } |
struct soap soap; soap_init(&soap); soap.proxy_host = "xx.xx.xx.xx"; // IP or domain soap.proxy_port = 8080; soap.proxy_userid = "guest"; soap.proxy_passwd = "guest"; ... |
POST /XXX HTTP/1.0 Host: YYY User-Agent: gSOAP/2.2 Content-Type: text/xml; charset=utf-8 Content-Length: nnn Proxy-Authorization: Basic Z3Vlc3Q6Z3Vlc3Q= ... |
struct soap soap; soap_init(&soap); soap.send_timeout = 10; soap.recv_timeout = 10; |
soap.send_timeout = 0; soap.recv_timeout = 0; |
#define uSec *-1 #define mSec *-1000 soap.accept_timeout = 10 uSec; soap.send_timeout = 20 mSec; soap.recv_timeout = 20 mSec; |
int sock = soap_bind(soap, host, port, backlog); if (soap_valid_socket(sock)) { setsockopt(sock, ..., ..., ..., ...); setsockopt(sock, ..., ..., ..., ...); |
g++ -DWITH_OPENSSL -o myprog myprog.cpp stdsoap2.cpp soapC.cpp soapServer.cpp -lssl -lcrypto |
int main() { int m, s; pthread_t tid; struct soap soap, *tsoap; soap_ssl_init(); /* init OpenSSL (just once) */ if (CRYPTO_thread_setup()) { fprintf(stderr, "Cannot setup thread mutex\n"); exit(1); } soap_init(&soap); if (soap_ssl_server_context(&soap, SOAP_SSL_DEFAULT, "server.pem", /* keyfile: required when server must authenticate to clients (see SSL docs on how to obtain this file) */ "password", /* password to read the key file */ "cacert.pem", /* optional cacert file to store trusted certificates */ NULL, /* optional capath to directory with trusted certificates */ "dh512.pem", /* DH file, if NULL use RSA */ NULL, /* if randfile!=NULL: use a file with random data to seed randomness */ NULL /* optional server identification to enable SSL session cache (must be a unique name) */ )) { soap_print_fault(&soap, stderr); exit(1); } m = soap_bind(&soap, NULL, 18000, 100); // use port 18000 if (m < 0) { soap_print_fault(&soap, stderr); exit(1); } fprintf(stderr, "Socket connection successful: master socket = %d\n", m); for (;;) { s = soap_accept(&soap); fprintf(stderr, "Socket connection successful: slave socket = %d\n", s); if (s < 0) { soap_print_fault(&soap, stderr); break; } tsoap = soap_copy(&soap); /* should call soap_ssl_accept on a copy */ if (!tsoap) break; if (soap_ssl_accept(tsoap)) { soap_print_fault(tsoap, stderr); soap_free(tsoap); continue; /* when soap_ssl_accept fails, we should just go on */ } pthread_create(&tid, NULL, &process_request, (void*)tsoap); } soap_done(&soap); /* deallocates SSL context */ CRYPTO_thread_cleanup(); return 0; } void *process_request(void *soap) { pthread_detach(pthread_self()); soap_serve((struct soap*)soap); soap_destroy((struct soap*)soap); soap_end((struct soap*)soap); soap_done((struct soap*)soap); free(soap); return NULL; } |
#include < unistd.h > /* defines _POSIX_THREADS if pthreads are available */ #ifdef _POSIX_THREADS # include < pthread.h > #endif #if defined(WIN32) # define MUTEX_TYPE HANDLE # define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL) # define MUTEX_CLEANUP(x) CloseHandle(x) # define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE) # define MUTEX_UNLOCK(x) ReleaseMutex(x) # define THREAD_ID GetCurrentThreadID() #elif defined(_POSIX_THREADS) # define MUTEX_TYPE pthread_mutex_t # define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL) # define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x)) # define MUTEX_LOCK(x) pthread_mutex_lock(&(x)) # define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x)) # define THREAD_ID pthread_self() #else # error "You must define mutex operations appropriate for your platform" # error "See OpenSSL /threads/th-lock.c on how to implement mutex on your platform" #endif struct CRYPTO_dynlock_value { MUTEX_TYPE mutex; }; static MUTEX_TYPE *mutex_buf; static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line) { struct CRYPTO_dynlock_value *value; value = (struct CRYPTO_dynlock_value*)malloc(sizeof(struct CRYPTO_dynlock_value)); if (value) MUTEX_SETUP(value->mutex); return value; } static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line) { if (mode & CRYPTO_LOCK) MUTEX_LOCK(l->mutex); else MUTEX_UNLOCK(l->mutex); } static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line) { MUTEX_CLEANUP(l->mutex); free(l); } void locking_function(int mode, int n, const char *file, int line) { if (mode & CRYPTO_LOCK) MUTEX_LOCK(mutex_buf[n]); else MUTEX_UNLOCK(mutex_buf[n]); } unsigned long id_function() { return (unsigned long)THREAD_ID; } int CRYPTO_thread_setup() { int i; mutex_buf = (MUTEX_TYPE*)malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE)); if (!mutex_buf) return SOAP_EOM; for (i = 0; i < CRYPTO_num_locks(); i++) MUTEX_SETUP(mutex_buf[i]); CRYPTO_set_id_callback(id_function); CRYPTO_set_locking_callback(locking_function); CRYPTO_set_dynlock_create_callback(dyn_create_function); CRYPTO_set_dynlock_lock_callback(dyn_lock_function); CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); return SOAP_OK; } void CRYPTO_thread_cleanup() { int i; if (!mutex_buf) return; CRYPTO_set_id_callback(NULL); CRYPTO_set_locking_callback(NULL); CRYPTO_set_dynlock_create_callback(NULL); CRYPTO_set_dynlock_lock_callback(NULL); CRYPTO_set_dynlock_destroy_callback(NULL); for (i = 0; i < CRYPTO_num_locks(); i++) MUTEX_CLEANUP(mutex_buf[i]); free(mutex_buf); mutex_buf = NULL; } |
signal(SIGPIPE, sigpipe_handle); |
void sigpipe_handle(int x) { } |
if (soap_ssl_server_context(&soap, SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION, "server.pem", "password", "cacert.pem", NULL, "dh512.pem", NULL, NULL )) { soap_print_fault(&soap, stderr); exit(1); } |
g++ -DWITH_OPENSSL myclient.cpp stdsoap.cpp soapC.cpp soapClient.cpp -lssl -lcrypto |
g++ -DWITH_OPENSSL myclient.cpp stdsoap.cpp soapC.cpp soapClient.cpp -lxnet -lsocket -lnsl -lssl -lcrypto |
#define WITH_OPENSSL |
soap_ssl_init(); /* init OpenSSL (just once) */ if (soap_ssl_client_context(&soap, SOAP_SSL_DEFAULT, "client.pem", /* keyfile: required only when client must authenticate to server (see SSL docs on how to obtain this file) */ "password", /* password to read the key file */ "cacerts.pem", /* cacert file to store trusted certificates (needed to verify server) */ NULL, /* capath to direcoty with trusted certificates */ NULL /* if randfile!=NULL: use a file with random data to seed randomness */ )) { soap_print_fault(&soap, stderr); exit(1); } soap_call_ns__mymethod(&soap, "https://domain/path/secure.cgi", "", ...); |
soap_ssl_init(); /* init OpenSSL (just once) */ if (soap_ssl_client_context(&soap, SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSL_SKIP_HOST_CHECK, | SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE, "client.pem", /* keyfile: required only when client must authenticate to server (see SSL docs on how to obtain this file) */ "password", /* password to read the key file */ "cacerts.pem", /* cacert file to store trusted certificates (needed to verify server) */ NULL, /* capath to direcoty with trusted certificates */ NULL /* if randfile!=NULL: use a file with random data to seed randomness */ )) { soap_print_fault(&soap, stderr); exit(1); } soap_call_ns__mymethod(&soap, "https://domain/path/secure.cgi", "", ...); |
if (soap_ssl_client_context(&soap, SOAP_SSL_NO_AUTHENTICATION, NULL, NULL, NULL, NULL, NULL )) { soap_print_fault(&soap, stderr); exit(1); } |
signal(SIGPIPE, sigpipe_handle); |
void sigpipe_handle(int x) { } |
|
static const char *engine = "cswift"; /* engine name */ int main() { ... ENGINE *e; if (!(e = ENGINE_by_id(engine))) fprintf(stderr, "Error finding engine %s\n", engine); else if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) fprintf(stderr, "Error using engine %s\n", engine); ... |
|
soap_init(&soap); ... soap_set_omode(&soap, SOAP_ENC_ZLIB); // enable Zlib's gzip if (soap_call_ns__myMethod(&soap, ...)) ... soap_clr_omode(&soap, SOAP_ENC_ZLIB); // disable Zlib's gzip ... |
soap_init(&soap); ... soap_set_omode(&soap, SOAP_ENC_ZLIB); soap.z_level = 9; // best compression ... |
soap_call_ns__myMethod(&soap, ...); ... printf("Compression ratio: %f%% (in) %f%% (out)\n", 100*soap.z_ratio_out, 100*soap.z_ratio_in); ... |
g++ -DWITH_COOKIES -o myclient stdsoap2.cpp soapC.cpp soapClient.cpp |
#define WITH_COOKIES |
struct soap soap; soap_init(&soap); soap.cookie_max = 10; |
struct soap_cookie { char *name; char *value; char *domain; char *path; long expire; /* client-side: local time to expire; server-side: seconds to expire */ unsigned int version; short secure; short session; /* server-side */ short env; /* server-side: 1 = got cookie from client */ short modified; /* server-side: 1 = client cookie was modified */ struct soap_cookie *next; }; |
g++ -DWITH_COOKIES -o myserver ... |
|
|
int main() { struct soap soap; int m, s; soap_init(&soap); soap.cookie_domain = "..."; soap.cookie_path = "/"; // the path which is used to filter/set cookies with this destination if (argc < 2) { soap_getenv_cookies(&soap); // CGI app: grab cookies from 'HTTP_COOKIE' env var soap_serve(&soap); } else { m = soap_bind(&soap, NULL, atoi(argv[1]), 100); if (m < 0) exit(1); for (int i = 1; ; i++) { s = soap_accept(&soap); if (s < 0) exit(1); soap_serve(&soap); soap_end(&soap); // clean up soap_free_cookies(&soap); // remove all old cookies from database so no interference occurs with the arrival of new cookies } } return 0; } int ck__demo(struct soap *soap, ...) { int n; const char *s; s = soap_cookie_value(soap, "demo", NULL, NULL); // cookie returned by client? if (!s) s = "init-value"; // no: set initial cookie value else ... // modify 's' to reflect session control soap_set_cookie(soap, "demo", s, NULL, NULL); soap_set_cookie_expire(soap, "demo", 5, NULL, NULL); // cookie may expire at client-side in 5 seconds return SOAP_OK; } |
struct soap soap; soap_init(&soap); soap.proxy_host = "proxyhostname"; soap.proxy_port = 8080; if (soap_call_ns__method(&soap, "http://host:port/path", "action", ...)) soap_print_fault(&soap, stderr); else ... |
#define WITH_FASTCGI |
struct soap soap; soap_init(&soap); /* fsend is used to transmit data in blocks */ soap.fsend = my_send; /* frecv is used to receive data in blocks */ soap.frecv = my_recv; /* fopen is used to connect */ soap.fopen = my_tcp_connect; /* fclose is used to disconnect */ soap.fclose = my_tcp_disconnect; /* fclosesocket is used only to close the master socket in a server upon soap_done() */ soap.fclosesocket = my_tcp_closesocket; /* fshutdownsocket is used after completing a send operation to send TCP FIN */ soap.fshutdownsocket = my_tcp_shutdownsocket; /* setting fpoll is optional, leave it NULL to omit polling the server */ soap.fpoll = my_poll; /* faccept is used only by a server application */ soap.faccept = my_accept; |
wsdl2h -s -o qx.h http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl |
soapcpp2 -C qx.h |
soapStub.h soapH.h soapC.cpp soapClient.cpp soapStockQuoteProxy.h soapCurrencyExchangeBindingProxy.h StockQuote.nsmap |
#include "soapStockQuoteProxy.h" #include "soapCurrencyExchangeBindingProxy.h" #include "StockQuote.nsmap" main() { StockQuote stock; CurrencyExchangeBinding exchange; float quote, rate; stock.ns1__getQuote("IBM", quote); // get quote for IBM if (stock.soap->error) exit(1); exchange.ns2__getRate(üs", ük", rate); // get US to UK rate if (exchange.soap->error) exit(1); cout << "IBM in UK pounds = " << rate*quote << endl; } |
namespace myNamespaceName { ... gSOAP header file contents ... } |
soapcpp2 -penv env.h |
soapcpp2 -c -penv env.h |
g++ -DWITH_NONAMESPACES -c stdsoap2.cpp |
soapcpp2 -c -penv env.h |
soapcpp2 -c -n -pmyClient1 client1.h soapcpp2 -c -n -pmyClient2 client2.h |
#include "envH.h" // include this file first! #include "myClient1H.h" // include client 1 stubs #include "myClient2H.h" // include client 2 stubs ... #include "myClient1H.nsmap" // include client 1 nsmap #include "myClient2H.nsmap" // include client 2 nsmap ... soap_init(&soap); soap_set_namespaces(&soap, myClient1_namespaces); ... make Client 1 invocations ... ... soap_set_namespaces(&soap, myClient2_namespaces); ... make Client 2 invocations ... |
soapcpp2 -penv env.h g++ -c envC.cpp |
g++ -c -DWITH_NONAMESPACES stdsoap2.cpp |
namespace quote { //gsoap ns service name: Service //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service location: http://services.xmethods.net/soap //gsoap ns schema namespace: urn:xmethods-delayed-quotes //gsoap ns service method-action: getQuote "" int ns__getQuote(char *symbol, float &Result); } |
soapcpp2 -n quote.h g++ -c quoteClientLib.cpp |
soapcpp2 -n -pquote quote.h g++ -c quoteClientLib.cpp |
namespace rate { //gsoap ns service name: Service //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service location: http://services.xmethods.net/soap //gsoap ns schema namespace: urn:xmethods-CurrencyExchange //gsoap ns service method-action: getRate "" int ns__getRate(char *country1, char *country2, float &Result); } |
soapcpp2 -n rate.h |
#include "quoteServiceProxy.h" // get quote Service proxy #include "rateServiceProxy.h" // get rate Service proxy #include "quote.nsmap" // get quote namespace bindings #include "rate.nsmap" // get rate namespace bindings int main(int argc, char *argv[]) { if (argc < = 1) { std::cerr << "Usage: main ticker [currency]" << std::endl exit(0); } quote::Service quote; float q; if (quote.getQuote(argv[1], q)) // get quote soap_print_fault(quote.soap, stderr); else { if (argc > 2) { rate::Service rate; float r; if (rate.getRate("us", argv[2], r)) // get rate in US dollars soap_print_fault(rate.soap, stderr); else q *= r; // convert the quote } std::cout << argv[1] << ": " << q << std::endl; } return 0; } |
namespace calc { //gsoap ns service name: Service //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service location: http://www.cs.fsu.edu/~engelen/calc.cgi //gsoap ns schema namespace: urn:calc int ns__add(double a, double b, double &result); int ns__sub(double a, double b, double &result); int ns__mul(double a, double b, double &result); int ns__div(double a, double b, double &result); } |
soapcpp2 -n calc.h |
#include "calcServiceObject.h" // get Service object #include "calc.nsmap" // get calc namespace bindings ... calc::Service calc; calc.serve(); // calls request dispatcher to invoke one of the functions below ... int calc::Service::add(double a, double b, double &result); { result = a + b; returnSOAP_OK; } int calc::Service::sub(double a, double b, double &result); { result = a - b; returnSOAP_OK; } int calc::Service::mul(double a, double b, double &result); { result = a * b; returnSOAP_OK; } int calc::Service::div(double a, double b, double &result); { result = a / b; returnSOAP_OK; } |
soapcpp2 -c -penv env.h gcc -c envC.c |
gcc -c -DWITH_NONAMESPACES stdsoap2.c |
//gsoap ns service name: Service //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service location: http://services.xmethods.net/soap //gsoap ns schema namespace: urn:xmethods-delayed-quotes //gsoap ns service method-action: getQuote "" int ns__getQuote(char *symbol, float *Result); |
soapcpp2 -c -n -pquote quote.h gcc -c quoteClientLib.c |
//gsoap ns service name: Service //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service location: http://services.xmethods.net/soap //gsoap ns schema namespace: urn:xmethods-CurrencyExchange //gsoap ns service method-action: getRate "" int ns__getRate(char *country1, char *country2, float *Result); |
soapcpp2 -c -n -prate rate.h gcc -c rateClientLib.c |
#include "quoteStub.h" // get quote Service stub #include "rateStub.h" // get rate Service stub #include "quote.nsmap" // get quote namespace bindings #include "rate.nsmap" // get rate namespace bindings int main(int argc, char *argv[]) { if (argc < = 1) { fprintf(stderr, "Usage: main ticker [currency]\n"); exit(0); } struct soap soap; float q; soap_init(&soap); soap_set_namespaces(&soap, quote_namespaces); if (soap_call_ns__getQuote(&soap, "http://services.xmethods.net/soap", "", argv[1], &q)) // get quote soap_print_fault(&soap, stderr); else { if (argc > 2) { soap_set_namespaces(&soap, rate_namespaces); float r; if (soap_call_ns__getRate(&soap, "http://services.xmethods.net/soap", "", "us", argv[2], &r)) // get rate in US dollars soap_print_fault(&soap, stderr); else q *= r; // convert the quote } printf("%s: %f \n", argv[1], q); } return 0; } |
soapcpp2 -penv env.h |
soap_init(&soap); soap_set_namespaces(&soap, namespaces); |
int soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap *soap, struct soap_plugin *p, void *arg), void *arg) void* soap_lookup_plugin(struct soap*, const char*); |
int soap_copy(struct soap *soap); void soap_done(struct soap *soap); |
#include "stdsoap2.h" #define PLUGIN_ID "PLUGIN-1.0" // some name to identify plugin struct plugin_data // local plugin data { int (*fsend)(struct soap*, const char*, size_t); // to save and use send callback size_t (*frecv)(struct soap*, char*, size_t); // to save and use recv callback }; int plugin(struct soap *soap, struct soap_plugin *plugin, void *arg); |
#include "plugin.h" static const char plugin_id[] = PLUGIN_ID; // the plugin id static int plugin_init(struct soap *soap, struct plugin_data *data); static int plugin_copy(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); static void plugin_delete(struct soap *soap, struct soap_plugin *p); static int plugin_send(struct soap *soap, const char *buf, size_t len); static size_t plugin_recv(struct soap *soap, char *buf, size_t len); // the registry function: int plugin(struct soap *soap, struct soap_plugin *p, void *arg) { p->id = plugin_id; p->data = (void*)malloc(sizeof(struct plugin_data)); p->fcopy = plugin_copy; /* optional: when set the plugin must copy its local data */ p->fdelete = plugin_delete; if (p->data) if (plugin_init(soap, (struct plugin_data*)p->data)) { free(p->data); // error: could not init return SOAP_EOM; // return error } return SOAP_OK; } static int plugin_init(struct soap *soap, struct plugin_data *data) { data->fsend = soap->fsend; // save old recv callback data->frecv = soap->frecv; // save old send callback soap->fsend = plugin_send; // replace send callback with new soap->frecv = plugin_recv; // replace recv callback with new return SOAP_OK; } // copy plugin data, called by soap_copy() // This is important: we need a deep copy to avoid data sharing by two run-time environments static int plugin_copy(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src) { if (!(dst->data = (struct plugin_data*)malloc(sizeof(struct plugin_data)))) return SOAP_EOM; *dst->data = *src->data; return SOAP_OK; } // plugin deletion, called by soap_done() static void plugin_delete(struct soap *soap, struct soap_plugin *p) { free(p->data); // free allocated plugin data } // the new send callback static int plugin_send(struct soap *soap, const char *buf, size_t len) { struct plugin_data *data = (struct plugin_data*)soap_lookup_plugin(soap, plugin_id); // fetch plugin's local data fwrite(buf, len, 1, stderr); // write message to stderr return data->fsend(soap, buf, len); // pass data on to old send callback } // the new receive callback static size_t plugin_recv(struct soap *soap, char *buf, size_t len) { struct plugin_data *data = (struct plugin_data*)soap_lookup_plugin(soap, plugin_id); // fetch plugin's local data size_t res = data->frecv(soap, buf, len); // get data from old recv callback fwrite(buf, res, 1, stderr); return res; } |
struct soap soap; soap_init(&soap); soap_register_plugin(&soap, plugin); ... soap_done(&soap); |
#include "logging.h" ... if (soap_register_plugin(&soap, logging)) soap_print_fault(&soap, stderr); // failed to register ... struct logging_data *logdata; logdata = (struct logging_data*)soap_lookup_plugin(&soap, logging_id); if (!logdata) ... // if the plug-in registered OK, there is certainly data but can't hurt to check logdata->inbound = stdout; // log to stdout logdata->outbound = stdout; // log to stdout ... process messages ... logdata->inbound = NULL; // don't log logdata->outbound = NULL; // don't log ... process messages ... size_t bytes_in = logdata->stat_recv; size_t bytes_out = logdata->stat_sent; |
#include "httpget.h" ... if (soap_register_plugin_arg(&soap, httpget, (void*)my_http_get_handler)) soap_print_fault(&soap, stderr); // failed to register ... struct http_get_data *httpgetdata; httpgetdata = (struct http_get_data*)soap_lookup_plugin(&soap, http_get_id); if (!httpgetdata) ... // if the plug-in registered OK, there is certainly data but can't hurt to check ... process messages ... size_t get_ok = httpgetdata->stat_get; size_t post_ok = httpgetdata->stat_post; size_t errors = httpgetdata->stat_fail; ... time_t now = time(NULL); struct tm *T; T = localtime(&now); size_t hitsthisminute = httpgetdata->min[T->tm_min]; size_t hitsthishour = httpgetdata->hour[T->tm_hour]; size_t hitstoday = httpgetdata->day[T->tm_yday]; |
int my_http_get_handler(struct soap) { soap->http_content = "text/html"; soap_response(soap, SOAP_FILE); soap_send(soap, «html>Hello</html>"); soap_end_send(soap); return SOAP_OK; // return SOAP_OK or HTTP error code, e.g. 404 } |
#include "httpmd5.h" ... if (soap_register_plugin(&soap, http_md5)) soap_print_fault(&soap, stderr); // failed to register |
#include "httpmd5.h" ... struct soap soap; soap_init1(&soap, SOAP_IO_STORE); if (soap_register_plugin(&soap, http_md5) soap_print_fault(&soap, stderr); // failed to register ... now safe to send SOAP with attachments ... |
#include "httpda.h" ... if soap_register_plugin(&soap, http_da)) soap_print_fault(&soap, stderr); // failed to register ... if (soap_call_ns__method(&soap, ...) != SOAP_OK) { if (soap.error == 401) // challenge: HTTP authentication required { if (!strcmp(soap.authrealm, authrealm)) // determine authentication realm { struct http_da_info info; // to store userid and passwd http_da_save(&soap, &info, authrealm, userid, passwd); // set userid and passwd for this realm if (soap_call_ns__method(&soap, ...) == SOAP_OK) // retry { ... soap_end(&soap); // userid and passwd were deallocated http_da_restore(&soap, &info); // restore userid and passwd if (!soap_call_ns__method(&soap, ...) == SOAP_OK) // another call ... http_da_release(&soap, &info); // remove userid and passwd |
#include "httpda.h" ... if (soap_register_plugin(&soap, http_da)) soap_print_fault(&soap, stderr); // failed to register ... soap_serve(&soap); ... int ns__method(struct soap *soap, ...) { if (soap->userid && soap->passwd) // client used basic authentication { // may decide not to handle, but if ok then go ahead and compare info: if (!strcmp(soap->userid, userid) && !strcmp(soap->passwd, passwd)) { ... handle request ... return SOAP_OK; } } else if (soap->authrealm && soap->userid) // Digest authentication { passwd = ... // database lookup on userid and authrealm to find passwd if (!strcmp(soap->authrealm, authrealm) && !strcmp(soap->userid, userid)) { if (!http_da_verify_post(soap, passwd)) { ... handle request ... return SOAP_OK; } } } soap->authrealm = authrealm; // set realm for challenge return 401; // Not authorized, challenge digest authentication } |