diff options
author | gokhale <asgokhale@users.noreply.github.com> | 1998-04-14 19:09:33 +0000 |
---|---|---|
committer | gokhale <asgokhale@users.noreply.github.com> | 1998-04-14 19:09:33 +0000 |
commit | 44dbcae7fbbc45d362e9a108952846f2f95de935 (patch) | |
tree | 2cb384ef4a293f6a7a2cdbefc86fb2f99d48c8a2 /TAO/tao/skip.cpp | |
parent | dc91dcc9c80369d1a005b95336c6baefc83b6032 (diff) | |
download | ATCD-44dbcae7fbbc45d362e9a108952846f2f95de935.tar.gz |
*** empty log message ***
Diffstat (limited to 'TAO/tao/skip.cpp')
-rw-r--r-- | TAO/tao/skip.cpp | 751 |
1 files changed, 751 insertions, 0 deletions
diff --git a/TAO/tao/skip.cpp b/TAO/tao/skip.cpp new file mode 100644 index 00000000000..7bd33e93642 --- /dev/null +++ b/TAO/tao/skip.cpp @@ -0,0 +1,751 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO +// +// = FILENAME +// skip.cpp +// +// = DESCRIPTION +// Code for skipping different data types +// +// Data types encoded as CDR streams need to be skipped when they are part of +// an Any. +// +// = AUTHOR +// Aniruddha Gokhale +// +// ============================================================================ + +#include "tao/corba.h" + +CORBA::TypeCode::traverse_status +TAO_Marshal_Primitive::skip (CORBA::TypeCode_ptr tc, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + TAO_InputCDR *stream = (TAO_InputCDR *) context; + // status of skip operation + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + + switch (tc->kind_) + { + case CORBA::tk_null: + case CORBA::tk_void: + break; + case CORBA::tk_short: + case CORBA::tk_ushort: + continue_decoding = stream->skip_short (); + break; + case CORBA::tk_long: + case CORBA::tk_ulong: + case CORBA::tk_float: + case CORBA::tk_enum: + continue_decoding = stream->skip_long (); + break; + case CORBA::tk_double: + case CORBA::tk_longlong: + case CORBA::tk_ulonglong: + continue_decoding = stream->skip_longlong (); + break; + case CORBA::tk_boolean: + continue_decoding = stream->skip_boolean (); + break; + case CORBA::tk_char: + case CORBA::tk_octet: + continue_decoding = stream->skip_char (); + break; + case CORBA::tk_longdouble: + continue_decoding = stream->skip_longdouble (); + break; + case CORBA::tk_wchar: + continue_decoding = stream->skip_wchar (); + break; + default: + retval = CORBA::TypeCode::TRAVERSE_STOP; + // we are not a primitive type + } + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE + && continue_decoding == CORBA::B_TRUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Primitive::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +CORBA::TypeCode::traverse_status +TAO_Marshal_Any::skip (CORBA::TypeCode_ptr, + void *context, + CORBA::Environment &env) +{ + // Typecode of the element that makes the Any. + CORBA::TypeCode_ptr elem_tc; + + // Context is the CDR stream. + TAO_InputCDR *stream = (TAO_InputCDR *) context; + + // Status of encode operation. + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + + // first retrieve the TypeCode for the element so that we can skip the value + // based on this typecode + if (stream->decode (CORBA::_tc_TypeCode, + &elem_tc, + 0, + env) == CORBA::TypeCode::TRAVERSE_CONTINUE) + { + if (env.exception () == 0) + retval = stream->skip (elem_tc, env); + else + retval = CORBA::TypeCode::TRAVERSE_STOP; + } + return retval; +} + +CORBA::TypeCode::traverse_status +TAO_Marshal_TypeCode::skip (CORBA::TypeCode_ptr, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + + // Context is the CDR stream. + TAO_InputCDR *stream = (TAO_InputCDR *) context; + + // Typecode to be decoded. + CORBA::TypeCode_ptr *tcp; + + // Typecode kind. + CORBA::ULong kind; + + // Decode the "kind" field of the typecode from the stream + continue_decoding = stream->read_ulong (kind); + + if (continue_decoding == CORBA::B_TRUE) + { + // Typecodes with empty parameter lists all have preallocated + // constants. We use those to reduce memory consumption and + // heap access ... also, to speed things up! + if ((kind < CORBA::TC_KIND_COUNT) || + (kind == ~(CORBA::ULong)0)) + { + // Either a non-constant typecode or an indirected typecode. + switch (kind) + { + // Need special handling for all kinds of typecodes that + // have nonempty parameter lists ... + default: + // simple typecodes, nothing to do + break; + case CORBA::tk_string: + case CORBA::tk_wstring: + { + // skip the bounds + continue_decoding = stream->skip_ulong (); + } + break; + + // Indirected typecodes, illegal at "top level". + case ~0: + { + // skip the long indicating the encapsulation offset, + continue_decoding = stream->skip_long (); + } + break; + + // The rest have "complex" parameter lists that are + // encoded as bulk octets ... + case CORBA::tk_objref: + case CORBA::tk_struct: + case CORBA::tk_union: + case CORBA::tk_enum: + case CORBA::tk_sequence: + case CORBA::tk_array: + case CORBA::tk_alias: + case CORBA::tk_except: + { + CORBA::ULong length; + + // get the encapsulation length + continue_decoding = stream->read_ulong (length); + if (!continue_decoding) + break; + // skip the encapsulation + continue_decoding = stream->skip_bytes (length); + } + } // end of switch + } + else // bad kind_ value to be decoded + { + env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); + dmsg ("TAO_Marshal_TypeCode: Bad kind_ value in CDR stream"); + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + + if (continue_decoding == CORBA::B_TRUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_TypeCode::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +// Encode Principal. + +CORBA::TypeCode::traverse_status +TAO_Marshal_Principal::skip (CORBA::TypeCode_ptr, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + + // Context is the CDR stream. + TAO_InputCDR *stream = (TAO_InputCDR *) context; + + // specifies the number of bytes in the Principal + CORBA::ULong len; + + continue_decoding = stream->read_ulong (len); + if (len > 0 && continue_decoding) + { + continue_decoding = stream->skip_bytes (len); + } + + if (continue_decoding == CORBA::B_TRUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Principal::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +CORBA::TypeCode::traverse_status +TAO_Marshal_ObjRef::skip (CORBA::TypeCode_ptr, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + + // Context is the CDR stream. + TAO_InputCDR *stream = (TAO_InputCDR *) context; + // return status + CORBA::TypeCode::traverse_status retval = CORBA::TypeCode::TRAVERSE_CONTINUE; + + // First, skip the type hint. This will be the type_id encoded in an + // object reference. + stream->skip_string (); + + // Read the profiles, discarding all until an IIOP profile comes by. + // Once we see an IIOP profile, ignore any further ones. + // + // XXX this will need to change someday to let different protocol + // code be accessed, not just IIOP. Protocol modules will be + // dynamically loaded from shared libraries via ORB_init (), and we + // just need to be able to access such preloaded libraries here as + // we unmarshal objrefs. + CORBA::ULong profiles = 0; + + // get the count of profiles that follow + continue_decoding = stream->read_ulong (profiles); + + while (profiles-- != 0 && continue_decoding) + { + CORBA::ULong tag; + + // get the profile ID tag + if ( (continue_decoding = stream->read_ulong (tag)) == CORBA::B_FALSE) + continue; + + if (tag != TAO_IOP_TAG_INTERNET_IOP) + { + continue_decoding = stream->skip_string (); + continue; + } + + // OK, we've got an IIOP profile. It's going to be + // encapsulated ProfileData. Create a new decoding stream and + // context for it, and tell the "parent" stream that this data + // isn't part of it any more. + + CORBA::ULong encap_len; + // ProfileData is encoded as a sequence of octet. So first get + // the length of the sequence. + // Create the decoding stream from the encapsulation in the + // buffer, and skip the encapsulation. + if ( (continue_decoding = stream->read_ulong (encap_len)) == CORBA::B_FALSE) + continue; + + TAO_InputCDR str (*stream, encap_len); + + continue_decoding = + str.good_bit () + && stream->skip_bytes (encap_len); + + if (!continue_decoding) + continue; + + // Read and verify major, minor versions, ignoring IIOP + // profiles whose versions we don't understand. + // + // XXX this doesn't actually go back and skip the whole + // encapsulation... + if (!(str.skip_octet () + && str.skip_octet ())) + continue; + + // skip host and port + if (!str.skip_string () + || !str.skip_ushort ()) + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("error decoding IIOP host/port"); + return CORBA::TypeCode::TRAVERSE_STOP; + } + + // ... and object key. + if (str.skip (&TC_opaque, + env) != CORBA::TypeCode::TRAVERSE_CONTINUE) + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE + && continue_decoding == CORBA::B_TRUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + ACE_DEBUG ((LM_DEBUG, "marshaling decode_objref detected error")); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +// Decode structs. +CORBA::TypeCode::traverse_status +TAO_Marshal_Struct::skip (CORBA::TypeCode_ptr tc, + void *context, + CORBA::Environment &env) +{ + TAO_InputCDR *stream = (TAO_InputCDR *) context; + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + CORBA::TypeCode_ptr param; + + // Number of fields in the struct. + int member_count = tc->member_count (env); + + if (env.exception () == 0) + for (int i = 0; i < member_count + && retval == CORBA::TypeCode::TRAVERSE_CONTINUE; + i++) + { + param = tc->member_type (i, env); + if (env.exception () == 0) + { + retval = stream->skip (param, env); + } + else + return CORBA::TypeCode::TRAVERSE_STOP; + } + else + return CORBA::TypeCode::TRAVERSE_STOP; + + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("marshaling encode_struct detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +// Encode unions. +CORBA::TypeCode::traverse_status +TAO_Marshal_Union::skip (CORBA::TypeCode_ptr tc, + void *context, + CORBA::Environment &env) +{ + // Context is the CDR stream. + TAO_InputCDR *stream = (TAO_InputCDR *) context; + + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + + CORBA::TypeCode_ptr discrim_tc; + CORBA::TypeCode_ptr member_tc; + CORBA::Any_ptr member_label; + CORBA::Long discrim_val; + CORBA::ULong member_count; + CORBA::Long default_index; + CORBA::ULong i; + CORBA::TypeCode_ptr default_tc = 0; + CORBA::Boolean discrim_matched = CORBA::B_FALSE; + + // get the discriminator type which will enable us to skip the discriminator + // value + discrim_tc = tc->discriminator_type (env); + + if (env.exception () == 0) + { + // decode the discriminator value + retval = stream->decode (discrim_tc, &discrim_val, 0, env); + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE) + { + // now get ready to skip the actual union value + default_index = tc->default_index (env); + + if (env.exception () == 0) + { + member_count = tc->member_count (env); + if (env.exception () == 0) + { + // check which label value matches with the discriminator + // value. Accordingly, marshal the corresponding + // member_type. If none match, check if default exists + // and marshal accordingly. Otherwise it is an error. + + for (i = 0; i < member_count; i++) + { + member_label = tc->member_label (i, env); + if (env.exception () == 0) + { + // do the matching + switch (member_label->type ()->kind (env)) + { + case CORBA::tk_short: + case CORBA::tk_ushort: + if (*(CORBA::Short *) member_label->value () == + *(CORBA::Short *) discrim_val) + discrim_matched = CORBA::B_TRUE; + break; + case CORBA::tk_long: + case CORBA::tk_ulong: + case CORBA::tk_enum: + if (*(CORBA::ULong *) member_label->value () == + *(CORBA::ULong *) discrim_val) + discrim_matched = CORBA::B_TRUE; + break; + case CORBA::tk_char: + if (*(CORBA::Char *) member_label->value () == + *(CORBA::Char *) discrim_val) + discrim_matched = CORBA::B_TRUE; + break; + case CORBA::tk_wchar: + if (*(CORBA::WChar *) member_label->value () == + *(CORBA::WChar *) discrim_val) + discrim_matched = CORBA::B_TRUE; + break; + case CORBA::tk_boolean: + if (*(CORBA::Boolean *) member_label->value () == + *(CORBA::Boolean *) discrim_val) + discrim_matched = CORBA::B_TRUE; + break; + default: + env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO)); + return CORBA::TypeCode::TRAVERSE_STOP; + }// end of switch + + // get the member typecode + member_tc = tc->member_type (i, env); + if (env.exception () == 0) + { + if (default_index >= 0 && default_index-- == 0) + // have we reached the default label?, if so, + // save a handle to the typecode for the default + default_tc = member_tc; + if (discrim_matched) + // marshal according to the matched typecode + return stream->skip (member_tc, env); + } + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + return CORBA::TypeCode::TRAVERSE_STOP; + } + } // end of for loop + // we are here only if there was no match + if (default_tc) + return stream->skip (default_tc, env); + else + return CORBA::TypeCode::TRAVERSE_CONTINUE; + } + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +// decode string +CORBA::TypeCode::traverse_status +TAO_Marshal_String::skip (CORBA::TypeCode_ptr, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + // Context is the CDR stream. + TAO_InputCDR *stream = (TAO_InputCDR *) context; + + + // On decode, omit the check against specified string bounds, and + // cope with illegal "zero length" strings (all lengths on the wire + // must include a NUL). + // + // This is on the principle of being gracious in what we accept; we + // don't generate messages that fail to comply with protocol specs, + // but we will accept them when it's clear how to do so. + + continue_decoding = stream->skip_string (); + if (continue_decoding == CORBA::B_TRUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_TypeCode::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +// Decode sequence. + +CORBA::TypeCode::traverse_status +TAO_Marshal_Sequence::skip (CORBA::TypeCode_ptr tc, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + TAO_InputCDR *stream = (TAO_InputCDR *) context; + // Return status. + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + // Typecode of the element. + CORBA::TypeCode_ptr tc2; + // Size of element. + CORBA::ULong bounds; + + // First unmarshal the sequence length ... we trust it to be right + // here, on the "be gracious in what you accept" principle. We + // don't generate illegal sequences (i.e. length > bounds). + + continue_decoding = stream->read_ulong (bounds); + + if (continue_decoding) + { + // No point decoding an empty sequence. + if (bounds > 0) + { + // Get element typecode. + tc2 = tc->content_type (env); + + if (env.exception () == 0) + { + while (bounds-- && continue_decoding == CORBA::B_TRUE) + { + continue_decoding = stream->skip (tc2, env); + } + } // no exception computing content type + } // length is > 0 + else + return CORBA::TypeCode::TRAVERSE_CONTINUE; + } + // error exit + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; +} + +// Decode array. + +CORBA::TypeCode::traverse_status +TAO_Marshal_Array::skip (CORBA::TypeCode_ptr tc, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + TAO_InputCDR *stream = (TAO_InputCDR *) context; + + // Return status. + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + + // Typecode of the element. + CORBA::TypeCode_ptr tc2; + + CORBA::ULong bounds; + + // retrieve the bounds of the array + bounds = tc->length (env); + if (env.exception () == 0) + { + // get element typecode + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + while (bounds-- && continue_decoding == CORBA::B_TRUE) + { + continue_decoding = stream->skip (tc2, env); + } + } // no exception computing content type + } // no exception computing bounds + // error exit + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO)); + dmsg ("marshaling TAO_Marshal_Sequence::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; +} + +// Decode alias. +CORBA::TypeCode::traverse_status +TAO_Marshal_Alias::skip (CORBA::TypeCode_ptr tc, + void *context, + CORBA::Environment &env) +{ + // Typecode of the aliased type. + CORBA::TypeCode_ptr tc2; + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + + // Context is the CDR stream. + TAO_InputCDR *stream = (TAO_InputCDR *) context; + + // Status of decode operation. + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + + tc2 = tc->content_type (env); + if (env.exception () == 0) + { + retval = stream->skip (tc2, env); + } + // tc2->Release (); + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE + && continue_decoding == CORBA::B_TRUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Alias::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +// Decode exception For exceptions, the "hidden" type ID near the +// front of the on-wire representation was previously unmarshaled and +// mapped to the "tc" typcode we're using to traverse the memory ... +// at the same time its vtable, refcount, and other state was +// established. +// +// NOTE: This is asymmetric with respect to encoding exceptions. +CORBA::TypeCode::traverse_status +TAO_Marshal_Except::skip (CORBA::TypeCode_ptr tc, + void *context, + CORBA::Environment &env) +{ + TAO_InputCDR *stream = (TAO_InputCDR *) context; + CORBA::TypeCode::traverse_status retval = + CORBA::TypeCode::TRAVERSE_CONTINUE; + CORBA::TypeCode_ptr param; + + // Number of fields in the exception + int member_count = tc->member_count (env); + if (env.exception () == 0) + { + for (int i = 0; i < member_count + && retval == CORBA::TypeCode::TRAVERSE_CONTINUE; + i++) + { + param = tc->member_type (i, env); + if (env.exception () == 0) + { + retval = stream->skip (param, env); + } + else + return CORBA::TypeCode::TRAVERSE_STOP; + } + } + else + return CORBA::TypeCode::TRAVERSE_STOP; + + if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_Except detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} + +// decode wstring +CORBA::TypeCode::traverse_status +TAO_Marshal_WString::skip (CORBA::TypeCode_ptr, + void *context, + CORBA::Environment &env) +{ + CORBA::Boolean continue_decoding = CORBA::B_TRUE; + TAO_InputCDR *stream = (TAO_InputCDR *) context; + CORBA::ULong len; + + // On decode, omit the check against specified wstring bounds, and + // cope with illegal "zero length" strings (all lengths on the wire + // must include a NUL). + // + // This is on the principle of being gracious in what we accept; we + // don't generate messages that fail to comply with protocol specs, + // but we will accept them when it's clear how to do so. + + continue_decoding = stream->read_ulong (len); + + if (len != 0) + while (continue_decoding != CORBA::B_FALSE && len--) + { + continue_decoding = stream->skip_wchar (); + } + + if (continue_decoding == CORBA::B_TRUE) + return CORBA::TypeCode::TRAVERSE_CONTINUE; + else + { + env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); + dmsg ("TAO_Marshal_TypeCode::skip detected error"); + return CORBA::TypeCode::TRAVERSE_STOP; + } +} |