summaryrefslogtreecommitdiff
path: root/TAO/IIOP/lib/marshal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/IIOP/lib/marshal.cpp')
-rw-r--r--TAO/IIOP/lib/marshal.cpp1108
1 files changed, 0 insertions, 1108 deletions
diff --git a/TAO/IIOP/lib/marshal.cpp b/TAO/IIOP/lib/marshal.cpp
deleted file mode 100644
index cda3a232723..00000000000
--- a/TAO/IIOP/lib/marshal.cpp
+++ /dev/null
@@ -1,1108 +0,0 @@
-// @(#)marshal.cpp 1.7 95/11/04
-// Copyright 1994-1995 by Sun Microsystems Inc.
-// All Rights Reserved
-//
-// CDR: Marshaling interpreter
-//
-// This marshaling interpreter is driven by the typecode interpreter. The
-// typecode interpreter understands each compiler environment's rules for
-// data structure layout; this understands CDR's rules for on-the-wire data
-// structure layout.
-//
-// Apart from some high level rules related to construction of complex data
-// types, the marshaling interpreter just knows how to encode primitive data
-// types and allocate memory on decode.
-//
-// NOTE: to reduce the amount of compiled code, this "knows" facts like
-// native float/long/ulong being in legal CDR format, and that "char" is
-// native in ISO Latin/1 (so no transformation is needed, and octet/char
-// marshaling code is identical). On exotic platforms where this is not
-// true, some of the merged "switch" branches will need to be split.
-//
-// REMEMBER: goal is to have the typecode interpreter plus one side of the
-// marshaling interpreter reside in a CPU's code cache; or at least to have
-// as litle as possible _outside_ cache when marshaling. Compiled marshaling
-// code will have a few less instructions, but most will of them will be
-// outside the instruction cache; access time to get at them will be high.
-//
-// NOTE: One interesting optimization is inlining the primitive put/get
-// calls ... it'd typically save at least 40% in terms of instruction count
-// on each of these critical paths by eliminating subroutine call overhead.
-// Since it would increase code size, such changes might not be desirable
-// on machines with small caches. Also, with network I/O being today's most
-// significant bottleneck, such optimizations haven't been well explored.
-//
-// THREADING NOTE: The only threading concern is as always, that data
-// structures being manipulated by any given thread must be reserved to
-// it by some mechanism (e.g. mutex). This uses no mutable data outside
-// of the thread stack, so the onus is entirely on the caller.
-//
-
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-#include <orb.hh>
-
-#include "debug.hh"
-#include "cdr.hh"
-
-#include "giop.hh"
-
-
-#if defined (HAVE_WIDEC_H)
-# include <widec.h>
-#else
- extern "C" {
- unsigned wslen (const wchar_t *);
- wchar_t *wscpy (wchar_t *, const wchar_t *);
- }
-#endif
-
-extern CORBA_TypeCode TC_opaque;
-
-
-//
-// Encode instances of arbitrary data types based only on typecode. "data"
-// points to the data type; if it's not a primitve data type, the TypeCode
-// interpreter is used to recursively encode its components. "context" is
-// the marshaling stream on which to encode the data value.
-//
-// This is a fairly typical TypeCode interpreter visit() routine; it works
-// on a single data value in conjunction with context information, and must
-// handle all IDL data types.
-//
-CORBA_TypeCode::traverse_status
-CDR::encoder (
- CORBA_TypeCode_ptr tc,
- const void *data,
- const void *,
- void *context,
- CORBA_Environment &env
-)
-{
- CORBA_Boolean continue_encoding = CORBA_B_TRUE;
- CDR *stream = (CDR *)context;
-
- switch (tc->_kind) {
- case tk_null:
- case tk_void:
- // nothing to encode!
- break;
-
- case tk_char:
- case tk_octet:
- continue_encoding = stream->put_char (*(char *)data);
- break;
-
- case tk_short:
- case tk_ushort:
- continue_encoding = stream->put_short (*(short *)data);
- break;
-
- case tk_long:
- case tk_ulong:
- case tk_float:
- continue_encoding = stream->put_long (*(CORBA_Long *)data);
- break;
-
- case tk_double:
- case tk_longlong:
- case tk_ulonglong:
- continue_encoding = stream->put_longlong (*(CORBA_LongLong *)data);
- break;
-
- case tk_boolean:
- continue_encoding = stream->put_boolean (*(CORBA_Boolean *)data);
- break;
-
- case tk_enum:
- {
- //
- // NOTE assumption that this is in-range.
- //
- // XXX should check this, it's a hard-to-recover error
- // for the other side
- //
- unsigned value = *(unsigned *)data;
- continue_encoding = stream->put_ulong (value);
- }
- break;
-
- case tk_any:
- {
- CORBA_Any *any = (CORBA_Any *)data;
-
- tc = any->type ();
- if (encoder (_tc_CORBA_TypeCode, &tc, 0, context, env)
- != CORBA_TypeCode::TRAVERSE_CONTINUE)
- return CORBA_TypeCode::TRAVERSE_STOP;
-
- data = any->value ();
- return encoder (tc, data, 0, context, env);
- }
- // NOTREACHED
-
- case tk_TypeCode:
- {
- CORBA_TypeCode_ptr tc2;
-
- tc2 = *(CORBA_TypeCode_ptr *)data;
-
- continue_encoding = stream->put_ulong ((CORBA_ULong) tc2->_kind);
- if (continue_encoding == CORBA_B_FALSE)
- break;
-
- switch (tc2->_kind) {
- //
- // Most TypeCodes have empty parameter lists
- //
- default:
- break;
-
- //
- // A few have "simple" parameter lists
- //
- case tk_string:
- case tk_wstring:
- continue_encoding = stream->put_ulong (tc2->_length);
- break;
-
- //
- // Indirected typecodes can't occur at "top level" like
- // this, only nested inside others!
- //
- case ~0:
- dmsg ("indirected typecode at top level!");
- continue_encoding = CORBA_B_FALSE;
- break;
-
- //
- // The rest have "complex" parameter lists that are already
- // encoded as bulk octets ... put length, then octets
- //
- case tk_objref:
- case tk_struct:
- case tk_union:
- case tk_enum:
- case tk_sequence:
- case tk_array:
- case tk_alias:
- case tk_except:
- {
- unsigned i;
-
- continue_encoding = stream->put_ulong (tc2->_length);
- for (i = 0; i < tc2->_length && continue_encoding; i++)
- continue_encoding =
- stream->put_octet (tc2->_buffer [i]);
- }
- }
- }
- break;
-
- case tk_Principal:
- {
- CORBA_Principal_ptr p = *(CORBA_Principal_ptr*) data;
- unsigned i;
-
- if (p != 0) {
- continue_encoding = stream->put_long (p->id.length);
- for (i = 0; continue_encoding && i < p->id.length; i++)
- continue_encoding = stream->put_octet (p->id.buffer [i]);
- } else
- continue_encoding = stream->put_long (0);
- }
- break;
-
- case tk_objref:
- //
- // Current version: objref is really an IIOP_Object.
- //
- // This will change in the future; STUB_Object knows how to
- // marshal itself, that will be used.
- //
- // XXX this doesn't actually verify that the stuff got written
- // OK to the "wire" ...
- //
- {
- CORBA_Object_ptr obj = *(CORBA_Object_ptr *)data;
-
- //
- // NIL objrefs ... marshal as empty type hint, no elements.
- //
- if (CORBA_is_nil (obj)) {
- continue_encoding =
- stream->put_ulong (1) // strlen
- && stream->put_char (0) // NUL
- && stream->put_ulong (0); // no profiles
- break;
- }
-
- //
- // All other objrefs ... narrow to a "real type" that we
- // recognize, then marshal.
- //
- // XXX this will be changed so it narrows to STUB_Object
- // and then asks that surrogate/proxy to marshal itself.
- //
- // For now, the original code is minimally changed.
- //
- IIOP_Object *objdata;
- IIOP::ProfileBody *profile;
-
- if (obj->QueryInterface (IID_IIOP_Object, (void **)&objdata)
- != NOERROR) {
- env.exception (new CORBA_MARSHAL (COMPLETED_NO));
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
- obj->Release ();
- profile = &objdata->profile;
-
- //
- // STRING, a type ID hint
- //
- encoder (_tc_CORBA_String, &objdata->type_id, 0, context, env);
-
- //
- // UNSIGNED LONG, value one, count of the sequence
- // of encapsulated protocol profiles;
- //
- stream->put_ulong (1);
-
- //
- // UNSIGNED LONG, tag for this protocol profile;
- //
- stream->put_ulong (IOP::TAG_INTERNET_IOP);
-
- //
- // UNSIGNED LONG, number of succeeding bytes in the encapsulation.
- // We don't actually need to make the encapsulation, as nothing
- // needs stronger alignment than this longword; it guarantees
- // the rest is aligned for us.
- //
- unsigned hostlen;
-
- hostlen = ACE_OS::strlen ((char *)profile->host);
- stream->put_ulong (
- 1 // byte order
- + 3 // version + pad byte
- + 4 // sizeof (strlen)
- + hostlen + 1 // strlen + null
- + (~hostlen & 01) // optional pad byte
- + 2 // port
- + (hostlen & 02) // optional pad short
- + 4 // sizeof (key length)
- + profile->object_key.length); // key length
-
- //
- // CHAR describing byte order, starting the encapsulation
- //
- stream->put_char (MY_BYTE_SEX);
-
- //
- // IIOP::Version, two characters (version 1.0)
- // padding
- //
- stream->put_char (profile->iiop_version.major);
- stream->put_char (profile->iiop_version.minor);
-
- //
- // STRING hostname from profile
- //
- encoder (_tc_CORBA_String, &profile->host, 0, context, env);
-
- //
- // UNSIGNED SHORT port number
- //
- stream->put_ushort (profile->port);
-
- //
- // OCTET SEQUENCE for object key
- //
- encoder (&TC_opaque, &profile->object_key, 0, context, env);
- }
- break;
-
- case tk_sequence:
- {
- //
- // First marshal the sequence length, verifying that
- // it's within the sequence bounds ...
- //
- CORBA_OctetSeq *seq = (CORBA_OctetSeq *) data;
- CORBA_ULong len = seq ? seq->length : 0;
-
- if (len > 0) {
- CORBA_ULong bounds;
-
- bounds = tc->ulong_param (1, env);
- if (env.exception () != 0)
- return CORBA_TypeCode::TRAVERSE_STOP;
-
- if (bounds != 0 && len > bounds) {
- env.exception (new CORBA_BAD_PARAM (COMPLETED_MAYBE));
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
- }
- continue_encoding = stream->put_ulong (len);
-
- //
- // Fast exit on error or empty sequence
- //
- if (!continue_encoding || len == 0)
- break;
- }
- // FALLTHROUGH
-
- case tk_struct:
- case tk_union:
- case tk_array:
- case tk_alias:
- //
- // Marshal each member in order.
- //
- return tc->traverse (data, 0, encoder, context, env);
-
- case tk_except:
- //
- // Convert the the "hidden" TypeCode at the beginning of the
- // exception into an on-the-wire ID, then marshal the members
- // in order (traversal skips that hidden typecode, and more).
- //
- // NOTE: This is asymmetric with respect to decoding the exception,
- // since whoever decodes must pull off the ID and map it to the
- // typecode to be used to unmarshal it (search among legal choices).
- //
- {
- CORBA_String id = tc->id (env);
-
- if (env.exception () == 0) {
- continue_encoding =
- encoder (_tc_CORBA_String, &id, 0, context, env)
- == CORBA_TypeCode::TRAVERSE_CONTINUE
- && tc->traverse (data, 0, encoder, context, env);
- } else
- continue_encoding = CORBA_B_FALSE;
- }
- break;
-
- case tk_string:
- {
- CORBA_String str = *(CORBA_String *) data;
- CORBA_ULong len, bounds;
-
- //
- // Be nice to programmers: treat nulls as empty strings
- // not errors. (OMG-IDL supports languages that don't use
- // the C/C++ notion of null v. empty strings; nulls aren't
- // part of the OMG-IDL string model.)
- //
- if (str == 0) {
- stream->put_ulong (1);
- stream->put_char (0);
- break;
- }
-
- //
- // Verify string satisfies bounds requirements. We're not
- // so permissive as to send messages violating the interface
- // spec by having excessively long strings!
- //
- bounds = tc->ulong_param (0, env);
- if (env.exception () != 0)
- return CORBA_TypeCode::TRAVERSE_STOP;
- len = ACE_OS::strlen ((char *)str);
-
- if (bounds != 0 && len > bounds) {
- continue_encoding = CORBA_B_FALSE;
- break;
- }
-
- //
- // Encode the string, followed by a NUL character.
- //
- continue_encoding = stream->put_ulong (len + 1);
- while (continue_encoding != CORBA_B_FALSE && *str)
- continue_encoding = stream->put_char (*str++);
- stream->put_char (0);
- }
- break;
-
- case tk_wstring:
- {
- wchar_t *str = *(wchar_t **) data;
- CORBA_ULong len, bounds;
-
- //
- // Be nice to programmers: treat nulls as empty strings
- // not errors. (OMG-IDL supports languages that don't use
- // the C/C++ notion of null v. empty strings; nulls aren't
- // part of the OMG-IDL string model.)
- //
- if (str == 0) {
- stream->put_ulong (1);
- stream->put_wchar (0);
- break;
- }
-
- //
- // Verify wide string satisfies bounds requirements. We're
- // not so permissive as to send messages violating the interface
- // spec by having excessively long strings!
- //
- bounds = tc->ulong_param (0, env);
- if (env.exception () != 0)
- return CORBA_TypeCode::TRAVERSE_STOP;
- len = wslen (str);
- if (bounds != 0 && len > bounds) {
- continue_encoding = CORBA_B_FALSE;
- break;
- }
-
- //
- // Encode the wide string, followed by a NUL character.
- //
- continue_encoding = stream->put_ulong (wslen (str) + 1);
- while (continue_encoding != CORBA_B_FALSE && *str)
- continue_encoding = stream->put_wchar (*str++);
- stream->put_wchar (0);
- }
- break;
-
- case tk_longdouble:
- continue_encoding =
- stream->put_longdouble (*(CORBA_LongDouble *)data);
- break;
-
- case tk_wchar:
- continue_encoding = stream->put_wchar (*(wchar_t *)data);
- break;
-
- // case ~0:
- default:
- dmsg ("encoder default case ?");
- continue_encoding = CORBA_B_FALSE;
- break;
- }
-
- if (continue_encoding == CORBA_B_FALSE) {
- env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE));
- dmsg ("marshaling encoder detected error");
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
- return CORBA_TypeCode::TRAVERSE_CONTINUE;
-}
-
-
-//
-// This table of TypeCode constants lets us unmarshal most typecodes using
-// the predefined constants, rather than constantly reallocating them.
-//
-// XXX CFRONT-based compilers can't cope with this table initialization,
-// and need some kind of init function. Luckily, they're increasingly
-// rare in any "production" environment.
-//
-#if THE_COMPILER_CAN_FIND_THIS_PROPERLY
-const // The extern reference in onc/xdr.cpp doesn't
- // seem to be able to find this decl with as
- // long as the const is part of it. I even
- // tried changing the ref decl to have 'const'
- // in it, to no avail. --cjc
-#endif
-CORBA_TypeCode_ptr
-__tc_consts [TC_KIND_COUNT] = {
- _tc_CORBA_Null
- , _tc_CORBA_Void
- , _tc_CORBA_Short
- , _tc_CORBA_Long
- , _tc_CORBA_UShort
-
- , _tc_CORBA_ULong
- , _tc_CORBA_Float
- , _tc_CORBA_Double
- , _tc_CORBA_Boolean
- , _tc_CORBA_Char
-
- , _tc_CORBA_Octet
- , _tc_CORBA_Any
- , _tc_CORBA_TypeCode
- , _tc_CORBA_Principal
- , 0 // _tc_CORBA_Object ... type ID is CORBA::Object
-
- , 0 // tk_struct
- , 0 // tk_union
- , 0 // tk_enum
- , 0 // _tc_CORBA_String ... unbounded
- , 0 // tk_sequence
-
- , 0 // tk_array
-
- , 0 // tk_alias
- , 0 // tk_except
-
- , _tc_CORBA_LongLong
- , _tc_CORBA_ULongLong
- , _tc_CORBA_LongDouble
- , _tc_CORBA_WChar
- , 0 // _tc_CORBA_WString ... unbounded
-};
-
-
-//
-// The decoder is exactly the reverse of the encoder, except that:
-//
-// * Unmarshaling some data types involve allocating memory. Such
-// types include sequences (the buffer), objrefs, Principals, Anys,
-// TypeCodes, and strings.
-//
-// * The decoder is used when retrieving typecode parameters from
-// encapsulations. This means it must deal with "tk_indirect",
-// the magic value (~0) signifying typecode indirection.
-//
-// This second case is identified by a bit of a hack: the second "data"
-// value is used to hold the parent typecode, rather than being ignored.
-// This means that all other invocations of decoder() ** MUST ** pass zero
-// for the second data parameter, in case they decode a TypeCode. If they
-// didn't, this case might be signified inappropriately.
-//
-// XXX desirable to have a less hacky solution to that ... pull that code
-// out into a separate routine called both by CDR::decoder() and by the
-// code retrieving typecode parameters from encapsulations.
-//
-CORBA_TypeCode::traverse_status
-CDR::decoder (
- CORBA_TypeCode_ptr tc,
- const void *data,
- const void *parent_typecode,
- void *context,
- CORBA_Environment &env
-)
-{
- CORBA_Boolean continue_decoding = CORBA_B_TRUE;
- CDR *stream = (CDR *)context;
-
- switch (tc->_kind) {
- case tk_null:
- case tk_void:
- // nothing to decode!
- break;
-
- case tk_char:
- case tk_octet:
- continue_decoding = stream->get_char (*(CORBA_Char *)data);
- break;
-
- case tk_short:
- case tk_ushort:
- continue_decoding = stream->get_short (*(short *)data);
- break;
-
- case tk_long:
- case tk_ulong:
- case tk_float:
- continue_decoding = stream->get_long (*(CORBA_Long *)data);
- break;
-
- case tk_longlong:
- case tk_ulonglong:
- case tk_double:
- continue_decoding = stream->get_longlong (*(CORBA_LongLong *)data);
- break;
-
- case tk_boolean:
- continue_decoding = stream->get_boolean (*(CORBA_Boolean *)data);
- break;
-
- case tk_enum:
- {
- CORBA_ULong val;
-
- //
- // NOTE assumption that this is in-range.
- //
- // XXX should check this, it's rather hard to recover
- // from such errors since they "do not occur" and are
- // essentially never tested for.
- //
- continue_decoding = stream->get_ulong (val);
- *(unsigned *)data = (unsigned) val;
- }
- break;
-
- case tk_any:
- {
- CORBA_Any *any = (CORBA_Any *)data;
- CORBA_TypeCode_ptr tc2;
- void *value;
-
- if (decoder (_tc_CORBA_TypeCode, &tc2, 0, context, env)
- != CORBA_TypeCode::TRAVERSE_CONTINUE)
- return CORBA_TypeCode::TRAVERSE_STOP;
-
- value = new CORBA_Octet [tc2->size (env)];
-
- if (decoder (tc2, value, 0, context, env)
- != CORBA_TypeCode::TRAVERSE_CONTINUE) {
- delete value;
- CORBA_release (tc2);
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
- (void) new (any) CORBA_Any (tc2, value, CORBA_B_TRUE);
- }
- break;
-
- case tk_TypeCode:
- {
- CORBA_ULong kind;
- CORBA_TypeCode_ptr *tcp;
-
- continue_decoding = stream->get_ulong (kind);
- if (continue_decoding == CORBA_B_FALSE)
- break;
- if (kind >= TC_KIND_COUNT) {
- continue_decoding = CORBA_B_FALSE;
- break;
- }
-
- tcp = (CORBA_TypeCode_ptr *)data;
-
- //
- // 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 (((*tcp) = __tc_consts [(unsigned) kind]) != 0) {
- *tcp = __tc_consts [(unsigned) kind];
- break;
- } else switch (kind) {
- //
- // Need special handling for all kinds of typecodes that have
- // nonempty parameter lists ...
- //
- default: // error: missed a case!
- env.exception (new CORBA_INTERNAL (COMPLETED_MAYBE));
- return CORBA_TypeCode::TRAVERSE_STOP;
-
- //
- // Some have "simple" parameter lists ... some of these also
- // have preallocated constants that could be used.
- //
- case tk_string:
- case tk_wstring:
- {
- CORBA_ULong bound;
-
- continue_decoding = stream->get_ulong (bound);
- if (continue_decoding) {
- if (bound == 0) {
- if (kind == tk_string)
- *tcp = _tc_CORBA_String;
- else
- *tcp = _tc_CORBA_WString;
- } else {
- *tcp = new CORBA_TypeCode ((CORBA_TCKind) kind,
- bound, 0, CORBA_B_TRUE);
- }
- }
- }
- break;
-
- //
- // Indirected typecodes, illegal at "top level" but we allow
- // unmarshaling of them here because we use the same code to
- // read "off the wire" (where they're illegal) and to read
- // out of an encapsulation stream. We distinguish the case
- // where this is legal as described above.
- //
- case ~0:
- {
- CORBA_TypeCode_ptr parent;
-
- if (parent_typecode == 0) {
- env.exception (new CORBA_INTERNAL (COMPLETED_MAYBE));
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
- parent = (CORBA_TypeCode_ptr) parent_typecode;
-
- //
- // Get the long indicating the encapsulation offset,
- // then set up indirection stream that's like "stream"
- // but has space enough only for the typecode and
- // the length for the encapsulated parameters.
- //
- CDR indir_stream;
- CORBA_Long offset;
-
- continue_decoding = stream->get_long (offset);
- if (continue_decoding)
- continue_decoding = (offset < 0);
- if (continue_decoding) {
- indir_stream.buffer = indir_stream.next
- = stream->next + offset;
- indir_stream.remaining = indir_stream.length = 8;
-
- //
- // Reject indirections outside parent's scope.
- //
- if (indir_stream.next < parent->_buffer)
- continue_decoding = CORBA_B_FALSE;
- }
-
- //
- // Get "kind" and length of target typecode
- //
- // XXX this currently assumes the TCKind to which
- // we indirect is the same byte order as the "parent"
- // typecode -- not the right assumption; see how
- // the TypeCode interpreter does it.
- //
- CORBA_ULong indir_kind, indir_len;
-
- if (continue_decoding)
- continue_decoding = stream->get_ulong (indir_kind);
- if (continue_decoding
- && indir_kind >= TC_KIND_COUNT)
- continue_decoding = CORBA_B_FALSE;
- if (continue_decoding)
- continue_decoding = stream->get_ulong (indir_len);
-
- //
- // Now construct indirected typecode. This shares the
- // typecode octets with the "parent" typecode, increasing
- // the amount of memory sharing and reducing the cost of
- // getting typecodes.
- //
- if (continue_decoding) {
- *tcp = new CORBA_TypeCode (
- (CORBA_TCKind) indir_kind,
- indir_len, indir_stream.next,
- CORBA_B_FALSE);
- (*tcp)->_parent = parent;
- parent->AddRef ();
- }
- }
- break;
-
- //
- // The rest have "complex" parameter lists that are
- // encoded as bulk octets ...
- //
- case tk_objref:
- case tk_struct:
- case tk_union:
- case tk_enum:
- case tk_sequence:
- case tk_array:
- case tk_alias:
- case tk_except:
- {
- unsigned len, i;
- CORBA_ULong length;
- CORBA_Octet *buffer;
-
- continue_decoding = stream->get_ulong (length);
- if (!continue_decoding)
- break;
-
- // if length > MAXUNSIGNED, error ...
- len = (unsigned) length;
-
- buffer = new CORBA_Octet [len];
-
- for (i = 0; i < len && continue_decoding; i++)
- continue_decoding = stream->get_octet (buffer [i]);
-
- if (!continue_decoding) {
- delete buffer;
- break;
- }
- *tcp = new CORBA_TypeCode ((CORBA_TCKind)kind,
- len, buffer, CORBA_B_TRUE);
- }
- }
- }
- break;
-
- case tk_Principal:
- {
- CORBA_Principal_ptr *pp = (CORBA_Principal_ptr *)data;
- CORBA_ULong len;
-
- continue_decoding = stream->get_ulong (len);
- if (len == 0)
- *pp = 0;
- else {
- *pp = new CORBA_Principal;
- (*pp)->id.buffer = new CORBA_Octet [(size_t) len];
- (*pp)->id.maximum = (*pp)->id.length = len;
-
- for (unsigned i = 0;
- continue_decoding != CORBA_B_FALSE && i < len;
- i++)
- continue_decoding = stream->get_octet (
- (*pp)->id.buffer [i]);
- }
- }
- break;
-
- case tk_objref:
- {
- //
- // First, read the type hint.
- //
- CORBA_String type_hint;
-
- decoder (_tc_CORBA_String, &type_hint, 0, context, env);
-
- //
- // 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;
- IIOP_Object *objdata = 0;
-
- stream->get_ulong (profiles);
-
- //
- // No profiles means a NIL objref.
- //
- if (profiles == 0) {
- *(CORBA_Object_ptr *)data = CORBA_Object::_nil ();
- delete type_hint;
- break;
- }
- while (profiles-- != 0 && continue_decoding) {
- CORBA_ULong tmp;
-
- stream->get_ulong (tmp);
- if (tmp != IOP::TAG_INTERNET_IOP || objdata != 0) {
- 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.
- //
- continue_decoding = stream->get_ulong (tmp);
- assert (stream->remaining >= tmp);
-
- //
- // Create the decoding stream from the encapsulation
- // in the buffer, and skip the encapsulation.
- //
- CDR str;
-
- str.setup_encapsulation (stream->next, (size_t) tmp);
-
- stream->next += (unsigned) tmp;
- stream->remaining -= (unsigned) tmp;
-
- objdata = new IIOP_Object (type_hint);
-
- IIOP::ProfileBody *profile = &objdata->profile;
-
- //
- // 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.get_octet (profile->iiop_version.major)
- && profile->iiop_version.major == IIOP::MY_MAJOR
- && str.get_octet (profile->iiop_version.minor)
- && profile->iiop_version.minor <= IIOP::MY_MINOR)) {
- dmsg2 ("detected new v%d.%d IIOP profile",
- profile->iiop_version.major,
- profile->iiop_version.minor);
- objdata->type_id = 0;
- objdata->Release ();
- objdata = 0;
- continue;
- }
-
- //
- // Get host and port
- //
- if (decoder (_tc_CORBA_String, &profile->host, 0, &str, env)
- != CORBA_TypeCode::TRAVERSE_CONTINUE
- || !str.get_ushort (profile->port)) {
- env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE));
- dmsg ("error decoding IIOP host/port");
- objdata->Release ();
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
-
- //
- // ... and object key
- //
- continue_decoding =
- (decoder (&TC_opaque, &profile->object_key, 0, &str, env)
- == CORBA_TypeCode::TRAVERSE_CONTINUE);
-
- if (str.remaining != 0) {
- env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE));
- dmsg ("extra data at end of IIOP profile data");
- objdata->Release ();
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
- }
- if (objdata == 0) {
- env.exception (new CORBA_MARSHAL (COMPLETED_MAYBE));
- dmsg2 ("no IIOP v%d.%d (or earlier) profile in IOR!",
- IIOP::MY_MAJOR, IIOP::MY_MINOR);
- return CORBA_TypeCode::TRAVERSE_STOP;
- } else {
- if (objdata->QueryInterface (IID_CORBA_Object, (void **) data)
- != NOERROR)
- continue_decoding = CORBA_B_FALSE;
- objdata->Release ();
- }
- }
- break;
-
- case tk_sequence:
- {
- //
- // 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).
- //
- CORBA_OctetSeq *seq = (CORBA_OctetSeq *) data;
-
- continue_decoding = stream->get_ulong (seq->length);
- seq->maximum = seq->length;
- seq->buffer = 0;
-
- //
- // Fast exit on empty sequences or errors
- //
- if (!continue_decoding || seq->length == 0)
- break;
-
- //
- // ... then allocate the memory into which we'll unmarshal
- //
- CORBA_TypeCode_ptr tc2;
- size_t size;
-
- tc2 = tc->typecode_param (0, env);
- if (env.exception ())
- return CORBA_TypeCode::TRAVERSE_STOP;
-
- size = tc2->size (env);
- if (env.exception ())
- return CORBA_TypeCode::TRAVERSE_STOP;
-
- tc2->Release ();
-
- seq->buffer = new CORBA_Octet [size * (size_t) seq->maximum];
- }
- // FALLTHROUGH
-
- case tk_struct:
- case tk_union:
- case tk_array:
- case tk_alias:
- //
- // Unmarshal all the individual elements using the per-member
- // description held in the "parent" TypeCode.
- //
-
- // FALLTHROUGH
-
- case tk_except:
- //
- // 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.
- //
- return tc->traverse (data, 0, decoder, context, env);
-
- case tk_string:
- {
- CORBA_String str;
- CORBA_ULong len = 0;
-
- //
- // 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->get_ulong (len);
- *((CORBA_String*)data) = str = new CORBA_Char [(size_t) (len)];
- if (len != 0)
- while (continue_decoding != CORBA_B_FALSE && len-- != 0) {
- continue_decoding = stream->get_char (*(CORBA_Char *)str);
- str++;
- }
- break;
- }
-
- case tk_wstring:
- {
- wchar_t *str;
- CORBA_ULong len = 0;
-
- //
- // 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->get_ulong (len);
- *((wchar_t **)data) = str = new wchar_t [(size_t) (len)];
- if (len != 0) {
- while (continue_decoding != CORBA_B_FALSE && len--) {
- continue_decoding = stream->get_wchar (*str);
- str++;
- }
- }
- }
- break;
-
- case tk_longdouble:
- continue_decoding =
- stream->get_longdouble (*(CORBA_LongDouble *)data);
- break;
-
- case tk_wchar:
- continue_decoding = stream->get_wchar (*(wchar_t *)data);
- break;
-
- // case ~0:
- default:
- continue_decoding = CORBA_B_FALSE;
- dmsg ("decode, default case?");
- break;
- }
-
- if (continue_decoding == CORBA_B_FALSE) {
- env.exception (new CORBA_MARSHAL (COMPLETED_NO));
- dmsg ("marshaling decoder detected error");
- return CORBA_TypeCode::TRAVERSE_STOP;
- }
- return CORBA_TypeCode::TRAVERSE_CONTINUE;
-}
-