5.7. BadCall client & server

Example 5-27. badcall.idl


module Examples {

	interface BadCall {
		struct Foo { 
			double fval; 
		};

		exception NoParam     { };
		exception SingleParam { string mesg; };
		exception DoubleParam { string mesg; long val; };

		Foo trigger (in long val, out Foo bar) 
			raises (NoParam, SingleParam, DoubleParam);
	};
};
$ orbit-idl-2 --skeleton-impl badcall.idl geenrates all the files we will use in this example.

FileUsage for ClientUsage for Server
badcall.hreadonlyreadonly
badcall-common.creadonlyreadonly
badcall-stubs.creadonly-
badcall-skels.c-readonly
badcall-skelimpl.c-template for user code

Files remaining to write are listed in following table, starting with badcall-client.c in following chapter.

badcall-client.cwrite the client code
badcall-server.cwrite the generic code for servant creation

5.7.1. BadCall client

Example 5-28. badcall-client.c

/* badcall-client.c hacked by Frank Rehberger
 * <F.Rehberger@xtradyne.de>.  */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <orbit/orbit.h>

#include "badcall.h"

#include "examples-toolkit.h" /* ie. etk_abort_if_exception() */

static CORBA_ORB  global_orb = CORBA_OBJECT_NIL; /* global orb */
 
/* Is called in case of process signals. it invokes CORBA_ORB_shutdown()
 * function, which will terminate the processes main loop.
 */
static
void
client_shutdown (int sig)
{
        CORBA_Environment  local_ev[1];
        CORBA_exception_init(local_ev);
 
        if (global_orb != CORBA_OBJECT_NIL)
        {
                CORBA_ORB_shutdown (global_orb, FALSE, local_ev); 
                etk_abort_if_exception (local_ev, "caught exception");
        }
}
 
        
/* Inits ORB @orb using @argv arguments for configuration. For each
 * ORBit options consumed from vector @argv the counter of @argc_ptr
 * will be decremented. Signal handler is set to call
 * echo_client_shutdown function in case of SIGINT and SIGTERM
 * signals.  If error occures @ev points to exception object on
 * return.
 */
