OpenVMS Source Code Demos
SIMPLE_SERVICE_SERVER_101.C
//===============================================================================================================================
// title : simple_service_server_xxx.c
// author : Neil Rieck
// created: 2011-10-14
// Build : @build_simple_service_step1_common.com (only need to do this once for every new WSDL)
// @build_simple_service_step2_server.com
// @build_simple_service_step3_client.com
// Notes : Attention Hackers! be prepared to inspect file "GSOAP$ROOT:[000000.INCLUDE]stdsoap2.h"
// looking at the SOAP structure to find variable names then working backwards
//===============================================================================================================================
// history:
// ver who when what
// --- --- ------ ---------------------------------------------------------------------------------------------------------------
// 100 NSR 111015 1. original work
// 101 NSR 111016 1. added bells and whistles
//
// remember to modify VERSION on the first line of this file
//===============================================================================================================================
#define VERSION "simple_service_server_101.1" //
#define PATH "csmis$root3:[dvlp._gsoap_simple_service_2011]" // our current working directory
#define WSDL "simple_service.wsdl" // used in http_get()
#define NSR_DEBUG 0 // must link with gsoap$root:[lib]
#define NSR_STRICT 1 // XML must be well-formed and valid
//
// import the usual stuff
//
#include <stdio.h> //
#include <stdlib.h> //
#include <string.h> //
#include <time.h> //
//
// a few prototypes
//
void my_close(); //
void build_gmt_stamp(); //
void build_ats_filenames(); //
int http_get(); //
//
// stuff needed for our gSOAP app
//
#include "SIMPLE_SERVICE_GSC_H.H" // generated by tool "soapcpp2"
#include "SIMPLESERVICESOAP11BINDING.NSMAP" // generated by tool "soapcpp2"
//
// global variables
//
int gDcl = 0; //
FILE *xml_file = 0; //
FILE *trc_file = 0; //
char ats_xml_fs[128]; //
char ats_trc_fs[128]; //
char gmt_stamp[30]; //
//==============================================================================
// main (this is our server)
//==============================================================================
int main(int argc, char **argv) //
{ int m, s; // master and slave sockets
struct soap soap; //
soap_init(&soap); //
#if (NSR_DEBUG==1) // -----------------------
char logf1[99]; //
char logf2[99]; //
char logf3[99]; //
sprintf(logf1,"%s%s",PATH,"aaa_s_recv.log"); // for extensive server logging
sprintf(logf2,"%s%s",PATH,"aaa_s_sent.log"); //
sprintf(logf3,"%s%s",PATH,"aaa_s_test.log"); //
soap_set_recv_logfile(&soap, logf1); // must link to gsoapdbg.olb
soap_set_sent_logfile(&soap, logf2); //
soap_set_test_logfile(&soap, logf3); //
#endif // -----------------------
#ifdef NSR_STRICT // ---------------------
soap_set_imode(&soap, SOAP_XML_STRICT); // set input mode strict
#endif // ---------------------
#ifdef NSR_HTTP10 // ------------------
soap.http_version = "1.0"; // revert to HTTP 1.0
#endif // ------------------
soap.fget = &http_get; // to support "?wsdl" (requires new "mod_gsoap")
if (argc < 2) // must have been started from Apache
{ soap_serve(&soap); // serve as CGI application
gDcl = 0; // not in developer mode
} //
else // must have been started from DCL
{ gDcl = 1; // developer mode
m = soap_bind(&soap, NULL, atoi(argv[1]), 100); // argv[1] holds the specified port
if (m < 0) // if some sort of error
{ soap_print_fault(&soap, stderr); //
exit(-1); //
} //
fprintf(stderr, "Program: %s\n",VERSION); //
fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
for ( ; ; ) // loop forever
{ s = soap_accept(&soap); //
fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);
if (s < 0) //
{ soap_print_fault(&soap, stderr); //
exit(-1); //
} //
soap_serve(&soap); //
soap_end(&soap); //
fprintf(stderr, "end-of-server: slave socket\n"); //
} //
}; //
return 0; //
}
//==============================================================================
// ssAdd (SOAP 1.1)
//
// 1. the following declaration was found in file: SOAPSERVER.C
// 2. it can also be found in file "SOAPSTUB.H" near "Client-Side Call Stubs"
//
// __ns2__ssAdd( struct soap*,
// struct _ns1__ssAdd *ns1__ssAdd,
// struct _ns1__ssAddResponse *ns1__ssAddResponse);
//==============================================================================
//trek1
int __ns2__ssAdd( struct soap *soap,
struct _ns1__ssAdd *myAddRequest,
struct _ns1__ssAddResponse *myAddResponse)
{
if (gDcl == 1){ // if started from DCL (developer activated)
trc_file = stderr; // copy address
xml_file = stderr; // ''
}else{ //
build_ats_filenames(); //
xml_file = 0; //
trc_file = fopen(ats_trc_fs, "a"); // open the trace file
} //
if ((myAddRequest->param0 == NULL) ||
(myAddRequest->param1 == NULL) )
{
char *s = (char*)soap_malloc(soap, 1024);
sprintf(s, "<error xmlns=\"http://tempuri.org/\">Missing one or more params (-1)</error>");
return soap_sender_fault(soap, "Missing one or more params (-2)", s);
}
if (trc_file == NULL){ // if the trace did not open (should never happen)
if (gDcl==1){ //
fprintf(stderr,"%s\n","oops, trc_file did not open"); //
return 2; // vms error
}else{ //
char *s = (char*)soap_malloc(soap, 1024); //
sprintf(s, "<error xmlns=\"http://tempuri.org/\">Server Problem (-1) could not open output file</error>");
return soap_sender_fault(soap, "Server Problem (-2) could not open output file", s);
return SOAP_OK; //
} //
} //
build_gmt_stamp(); //
fprintf(trc_file,"%s\n", "ssAdd: start ---"); //
fprintf(trc_file,"%s%s\n", "Event Time (GMT): ",gmt_stamp); //
//----------------------------------------------------------------------
// service: ssAdd() starts here
//----------------------------------------------------------------------
int param0, param1, param2; //
param0 = *myAddRequest->param0; //
param1 = *myAddRequest->param1; //
param2 = param0 + param1; // needs some overflow protection
fprintf(trc_file,"param0 %d\n",param0);
fprintf(trc_file,"param1 %d\n",param1);
fprintf(trc_file,"param2 %d\n",param2);
//----------------------------------------------------
// method 1 (easy way which does not work)
//----------------------------------------------------
// *myAddResponse.return_ = param2; //
//----------------------------------------------------
// method 2 (harder way which works)
//----------------------------------------------------
int *safe = (int*)soap_malloc(soap, 1); // allocate mem to survive this function
*safe = param2; // copy data
myAddResponse->return_ = safe; // copy address
//----------------------------------------------------------------------
fprintf(trc_file,"ssAdd: normal exit ---\n"); //
my_close(); // flush and close
return SOAP_OK; //
}
//==============================================================================
// ssSubtract (SOAP 1.1)
//
// 1. the following declaration was found in file: SOAPCLIENT.C
// 2. it can also be found in file "SOAPSTUB.H" near "Client-Side Call Stubs"
//
// __ns2__ssSubtract( struct soap*,
// struct _ns1__ssSubtract *ns1__ssSubtract,
// struct _ns1__ssSubtractResponse *ns1__ssSubtractResponse);
//==============================================================================
//trek2
int __ns2__ssSubtract( struct soap *soap,
struct _ns1__ssSubtract *mySubtractRequest,
struct _ns1__ssSubtractResponse *mySubtractResponse)
{
if (gDcl == 1){ // if started from DCL (developer activated)
trc_file = stderr; // copy address
xml_file = stderr; // ''
}else{ //
build_ats_filenames(); //
xml_file = 0; //
trc_file = fopen(ats_trc_fs, "a"); // open the trace file
} //
if ((mySubtractRequest->param0 == NULL) ||
(mySubtractRequest->param1 == NULL) )
{
char *s = (char*)soap_malloc(soap, 1024);
sprintf(s, "<error xmlns=\"http://tempuri.org/\">Missing one or more params (-1)</error>");
return soap_sender_fault(soap, "Missing one or more params (-2)", s);
}
if (trc_file == NULL){ // if the trace did not open (should never happen)
if (gDcl==1){ //
fprintf(stderr,"%s\n","oops, trc_file did not open"); //
return 2; // vms error
}else{ //
char *s = (char*)soap_malloc(soap, 1024); //
sprintf(s, "<error xmlns=\"http://tempuri.org/\">Server Problem (-1) could not open output file</error>");
return soap_sender_fault(soap, "Server Problem (-2) could not open output file", s);
return SOAP_OK; //
} //
} //
build_gmt_stamp(); //
fprintf(trc_file,"%s\n", "ssSubtract: start ---"); //
fprintf(trc_file,"%s%s\n", "Event Time (GMT): ",gmt_stamp); //
int param0, param1, param2; //
param0 = *mySubtractRequest->param0; //
param1 = *mySubtractRequest->param1; //
param2 = param0 - param1; // needs some overflow protection
//----------------------------------------------------
// method 1 (easy way which does not work)
//----------------------------------------------------
// mySubtractResponse.return_ = param2; //
//----------------------------------------------------
// method 2 (harder way which works)
//----------------------------------------------------
int *safe = (int*)soap_malloc(soap, 1); // allocate mem to survive this function
*safe = param2; // copy data
mySubtractResponse->return_ = safe; // copy address
//----------------------------------------------------------------------
fprintf(trc_file,"ssAdd: normal exit ---\n"); //
my_close(); // flush and close
return SOAP_OK; //
}
//==============================================================================
// ssEcho (SOAP 1.1)
//
// 1. the following declaration was found in file: SOAPCLIENT.C
// 2. it can also be found in file "SOAPSTUB.H" near "Client-Side Call Stubs"
//
// __ns2__ssEcho( struct soap*,
// struct _ns1__ssEcho *ns1__ssEcho,
// struct _ns1__ssEchoResponse *ns1__ssEchoResponse);
//==============================================================================
//trek3
int __ns2__ssEcho( struct soap *soap,
struct _ns1__ssEcho *myEchoRequest,
struct _ns1__ssEchoResponse *myEchoResponse)
{
if (gDcl == 1){ // if started from DCL (developer activated)
trc_file = stderr; // copy address
xml_file = stderr; // ''
}else{ //
build_ats_filenames(); //
xml_file = 0; //
trc_file = fopen(ats_trc_fs, "a"); // open the trace file
} //
if (myEchoRequest->param0 == NULL)
{
char *s = (char*)soap_malloc(soap, 1024);
sprintf(s, "<error xmlns=\"http://tempuri.org/\">Missing one or more params (-1)</error>");
return soap_sender_fault(soap, "Missing one or more params (-2)", s);
}
if (trc_file == NULL){ // if the trace did not open (should never happen)
if (gDcl==1){ //
fprintf(stderr,"%s\n","oops, trc_file did not open"); //
return 2; // vms error
}else{ //
char *s = (char*)soap_malloc(soap, 1024); //
sprintf(s, "<error xmlns=\"http://tempuri.org/\">Server Problem (-1) could not open output file</error>");
return soap_sender_fault(soap, "Server Problem (-2) could not open output file", s);
return SOAP_OK; //
} //
} //
build_gmt_stamp(); //
fprintf(trc_file,"%s\n", "ssEcho: start ---"); //
fprintf(trc_file,"%s%s\n","Event Time (GMT): ",gmt_stamp); //
fprintf(trc_file,"%s%s\n","data: ",myEchoRequest->param0); //
//----------------------------------------------------
// method 1 (easy way which does not work)
//----------------------------------------------------
// char buffer[255] = '\0';
// sprintf(buffer,"You sent: %s\n",myEchoRequest.param0");
// mySubtractResponse->return_ = buffer; // copy input directly to output
//----------------------------------------------------
// method 2 (harder way which works)
//----------------------------------------------------
int my_Size = strlen(myEchoRequest->param0); // get the size of the string sent here
char *s = (char*)soap_malloc(soap, my_Size + 20); // allocate mem to survive this function
sprintf(s, "You sent \"%s\"",myEchoRequest->param0); //
myEchoResponse->return_ = s; // copy address of new variable
fprintf(trc_file,"Sending back: %s\n",s); // send this to stdout (or DCL)
//----------------------------------------------------------------------
fprintf(trc_file,"ssEcho: normal exit ---\n"); //
my_close(); // flush and close
return SOAP_OK; //
}
//==============================================================================
// http_get (to support "?wsdl")
// caveat: the current (2011) version of Apache plugin mod_gsoap.c does not allow HTTP GET
//==============================================================================
//trek4
int http_get(struct soap *soap)
{
int rc = 0; //
int error = 0; //
//----------------------------------------------------------------------
if (gDcl == 1){ // if started from DCL (developer activated)
trc_file = stderr; // copy address
xml_file = stderr; //
}else{ //
xml_file = 0; //
build_ats_filenames(); //
trc_file = fopen(ats_trc_fs, "a"); // open the trace file
} //
if (trc_file == NULL){ // if the trace did not open (should never happen)
if (gDcl==1){
fprintf(stderr,"%s\n","oops, trc_file did not open");
return 1;
}else{
char *s = (char*)soap_malloc(soap, 1024);
sprintf(s, "<error xmlns=\"http://tempuri.org/\">Server Problem (-1) could not open output file</error>");
return soap_sender_fault(soap, "Server Problem (-2) could not open output file", s);
return SOAP_OK;
}
}
build_gmt_stamp(); //
fprintf(trc_file,"%s\n", "httpGet: start ---"); //
fprintf(trc_file,"%s%s\n", "Event Time (GMT): ",gmt_stamp); //
FILE *fd = NULL; //
char *s = strchr(soap->path, '?'); //
if (!s || strcmp(s, "?wsdl")){ //
fprintf(trc_file,"httpGet: not '?wsdl' exit ---\n"); //
my_close(); //
return SOAP_GET_METHOD; //
} //
char wsdl_fs[255]; // wsdl file spec
sprintf(wsdl_fs,"%s%s",PATH,WSDL); // create full file spec
fd = fopen(wsdl_fs, "rb"); // open WSDL file to display
if (!fd){ //
fprintf(trc_file,"httpGet: 404 exit ---\n"); // "file-not-found" or "no privs"?
my_close(); //
return 404; // return HTTP not found error
} //
soap->http_content = "text/xml"; // HTTP header with text/xml content
soap_response(soap, SOAP_FILE); //
for (;;) //
{ //
size_t 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); //
fprintf(trc_file,"httpGet: normal exit ---\n"); //
my_close(); //
return SOAP_OK; //
}
//==============================================================================
// my_close (might be better if this was a macro)
//==============================================================================
void my_close()
{
if ((xml_file != 0) && (xml_file != stderr)){ //
fflush(xml_file); // flush
fclose(xml_file); // and close
xml_file = 0; //
} //
if ((trc_file != 0) && (trc_file != stderr)){ //
fflush(trc_file); // flush
fclose(trc_file); // and close
trc_file = 0; //
} //
}
//==============================================================================
// function: build_gmt_stamp()
// purpose : build a time stamp string for message logging
//==============================================================================
void build_gmt_stamp() { //
//----------------------------------------------------------------------
struct timeb timebuffer; // for ftime()
struct tm *time_fields; // for localtime()
char millisecs[5]; //
char my_date_time[30]; //
//----------------------------------------------------------------------
ftime( &timebuffer ); // record current system time
sprintf(millisecs, "%03hu", timebuffer.millitm); // extract milliseconds as three chars
time_fields = gmtime( &timebuffer.time ); // breakout other time fields in GMT
strftime( my_date_time, // ccyymmdd.hhmmss
sizeof(my_date_time), //
"%Y%m%d.%H%M%S", //
time_fields ); //
sprintf( gmt_stamp, // ccyymmdd.hhmmss.xxx
"%s%s%s", //
my_date_time, //
".", //
millisecs); // xxx
}
//==============================================================================
// function: build_ats_filenames()
// purpose : build new filenames (based upon the current GMT time stamp)
//==============================================================================
void build_ats_filenames() {
//----------------------------------------------------------------------
struct timeb timebuffer; // for ftime()
struct tm *time_fields; // for localtime()
char millisecs[5]; //
char my_date_time[30]; //
//----------------------------------------------------------------------
ftime( &timebuffer ); // record current system time
sprintf(millisecs, "%03hu", timebuffer.millitm); // extract milliseconds as three chars
time_fields = gmtime( &timebuffer.time ); // breakout other time fields in GMT
strftime(my_date_time, // ccyymmdd-hhmmss
sizeof(my_date_time), //
"%Y%m%d-%H%M%S", //
time_fields ); //
sprintf(ats_xml_fs, //
"%s%s%s%s%s%s", //
PATH, //
"cgi-incident-", //
my_date_time, //
"-", //
millisecs, //
".txt" ); //
sprintf(ats_trc_fs, //
"%s%s%s%s%s%s", //
PATH, //
"cgi-incident-", //
my_date_time, //
"-", //
millisecs, //
".trc" ); //
}
//====================================================================================
// ssEcho (soap 1.2)
//====================================================================================
int __ns3__ssEcho( struct soap *soap,
struct _ns1__ssEcho *ns1__ssEcho,
struct _ns1__ssEchoResponse *ns1__ssEchoResponse)
{
fprintf(stderr,"ssEcho (soap 1.2) entry\n"); //
int yada = __ns2__ssEcho(soap, ns1__ssEcho, ns1__ssEchoResponse); //
fprintf(stderr,"ssEcho (soap 1.2) exit\n"); //
return yada; //
}
//====================================================================================
// ssAdd (soap 1.2)
//====================================================================================
int __ns3__ssAdd( struct soap *soap,
struct _ns1__ssAdd *ns1__ssAdd,
struct _ns1__ssAddResponse *ns1__ssAddResponse)
{
fprintf(stderr,"ssAdd (soap 1.2) start\n"); //
int yada = __ns2__ssAdd(soap, ns1__ssAdd,ns1__ssAddResponse); //
fprintf(stderr,"ssAdd (soap 1.2) exit\n"); //
return yada; //
}
//====================================================================================
// ssSubtract (soap 1.2)
//====================================================================================
int __ns3__ssSubtract( struct soap *soap,
struct _ns1__ssSubtract *ns1__ssSubtract,
struct _ns1__ssSubtractResponse *ns1__ssSubtractResponse)
{
fprintf(stderr,"ssSubtract (soap 1.2) start\n"); //
int yada = __ns2__ssSubtract(soap, ns1__ssSubtract, ns1__ssSubtractResponse); //
fprintf(stderr,"ssSubtract (soap 1.2) exit\n"); //
return yada; //
}