/* * orbit-name-server : a CORBA CosNaming server * * Copyright (C) 1998 Sebastian Wilhelmi; University of Karlsruhe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "CosNaming.h" #include #include #include #include #include #define THROW(name,arg,ev) \ CORBA_exception_set( ev, CORBA_USER_EXCEPTION, ex_##name, arg ), \ syslog(LOG_ERR,"ERROR: %s thrown.\n", ex_##name ); #define RETHROW(ev, val ) if ((ev)->_major != CORBA_NO_EXCEPTION ) return val; #define RETHROW_VOID(ev) RETHROW(ev,) #define THROW_NotFound(reason, name, ev) \ G_STMT_START { \ CosNaming_NamingContext_NotFound* exception = \ CosNaming_NamingContext_NotFound__alloc (); \ exception->why = CosNaming_NamingContext_##reason; \ Name__copy ( &exception->rest_of_name, name, 0 ); \ THROW (CosNaming_NamingContext_NotFound, exception, ev); \ } G_STMT_END #define THROW_CannotProceed(context, name, ev ) \ G_STMT_START { \ CosNaming_NamingContext_CannotProceed* exception = \ CosNaming_NamingContext_CannotProceed__alloc (); \ exception->ctx = CORBA_Object_duplicate( context, ev ); \ Name__copy ( &exception->rest_of_name, name, 0 ); \ THROW (CosNaming_NamingContext_NotFound, exception, ev); \ } G_STMT_END #define THROW_InvalidName(ev) \ THROW(CosNaming_NamingContext_InvalidName, NULL, ev) #define THROW_AlreadyBound(ev) \ THROW(CosNaming_NamingContext_AlreadyBound, NULL, ev) #define THROW_NotEmpty(ev) \ THROW(CosNaming_NamingContext_NotEmpty, NULL, ev) typedef enum { result_ok, result_lower_level, result_exception, result_not_found } ActionReturnType; /* hash and comparision function for a NameComponent */ static guint CosNaming_NameComponent__hash(gconstpointer v) { CosNaming_NameComponent const* c = v; return g_str_hash( c->id ) ^ g_str_hash( c->kind ); } static gint CosNaming_NameComponent__equal(gconstpointer v1, gconstpointer v2) { CosNaming_NameComponent const* c1 = v1; CosNaming_NameComponent const* c2 = v2; return strcmp( c1->id , c2->id ) == 0 && strcmp( c1->kind , c2->kind ) == 0; } /* The following is mostly taken from CosNaming-impl.c as generated by "orbit-idl -Eskeleton_impl CosNaming.idl", only the stub implemementations have been removed and some lines have been added, those are marked with "added" */ /***************************************************************************/ /* begin of generated part */ /***************************************************************************/ /*** App-specific servant structures ***/ typedef struct { POA_CosNaming_NamingContext servant; PortableServer_POA poa; GHashTable *table; /* added */ } impl_POA_CosNaming_NamingContext; typedef struct { POA_CosNaming_BindingIterator servant; PortableServer_POA poa; GArray *array; /* added */ guint transmitted; /* added */ } impl_POA_CosNaming_BindingIterator; /*** Implementation stub prototypes ***/ static void impl_CosNaming_NamingContext__destroy (impl_POA_CosNaming_NamingContext * servant, CORBA_Environment * ev); void impl_CosNaming_NamingContext_bind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Object obj, CORBA_Environment * ev); void impl_CosNaming_NamingContext_rebind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Object obj, CORBA_Environment * ev); void impl_CosNaming_NamingContext_bind_context (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CosNaming_NamingContext nc, CORBA_Environment * ev); void impl_CosNaming_NamingContext_rebind_context (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CosNaming_NamingContext nc, CORBA_Environment * ev); CORBA_Object impl_CosNaming_NamingContext_resolve (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Environment * ev); void impl_CosNaming_NamingContext_unbind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Environment * ev); CosNaming_NamingContext impl_CosNaming_NamingContext_new_context (impl_POA_CosNaming_NamingContext * servant, CORBA_Environment * ev); CosNaming_NamingContext impl_CosNaming_NamingContext_bind_new_context (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Environment * ev); void impl_CosNaming_NamingContext_destroy (impl_POA_CosNaming_NamingContext * servant, CORBA_Environment * ev); void impl_CosNaming_NamingContext_list (impl_POA_CosNaming_NamingContext * servant, CORBA_unsigned_long how_many, CosNaming_BindingList ** bl, CosNaming_BindingIterator * bi, CORBA_Environment * ev); static void impl_CosNaming_BindingIterator__destroy (impl_POA_CosNaming_BindingIterator * servant, CORBA_Environment * ev); CORBA_boolean impl_CosNaming_BindingIterator_next_one (impl_POA_CosNaming_BindingIterator * servant, CosNaming_Binding ** b, CORBA_Environment * ev); CORBA_boolean impl_CosNaming_BindingIterator_next_n (impl_POA_CosNaming_BindingIterator * servant, CORBA_unsigned_long how_many, CosNaming_BindingList ** bl, CORBA_Environment * ev); void impl_CosNaming_BindingIterator_destroy (impl_POA_CosNaming_BindingIterator * servant, CORBA_Environment * ev); /*** epv structures ***/ static PortableServer_ServantBase__epv impl_CosNaming_NamingContext_base_epv = { NULL, /* _private data */ (gpointer) & impl_CosNaming_NamingContext__destroy, /* finalize routine */ NULL, /* default_POA routine */ }; static POA_CosNaming_NamingContext__epv impl_CosNaming_NamingContext_epv = { NULL, /* _private */ (gpointer) & impl_CosNaming_NamingContext_bind, (gpointer) & impl_CosNaming_NamingContext_rebind, (gpointer) & impl_CosNaming_NamingContext_bind_context, (gpointer) & impl_CosNaming_NamingContext_rebind_context, (gpointer) & impl_CosNaming_NamingContext_resolve, (gpointer) & impl_CosNaming_NamingContext_unbind, (gpointer) & impl_CosNaming_NamingContext_new_context, (gpointer) & impl_CosNaming_NamingContext_bind_new_context, (gpointer) & impl_CosNaming_NamingContext_destroy, (gpointer) & impl_CosNaming_NamingContext_list, }; static PortableServer_ServantBase__epv impl_CosNaming_BindingIterator_base_epv = { NULL, /* _private data */ (gpointer) & impl_CosNaming_BindingIterator__destroy, /* finalize routine */ NULL, /* default_POA routine */ }; static POA_CosNaming_BindingIterator__epv impl_CosNaming_BindingIterator_epv = { NULL, /* _private */ (gpointer) & impl_CosNaming_BindingIterator_next_one, (gpointer) & impl_CosNaming_BindingIterator_next_n, (gpointer) & impl_CosNaming_BindingIterator_destroy, }; /*** vepv structures ***/ static POA_CosNaming_NamingContext__vepv impl_CosNaming_NamingContext_vepv = { &impl_CosNaming_NamingContext_base_epv, &impl_CosNaming_NamingContext_epv, }; static POA_CosNaming_BindingIterator__vepv impl_CosNaming_BindingIterator_vepv = { &impl_CosNaming_BindingIterator_base_epv, &impl_CosNaming_BindingIterator_epv, }; /*** Stub implementations ***/ static CosNaming_NamingContext impl_CosNaming_NamingContext__create (PortableServer_POA poa, CORBA_Environment * ev) { CosNaming_NamingContext retval; impl_POA_CosNaming_NamingContext *newservant; PortableServer_ObjectId *objid; newservant = g_new0 (impl_POA_CosNaming_NamingContext, 1); newservant->servant.vepv = &impl_CosNaming_NamingContext_vepv; newservant->poa = poa; newservant->table = g_hash_table_new( CosNaming_NameComponent__hash, CosNaming_NameComponent__equal); /* added */ POA_CosNaming_NamingContext__init ((PortableServer_Servant) newservant, ev); objid = PortableServer_POA_activate_object (poa, newservant, ev); CORBA_free (objid); retval = PortableServer_POA_servant_to_reference (poa, newservant, ev); return retval; } /* You shouldn't call this routine directly without first deactivating the servant... */ static void impl_CosNaming_NamingContext__destroy (impl_POA_CosNaming_NamingContext * servant, CORBA_Environment * ev) { POA_CosNaming_NamingContext__fini ((PortableServer_Servant) servant, ev); g_free (servant); } static CosNaming_BindingIterator impl_CosNaming_BindingIterator__create (PortableServer_POA poa, impl_POA_CosNaming_BindingIterator** servant, /* added */ CORBA_Environment * ev) { CosNaming_BindingIterator retval; impl_POA_CosNaming_BindingIterator *newservant; PortableServer_ObjectId *objid; newservant = g_new0 (impl_POA_CosNaming_BindingIterator, 1); newservant->servant.vepv = &impl_CosNaming_BindingIterator_vepv; newservant->poa = poa; *servant = newservant; /* added */ POA_CosNaming_BindingIterator__init ((PortableServer_Servant) newservant, ev); objid = PortableServer_POA_activate_object (poa, newservant, ev); CORBA_free (objid); retval = PortableServer_POA_servant_to_reference (poa, newservant, ev); return retval; } /* You shouldn't call this routine directly without first deactivating the servant... */ static void impl_CosNaming_BindingIterator__destroy (impl_POA_CosNaming_BindingIterator * servant, CORBA_Environment * ev) { POA_CosNaming_BindingIterator__fini ((PortableServer_Servant) servant, ev); g_free (servant); } /***************************************************************************/ /* end of generated part */ /***************************************************************************/ static void NameComponent__copy (CosNaming_NameComponent * dest, CosNaming_NameComponent * src) { dest->id = CORBA_string_alloc (strlen (src->id)); dest->kind = CORBA_string_alloc (strlen (src->kind)); strcpy (dest->id, src->id); strcpy (dest->kind, src->kind); } static void Name__copy ( CosNaming_Name* dest, CosNaming_Name* src, int from_pos ) { int i; g_assert( src->_length > from_pos ); dest->_length = src->_length - from_pos; dest->_buffer = CORBA_sequence_CosNaming_NameComponent_allocbuf (dest->_length); for (i = 0; i < dest->_length; i++) { NameComponent__copy (dest->_buffer + i, src->_buffer + i + from_pos); } } static gchar* NamingName2String(CosNaming_Name* name) { static GString *bfr = NULL; gint idx; if(bfr) g_string_assign(bfr, ""); else bfr = g_string_new(""); for (idx = 0; idx < name->_length; idx++) { g_string_sprintfa(bfr, "/%s.%s", name->_buffer[idx].id, name->_buffer[idx].kind); } return bfr->str; } typedef struct _TableEntry TableEntry; struct _TableEntry { CosNaming_NameComponent name; CosNaming_BindingType type; CORBA_Object object; }; static gint server_is_alive(CORBA_Object server) { GIOPConnection* cnx = _ORBit_object_get_connection(server); syslog(LOG_DEBUG, "server_is_alive: cnx = %p\n", cnx); if (server->connection) { giop_connection_unref(server->connection); server->connection=NULL; server->active_profile = NULL; /* mila: perhaps this is wrong: no connection means no profile */ } return cnx != 0; } static ActionReturnType lookup_name (GHashTable* table, CosNaming_Name * n, TableEntry **found, CORBA_Environment * ev) { if (n->_length == 0) /* no name given. */ { THROW_InvalidName (ev); return result_exception; } syslog(LOG_DEBUG, "lookup for = '%s'", NamingName2String(n)); *found = g_hash_table_lookup( table, n->_buffer ); if (*found) { if (n->_length > 1) /* in a lower-level context */ { syslog(LOG_DEBUG,"lookup_name: Returning result_lower_level\n"); return result_lower_level; /* in current context */ } syslog(LOG_DEBUG,"lookup_name: Returning result_ok\n"); return result_ok; } else { if (n->_length > 1) /* result should be a context, but is not found */ { THROW_NotFound (missing_node, n, ev); return result_exception; } } syslog(LOG_DEBUG,"lookup_name: result_not_found\n"); return result_not_found; } static void insert_name (GHashTable* table, CosNaming_NameComponent * name, CosNaming_BindingType type, CORBA_Object obj, CORBA_Environment * ev) { TableEntry *insert = g_new (TableEntry, 1); syslog(LOG_DEBUG,"Inserting name = '%s.%s'\n", name->id, name->kind); NameComponent__copy( &insert->name, name ); insert->type = type; insert->object = CORBA_Object_duplicate (obj, ev); g_hash_table_insert( table, &insert->name, insert ); } static void remove_name (GHashTable* table, CosNaming_NameComponent * name, CORBA_Environment * ev) { TableEntry *found = g_hash_table_lookup(table, name); g_assert( found ); syslog(LOG_DEBUG,"Removing name = '%s.%s'\n", found->name.id, found->name.kind); g_hash_table_remove( table, name ); CORBA_free (found->name.id); CORBA_free (found->name.kind); CORBA_Object_release (found->object, ev); g_free (found); } static CORBA_Object prepare_resending (TableEntry *entry, CosNaming_Name * old, CosNaming_Name ** new_name) { if( entry->type != CosNaming_ncontext ) { return NULL; } *new_name = CosNaming_Name__alloc (); Name__copy ( *new_name, old, 1 ); /* FIXME: narrowing to CosNaming_NamingContext */ return entry->object; } static void do_re_bind_no_context (GHashTable *table, CosNaming_Name * n, CORBA_Object obj, gboolean is_rebind, gboolean is_context, CORBA_Environment * ev) { TableEntry* entry; ActionReturnType res = lookup_name (table, n, &entry, ev); if (res == result_exception) return; if (res == result_lower_level) { CosNaming_Name *new_name; CORBA_Object context = prepare_resending (entry, n, &new_name); if( !context ) { THROW_NotFound (not_context, n, ev); return; } if (is_rebind) { if (is_context) { CosNaming_NamingContext_rebind_context (context, new_name, obj, ev); } else { CosNaming_NamingContext_rebind (context, new_name, obj, ev); } } else { if (is_context) { CosNaming_NamingContext_bind_context (context, new_name, obj, ev); } else { CosNaming_NamingContext_bind (context, new_name, obj, ev); } } CORBA_free (new_name); return; } if (res == result_not_found && is_rebind) { THROW_NotFound (missing_node, n, ev); return; } if (res == result_ok && !is_rebind) { THROW_AlreadyBound (ev); return; } if (is_rebind) { remove_name (table, &entry->name, ev); } insert_name (table, n->_buffer, is_context ? CosNaming_ncontext : CosNaming_nobject, obj, ev); } void impl_CosNaming_NamingContext_bind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Object obj, CORBA_Environment * ev) { do_re_bind_no_context (servant->table, n, obj, FALSE, FALSE, ev); } void impl_CosNaming_NamingContext_rebind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Object obj, CORBA_Environment * ev) { do_re_bind_no_context (servant->table, n, obj, TRUE, FALSE, ev); } void impl_CosNaming_NamingContext_bind_context (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CosNaming_NamingContext nc, CORBA_Environment * ev) { do_re_bind_no_context (servant->table, n, nc, FALSE, TRUE, ev); } void impl_CosNaming_NamingContext_rebind_context (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CosNaming_NamingContext nc, CORBA_Environment * ev) { do_re_bind_no_context (servant->table, n, nc, TRUE, TRUE, ev); } CORBA_Object impl_CosNaming_NamingContext_resolve (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Environment * ev) { TableEntry *found; ActionReturnType res = lookup_name (servant->table, n, &found, ev); syslog(LOG_DEBUG, "NameContext_resolving '%s', res = %d\n", NamingName2String(n), res); if (res == result_exception) { return CORBA_OBJECT_NIL; } if (res == result_lower_level) { CosNaming_Name *new_name; CORBA_Object result; CORBA_Object context = prepare_resending (found, n, &new_name); if( !context ) { THROW_NotFound (not_context, n, ev); return CORBA_OBJECT_NIL; } result = CosNaming_NamingContext_resolve (context, new_name, ev); CORBA_free (new_name); return result; } if (res == result_not_found) { THROW_NotFound (missing_node, n, ev); return CORBA_OBJECT_NIL; } if (found->type == CosNaming_ncontext || server_is_alive(found->object)) { return CORBA_Object_duplicate (found->object, ev); } syslog(LOG_DEBUG, "Removing dead server '%s' from name service\n", NamingName2String(n)); remove_name (servant->table, &found->name, ev); THROW_NotFound (missing_node, n, ev); return CORBA_OBJECT_NIL; } void impl_CosNaming_NamingContext_unbind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Environment * ev) { TableEntry *found; ActionReturnType res = lookup_name (servant->table, n, &found, ev); if (res == result_exception) { return; } if (res == result_lower_level) { CosNaming_Name *new_name; CORBA_Object context = prepare_resending (found, n, &new_name); if( !context ) { THROW_NotFound (not_context, n, ev); return; } CosNaming_NamingContext_unbind (context, new_name, ev); CORBA_free (new_name); return; } if (res == result_not_found) { THROW_NotFound (missing_node, n, ev); return; } remove_name (servant->table, &found->name, ev); } CORBA_Object impl_CosNaming_NamingContext_new_context (impl_POA_CosNaming_NamingContext * servant, CORBA_Environment * ev) { return impl_CosNaming_NamingContext__create (servant->poa, ev); } CORBA_Object impl_CosNaming_NamingContext_bind_new_context (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Environment * ev) { CosNaming_NamingContext context = impl_CosNaming_NamingContext__create (servant->poa, ev); RETHROW (ev, NULL); do_re_bind_no_context (servant->table, n, context, FALSE, TRUE, ev); if ((ev)->_major != CORBA_NO_EXCEPTION ) { impl_CosNaming_NamingContext_unbind ( servant, n, ev); CosNaming_NamingContext_destroy( context, ev ); } return context; } void impl_CosNaming_NamingContext_destroy (impl_POA_CosNaming_NamingContext * servant, CORBA_Environment * ev) { if (g_hash_table_size( servant->table ) > 0) { THROW_NotEmpty (ev); return; } g_hash_table_destroy(servant->table); impl_CosNaming_NamingContext__destroy( servant, ev ); return; } void TableEntry_to_Binding(gpointer key /* not needed */, gpointer value, gpointer user_data) { CosNaming_Binding** curr_pointer = user_data; TableEntry* entry = value; (**curr_pointer).binding_name._length = 1; (**curr_pointer).binding_name._buffer = CORBA_sequence_CosNaming_NameComponent_allocbuf (1); NameComponent__copy( (**curr_pointer).binding_name._buffer, &entry->name); (**curr_pointer).binding_type = entry->type; (*curr_pointer)++; } GArray* HashTable_to_Array( GHashTable* table ) { int len = g_hash_table_size( table ); void *curr_pointer; GArray* result = g_array_new( FALSE, FALSE, sizeof(CosNaming_Binding) ); g_array_set_size( result, len ); curr_pointer = result->data; g_hash_table_foreach( table, TableEntry_to_Binding, &curr_pointer); g_assert( curr_pointer == result->data + len * sizeof(CosNaming_Binding) ); return result; } CosNaming_BindingList * Array_to_BindingList( GArray* array, guint begin_pos, guint len ) { CosNaming_BindingList *result = CosNaming_BindingList__alloc (); g_assert( begin_pos + len <= array->len ); result->_length = len; result->_buffer = CORBA_sequence_CosNaming_Binding_allocbuf (len); memcpy(result->_buffer, array->data + sizeof(CosNaming_Binding) * begin_pos, sizeof(CosNaming_Binding) * len ); return result; } void impl_CosNaming_NamingContext_list (impl_POA_CosNaming_NamingContext * servant, CORBA_unsigned_long how_many, CosNaming_BindingList ** bl, CosNaming_BindingIterator * bi, CORBA_Environment * ev) { GArray* array = HashTable_to_Array( servant->table ); if( array->len <= how_many ) { *bi = CORBA_OBJECT_NIL; how_many = array->len; } else { impl_POA_CosNaming_BindingIterator * iterator_servant; *bi = impl_CosNaming_BindingIterator__create (servant->poa, &iterator_servant, ev); RETHROW_VOID(ev); iterator_servant->array = array; iterator_servant->transmitted = how_many; } *bl = Array_to_BindingList( array, 0, how_many ); } CORBA_boolean impl_CosNaming_BindingIterator_next_one (impl_POA_CosNaming_BindingIterator * servant, CosNaming_Binding ** b, CORBA_Environment * ev) { if(servant->transmitted < servant->array->len) { *b = CosNaming_Binding__alloc(); memcpy( *b, servant->array->data + sizeof( CosNaming_Binding ) * servant->transmitted , sizeof( CosNaming_Binding ) ); servant->transmitted++; return CORBA_TRUE; } return CORBA_FALSE; } CORBA_boolean impl_CosNaming_BindingIterator_next_n (impl_POA_CosNaming_BindingIterator * servant, CORBA_unsigned_long how_many, CosNaming_BindingList ** bl, CORBA_Environment * ev) { int len = MIN( how_many, servant->array->len - servant->transmitted); *bl = Array_to_BindingList( servant->array, servant->transmitted, len ); servant->transmitted += len; return servant->array->len - servant->transmitted > 0 ? CORBA_TRUE : CORBA_FALSE; } void impl_CosNaming_BindingIterator_destroy (impl_POA_CosNaming_BindingIterator * servant, CORBA_Environment * ev) { g_array_free (servant->array, TRUE); impl_CosNaming_BindingIterator__destroy( servant, ev ); return; } void signal_handler(int signo) { syslog(LOG_ERR,"Receveived signal %d\nshutting down.", signo); switch(signo) { case SIGSEGV: abort(); default: exit(1); } } int main (int argc, char *argv[]) { CORBA_ORB orb; CORBA_Environment ev; CosNaming_NamingContext context; CORBA_char *objref; PortableServer_POA root_poa; PortableServer_POAManager pm; struct sigaction act; sigset_t empty_mask; openlog("orbit-name-server", LOG_NDELAY | LOG_PID, LOG_DAEMON); syslog(LOG_INFO,"starting"); sigemptyset(&empty_mask); act.sa_handler = signal_handler; act.sa_mask = empty_mask; act.sa_flags = 0; sigaction(SIGINT, &act, 0); sigaction(SIGHUP, &act, 0); sigaction(SIGSEGV, &act, 0); sigaction(SIGABRT, &act, 0); act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, 0); CORBA_exception_init (&ev); orb = CORBA_ORB_init (&argc, argv, "orbit-local-orb", &ev); root_poa = (PortableServer_POA) CORBA_ORB_resolve_initial_references (orb, "RootPOA", &ev); context = impl_CosNaming_NamingContext__create(root_poa, &ev); objref = CORBA_ORB_object_to_string (orb, context, &ev); g_print ("%s\n", objref); fflush (stdout); CORBA_free (objref); #if 0 /* Don't release it so that the same-address-space info will stay around */ CORBA_Object_release (context, &ev); #endif pm = PortableServer_POA__get_the_POAManager (root_poa, &ev); PortableServer_POAManager_activate (pm, &ev); CORBA_ORB_run (orb, &ev); syslog(LOG_INFO, "exiting"); return 0; }