5.8. NameResolve client & server

Example 5-32. name-resolve.idl

module Examples {
	module NameResolve {
		interface Service {
			void echoString (in string input);
		};
	};
};
$ orbit-idl-2 --skeleton-impl name-resolve.idl geenrates all the files we will use in this example.

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

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

name-resolve-client.cwrite the client code
name-resolve-server.cwrite the generic code for servant creation

5.8.1. Example-Toolkit Helpers

Example 5-33. example-toolkit.c(etk_get_name_service)


 
/** resolves default name-service, usually given to application as
 * command line argument "-ORBInitRef NameService=IOR:0100000028..",
 * or since release 2.8.0 corbalocs in form of URL can be used, eg:
 * "-ORBInitRef NameService=corbaloc:iiop:HOSTNAME:PORT/NameService%00"
 */
CosNaming_NamingContext 
etk_get_name_service (CORBA_ORB         orb,
		      CORBA_Environment *ev)
{
        CORBA_char   *str=NULL;
        CORBA_Object  ref
                = (CORBA_Object) CORBA_ORB_resolve_initial_references(orb,
								      "NameService",
                                                                      ev);
        if (etk_raised_exception(ev)) return CORBA_OBJECT_NIL;
	
        return (CosNaming_NamingContext) ref;
}

Example 5-34. example-toolkit.c(etk_name_service_bind)


/** calculate length of NULL terminated string vector */
static
guint 
id_vec_len (char *id_vec[]) 
{ 
	gint i=0; 
	for (i = 0; id_vec[i]; ++i); 
	return i;
} 

/* binds @servant object reference to unique @name at
 * @name_service. @name is a NULL terminated list of strings
 * (CORBA_char*). If error occures @ev points to exception object on
 * return.
 */
void 
etk_name_service_bind (CosNaming_NamingContext  name_service,
		       CORBA_Object             servant,
		       gchar                   *id_vec[], 
		       CORBA_Environment       *ev)
{
	gint i = 0;
	gint len = id_vec_len (id_vec);

	/* Allocate a CosNaming::Name (sequence of CosNaming::NameComponent) */
	CosNaming_Name *name = CosNaming_Name__alloc();

	name->_buffer = CORBA_sequence_CosNaming_NameComponent_allocbuf(len);
	name->_maximum = len;
	name->_length  = 0;
	
	/* Relinquish ownership of the NameComponent to the
         * sequence. When CORBA_free is called on it later, the
         * NameComponent will be freed */	
	CORBA_sequence_set_release (name, TRUE);

	/* iterate components of name and create sub-context
	 * (directory) if needed */ 
	for (i = 0; i < len; ++i) {
		name->_length = i+1;
		name->_buffer[i].id   = CORBA_string_dup(id_vec[i]);
		name->_buffer[i].kind = CORBA_string_dup(""); 
		/* don't know what 'kind' shall be good for */ 

		if (name->_length < len) 
		{
			/* create a sub-context */ 
			CosNaming_NamingContext nc = 
				CosNaming_NamingContext_bind_new_context (name_service, 
									  name, 
									  ev);	
			if (etk_raised_exception_is_a (ev, 
						       ex_CosNaming_NamingContext_AlreadyBound))
			{
				/* ignore - ctx allread exists, this
				 * is not dramatic */
				CORBA_exception_free (ev);
			}
			else if (etk_raised_exception (ev)) 
			{
				/* critical - unexpected exception  */ 
				CORBA_free (name); 
				return;
			}
		}
		else
		{
			/* Bind object to last context - use 'rebind'
			 * operation in case the name has been
			 * registered allready in context - note, this
			 * might interfere with other service choosing
			 * same name */ 
			CosNaming_NamingContext_rebind (name_service, 
							name, 
							servant,
							ev);
			if (etk_raised_exception(ev)) {
				/* critical - can not bind object */ 
				CORBA_free (name);
				return;
			}
		}
	}

	CORBA_free (name);
	return;
}

Example 5-35. example-toolkit.c(etk_name_service_resolve)


/* resolves object reference @return with unique @name at
 *  @name_service. @name is a NULL terminated list of strings
 *  (CORBA_char*).  If error occures @ev points to * exception object
 *  on return.
 */
