%%-------------------------------------------------------------------- %% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1997-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% %% %%----------------------------------------------------------------- %% File: cdr_decode.erl %% %% Description: %% This file contains all decoding functions for the CDR %% format. %% %%----------------------------------------------------------------- -module(cdr_decode). -include_lib("orber/src/orber_iiop.hrl"). -include_lib("orber/include/ifr_types.hrl"). -include_lib("orber/include/corba.hrl"). -include_lib("orber/src/ifr_objects.hrl"). %%----------------------------------------------------------------- %% External exports %%----------------------------------------------------------------- -export([dec_giop_message_header/1, dec_reply_header/4, dec_reply_body/6, dec_locate_reply_header/4, dec_locate_reply_body/5, dec_message_header/3, dec_request_body/6, dec_octet_sequence_bin/6, dec_message/2, peek_request_id/2]). %%----------------------------------------------------------------- %% Functions which only are exported for the testcases. %%----------------------------------------------------------------- -export([dec_type/5, dec_byte_order/1, dec_system_exception/4, dec_user_exception/4, dec_byte_order_list/1]). %%----------------------------------------------------------------- %% Internal exports %%----------------------------------------------------------------- %%----------------------------------------------------------------- %% Macros %%----------------------------------------------------------------- -define(DEBUG_LEVEL, 9). -define(ODD(N), (N rem 2) == 1). %%----------------------------------------------------------------- %% Func: dec_message/3 %% Args: %% TypeCodes - is the type_codes of the return value and out parameters %% when one decodes a reply. %% Bytes - is the the message as a byte sequence. %% Returns: %% A tupple which contains the decoded message, %% {ok, Header, Parameters, TypeCodes}. %%----------------------------------------------------------------- dec_message(TypeCodes, Bytes) -> Message = dec_giop_message_header(Bytes), case Message#giop_message.message_type of ?GIOP_MSG_REQUEST -> {Version, ReqHdr, Rest, Len, ByteOrder} = dec_request_header(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order, Bytes), dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Bytes); ?GIOP_MSG_REPLY -> dec_reply(Message#giop_message.giop_version, TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_CANCEL_REQUEST -> dec_cancel_request(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_LOCATE_REQUEST -> dec_locate_request(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_LOCATE_REPLY -> dec_locate_reply(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_CLOSE_CONNECTION -> 'close_connection'; ?GIOP_MSG_MESSAGE_ERROR -> 'message_error'; ?GIOP_MSG_FRAGMENT -> dec_fragment_header(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order, Bytes) end. %%----------------------------------------------------------------- %% Func: dec_giop_message_header/1 %% Args: %% Bytes - is the the message as a byte sequence. %% Returns: %% A giop_message record. %%----------------------------------------------------------------- %% Magic|Version|BO| Type | Size | Body dec_giop_message_header(<<"GIOP",1:8,0:8,1:8,MessType:8, MessSize:32/little-unsigned-integer,Message/binary>>) -> #giop_message{magic = "GIOP", giop_version = {1,0}, byte_order = little, message_type = MessType, message_size = MessSize, message = Message}; dec_giop_message_header(<<"GIOP",1:8,0:8,0:8,MessType:8, MessSize:32/big-unsigned-integer,Message/binary>>) -> #giop_message{magic = "GIOP", giop_version = {1,0}, byte_order = big, message_type = MessType, message_size = MessSize, message = Message}; dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8, MessSize:32/little-unsigned-integer,Message/binary>>) when ((Flags band 16#01) == 16#01) -> #giop_message{magic = "GIOP", giop_version = {1,Minor}, byte_order = little, fragments = ((Flags band 16#02) == 16#02), message_type = MessType, message_size = MessSize, message = Message}; dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8, MessSize:32/big-unsigned-integer,Message/binary>>) -> #giop_message{magic = "GIOP", giop_version = {1,Minor}, byte_order = big, fragments = ((Flags band 16#02) == 16#02), message_type = MessType, message_size = MessSize, message = Message}; dec_giop_message_header(<<Hdr:?GIOP_HEADER_SIZE/binary, _Body/binary>>) -> orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n" "Orber cannot decode the GIOP-header.", [?LINE, Hdr], ?DEBUG_LEVEL), exit(message_error); dec_giop_message_header(Other) -> orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n" "Orber cannot decode the GIOP-header.", [?LINE, Other], ?DEBUG_LEVEL), exit(message_error). peek_request_id(big, <<ReqId:32/big-unsigned-integer,_/binary>>) -> ReqId; peek_request_id(little, <<ReqId:32/little-unsigned-integer,_/binary>>) -> ReqId. %%----------------------------------------------------------------- %% Func: dec_message_header/2 %% Args: %% Header - #giop_message{} %% Bytes - is the the message body as a byte sequence. %% Returns: %%----------------------------------------------------------------- dec_message_header(TypeCodes, Message, Bytes) -> case Message#giop_message.message_type of ?GIOP_MSG_REQUEST -> dec_request_header(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order, Bytes); ?GIOP_MSG_REPLY -> dec_reply(Message#giop_message.giop_version, TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_CANCEL_REQUEST -> dec_cancel_request(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_LOCATE_REQUEST -> dec_locate_request(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_LOCATE_REPLY -> dec_locate_reply(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order); ?GIOP_MSG_CLOSE_CONNECTION -> 'close_connection'; ?GIOP_MSG_MESSAGE_ERROR -> 'message_error'; ?GIOP_MSG_FRAGMENT -> dec_fragment_header(Message#giop_message.giop_version, Message#giop_message.message, ?GIOP_HEADER_SIZE, Message#giop_message.byte_order, Bytes) end. %%----------------------------------------------------------------- %% Func: dec_byte_order/1 %% Args: %% The message as a byte sequence. %% Returns: %% A tuple {Endianness, Rest} where Endianness is big or little. %% Rest is the remaining message byte sequence. %%----------------------------------------------------------------- dec_byte_order(<<0:8,T/binary>>) -> {big, T}; dec_byte_order(<<1:8,T/binary>>) -> {little, T}. %%----------------------------------------------------------------- %% Func: dec_byte_order_list/1 %% Args: %% The message as a byte sequence. %% Returns: %% A tuple {Endianness, Rest} where Endianness is big or little. %% Rest is the remaining message byte sequence. %%----------------------------------------------------------------- dec_byte_order_list([0|T]) -> {big, T}; dec_byte_order_list([1|T]) -> {little, T}. %%----------------------------------------------------------------- %% Func : dec_response_flags %% Args : %% Returns : boolean %%----------------------------------------------------------------- %% FIX ME!! Not correct flag handling. dec_response_flags(_Version, <<0:8, Rest/binary>>, Len) -> {false, Rest, Len+1}; dec_response_flags(_Version, <<1:8, Rest/binary>>, Len) -> {true_oneway, Rest, Len+1}; dec_response_flags(_Version, <<3:8, Rest/binary>>, Len) -> {true, Rest, Len+1}; dec_response_flags(_Version, <<X:8, Rest/binary>>, Len) -> %% Not only the Response flag is set, test which. if %% Since the 6 most significant bits are unused we'll accept this for now. ((X band 16#03) == 16#03) -> {true, Rest, Len+1}; ((X band 16#01) == 16#01) -> {true_oneway, Rest, Len+1}; true -> {false, Rest, Len+1} end. %%----------------------------------------------------------------- %% Func : dec_target_addr %% Args : Octet %% Returns : boolean %%----------------------------------------------------------------- dec_target_addr(Version, Message, Len, ByteOrder, RequestId, Type) -> case dec_type(?TARGETADDRESS, Version, Message, Len, ByteOrder, [], 0) of {#'GIOP_TargetAddress'{label = ?GIOP_KeyAddr, value = KeyAddr}, Rest3, Len3, C} -> {dec_target_key(KeyAddr, RequestId, Version, Type), Rest3, Len3, C}; {#'GIOP_TargetAddress'{label = ?GIOP_ProfileAddr, value = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PA}}, Rest3, Len3, C} -> {dec_target_key(PA, RequestId, Version, Type), Rest3, Len3, C}; {#'GIOP_TargetAddress'{label = ?GIOP_ReferenceAddr, value = #'GIOP_IORAddressingInfo'{ selected_profile_index = _PI, ior = IOR}}, Rest3, Len3, C} -> {dec_target_key(iop_ior:get_objkey(IOR), RequestId, Version, Type), Rest3, Len3, C}; Other -> orber:dbg("[~p] cdr_decode:dec_target_addr(~p);~n" "Unsupported TargetAddress.", [?LINE, Other], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 12), completion_status=?COMPLETED_MAYBE}) end. %%----------------------------------------------------------------- %% Func : dec_target_key %% Args : Octet %% Returns : boolean %%----------------------------------------------------------------- dec_target_key(Key, RequestId, Version, Type) -> %% The Type argument is used as an identifier of which operation it is. %% We need it to be able to tell the difference if it's, for example, %% a request or locate-request. case corba:string_to_objkey_local(Key) of {location_forward, Object} -> throw({Type, Object, RequestId, Version, Key}); ObjRef -> ObjRef end. %%----------------------------------------------------------------- %% Func: dec_request_header/3 %% Args: %% Message - The message %% Len0 - Number of bytes already read. %% ByteOrder - little or big %% Returns: %%----------------------------------------------------------------- dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} -> {Request_id, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0, ByteOrder, [], 0), {ResponseFlags, Rest2, Len2} = dec_response_flags(Version, Rest1, Len1), {_, Rest2b, Len2b, _} = dec_type({'tk_array', 'tk_octet', 3}, Version, Rest2, Len2, ByteOrder, [], 0), {Object_key, Rest3, Len3, _} = dec_target_addr(Version, Rest2b, Len2b, ByteOrder, Request_id, 'location_forward'), {Operation, Rest4, Len4, _} = dec_type({'tk_string', 0}, Version, Rest3, Len3, ByteOrder, [], 0), {Context, Rest5, Len5} = dec_service_context(Version, Rest4, Len4, ByteOrder), {Version, #request_header{service_context=Context, request_id=Request_id, response_expected=ResponseFlags, object_key=Object_key, operation=list_to_atom(Operation), requesting_principal=""}, Rest5, Len5, ByteOrder}; dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) -> {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder), {Request_id, Rest2, Len2, _} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder, [], 0), {Response_expected, Rest3, Len3, _} = dec_type('tk_boolean', Version, Rest2, Len2, ByteOrder, [], 0), {ObjKey, Rest4, Len4, _} = dec_type({'tk_sequence', 'tk_octet', 0}, Version, Rest3, Len3, ByteOrder, [], 0), Object_key = dec_target_key(ObjKey, Request_id, Version, 'location_forward'), {Operation, Rest5, Len5, _} = dec_type({'tk_string', 0}, Version, Rest4, Len4, ByteOrder, [], 0), {Principal, Rest, Len, _} = dec_type({'tk_string', 0}, Version, Rest5,Len5, ByteOrder, [], 0), {Version, #request_header{service_context=Context, request_id=Request_id, response_expected=Response_expected, object_key=Object_key, operation=list_to_atom(Operation), requesting_principal=Principal}, Rest, Len, ByteOrder}. %%----------------------------------------------------------------- %% Func: dec_service_context/4 %% Args: Version - e.g. 1.2 %% Message - The message %% Len - Number of bytes already read. %% ByteOrder - little or big %% Returns: %%----------------------------------------------------------------- dec_service_context(Version, Message, Len, ByteOrder) -> {Context, Rest, Len1} = dec_type(?IOP_SERVICECONTEXT, Version, Message, Len, ByteOrder), {dec_used_contexts(Version, Context, []), Rest, Len1}. dec_used_contexts(_Version, [], Ctxs) -> Ctxs; dec_used_contexts({1,0}, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets}|T], Ctxs) -> %% Not supported by 1.0, drop it. dec_used_contexts({1,0}, T, Ctxs); dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets, context_data = Bytes}|T], Ctxs) -> {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)), {CodeCtx, _, _} = dec_type(?CONV_FRAME_CODESETCONTEXT, Version, Rest, 1, ByteOrder), dec_used_contexts(Version, T, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets, context_data = CodeCtx}|Ctxs]); dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP, context_data = Bytes}|T], Ctxs) -> {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)), {BiDirCtx, _, _} = dec_type(?IIOP_BIDIRIIOPSERVICECONTEXT, Version, Rest, 1, ByteOrder), dec_used_contexts(Version, T, [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP, context_data = BiDirCtx}|Ctxs]); dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST, context_data = Bytes}|T], Ctxs) -> {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)), {Ctx, _, _} = dec_type(?FT_FTRequestServiceContext, Version, Rest, 1, ByteOrder), dec_used_contexts(Version, T, [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST, context_data = Ctx}|Ctxs]); dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION, context_data = Bytes}|T], Ctxs) -> {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)), {Ctx, _, _} = dec_type(?FT_FTGroupVersionServiceContext, Version, Rest, 1, ByteOrder), dec_used_contexts(Version, T, [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION, context_data = Ctx}|Ctxs]); dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, context_data = Bytes}|T], Ctxs) -> {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)), {Ctx, _, _} = dec_type(?CSI_SASContextBody, Version, Rest, 1, ByteOrder), dec_used_contexts(Version, T, [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, context_data = Ctx}|Ctxs]); dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID, context_data = Bytes}|T], Ctxs) -> {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)), {Ctx, _, _} = dec_type(?ORBER_GENERIC_CTX, Version, Rest, 1, ByteOrder), dec_used_contexts(Version, T, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID, context_data = binary_to_term(list_to_binary(Ctx))}|Ctxs]); dec_used_contexts(Version, [H|T], Ctxs) -> dec_used_contexts(Version, T, [H|Ctxs]). %%----------------------------------------------------------------- %% Func: dec_request_body %% Args: Version - e.g. 1.2 %% Returns: %%----------------------------------------------------------------- dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Buffer) -> {Parameters, TypeCodes, _} = dec_request_body(Version, ReqHdr#request_header.object_key, ReqHdr#request_header.operation, Rest, Len, ByteOrder, Buffer, Len), {Version, ReqHdr, Parameters, TypeCodes}. dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter) when Version == {1,2} -> case orber_typedefs:get_op_def(Object_key, Operation) of {RetType, [], OutParameters} -> {[], {RetType, [], OutParameters}, Len}; {RetType, InParameters, OutParameters} -> {Rest, Len1, NewC} = dec_align(Body, Len, 8, Counter), {Parameters, Len2} = dec_parameters(Version, InParameters, Rest, Len1, ByteOrder, Buffer, NewC), {Parameters, {RetType, InParameters, OutParameters}, Len2} end; dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter) -> {RetType, InParameters, OutParameters} = orber_typedefs:get_op_def(Object_key, Operation), {Parameters, Len1} = dec_parameters(Version, InParameters, Body, Len, ByteOrder, Buffer, Counter), {Parameters, {RetType, InParameters, OutParameters}, Len1}. dec_parameters(_, [], _, Len, _, _, _) -> {[], Len}; dec_parameters(Version, [P1 |InParList], Body, Len, ByteOrder, Buffer, Counter) -> {Object, Rest, Len1, NewCounter} = dec_type(P1, Version, Body, Len, ByteOrder, Buffer, Counter), {List, Len2} = dec_parameters(Version, InParList, Rest, Len1, ByteOrder, Buffer, NewCounter), {[Object | List], Len2}. %%----------------------------------------------------------------- %% Func: dec_reply/5 %% Args: %% Message - The message %% Len0 - Number of bytes already read. %% ByteOrder - little or big %% Returns: %% A tuple {ReplyHeader, Result} where ReplyHeader is a %% reply_header record and Result the decode result. %%----------------------------------------------------------------- dec_reply(Version, TypeCodes, Message, Len0, ByteOrder) -> {ReplyHeader, Rest, Len} = dec_reply_header(Version, Message, Len0, ByteOrder), {Result, Par} = case ReplyHeader#reply_header.reply_status of 'no_exception' -> {R, P, _} = dec_reply_body(Version, TypeCodes, Rest, Len, ByteOrder, Message), {R, P}; 'system_exception' -> {R, _} = dec_system_exception(Version, Rest, Len, ByteOrder), {R, []}; 'user_exception' -> {R, _} = dec_user_exception(Version, Rest, Len, ByteOrder), {R, []}; 'location_forward' -> {R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]}, Rest, Len, ByteOrder, Message), {R, []}; %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for %% now. 'location_forward_perm' -> {R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]}, Rest, Len, ByteOrder, Message), {R, []}; 'needs_addressing_mode' -> {R, _, _} = dec_reply_body(Version, {'tk_short', [],[]}, Rest, Len, ByteOrder, Message), {R, []} end, {ReplyHeader, Result, Par}. %% ## NEW IIOP 1.2 ## dec_reply_header(Version, Message, Len0, ByteOrder) when Version == {1,2} -> {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len0, ByteOrder), {ReplyStatus, Rest2, Len2} = dec_reply_status(Version, Rest1, Len1, ByteOrder), {Context, Rest, Len3} = dec_service_context(Version, Rest2, Len2, ByteOrder), {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus}, Rest, Len3}; dec_reply_header(Version, Message, Len0, ByteOrder) -> {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder), {Request_id, Rest2, Len2} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder), {ReplyStatus, Rest, Len3} = dec_reply_status(Version, Rest2, Len2, ByteOrder), {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus}, Rest, Len3}. dec_reply_status(Version, Status, Len, ByteOrder) -> {L, Rest, Len1}= dec_type('tk_ulong', Version, Status, Len, ByteOrder), {dec_giop_reply_status_type(L), Rest, Len1}. dec_reply_body(_, {'tk_void', _, []}, <<>>, Len, _, _) -> %% This case is mainly to be able to avoid removing non-existent alignment for %% IIOP-1.2 messages if the body should be empty, i.e., void return value and %% no out parameters. {ok, [], Len}; dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len, ByteOrder, Bytes) when Version == {1,2} -> {Rest, Len1, Counter} = dec_align(Body, Len, 8, Len), {Result, Rest2, Len2, C} = dec_type(RetType, Version, Rest, Len1, ByteOrder, Bytes, Counter), {Par, Len3} = dec_parameters(Version, OutParameters, Rest2, Len2, ByteOrder, Bytes, C), {Result, Par, Len3}; dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len, ByteOrder, Bytes) -> {Result, Rest, Len1, C} = dec_type(RetType, Version, Body, Len, ByteOrder, Bytes, Len), {Par, Len2} = dec_parameters(Version, OutParameters, Rest, Len1, ByteOrder, Bytes, C), {Result, Par, Len2}. %%----------------------------------------------------------------- %% Func: dec_cancel_request/3 %% Args: %% Message - The message %% Len - Number of bytes already read. %% ByteOrder - little or big %% Returns: %% A cancel_request_header record. %%----------------------------------------------------------------- dec_cancel_request(Version, Message, Len, ByteOrder) -> {Request_id, _, _} = dec_type('tk_ulong', Version, Message, Len, ByteOrder), #cancel_request_header{request_id=Request_id}. %%----------------------------------------------------------------- %% Func: dec_locate_request/3 %% Args: %% Message - The message %% Len - Number of bytes already read. %% ByteOrder - little or big %% Returns: %% A locate_request_header record. %%----------------------------------------------------------------- %% ## NEW IIOP 1.2 ## dec_locate_request(Version, Message, Len, ByteOrder) when Version == {1,2} -> {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder), {Object_key, _, _, _} = dec_target_addr(Version, Rest, Len1, ByteOrder, Request_id, 'object_forward'), {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}}; dec_locate_request(Version, Message, Len, ByteOrder) -> {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder), {ObjKey, _, _} = dec_type({'tk_sequence', 'tk_octet', 0}, Version, Rest, Len1, ByteOrder), Object_key = dec_target_key(ObjKey, Request_id, Version, 'object_forward'), {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}}. %%----------------------------------------------------------------- %% Func: dec_locate_reply/3 %% Args: %% Message - The message %% Len - Number of bytes already read. %% ByteOrder - little or big %% Returns: %% A locate_reply_header record. %%----------------------------------------------------------------- dec_locate_reply(Version, Message, Len, ByteOrder) -> {ReplyHeader, Rest1, Len1} = dec_locate_reply_header(Version, Message, Len, ByteOrder), {ReplyHeader, dec_locate_reply_body(Version, ReplyHeader#locate_reply_header.locate_status, Rest1, Len1, ByteOrder)}. dec_locate_reply_header(Version, Message, Len, ByteOrder) -> {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder), {Locate_status, Rest2, Len2} = dec_locate_status(Version, Rest1, Len1, ByteOrder), {#locate_reply_header{request_id=Request_id, locate_status=Locate_status}, Rest2, Len2}. dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) when Version == {1,2} -> %% In CORBA-2.3.1 the LocateReply body didn't align the body (8-octet %% boundry) for IIOP-1.2. This have been changed in CORBA-2.4 and %% changed back in CORBA-2.6. Hence, we should not change this. case LocateStatus of 'object_forward' -> {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder), ObjRef; 'object_forward_perm' -> %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for %% now. {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder), ObjRef; 'loc_system_exception' -> %% This should be updated but since 'dec_system_exception' removes %% alignment, which the LocateReplyBody don't have, for 1.2 we %% pretend it's 1.1 for now. {SysExc, _} = dec_system_exception({1,1}, Rest, Len, ByteOrder), corba:raise(SysExc); 'loc_needs_addressing_mode' -> %% Not supported. []; _ -> [] end; dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) -> case LocateStatus of 'object_forward' -> {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder), ObjRef; _ -> [] end. dec_locate_status(Version, Bytes, Len, ByteOrder) -> {L, Rest, Len1} = dec_type('tk_ulong', Version, Bytes, Len, ByteOrder), {dec_giop_locate_status_type(L), Rest, Len1}. %%----------------------------------------------------------------- %% Func: dec_fragment_header/5 %% Args: %% Message - The message %% Len0 - Number of bytes already read. %% ByteOrder - little or big %% Returns: %%----------------------------------------------------------------- dec_fragment_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} -> {RequestId, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0, ByteOrder, [], 0), {Version, #fragment_header{request_id=RequestId}, Rest1, Len1, ByteOrder}; dec_fragment_header(Version, _Message, _Len0, _ByteOrder, _Buffer) -> %% The FragmentHeader is IIOP-1.2 specific. Hence, do nothing here. orber:dbg("[~p] cdr_decode:dec_fragment_header(~p)~n" "Orber only supports fragmented messages for IIOP-1.2.", [?LINE, Version], ?DEBUG_LEVEL), exit(message_error). % {Version, #fragment_header{}, Message, Len0, ByteOrder}. %%----------------------------------------------------------------- %% Func: dec_giop_reply_status_type %% Args: %% An integer status code %% Returns: %% An atom which is the reply status %%----------------------------------------------------------------- dec_giop_reply_status_type(0) -> 'no_exception'; dec_giop_reply_status_type(1) -> 'user_exception'; dec_giop_reply_status_type(2) -> 'system_exception'; dec_giop_reply_status_type(3) -> 'location_forward'; %% ## IIOP-1.2 ## dec_giop_reply_status_type(4) -> 'location_forward_perm'; dec_giop_reply_status_type(5) -> 'needs_addressing_mode'. %%----------------------------------------------------------------- %% Func: dec_giop_locate_status_type %% Args: %% An integer status code %% Returns: %% An atom which is the reply status %%----------------------------------------------------------------- dec_giop_locate_status_type(0) -> 'unknown_object'; dec_giop_locate_status_type(1) -> 'object_here'; dec_giop_locate_status_type(2) -> 'object_forward'; %% ## IIOP-1.2 ## dec_giop_locate_status_type(3) -> 'object_forward_perm'; dec_giop_locate_status_type(4) -> 'loc_system_exception'; dec_giop_locate_status_type(5) -> 'loc_needs_addressing_mode'. %%----------------------------------------------------------------- %% Func: dec_type/5 %%----------------------------------------------------------------- dec_type(Type, Version, Bytes, Len, ByteOrder) -> {Val, Rest, Len2, _} = dec_type(Type, Version, Bytes, Len, ByteOrder, [], 0), {Val, Rest, Len2}. dec_type('tk_null', _Version, Bytes, Len, _, _, C) -> {'null', Bytes, Len, C}; dec_type('tk_void', _Version, Bytes, Len, _, _, C) -> {'ok', Bytes, Len, C}; dec_type('tk_short', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C), {Short, Rest1} = cdrlib:dec_short(ByteOrder, Rest), {Short, Rest1, Len1 + 2, NewC+2}; dec_type('tk_long', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C), {Long, Rest1} = cdrlib:dec_long(ByteOrder, Rest), {Long, Rest1, Len1 + 4, NewC+4}; dec_type('tk_longlong', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C), {Long, Rest1} = cdrlib:dec_longlong(ByteOrder, Rest), {Long, Rest1, Len1 + 8, NewC+8}; dec_type('tk_ushort', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C), {Short, Rest1} = cdrlib:dec_unsigned_short(ByteOrder, Rest), {Short, Rest1, Len1 + 2, NewC+2}; dec_type('tk_ulong', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C), {Long, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), {Long, Rest1, Len1 + 4, NewC+4}; dec_type('tk_ulonglong', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C), {Long, Rest1} = cdrlib:dec_unsigned_longlong(ByteOrder, Rest), {Long, Rest1, Len1 + 8, NewC+8}; dec_type('tk_float', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C), {Float, Rest1} = cdrlib:dec_float(ByteOrder, Rest), {Float, Rest1, Len1 + 4, NewC+4}; dec_type('tk_double', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C), {Double, Rest1} = cdrlib:dec_double(ByteOrder, Rest), {Double, Rest1, Len1 + 8, NewC+8}; dec_type('tk_boolean', _Version, Bytes, Len, _, _, C) -> {Bool, Rest} = cdrlib:dec_bool(Bytes), {Bool, Rest, Len + 1, C+1}; dec_type('tk_char', _Version, Bytes, Len, _, _, C) -> {Char, Rest} = cdrlib:dec_char(Bytes), {Char, Rest, Len + 1, C+1}; dec_type('tk_wchar', {1,2}, Bytes, Len, _ByteOrder, _, C) -> %% For IIOP-1.2 a wchar is almost encoded the same way as an octet-sequence. %% The only difference is that the length-value is an octet as well. case cdrlib:dec_octet(Bytes) of {2, Rest1} -> %% Currently we only allow 2-bytes wchar. {WChar, Rest2} = cdrlib:dec_unsigned_short(big, Rest1), {WChar, Rest2, Len+3, C+3}; {What, _} -> orber:dbg("[~p] cdr_decode:dec_type(~p); unsupported wchar", [?LINE, What], ?DEBUG_LEVEL), corba:raise(#'DATA_CONVERSION'{completion_status=?COMPLETED_NO}) end; %% For 1.1 the wchar is limited to the use of two-octet fixed-length encoding. dec_type('tk_wchar', _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C), {WChar, Rest2} = cdrlib:dec_unsigned_short(ByteOrder, Rest), {WChar, Rest2, Len1 + 2, NewC+2}; dec_type('tk_octet', _Version, Bytes, Len, _, _, C) -> {Octet, Rest} = cdrlib:dec_octet(Bytes), {Octet, Rest, Len + 1, C+1}; dec_type('tk_any', Version, Bytes, Len, ByteOrder, Buff, C) -> {TypeCode, Rest1, Len1, NewC} = dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C), {Value, Rest2, Len2, NewC2} = dec_type(TypeCode, Version, Rest1, Len1, ByteOrder, Buff, NewC), {#any{typecode=TypeCode, value=Value}, Rest2, Len2, NewC2}; dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C) -> dec_type_code(Version, Bytes, Len, ByteOrder, Buff, C); dec_type('tk_Principal', Version, Bytes, Len, ByteOrder, Buff, C) -> dec_sequence(Version, Bytes, 'tk_octet', Len, ByteOrder, Buff, C); dec_type({'tk_objref', _IFRId, _Name}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_objref(Version, Bytes, Len, ByteOrder, Buff, C); dec_type({'tk_struct', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_struct(Version, IFRId, Name, ElementList, Bytes, Len, ByteOrder, Buff, C); dec_type({'tk_union', IFRId, Name, DiscrTC, Default, ElementList}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_union(Version, IFRId, Name, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C); dec_type({'tk_enum', _IFRId, _Name, ElementList}, _Version, Bytes, Len, ByteOrder, _, C) -> {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C), {Enum, Rest1} = cdrlib:dec_enum(ByteOrder, ElementList, Rest), {Enum, Rest1, Len1 + 4, NewC+4}; dec_type({'tk_string', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_string(Version, Bytes, Len, ByteOrder, Buff, C); dec_type({'tk_wstring', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_wstring(Version, Bytes, Len, ByteOrder, Buff, C); dec_type({'tk_sequence', ElemTC, _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_sequence(Version, Bytes, ElemTC, Len, ByteOrder, Buff, C); dec_type({'tk_array', ElemTC, Size}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_array(Version, Bytes, Size, ElemTC, Len, ByteOrder, Buff, C); dec_type({'tk_alias', _IFRId, _Name, TC}, Version, Bytes, Len, ByteOrder, Buff, C) -> dec_type(TC, Version, Bytes, Len, ByteOrder, Buff, C); %dec_type({'tk_except', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder) -> dec_type({'tk_fixed', Digits, Scale}, _Version, Bytes, Len, _ByteOrder, _Buff, C) -> dec_fixed(Digits, Scale, Bytes, Len, C); dec_type(Type, _, _, _, _, _, _) -> orber:dbg("[~p] cdr_decode:dec_type(~p)~n" "Incorrect TypeCode or unsupported type.", [?LINE, Type], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 13), completion_status=?COMPLETED_MAYBE}). stringify_enum({tk_enum,_,_,_}, Label) -> atom_to_list(Label); stringify_enum(_, Label) -> Label. %%----------------------------------------------------------------- %% Func: dec_fixed %%----------------------------------------------------------------- %% Digits eq. total number of digits. %% Scale eq. position of the decimal point. %% E.g. fixed<5,2> - "123.45" %% E.g. fixed<4,2> - "12.34" %% These are encoded as: %% ## <5,2> ## ## <4,2> ## %% 1,2 0,1 eq. 1 octet %% 3,4 2,3 %% 5,0xC 4,0xC %% %% Each number is encoded as a half-octet. Note, for <4,2> a zero is %% added first to to be able to create "even" octets. dec_fixed(0, 0, Bytes, Len, C) -> {#fixed{digits = 0, scale = 0, value = ""}, Bytes, Len, C}; dec_fixed(Digits, Scale, Bytes, Len, C) -> case ?ODD(Digits) of true -> {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits, Scale, Bytes, Len, C), case Sign of ?FIXED_POSITIVE -> {#fixed{digits = Digits, scale = Scale, value = list_to_integer(Fixed)}, Bytes2, Len2, C2}; ?FIXED_NEGATIVE -> {#fixed{digits = Digits, scale = Scale, value = -list_to_integer(Fixed)}, Bytes2, Len2, C2} end; false -> %% If the length (of fixed) is even a zero is added first. %% Subtract that we've read 1 digit. <<0:4,D2:4,T/binary>> = Bytes, {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits-1, Scale, T, Len+1, C+1), case Sign of ?FIXED_POSITIVE -> {#fixed{digits = Digits, scale = Scale, value = list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2}; ?FIXED_NEGATIVE -> {#fixed{digits = Digits, scale = Scale, value = -list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2} end end. dec_fixed_2(1, _Scale, <<D1:4,?FIXED_POSITIVE:4,T/binary>>, Len, C) -> {[D1+48], T, Len+1, C+1, ?FIXED_POSITIVE}; dec_fixed_2(1, _Scale, <<D1:4,?FIXED_NEGATIVE:4,T/binary>>, Len, C) -> {[D1+48], T, Len+1, C+1, ?FIXED_NEGATIVE}; dec_fixed_2(Digits, Scale, _Bytes, _Len, _C) when Digits =< 0 -> orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n" "Malformed fixed type.", [?LINE, Digits, Scale], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE}); dec_fixed_2(Digits, Scale, <<>>, _Len, _C) -> orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n" "The fixed type received was to short.", [?LINE, Digits, Scale], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE}); dec_fixed_2(Digits, Scale, <<D1:4,D2:4,T/binary>>, Len, C) -> {Seq, Rest2, Len2, NewC2, Sign} = dec_fixed_2(Digits-2, Scale, T, Len+1, C+1), {[D1+48, D2+48 | Seq], Rest2, Len2, NewC2, Sign}. %%----------------------------------------------------------------- %% Func: dec_sequence/7 and dec_sequence/8 %%----------------------------------------------------------------- dec_sequence(_Version, Message, 'tk_octet', Len, ByteOrder, _Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), <<OctetSeq:Size/binary, Rest2/binary>> = Rest1, {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size}; dec_sequence(_Version, Message, 'tk_char', Len, ByteOrder, _Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), <<OctetSeq:Size/binary, Rest2/binary>> = Rest1, {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size}; %% We test if it's a sequence of struct's or unions. By doing this we only %% have to look up the IFR-ID once instead of N times (N eq length of sequence). dec_sequence(Version, Message, {'tk_struct', IFRId, ShortName, ElementList}, Len, ByteOrder, Buff, C) when IFRId /= "", ShortName /= "" -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), case IFRId of ?SYSTEM_TYPE -> dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4, ByteOrder, Buff, NewC+4, ShortName); _ -> Name = ifrid_to_name(IFRId, ?IFR_StructDef), dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4, ByteOrder, Buff, NewC+4, Name) end; dec_sequence(Version, Message, {'tk_union', ?SYSTEM_TYPE, TCName, DiscrTC, Default, ElementList}, Len, ByteOrder, Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4, ByteOrder, Buff, NewC+4, TCName); dec_sequence(Version, Message, {'tk_union', IFRId, _TCName, DiscrTC, Default, ElementList}, Len, ByteOrder, Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), Name = ifrid_to_name(IFRId, ?IFR_UnionDef), dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4, ByteOrder, Buff, NewC+4, Name); dec_sequence(Version, Message, TypeCode, Len, ByteOrder, Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), dec_sequence(Version, Rest1, Size, TypeCode, Len1 + 4, ByteOrder, Buff, NewC+4). dec_sequence(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C) -> {[], Message, Len, C}; dec_sequence(Version, Message, N, Type, Len, ByteOrder, Buff, C) -> {Object, Rest1, Len1, NewC} = dec_type(Type, Version, Message, Len, ByteOrder, Buff, C), {Seq, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, N - 1, Type, Len1, ByteOrder, Buff, NewC), {[Object | Seq], Rest2, Len2, NewC2}. dec_sequence_struct(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C, _Name) -> {[], Message, Len, C}; dec_sequence_struct(Version, Message, N, TypeCodeList, Len, ByteOrder, Buff, C, Name) -> {Struct, Rest1, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C), {Seq, Rest2, Len2, NewC2} = dec_sequence_struct(Version, Rest1, N - 1, TypeCodeList, Len1, ByteOrder, Buff, NewC, Name), {[list_to_tuple([Name |Struct]) | Seq], Rest2, Len2, NewC2}. dec_sequence_union(_, Message, 0, _DiscrTC, _Default, _ElementList, Len, _ByteOrder, _Buff, C, _Name) -> {[], Message, Len, C}; dec_sequence_union(Version, Message, N, DiscrTC, Default, ElementList, Len, ByteOrder, Buff, C, Name) when is_list(ElementList) -> {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Message, Len, ByteOrder, Buff, C), Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default, Rest1, Len1, ByteOrder, Buff, NewC), {Value, Rest2, Len2, NewC3} = case Result of {default, R, L, NewC2} -> dec_union(Version, default, ElementList, Default, R, L, ByteOrder, Buff, NewC2); X -> X end, {Seq, Rest3, Len3, NewC4} = dec_sequence_union(Version, Rest2, N - 1, DiscrTC, Default, ElementList, Len2, ByteOrder, Buff, NewC3, Name), {[{Name, Label, Value} | Seq], Rest3, Len3, NewC4}; dec_sequence_union(Version, Message, N, _DiscrTC, _Default, Module, Len, ByteOrder, Buff, C, Name) when is_atom(Module) -> case catch Module:tc() of {tk_union, _, _, DiscrTC, Default, ElementList} -> dec_sequence_union(Version, Message, N, DiscrTC, Default, ElementList, Len, ByteOrder, Buff, C, Name); What -> orber:dbg("[~p] ~p:dec_sequence_union(~p). Union module doesn't exist or incorrect.", [?LINE, ?MODULE, What], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE}) end. %% A special case; when something is encapsulated (i.e. sent as octet-sequence) %% we sometimes don not want the result to be converted to a list. dec_octet_sequence_bin(_Version, Message, Len, ByteOrder, _Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), <<OctetSeq:Size/binary, Rest2/binary>> = Rest1, {OctetSeq, Rest2, Len1+4+Size, NewC+4+Size}. %%----------------------------------------------------------------- %% Func: dec_array/5 %%----------------------------------------------------------------- dec_array(Version, Message, Size, TypeCode, Len, ByteOrder, Buff, C) -> {Seq, Rest1, Len1, NewC} = dec_sequence(Version, Message, Size, TypeCode, Len, ByteOrder, Buff, C), {list_to_tuple(Seq), Rest1, Len1, NewC}. %%----------------------------------------------------------------- %% Func: dec_string/4 %%----------------------------------------------------------------- dec_string(_Version, Message, Len, ByteOrder, _Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), if Size > 0 -> DataSize = Size-1, <<String:DataSize/binary, _Null:1/binary, Rest2/binary>> = Rest1, {binary_to_list(String), Rest2, Len1+4+Size, NewC+4+Size}; true -> {"", Rest1, Len1 + 4, NewC+4} end. %%----------------------------------------------------------------- %% Func: dec_string/4 %%----------------------------------------------------------------- dec_wstring({1,2}, Message, Len, ByteOrder, Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Octets, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), if Octets == 0 -> {"", Rest1, Len1 + 4, NewC+4}; Octets > 0 -> Size = round(Octets/2), {String, Rest2, Len2, NewC2} = dec_sequence({1,2}, Rest1, Size, 'tk_ushort', Len1 + 4, big, Buff, NewC+4), {String, Rest2, Len2, NewC2}; true -> orber:dbg("[~p] cdr_decode:dec_wstring(~p);", [?LINE, Rest1], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO}) end; dec_wstring(Version, Message, Len, ByteOrder, Buff, C) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, C), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), if Size > 0 -> {String, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, Size - 1, 'tk_wchar', Len1 + 4, ByteOrder, Buff, NewC+4), %% Remove the NULL character. {_, Rest3} = cdrlib:dec_unsigned_short(ByteOrder, Rest2), {String, Rest3, Len2 + 2, NewC2+2}; Size == 0 -> {"", Rest1, Len1 + 4, NewC+4}; true -> orber:dbg("[~p] cdr_decode:dec_wstring(~p);", [?LINE, Rest1], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO}) end. %%----------------------------------------------------------------- %% Func: dec_union/9 %%----------------------------------------------------------------- %% ## NEW IIOP 1.2 ## dec_union(Version, ?SYSTEM_TYPE, Name, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C) -> {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C), {Value, Rest2, Len2, NewC3} = dec_union(Version, Label, ElementList, Default, Rest1, Len1, ByteOrder, Buff, NewC), {{Name, Label, Value}, Rest2, Len2, NewC3}; dec_union(Version, IFRId, _, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C) when is_list(ElementList) -> {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C), Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default, Rest1, Len1, ByteOrder, Buff, NewC), {Value, Rest2, Len2, NewC3} = case Result of {default, R, L, NewC2} -> dec_union(Version, default, ElementList, Default, R, L, ByteOrder, Buff, NewC2); X -> X end, Name = ifrid_to_name(IFRId, ?IFR_UnionDef), {{Name, Label, Value}, Rest2, Len2, NewC3}; dec_union(Version, IFRId, _, _DiscrTC, _Default, Module, Bytes, Len, ByteOrder, Buff, C) when is_atom(Module) -> case catch Module:tc() of {tk_union, _, Name, DiscrTC, Default, ElementList} -> dec_union(Version, IFRId, Name, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C); What -> orber:dbg("[~p] ~p:dec_union(~p). Union module doesn't exist or incorrect.", [?LINE, ?MODULE, What], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE}) end. dec_union(_, _, [], Default, Message, Len, _, _Buff, C) when Default < 0 -> {undefined, Message, Len, C}; dec_union(_, _, [], _Default, Message, Len, _, _Buff, C) -> {default, Message, Len, C}; dec_union(Version, Label, [{Label, _Name, Type}|_List], _Default, Message, Len, ByteOrder, Buff, C) -> dec_type(Type, Version, Message, Len, ByteOrder, Buff, C); dec_union(Version, Label, [_H|List], Default, Message, Len, ByteOrder, Buff, C) -> dec_union(Version, Label, List, Default, Message, Len, ByteOrder, Buff, C). %%----------------------------------------------------------------- %% Func: dec_struct/7 %%----------------------------------------------------------------- dec_struct(Version, "", "", TypeCodeList, Message, Len, ByteOrder, Buff, C) -> {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C), {list_to_tuple(Struct), Rest, Len1, NewC}; dec_struct(Version, [], Name, TypeCodeList, Message, Len, ByteOrder, Buff, C) -> %% This case is used when communicating with ORB:s which don't supply the IFRId %% field in struct type codes (used in any) {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C), {list_to_tuple([list_to_atom(Name) |Struct]), Rest, Len1, NewC}; dec_struct(Version, ?SYSTEM_TYPE, ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) -> {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C), {list_to_tuple([ShortName |Struct]), Rest, Len1, NewC}; dec_struct(Version, IFRId, _ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) -> Name = ifrid_to_name(IFRId, ?IFR_StructDef), {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C), {list_to_tuple([Name |Struct]), Rest, Len1, NewC}. dec_struct1(_, [], Message, Len, _ByteOrder, _, C) -> {[], Message, Len, C}; dec_struct1(Version, [{_ElemName, ElemType} | TypeCodeList], Message, Len, ByteOrder, Buff, C) -> {Element, Rest, Len1, NewC} = dec_type(ElemType, Version, Message, Len, ByteOrder, Buff, C), {Struct, Rest1, Len2, NewC2} = dec_struct1(Version, TypeCodeList, Rest, Len1, ByteOrder, Buff, NewC), {[Element |Struct], Rest1, Len2, NewC2}; dec_struct1(Version, Module, Message, Len, ByteOrder, Buff, C) -> case catch Module:tc() of {tk_struct, _, _, TypeCodeList} -> dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C); What -> orber:dbg("[~p] ~p:dec_struct1(~p). Struct module doesn't exist or incorrect.", [?LINE, ?MODULE, What], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE}) end. ifrid_to_name([], Type) -> orber:dbg("[~p] ~p:ifrid_to_name([], ~p). No Id supplied.", [?LINE, ?MODULE, Type], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?CORBA_OMGVMCID bor 11), completion_status=?COMPLETED_MAYBE}); ifrid_to_name(Id, Type) -> case orber:light_ifr() of true -> orber_ifr:get_module(Id, Type); false -> case catch ifrid_to_name_helper(Id, Type) of {'EXCEPTION', E} -> corba:raise(E); {'EXIT',{aborted,{no_exists,_}}} -> case orber:get_lightweight_nodes() of false -> orber:dbg("[~p] cdr_decode:ifrid_to_name(~p, ~p). IFRid not found.", [?LINE, Id, Type], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE}); Nodes -> L = length(Nodes), IFR = get_ifr_node(Nodes, rand:uniform(L), L), list_to_atom('OrberApp_IFR':get_absolute_name(IFR, Id)) end; {'EXIT', Other} -> orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). Unknown: ~p", [?LINE, Id, Other], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE}); Name -> list_to_atom(Name) end end. ifrid_to_name_helper(Id, ?IFR_UnionDef) -> case mnesia:dirty_index_read(ir_UnionDef, Id, #ir_UnionDef.id) of [#ir_UnionDef{absolute_name = [$:,$:|N]}] -> change_colons_to_underscore(N, []); Other -> orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p", [?LINE, Id, Other], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 9), completion_status=?COMPLETED_MAYBE}) end; ifrid_to_name_helper(Id, ?IFR_StructDef) -> case mnesia:dirty_index_read(ir_StructDef, Id, #ir_StructDef.id) of [#ir_StructDef{absolute_name = [$:,$:|N]}] -> change_colons_to_underscore(N, []); Other -> orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p", [?LINE, Id, Other], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 10), completion_status=?COMPLETED_MAYBE}) end; ifrid_to_name_helper(Id, ?IFR_ExceptionDef) -> case mnesia:dirty_index_read(ir_ExceptionDef, Id, #ir_ExceptionDef.id) of [#ir_ExceptionDef{absolute_name = [$:,$:|N]}] -> change_colons_to_underscore(N, []); Other -> orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p", [?LINE, Id, Other], ?DEBUG_LEVEL), corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1), completion_status=?COMPLETED_MAYBE}) end. change_colons_to_underscore([$:, $: | T], Acc) -> change_colons_to_underscore(T, [$_ |Acc]); change_colons_to_underscore([H |T], Acc) -> change_colons_to_underscore(T, [H |Acc]); change_colons_to_underscore([], Acc) -> lists:reverse(Acc). get_ifr_node([], _, _) -> %% Were not able to contact any of the given nodes. orber:dbg("[~p] cdr_decode:get_ifr_node([]). No Node available.", [?LINE], ?DEBUG_LEVEL), corba:raise(#'INTERNAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_MAYBE}); get_ifr_node(Nodes, N, L) -> Node = lists:nth(N, Nodes), case catch corba:resolve_initial_references_remote("OrberIFR", [Node]) of IFR when is_record(IFR, 'IOP_IOR') -> IFR; _ -> %% Not able to commincate with the node. Try next one. NewL = L-1, get_ifr_node(lists:delete(Node, Nodes), rand:uniform(NewL), NewL) end. %%----------------------------------------------------------------- %% Func: dec_objref/4 %%----------------------------------------------------------------- dec_objref(Version, Message, Len, ByteOrder) -> dec_objref(Version, Message, Len, ByteOrder, [], 0). dec_objref(Version, Message, Len, ByteOrder, _Buff, C) -> {IOR, Rest, Length} = iop_ior:decode(Version, Message, Len, ByteOrder), {IOR, Rest, Length, C+Length-Len}. %%----------------------------------------------------------------- %% Func: dec_system_exception/4 and dec_user_exception/4 %%----------------------------------------------------------------- dec_system_exception(Version, Message, Len, ByteOrder) when Version == {1,2} -> {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len), {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder), Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION), {Struct, _Rest2, Len2} = dec_exception_1(Version, [{"minor",'tk_ulong'}, {"completed", {'tk_enum', "", "completion_status", ["COMPLETED_YES", "COMPLETED_NO", "COMPLETED_MAYBE"]}}], Rest1, Len1, ByteOrder), {list_to_tuple([Name, "" |Struct]), Len2}; dec_system_exception(Version, Message, Len, ByteOrder) -> {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder), Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION), {Struct, _Rest2, Len2} = dec_exception_1(Version, [{"minor",'tk_ulong'}, {"completed", {'tk_enum', "", "completion_status", ["COMPLETED_YES", "COMPLETED_NO", "COMPLETED_MAYBE"]}}], Rest1, Len1, ByteOrder), {list_to_tuple([Name, "" |Struct]), Len2}. dec_user_exception(Version, Message, Len, ByteOrder) when Version == {1,2} -> {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len), {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder), Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef), {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId), {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1, ByteOrder), {list_to_tuple([Name, TypeId |Struct]), Len2}; dec_user_exception(Version, Message, Len, ByteOrder) -> {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder), Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef), {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId), {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1, ByteOrder), {list_to_tuple([Name, TypeId |Struct]), Len2}. dec_exception_1(_, [], Message, Len, _ByteOrder) -> {[], Message, Len}; dec_exception_1(Version, [{_ElemName, ElemType} | ElementList], Message, Len, ByteOrder) -> {Element, Rest, Len1} = dec_type(ElemType, Version, Message, Len, ByteOrder), {Struct, Rest1, Len2} = dec_exception_1(Version, ElementList, Rest, Len1, ByteOrder), {[Element |Struct], Rest1, Len2}. get_user_exception_type(TypeId) -> case orber:light_ifr() of true -> orber_ifr:get_tc(TypeId, ?IFR_ExceptionDef); false -> case orber:get_lightweight_nodes() of false -> case mnesia:dirty_index_read(ir_ExceptionDef, TypeId, #ir_ExceptionDef.id) of [ExcDef] when is_record(ExcDef, ir_ExceptionDef) -> ExcDef#ir_ExceptionDef.type; Other -> orber:dbg("[~p] cdr_decode:get_user_exception_type(~p). IFR Id not found: ~p", [?LINE, TypeId, Other], ?DEBUG_LEVEL), corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1), completion_status=?COMPLETED_MAYBE}) end; Nodes -> L = length(Nodes), IFR = get_ifr_node(Nodes, rand:uniform(L), L), 'OrberApp_IFR':get_user_exception_type(IFR, TypeId) end end. %%----------------------------------------------------------------- %% Func: dec_type_code/4 %%----------------------------------------------------------------- dec_type_code(Version, Message, Len, ByteOrder, Buff, C) -> {TypeNo, Message1, Len1, NewC} = dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C), TC = dec_type_code(TypeNo, Version, Message1, Len1, ByteOrder, Buff, NewC), erase(orber_indirection), TC. %%----------------------------------------------------------------- %% Func: dec_type_code/5 %%----------------------------------------------------------------- dec_type_code(0, _, Message, Len, _, _, C) -> {'tk_null', Message, Len, C}; dec_type_code(1, _, Message, Len, _, _, C) -> {'tk_void', Message, Len, C}; dec_type_code(2, _, Message, Len, _, _, C) -> {'tk_short', Message, Len, C}; dec_type_code(3, _, Message, Len, _, _, C) -> {'tk_long', Message, Len, C}; dec_type_code(23, _, Message, Len, _, _, C) -> {'tk_longlong', Message, Len, C}; dec_type_code(25, _, Message, Len, _, _, C) -> {'tk_longdouble', Message, Len, C}; dec_type_code(4, _, Message, Len, _, _, C) -> {'tk_ushort', Message, Len, C}; dec_type_code(5, _, Message, Len, _, _, C) -> {'tk_ulong', Message, Len, C}; dec_type_code(24, _, Message, Len, _, _, C) -> {'tk_ulonglong', Message, Len, C}; dec_type_code(6, _, Message, Len, _, _, C) -> {'tk_float', Message, Len, C}; dec_type_code(7, _, Message, Len, _, _, C) -> {'tk_double', Message, Len, C}; dec_type_code(8, _, Message, Len, _, _, C) -> {'tk_boolean', Message, Len, C}; dec_type_code(9, _, Message, Len, _, _, C) -> {'tk_char', Message, Len, C}; dec_type_code(26, _, Message, Len, _, _, C) -> {'tk_wchar', Message, Len, C}; dec_type_code(10, _, Message, Len, _, _, C) -> {'tk_octet', Message, Len, C}; dec_type_code(11, _, Message, Len, _, _, C) -> {'tk_any', Message, Len, C}; dec_type_code(12, _, Message, Len, _, _, C) -> {'tk_TypeCode', Message, Len, C}; dec_type_code(13, _, Message, Len, _, _, C) -> {'tk_Principal', Message, Len, C}; dec_type_code(14, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg get the byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_objref', RepId, Name}, Message1, Len1, NewC}; dec_type_code(15, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg get the byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name, ElementList}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}, {"element list", {'tk_sequence', {'tk_struct', "","", [{"member name", {'tk_string', 0}}, {"member type", 'tk_TypeCode'}]}, 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_struct', RepId, Name, ElementList}, Message1, Len1, NewC}; dec_type_code(16, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg get the byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name, DiscrTC, Default}, Rest2, RestLen2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}, {"discriminant type", 'tk_TypeCode'}, {"default used", 'tk_long'}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {ElementList, <<>>, _RestLen3, NewC2} = dec_type({'tk_sequence', {'tk_struct', "","", [{"label value", DiscrTC}, {"member name", {'tk_string', 0}}, {"member type", 'tk_TypeCode'}]}, 0}, Version, Rest2, RestLen2, ByteOrder1, Buff, NewC), NewElementList = case check_enum(DiscrTC) of true -> lists:map(fun({L,N,T}) -> {atom_to_list(L),N,T} end, ElementList); false -> ElementList end, {{'tk_union', RepId, Name, DiscrTC, Default, NewElementList}, Message1, Len1, NewC2}; dec_type_code(17, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg get the byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name, ElementList}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}, {"element list", {'tk_sequence', {'tk_string', 0}, 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_enum', RepId, Name, ElementList}, Message1, Len1, NewC}; dec_type_code(18, Version, Message, Len, ByteOrder, Buff, C) -> {MaxLength, Message1, Len1, NewC} = dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C), {{'tk_string', MaxLength}, Message1, Len1, NewC}; dec_type_code(19, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg get the byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{ElemTC, MaxLength}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'}, {"max length", 'tk_ulong'}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_sequence', ElemTC, MaxLength}, Message1, Len1, NewC}; dec_type_code(20, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg get the byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{ElemTC, Length}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'}, {"length", 'tk_ulong'}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_array', ElemTC, Length}, Message1, Len1, NewC}; dec_type_code(21, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg ge a byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name, TC}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}, {"TypeCode", 'tk_TypeCode'}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_alias', RepId, Name, TC}, Message1, Len1, NewC}; dec_type_code(22, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), %% Decode marshalled parameters, eg get the byteorder first {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name, ElementList}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}, {"element list", {'tk_sequence', {'tk_struct', "","", [{"member name", {'tk_string', 0}}, {"member type", 'tk_TypeCode'}]}, 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_except', RepId, Name, ElementList}, Message1, Len1, NewC}; dec_type_code(27, Version, Message, Len, ByteOrder, Buff, C) -> {MaxLength, Message1, Len1, NewC} = dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C), {{'tk_wstring', MaxLength}, Message1, Len1, NewC}; dec_type_code(28, Version, Message, Len, ByteOrder, Buff, C) -> {Digits, Message1, Len1, C1} = dec_type('tk_ushort', Version, Message, Len, ByteOrder, Buff, C), {Scale, Message2, Len2, C2} = dec_type('tk_short', Version, Message1, Len1, ByteOrder, Buff, C1), {{'tk_fixed', Digits, Scale}, Message2, Len2, C2}; dec_type_code(29, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name, ValueModifier, TC, ElementList}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}, {"ValueModifier", 'tk_short'}, {"TypeCode", 'tk_TypeCode'}, {"element list", {'tk_sequence', {'tk_struct', "","", [{"member name", {'tk_string', 0}}, {"member type", 'tk_TypeCode'}, {"Visibility", 'tk_short'}]}, 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_value', RepId, Name, ValueModifier, TC, ElementList}, Message1, Len1, NewC}; dec_type_code(30, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name, TC}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}, {"TypeCode", 'tk_TypeCode'}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_value_box', RepId, Name, TC}, Message1, Len1, NewC}; dec_type_code(31, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}}, {"name", {'tk_string', 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_native', RepId, Name}, Message1, Len1, NewC}; dec_type_code(32, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}}, {"name", {'tk_string', 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_abstract_interface', RepId, Name}, Message1, Len1, NewC}; dec_type_code(33, Version, Message, Len, ByteOrder, Buff, C) -> {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder), {ByteOrder1, Rest1} = dec_byte_order(ComplexParams), {{RepId, Name}, <<>>, _Len2, NewC} = dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}}, {"name", {'tk_string', 0}}]}, Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex), {{'tk_local_interface', RepId, Name}, Message1, Len1, NewC}; dec_type_code(16#ffffffff, Version, Message, Len, ByteOrder, Buff, C) -> {Indirection, Message1, Len1, NewC} = dec_type('tk_long', Version, Message, Len, ByteOrder, Buff, C), Position = C+Indirection, case put(orber_indirection, Position) of Position -> %% {{'none', Indirection}, Message1, Len1, NewC}; %% Recursive TypeCode. Break the loop. orber:dbg("[~p] cdr_decode:dec_type_code(~p); Recursive TC not supported.", [?LINE,Position], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO}); _ -> <<_:Position/binary, SubBuff/binary>> = Buff, {TC, _, _, _} = dec_type_code(Version, SubBuff, Position, ByteOrder, Buff, Position), {TC, Message1, Len1, NewC} end; dec_type_code(Type, _, _, _, _, _, _) -> orber:dbg("[~p] cdr_decode:dec_type_code(~p); No match.", [?LINE, Type], ?DEBUG_LEVEL), corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 8), completion_status=?COMPLETED_MAYBE}). check_enum({'tk_enum', _, _, _}) -> true; check_enum(_) -> false. decode_complex_tc_parameters(_Version, Message, Len, ByteOrder) -> {Rest, Len1, NewC} = dec_align(Message, Len, 4, 0), {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest), <<OctetSeq:Size/binary, Rest2/binary>> = Rest1, {OctetSeq, Rest2, Len1+4+Size, NewC+4}. %%----------------------------------------------------------------- %% Func: dec_align/3 %% Args: %% R - The byte sequence that shall be aligned. %% Len - The number of bytes read so far. %% Alignment - The alignment as an integer (for example: 2,4,8). %% Returns: %% An aligned byte sequence. %%----------------------------------------------------------------- dec_align(R, Len, Alignment, C) -> Rem = Len rem Alignment, if Rem == 0 -> {R, Len, C}; true -> Diff = Alignment - Rem, <<_:Diff/binary,Rest/binary>> = R, {Rest, Len + Diff, C + Diff} end. %%---------------- EOF MODULE ----------------------------------------