static
void
client_init (int               *argc_ptr,
	     char              *argv[],
             CORBA_ORB         *orb,
             CORBA_Environment *ev)
{
        /* init signal handling */
 
        signal(SIGINT,  client_shutdown);
        signal(SIGTERM, client_shutdown);
         
        /* create Object Request Broker (ORB) */
         
         (*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-mt-orb", ev); 
        if (etk_raised_exception(ev)) return;
}

/* Releases @servant object and finally destroys @orb. If error
 * occures @ev points to exception object on return.
 */
static
void
client_cleanup (CORBA_ORB                 orb,
                CORBA_Object              servant,
                CORBA_Environment        *ev)
{
        /* releasing managed object */
         CORBA_Object_release(servant, ev); 
        if (etk_raised_exception(ev)) return;
 
        /* tear down the ORB */
        if (orb != CORBA_OBJECT_NIL)
        {
                /* going to destroy orb.. */
                 CORBA_ORB_destroy(orb, ev); 
                if (etk_raised_exception(ev)) return;
        }
}


static 
void
client_trigger_exception (Examples_BadCall          servant,
			  CORBA_long                arg,
			  CORBA_Environment        *ev)
{
	CORBA_long            in_arg  = arg;	
	Examples_BadCall_Foo *out_arg = NULL;

	Examples_BadCall_Foo  ret_val;
	
	 ret_val = Examples_BadCall_trigger (servant, 
					    in_arg, 
					    out_arg,
					    ev);  
	
	switch(etk_exception_type(ev)) {
	case CORBA_NO_EXCEPTION:/* successful outcome*/
		
		/* now use data the server delivered to client
		 * over the return-value, or those out- and
		 * inout-parameters */
		
		break;
		
	case CORBA_USER_EXCEPTION:/* a user-defined exception */
		if (etk_raised_exception_is_a (ev, 
					       ex_Examples_BadCall_NoParam)) 
		{
			/* NoParam exception  does not own members */ 
			Examples_BadCall_NoParam *bc 
				= (Examples_BadCall_NoParam*)CORBA_exception_value(ev);
			g_warning ("raised exception: %s\n",  
				   CORBA_exception_id(ev));
		} 
		else if (etk_raised_exception_is_a (ev,
						    ex_Examples_BadCall_SingleParam)) 
		{
			Examples_BadCall_SingleParam *bc 
				= (Examples_BadCall_SingleParam*)
				CORBA_exception_value(ev);
			
			g_warning ("raised exception: %s\n"
				   " mesg: %s\n",  
				   CORBA_exception_id(ev),
				   bc->mesg);

		} else if (etk_raised_exception_is_a 
			   (ev, ex_Examples_BadCall_DoubleParam)) 
		{
			Examples_BadCall_DoubleParam *bc 
				= (Examples_BadCall_DoubleParam*)
				CORBA_exception_value(ev);
			
			g_warning ("raised exception: %s\n"
				   " mesg: %s\n"
				   " val: %d\n",  
				   CORBA_exception_id(ev),
				   bc->mesg,
				   bc->val);
		}
		else 
		{       
			/* should never get here ... */
			g_print ("unexpected CORBA_USER_EXCEPTION -%s\n",
				 CORBA_exception_id(ev));
		}
		break;
		
	case CORBA_SYSTEM_EXCEPTION:
	default: /* standard exception */
		/*
		 * CORBA_exception_id() can be used to determine which
		 * particular standard exception was raised; the minor
		 * member of the struct associated with the exception
		 * (as yielded by CORBA_exception_value()) may provide
		 * additional system-specific information about the
		 * exception
		 */
		g_print ("BadCall::trigger raised system exception: %s\n",  
			 CORBA_exception_id(ev));
		
		break;
	}
	
	/* free any storage associated with exception */
	CORBA_exception_free(ev);
	
	CORBA_free (out_arg); /* free Foo data */
	
}

/**
 *
 */
static
void
client_run (Examples_BadCall          servant,
	    CORBA_Environment        *ev)
{
	CORBA_long N=1000;
	CORBA_long i=0;

	/* increment sequence length, beginning with 0 up to 2048 */
	for (i=0; i<N; ++i)
	{
		 client_trigger_exception (servant, i, ev); 
	}
}


/*
 * main 
 */
int
main(int argc, char* argv[])
{
	CORBA_char filename[] = "badcall.ref";

        Examples_BadCall  servant = CORBA_OBJECT_NIL;

        CORBA_Environment ev[1];
        CORBA_exception_init(ev);

	 client_init (&argc, argv, &global_orb, ev); 
	etk_abort_if_exception(ev, "init failed");

	g_print ("Reading service reference from file \"%s\"\n", 
		 filename);

	 servant = etk_import_object_from_file (global_orb,
					       filename,
					       ev); 
        etk_abort_if_exception(ev, "importing IOR failed");

	 client_run (servant, ev); 
        etk_abort_if_exception(ev, "client stopped");
 
	 client_cleanup (global_orb, servant, ev); 
        etk_abort_if_exception(ev, "cleanup failed");
 
        exit (0);
}

5.7.2. BadCall server

Example 5-29. badcall-server.c

/*
 * echo-server program. Hacked from Echo test suite by by Frank
 * Rehberger <F.Rehberger@xtradyne.de>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <orbit/orbit.h>

#include "badcall.h"
#include "badcall-skelimpl.c" 

#include "examples-toolkit.h" /* ie. etk_abort_if_exception() */

static CORBA_ORB          global_orb = CORBA_OBJECT_NIL; /* global orb */
static PortableServer_POA root_poa   = CORBA_OBJECT_NIL; /* root POA
	
/* Is called in case of process signals. it invokes CORBA_ORB_shutdown()
 * function, which will terminate the processes main loop.
 */
static
void
server_shutdown (int sig)
{
	CORBA_Environment  local_ev[1];
	CORBA_exception_init(local_ev);

        if (global_orb != CORBA_OBJECT_NIL)
        {
                 CORBA_ORB_shutdown (global_orb, FALSE, local_ev); 
                etk_abort_if_exception (local_ev, "caught exception");
        }
}

/* Inits ORB @orb using @argv arguments for configuration. For each
 * ORBit options consumed from vector @argv the counter of @argc_ptr
 * will be decremented. Signal handler is set to call
 * echo_server_shutdown function in case of SIGINT and SIGTERM
 * signals.  If error occures @ev points to exception object on
 * return.
 */static 
void 
server_init (int                 *argc_ptr, 
	     char                *argv[],
	     CORBA_ORB           *orb,
	     PortableServer_POA  *poa,
	     CORBA_Environment   *ev)
{
	PortableServer_POAManager  poa_manager = CORBA_OBJECT_NIL; 

	CORBA_Environment  local_ev[1];
	CORBA_exception_init(local_ev);

	/* init signal handling */
	signal(SIGINT,  server_shutdown);
	signal(SIGTERM, server_shutdown);
	
	/* create Object Request Broker (ORB) */
	
         (*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-mt-orb", ev); 
	if (etk_raised_exception(ev)) 
		goto failed_orb;

         (*poa) = (PortableServer_POA) 
		CORBA_ORB_resolve_initial_references(*orb, "RootPOA", ev); 
	if (etk_raised_exception(ev)) 
		goto failed_poa;

         poa_manager = PortableServer_POA__get_the_POAManager(*poa, ev); 
	if (etk_raised_exception(ev)) 
		goto failed_poamanager;

	 PortableServer_POAManager_activate(poa_manager, ev); 
	if (etk_raised_exception(ev)) 
		goto failed_activation;

         CORBA_Object_release ((CORBA_Object) poa_manager, ev); 
	return;

 failed_activation:
 failed_poamanager:
        CORBA_Object_release ((CORBA_Object) poa_manager, local_ev);
 failed_poa:
	CORBA_ORB_destroy(*orb, local_ev);		
 failed_orb:
	return;
}

/* Entering main loop @orb handles incoming request and delegates to
 * servants. If error occures @ev points to exception object on
 * return.
 */
static void 
server_run (CORBA_ORB          orb,
	    CORBA_Environment *ev)
{
        /* enter main loop until SIGINT or SIGTERM */
	
         CORBA_ORB_run(orb, ev); 
	if (etk_raised_exception(ev)) return;

        /* user pressed SIGINT or SIGTERM and in signal handler
	 * CORBA_ORB_shutdown(.) has been called */
}

/* Releases @servant object and finally destroys @orb. If error
 * occures @ev points to exception object on return.
 */
static void 
server_cleanup (CORBA_ORB           orb,
		PortableServer_POA  poa,
		CORBA_Object        ref,
		CORBA_Environment  *ev)
{
	PortableServer_ObjectId   *objid       = NULL;

	 objid = PortableServer_POA_reference_to_id (poa, ref, ev); 
	if (etk_raised_exception(ev)) return;
		
	/* Servant: deactivatoin - will invoke  __fini destructor */
	 PortableServer_POA_deactivate_object (poa, objid, ev); 
	if (etk_raised_exception(ev)) return;

	 PortableServer_POA_destroy (poa, TRUE, FALSE, ev); 
	if (etk_raised_exception(ev)) return;

	CORBA_free (objid);

         CORBA_Object_release ((CORBA_Object) poa, ev); 
	if (etk_raised_exception(ev)) return;
	
         CORBA_Object_release (ref, ev); 
	if (etk_raised_exception(ev)) return;

        /* ORB: tear down the ORB */
        if (orb != CORBA_OBJECT_NIL)
        {
                /* going to destroy orb.. */
                 CORBA_ORB_destroy(orb, ev); 
		if (etk_raised_exception(ev)) return;
        }
}

/* Creates servant and registers in context of ORB @orb. The ORB will
 * delegate incoming requests to specific servant object.  @return
 * object reference. If error occures @ev points to exception object
 * on return.
 */
static CORBA_Object
server_activate_service (CORBA_ORB           orb,
			 PortableServer_POA  poa,
			 CORBA_Environment  *ev)
{
	Examples_BadCall ref = CORBA_OBJECT_NIL; 

	ref = impl_Examples_BadCall__create (poa, ev);
	if (etk_raised_exception(ev)) 
		return CORBA_OBJECT_NIL;
	
	return ref;
}

/* 
 * main 
 */

int
main (int argc, char *argv[])
{
	CORBA_Object servant = CORBA_OBJECT_NIL;
	
	CORBA_char filename[] = "badcall.ref";

	CORBA_Environment  ev[1];
	CORBA_exception_init(ev);
	
	server_init (&argc, argv, &global_orb, &root_poa, ev);
	etk_abort_if_exception(ev, "failed ORB init");

	servant = server_activate_service (global_orb, root_poa, ev);
	etk_abort_if_exception(ev, "failed activating service");

	g_print ("Writing service reference to: %s\n\n", filename);

	etk_export_object_to_file (global_orb, 
				   servant, 
				   filename, 
				   ev);
	etk_abort_if_exception(ev, "failed exporting IOR");
	
	server_run (global_orb, ev);
	etk_abort_if_exception(ev, "failed entering main loop");

	server_cleanup (global_orb, root_poa, servant, ev);
	etk_abort_if_exception(ev, "failed cleanup");

	exit (0);
}

Example 5-30. badcall-skelimpl.c

/* This is a template file generated by command */
/* orbit-idl-2 --skeleton-impl badcall.idl */
/* User must edit this file, inserting servant  */
/* specific code between markers. */

#include "badcall.h"

/*** App-specific servant structures ***/

typedef struct
{
   POA_Examples_BadCall servant;
   PortableServer_POA poa;

   /* ------ add private attributes here ------ */
   CORBA_long counter;
   /* ------ ---------- end ------------ ------ */
} impl_POA_Examples_BadCall;

/*** Implementation stub prototypes ***/

static void impl_Examples_BadCall__fini(impl_POA_Examples_BadCall *
					servant, CORBA_Environment * ev);

static Examples_BadCall_Foo
impl_Examples_BadCall_trigger(impl_POA_Examples_BadCall * servant,
			      const CORBA_long val,
			      Examples_BadCall_Foo * bar,
			      CORBA_Environment * ev);

/*** epv structures ***/

static PortableServer_ServantBase__epv impl_Examples_BadCall_base_epv = {
   NULL,			/* _private data */
   (gpointer) & impl_Examples_BadCall__fini,	/* finalize routine */
   NULL,			/* default_POA routine */
};
static POA_Examples_BadCall__epv impl_Examples_BadCall_epv = {
   NULL,			/* _private */

   (gpointer) & impl_Examples_BadCall_trigger,

};

/*** vepv structures ***/

static POA_Examples_BadCall__vepv impl_Examples_BadCall_vepv = {
   &impl_Examples_BadCall_base_epv,
   &impl_Examples_BadCall_epv,
};

/*** Stub implementations ***/

static Examples_BadCall
impl_Examples_BadCall__create(PortableServer_POA poa, CORBA_Environment * ev)
{
   Examples_BadCall retval;
   impl_POA_Examples_BadCall *newservant;
   PortableServer_ObjectId *objid;

   newservant = g_new0(impl_POA_Examples_BadCall, 1);
   newservant->servant.vepv = &impl_Examples_BadCall_vepv;
   newservant->poa =
      (PortableServer_POA) CORBA_Object_duplicate((CORBA_Object) poa, ev);
   POA_Examples_BadCall__init((PortableServer_Servant) newservant, ev);
   /* Before servant is going to be activated all
    * private attributes must be initialized.  */

   /* ------ init private attributes here ------ */ 
   newservant->counter=0;  /* init */
   /* ------ ---------- end ------------- ------ */

   objid = PortableServer_POA_activate_object(poa, newservant, ev);
   CORBA_free(objid);
   retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);

   return retval;
}

static void
impl_Examples_BadCall__fini (impl_POA_Examples_BadCall * servant,
			     CORBA_Environment * ev)
{
   CORBA_Object_release((CORBA_Object) servant->poa, ev);

   /* No further remote method calls are delegated to 
    * servant and you may free your private attributes. */
   /* ------ free private attributes here ------ */ 
   servant->counter=0;  /* reset */
   /* ------ ---------- end ------------- ------ */

   POA_Examples_BadCall__fini((PortableServer_Servant) servant, ev);
   
   g_free (servant);
}

static Examples_BadCall_Foo
impl_Examples_BadCall_trigger(impl_POA_Examples_BadCall * servant,
			      const CORBA_long val,
			      Examples_BadCall_Foo * bar,
			      CORBA_Environment * ev)
{
   Examples_BadCall_Foo ret_val = {0.0};


   /* ------   insert method code here   ------ */
   switch ((servant->counter++) % 2)
   {
   case 0:
   {
	   /* this piece of code demonstrates how to raise exception
	    * without any further parameter */

	   Examples_BadCall_Foo dummy_foo = {0.0};

	   /* after user has assinged exception attributes, user may
	    * not touch the data anymore, ownership is handed over to
	    * CORBA environment  */
           CORBA_exception_set (ev, 
				CORBA_USER_EXCEPTION,
                                ex_Examples_BadCall_NoParam,
                                NULL); /* exception has no members */
           
 	   /* on exception you need not to care about out-argument
	    * @bar, but due to programming language C it is necessary
	    * to return valid value */ 
           return dummy_foo;
           break;
   }
   case 1:
   {
	   /* this piece of code demonstrates how to raise exception
	    * that has a string as parameter */

	   Examples_BadCall_Foo dummy_foo = {0.0};

	   Examples_BadCall_SingleParam* ex_parameters
		   = Examples_BadCall_SingleParam__alloc();

	   ex_parameters->mesg 
		   = CORBA_string_dup ("raised in \"" __FILE__ "\"");

	   /* after user has assinged exception attributes, user may
	    * not touch the data anymore, ownership is handed over to
	    * CORBA environment  */
           CORBA_exception_set (ev, 
				CORBA_USER_EXCEPTION,
                                ex_Examples_BadCall_SingleParam,
                                ex_parameters); /* exception has members */
         
 	   /* on exception you need not to care about out-argument
	    * @bar, but due to programming language C it is necessary
	    * to return valid value */ 
           return dummy_foo;
           break;
   }
   /* this code will never raise exception DoubleParam */

   default:
           g_assert_not_reached ();
   }
   /* ------ ---------- end ------------ ------ */

   return ret_val;
}

5.7.3. Compiling client & server

Example 5-31. Makefile

PREFIX ?= /usr
CC = gcc
TARGETS=badcall-client badcall-server
ORBIT_IDL=$(PREFIX)/bin/orbit-idl-2
CFLAGS=-g -DORBIT2=1 -D_REENTRANT -I$(PREFIX)/include/orbit-2.0 \
         -I$(PREFIX)/include/linc-1.0 -I$(PREFIX)/include/glib-2.0 \
         -I$(PREFIX)/lib/glib-2.0/include 
LDFLAGS= -Wl,--export-dynamic  -L$(PREFIX)/lib -lORBit-2 -llinc -lgmodule-2.0 \
             -ldl -lgobject-2.0 -lgthread-2.0 -lpthread -lglib-2.0 -lm        \
             -lORBitCosNaming-2

IDLOUT=badcall-common.c badcall-stubs.c badcall-skels.c badcall.h

all: $(IDLOUT) badcall-client badcall-server

badcall-server.o: badcall-server.c badcall-skelimpl.c

badcall-client : badcall-client.o badcall-stubs.o badcall-common.o examples-toolkit.o
badcall-server : badcall-server.o badcall-skels.o badcall-common.o examples-toolkit.o

$(IDLOUT): badcall.idl
	$(ORBIT_IDL) badcall.idl

%-skelimpl.c: %.idl
	$(ORBIT_IDL) --skeleton-impl $^

clean:
	rm -rf *.o *~ $(IDLOUT) *.ior *.ref

distclean: clean
	rm -rf badcall-client badcall-server