CORBA_Object 
etk_name_service_resolve (CosNaming_NamingContext  name_service,
			  gchar                   *id_vec[], 
			  CORBA_Environment       *ev)
{
	CORBA_Object retval = CORBA_OBJECT_NIL;
	gint i = 0;
	gint len = id_vec_len (id_vec);

	/* Allocate a CosNaming::Name (sequence of CosNaming::NameComponent) */
	CosNaming_Name *name = CosNaming_Name__alloc();

	g_assert (id_vec_len (id_vec) > 0);

	name->_buffer = CORBA_sequence_CosNaming_NameComponent_allocbuf(len);
	name->_maximum = len;
	name->_length  = 0;
	
	/* Relinquish ownership of the NameComponent to the
         * sequence. When CORBA_free is called on it later, the
         * NameComponent will be freed */	
	CORBA_sequence_set_release (name, TRUE);

	/* iterate components of name and create sub-context
	 * (directory) if needed */ 
	for (i = 0; i < len; ++i) {
		name->_length = i+1;
		name->_buffer[i].id   = CORBA_string_dup(id_vec[i]);
		name->_buffer[i].kind = CORBA_string_dup(""); 
		/* don't know what 'kind' shall be good for */ 
	}
	
	retval = CosNaming_NamingContext_resolve (name_service, 
						  name, 
						  ev);
	
	if (etk_raised_exception (ev)) { 
		CORBA_free (name);
		return CORBA_OBJECT_NIL;
	}
	
	return retval;
}

5.8.2. NameResolve client

Example 5-36. name-resolve-client.c

/*
 * Name-Resolve client program.. Hacked by  Frank Rehberger
 * <F.Rehberger@xtradyne.de>
 *
 * Client connects to name-service and resolves object reference from server and
 * forwards console input to name-resolve-server. A dot . as single character
 * in input terminates the client.
 */

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

/*
 * This header file was generated from the idl
 */

