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;									//
}