/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * ORBit: A CORBA v2.2 ORB * * Copyright (C) 1998 Richard H. Porter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Dick Porter * */ /* * CORBA_Environment handling functions */ #include #include #include #include #include "orbit.h" #include "interface_repository.h" struct SysExInfo { const char *repo_id; const int exnum; }; static const struct SysExInfo exception_table[] = { {NULL, 0}, {"IDL:CORBA/UNKNOWN:1.0", 1}, {"IDL:CORBA/BAD_PARAM:1.0", 2}, {"IDL:CORBA/NO_MEMORY:1.0", 3}, {"IDL:CORBA/IMP_LIMIT:1.0", 4}, {"IDL:CORBA/COMM_FAILURE:1.0", 5}, {"IDL:CORBA/INV_OBJREF:1.0", 6}, {"IDL:CORBA/NO_PERMISSION:1.0", 7}, {"IDL:CORBA/INTERNAL:1.0", 8}, {"IDL:CORBA/MARSHAL:1.0", 9}, {"IDL:CORBA/INITIALIZE:1.0", 10}, {"IDL:CORBA/NO_IMPLEMENT:1.0", 11}, {"IDL:CORBA/BAD_TYPECODE:1.0", 12}, {"IDL:CORBA/BAD_OPERATION:1.0", 13}, {"IDL:CORBA/NO_RESOURCES:1.0", 14}, {"IDL:CORBA/NO_RESPONSE:1.0", 15}, {"IDL:CORBA/PERSIST_STORE:1.0", 16}, {"IDL:CORBA/BAD_INV_ORDER:1.0", 17}, {"IDL:CORBA/TRANSIENT:1.0", 18}, {"IDL:CORBA/FREE_MEM:1.0", 19}, {"IDL:CORBA/INV_IDENT:1.0", 20}, {"IDL:CORBA/INV_FLAG:1.0", 21}, {"IDL:CORBA/INTF_REPOS:1.0", 22}, {"IDL:CORBA/BAD_CONTEXT:1.0", 23}, {"IDL:CORBA/OBJ_ADAPTER:1.0", 24}, {"IDL:CORBA/DATA_CONVERSION:1.0", 25}, {"IDL:CORBA/OBJECT_NOT_EXIST:1.0", 26}, {"IDL:CORBA/TRANSACTION_REQUIRED:1.0", 27}, {"IDL:CORBA/TRANSACTION_ROLLEDBACK:1.0", 28}, {"IDL:CORBA/INVALID_TRANSACTION:1.0", 29}, {NULL,0} }; void CORBA_exception_free(CORBA_Environment *ev) { g_assert(ev!=NULL); ev->_major=CORBA_NO_EXCEPTION; if(ev->_repo_id) { CORBA_free(ev->_repo_id); ev->_repo_id=NULL; } if(ev->_params) { CORBA_free(ev->_params); ev->_params=NULL; } if(ev->_any) { CORBA_free(ev->_any); ev->_any=NULL; } } void CORBA_exception_set(CORBA_Environment *ev, CORBA_exception_type major, CORBA_char *except_repos_id, void *param) { g_assert(ev!=NULL); if(ev->_major != CORBA_NO_EXCEPTION) CORBA_exception_free(ev); ev->_major=major; if(except_repos_id==NULL) { ev->_repo_id=NULL; } else { ev->_repo_id=CORBA_string_dup(except_repos_id); } ev->_params=param; } void CORBA_exception_set_system(CORBA_Environment *ev, CORBA_unsigned_long minor, CORBA_completion_status completed) { CORBA_SystemException *new; new=ORBit_alloc(sizeof(CORBA_SystemException), NULL, NULL); if(new!=NULL) { new->minor=minor; new->completed=completed; /* XXX what should the repo ID be? */ CORBA_exception_set(ev, CORBA_SYSTEM_EXCEPTION, (gchar *)exception_table[minor].repo_id, new); } } void CORBA_exception_init(CORBA_Environment *ev) { g_assert(ev!=NULL); ev->_major=CORBA_NO_EXCEPTION; ev->_repo_id=NULL; ev->_params=NULL; ev->_any=NULL; } CORBA_char *CORBA_exception_id(CORBA_Environment *ev) { g_assert(ev!=NULL); if(ev->_major==CORBA_NO_EXCEPTION) { return(NULL); } else { return(ev->_repo_id); } } void *CORBA_exception_value(CORBA_Environment *ev) { g_assert(ev!=NULL); if(ev->_major==CORBA_NO_EXCEPTION) { return(NULL); } else { return(ev->_params); } } CORBA_any *CORBA_exception_as_any(CORBA_Environment *ev) { g_assert(ev!=NULL); if(ev->_major==CORBA_NO_EXCEPTION) { return(NULL); } if(ev->_any!=NULL) { return(ev->_any); } ev->_any=g_new(CORBA_any, 1); if(ev->_any!=NULL) { ev->_any->_type = TC_CORBA_ExceptionDescription; ev->_any->_value = ev->_params; ev->_any->_release = 0; } return(ev->_any); } /**** ORBit_handle_exception Inputs: 'rb' - a receive buffer for which an exception condition has been determined 'ev' - memory in which to store the exception information 'user_exceptions' - list of user exceptions raisable for this particular operation. Side-effects: reinitializes '*ev' Description: During demarshalling a reply, if reply_status != CORBA_NO_EXCEPTION, we must find out what exception was raised and place that information in '*ev'. */ void ORBit_handle_exception(GIOPRecvBuffer *rb, CORBA_Environment *ev, const ORBit_exception_demarshal_info *user_exceptions, CORBA_ORB orb) { CORBA_SystemException *new; CORBA_unsigned_long len, minor, completion_status; CORBA_char *my_repoid; g_return_if_fail(GIOP_MESSAGE_BUFFER(rb)->message_header.message_type == GIOP_REPLY); CORBA_exception_free(ev); rb->cur = ALIGN_ADDRESS(rb->cur, sizeof(len)); rb->decoder(&len, rb->cur, sizeof(len)); (guchar *)rb->cur += sizeof(len); if(len) { my_repoid = rb->cur; (guchar *)rb->cur += len; } else my_repoid = NULL; if(rb->message.u.reply.reply_status == CORBA_SYSTEM_EXCEPTION) { ev->_major = CORBA_SYSTEM_EXCEPTION; rb->cur = ALIGN_ADDRESS(rb->cur, sizeof(minor)); rb->decoder(&minor, rb->cur, sizeof(len)); (guchar *)rb->cur += sizeof(len); for(minor = 1; exception_table[minor].repo_id; minor++) { if(!strcmp(exception_table[minor].repo_id, my_repoid)) break; } rb->cur = ALIGN_ADDRESS(rb->cur, sizeof(completion_status)); rb->decoder(&completion_status, rb->cur, sizeof(completion_status)); (guchar *)rb->cur += sizeof(completion_status); new=ORBit_alloc(sizeof(CORBA_SystemException), NULL, NULL); if(new!=NULL) { new->minor=minor; new->completed=completion_status; /* XXX what should the repo ID be? */ CORBA_exception_set(ev, CORBA_SYSTEM_EXCEPTION, (gchar *)exception_table[new->minor].repo_id, new); } } else if(rb->message.u.reply.reply_status == CORBA_USER_EXCEPTION) { int i; if(!user_exceptions) { /* weirdness; they raised an exception that we don't know about */ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL, CORBA_COMPLETED_MAYBE); } else { for(i = 0; user_exceptions[i].tc != CORBA_OBJECT_NIL; i++) { if(!strcmp(user_exceptions[i].tc->repo_id, my_repoid)) break; } if(user_exceptions[i].tc == CORBA_OBJECT_NIL) { /* weirdness; they raised an exception that we don't know about */ CORBA_exception_set_system(ev, ex_CORBA_MARSHAL, CORBA_COMPLETED_MAYBE); } else { user_exceptions[i].demarshal(rb, ev); } } }; /* ignore LOCATION_FORWARD here, that gets handled in the stub */ } void ORBit_send_system_exception(GIOPSendBuffer *send_buffer, CORBA_Environment *ev) { CORBA_unsigned_long minor; CORBA_unsigned_long completion_status; CORBA_SystemException *se = ev->_params; minor = se->minor; completion_status = se->completed; ENCODER_CALL(CORBA_char, exception_table[minor].repo_id); giop_send_buffer_append_mem_indirect_a(send_buffer, &completion_status, sizeof(completion_status)); } void ORBit_send_user_exception(GIOPSendBuffer *send_buffer, CORBA_Environment *ev, const ORBit_exception_marshal_info *user_exceptions) { int i; for(i = 0; user_exceptions[i].tc != CORBA_OBJECT_NIL; i++) { if(!strcmp(user_exceptions[i].tc->repo_id, ev->_repo_id)) break; } if(user_exceptions[i].tc == CORBA_OBJECT_NIL || !ev->_params) { CORBA_Environment fakeev; CORBA_exception_init(&fakeev); CORBA_exception_set_system(&fakeev, ex_CORBA_UNKNOWN, CORBA_COMPLETED_MAYBE); ORBit_send_system_exception(send_buffer, &fakeev); CORBA_exception_free(&fakeev); } else { ENCODER_CALL(CORBA_char, ev->_repo_id); user_exceptions[i].marshal(send_buffer, ev); } }