#include "name-resolve.h"
#include "examples-toolkit.h" /* provides 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              service,
                CORBA_Environment        *ev)
{
        /* releasing managed object */
        CORBA_Object_release(service, 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_run (Examples_NameResolve_Service  service,
	    CORBA_Environment            *ev)
{
	char filebuffer[1024+1];

	g_print("Type any text to console to be sent to server,\n"
		"a single dot in line will terminate input\n");
	
	while( fgets(filebuffer,1024,stdin) ) {
		if( filebuffer[0] == '.' && filebuffer[1] == '\n' ) 
			break;
		
		/* chop the newline off */
		filebuffer[strlen(filebuffer)-1] = '\0';
      
		/* using the echoString method in the Echo object 
		 * this is defined in the echo.h header, compiled from
		 * echo.idl */

		Examples_NameResolve_Service_echoString (service,
							 filebuffer,
							 ev);
		if (etk_raised_exception (ev)) return;
	}
}

/*
 * main 
 */
int
main(int argc, char* argv[])
{
	Examples_NameResolve_Service service = CORBA_OBJECT_NIL;
	CosNaming_NamingContext name_service = CORBA_OBJECT_NIL;

	gchar *id[] = {"Examples", "NameResolve", "Service", NULL};

        CORBA_Environment ev[1];
        CORBA_exception_init(ev);

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

	g_print ("Resolving service reference from name-service with id \"%s/%s/%s\"\n", id[0], id[1], id[2]);

	name_service = etk_get_name_service (global_orb, ev);
	etk_abort_if_exception(ev, "failed resolving name-service");

	service 
	  = (Examples_NameResolve_Service) 
		etk_name_service_resolve (name_service, id, ev);
	etk_abort_if_exception(ev, "failed resolving service at name-service");

	client_run (service, ev);
        etk_abort_if_exception(ev, "service not reachable");
 
	client_cleanup (global_orb, service, ev);
        etk_abort_if_exception(ev, "cleanup failed");
 
        exit (0);
}

5.8.3. NameResolve server

Example 5-37. name-resolve-server.c

/*
 * echo-server program. Hacked from Echo test suite by
 * <birney@sanger.ac.uk>, ORBit2 udpate by Frank Rehberger
 * <F.Rehberger@xtradyne.de>
 */

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

#include "name-resolve-skelimpl.c"
#include "examples-toolkit.h" /* provides 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_NameResolve_Service ref = CORBA_OBJECT_NIL; 

	ref = impl_Examples_NameResolve_Service__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;
	CosNaming_NamingContext name_service = CORBA_OBJECT_NIL;

	gchar *id[] = {"Examples", "NameResolve", "Service", NULL};

	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 ("Binding service reference at name service against id: %s/%s/%s\n\n", id[0], id[1], id[2]);
	
	name_service = etk_get_name_service (global_orb, ev);
	etk_abort_if_exception(ev, "failed resolving name-service");

	etk_name_service_bind (name_service, servant, id, ev);
	etk_abort_if_exception(ev, "failed binding of service");

	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-38. name-resolve-skelimpl.c

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

#include "name-resolve.h"

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

typedef struct
{
   POA_Examples_NameResolve_Service servant;
   PortableServer_POA poa;

   /* ------ add private attributes here ------ */
   /* ------ ---------- end ------------ ------ */
} impl_POA_Examples_NameResolve_Service;

/*** Implementation stub prototypes ***/

static void
impl_Examples_NameResolve_Service__fini(impl_POA_Examples_NameResolve_Service
					* servant, CORBA_Environment * ev);
static void
impl_Examples_NameResolve_Service_echoString
(impl_POA_Examples_NameResolve_Service * servant, const CORBA_char * input,
CORBA_Environment * ev);

/*** epv structures ***/

static PortableServer_ServantBase__epv
   impl_Examples_NameResolve_Service_base_epv = {
   NULL,			/* _private data */
   (gpointer) & impl_Examples_NameResolve_Service__fini,	/* finalize routine */
   NULL,			/* default_POA routine */
};
static POA_Examples_NameResolve_Service__epv
   impl_Examples_NameResolve_Service_epv = {
   NULL,			/* _private */
   (gpointer) & impl_Examples_NameResolve_Service_echoString,

};

/*** vepv structures ***/

static POA_Examples_NameResolve_Service__vepv
   impl_Examples_NameResolve_Service_vepv = {
   &impl_Examples_NameResolve_Service_base_epv,
   &impl_Examples_NameResolve_Service_epv,
};

/*** Stub implementations ***/

static Examples_NameResolve_Service
impl_Examples_NameResolve_Service__create(PortableServer_POA poa,
					  CORBA_Environment * ev)
{
   Examples_NameResolve_Service retval;
   impl_POA_Examples_NameResolve_Service *newservant;
   PortableServer_ObjectId *objid;

   newservant = g_new0(impl_POA_Examples_NameResolve_Service, 1);
   newservant->servant.vepv = &impl_Examples_NameResolve_Service_vepv;
   newservant->poa =
      (PortableServer_POA) CORBA_Object_duplicate((CORBA_Object) poa, ev);

   POA_Examples_NameResolve_Service__init((PortableServer_Servant) newservant,
					  ev);
   /* Before servant is going to be activated all
    * private attributes must be initialized.  */

   /* ------ init private attributes here ------ */
   /* ------ ---------- end ------------- ------ */

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

   return retval;
}

/**
 * impl_Examples_NameResolve_Service__fini
 * 
 * Destructor called after servant has been deactivated finally.
 * In case any active operation invocation, method call is being delayed.
 * Note, in former versions of ORBit2 this function would have been
 * named impl_Examples_NameResolve_Service__destroy.
**/
static void
impl_Examples_NameResolve_Service__fini(impl_POA_Examples_NameResolve_Service
					* 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 ------ */
   /* ------ ---------- end ------------- ------ */

   POA_Examples_NameResolve_Service__fini((PortableServer_Servant) servant,
					  ev);

   g_free(servant);
}

static void
impl_Examples_NameResolve_Service_echoString
   (impl_POA_Examples_NameResolve_Service * servant, const CORBA_char * input,
    CORBA_Environment * ev)
{
   /* ------   insert method code here   ------ */
   g_print (">> %s\n", input);
   /* ------ ---------- end ------------ ------ */
}

5.8.4. Compiling client & server

Example 5-39. Makefile

PREFIX ?= /usr
CC = gcc
TARGETS=name-resolve-client name-resolve-server
ORBIT_IDL=$(PREFIX)/bin/orbit-idl-2
CFLAGS=-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 -g
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=name-resolve-common.c name-resolve-stubs.c name-resolve-skels.c name-resolve.h

all: $(IDLOUT) name-resolve-client name-resolve-server

name-resolve-server.o: name-resolve-server.c name-resolve-skelimpl.c

name-resolve-client : name-resolve-client.o name-resolve-stubs.o name-resolve-common.o examples-toolkit.o
name-resolve-server : name-resolve-server.o name-resolve-skels.o name-resolve-common.o examples-toolkit.o name-resolve-skelimpl.o

$(IDLOUT): name-resolve.idl
	$(ORBIT_IDL) name-resolve.idl

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

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

distclean: clean
	rm -rf name-resolve-client name-resolve-server