diff options
Diffstat (limited to 'TAO/tao/xdr.cpp')
-rw-r--r-- | TAO/tao/xdr.cpp | 772 |
1 files changed, 0 insertions, 772 deletions
diff --git a/TAO/tao/xdr.cpp b/TAO/tao/xdr.cpp deleted file mode 100644 index 113d68a589f..00000000000 --- a/TAO/tao/xdr.cpp +++ /dev/null @@ -1,772 +0,0 @@ -// @(#)xdr.cpp 1.3 95/11/07 -// Copyright 1995 by Sun Microsystems, Inc. -// -// XDR/TCP ORB Marshaler/unmarshaler -// -// Includes functions to encode 64 and 128 bit quantities, interpretive -// encoder/decoder. -// -// XXX note -- this is incomplete (see xdr.hh) and doesn't do -// exactly what the Prelude protocol does, particularly in the -// area of typecodes. -// -// XXX implement the put/get primitives for 64 and 128 bit data types -// -// XXX strings, principals, typecodes, char arrays, char seqs, and -// same for octets ... all should marshal the bulk characters tightly -// packed, four to a word, else this violates the XDR spec. -// -// XXX optimization 1: allowed by current XDR spec, when marshaling -// true bulk data could eliminate a buffer copy by writing long -// buffers (bigger than 'remainder of current fragment') in single -// large chunks ... weigh cost of an extra kernel write against data -// copy getting added. Applies to byte-structured bulk data only, -// not (portably) to arrays of longs etc. -// -// XXX optimization 2: modifies current XDR spec: when marshaling -// arrays of "short" data (e.g. unicode strings) pack tightly. -// - -#include "tao/orb.h" -#include "tao/debug.h" -#include "tao/principa.h" -#include "tao/xdr.h" - -// I/O for 64 bit quantities -- integers, doubles - -CORBA_Boolean -XDR_stream::put_longlong (const CORBA_LongLong &) -THROWS_NOTHING -{ - return CORBA_B_FALSE; -} - -CORBA_Boolean -XDR_stream::get_longlong (CORBA_LongLong &) -THROWS_NOTHING -{ - return CORBA_B_FALSE; -} - -// I/O for 128 bit quantities -- long doubles - -CORBA_Boolean -XDR_stream::put_longdouble (const CORBA_LongDouble &) -THROWS_NOTHING -{ - return CORBA_B_FALSE; -} - -CORBA_Boolean -XDR_stream::get_longdouble (CORBA_LongDouble &) -THROWS_NOTHING -{ - return CORBA_B_FALSE; -} - -// 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 -XDR_stream::encoder (CORBA_TypeCode_ptr tc, - const void *data, - const void *, - void *context, - CORBA_Environment &env) - THROWS_NOTHING -{ - CORBA_Boolean continue_encoding = CORBA_B_TRUE; - XDR_stream *stream = (XDR_stream *)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 - u_int value = *(u_int *)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: - { - u_int 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; - u_int 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: - // XXX implement me - 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 = ACE_OS::strlen (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 (ACE_OS::strlen (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; -} - -// Array of typecodes used to unmarshal ... - -extern CORBA_TypeCode_ptr __tc_consts [TC_KIND_COUNT]; - -CORBA_TypeCode::traverse_status -XDR_stream::decoder (CORBA_TypeCode_ptr tc, - const void *data, - const void *, - void *context, - CORBA_Environment &env) - THROWS_NOTHING -{ - CORBA_Boolean continue_decoding = CORBA_B_TRUE; - XDR_stream *stream = (XDR_stream *)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); - *(u_int *)data = (u_int) 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 [(u_int) kind]) != 0) - { - *tcp = __tc_consts [(u_int) 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: - // XXX implement me - 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: - { - u_int len, i; - CORBA_ULong length; - CORBA_Octet *buffer; - - continue_decoding = stream->get_ulong (length); - if (!continue_decoding) - break; - - // if length > MAXUNSIGNED, error ... - len = (u_int) 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 (u_int i = 0; - continue_decoding != CORBA_B_FALSE && i < len; - i++) - continue_decoding = - stream->get_octet ((*pp)->id.buffer [i]); - } - } - break; - - case tk_objref: - // XXX implement me - 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; -} - -// Write an XDR message fragment out on the stream. - -CORBA_Boolean -XDR_stream::flush_frag (CORBA_Boolean /* is_last */) - THROWS_NOTHING -{ - return CORBA_B_FALSE; - -#if 0 - int status; - CORBA_ULong size, header; - - size = index * sizeof (CORBA_ULong); // byte length of msg - if (is_last) - header = 0x80000000 | size; // indicates last frag - else - header = size; - buffer [0] = htonl (header); - - // - // XXX for portability, loop until there's no error. Some - // platforms/mode don't guarantee full TCP writes even when - // async (or nonblocking) mode was not set on this socket. - // - size += sizeof (CORBA_ULong); - status = ACE_OS::write (fd, &buffer [0], size); - - index = 0; - - return (status == size); -#endif /* 0 */ -} - -// Read an XDR message fragment in from the stream. - -CORBA_Boolean -XDR_stream::read_frag (void) - THROWS_NOTHING -{ - // read cookie, split out size and "is last" flag - // read rest of buffer - - return CORBA_B_FALSE; -} |