1%%--------------------------------------------------------------------
2%%
3%% %CopyrightBegin%
4%%
5%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
6%%
7%% Licensed under the Apache License, Version 2.0 (the "License");
8%% you may not use this file except in compliance with the License.
9%% You may obtain a copy of the License at
10%%
11%%     http://www.apache.org/licenses/LICENSE-2.0
12%%
13%% Unless required by applicable law or agreed to in writing, software
14%% distributed under the License is distributed on an "AS IS" BASIS,
15%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16%% See the License for the specific language governing permissions and
17%% limitations under the License.
18%%
19%% %CopyrightEnd%
20%%
21%%
22%%-----------------------------------------------------------------
23%% File: cdr_decode.erl
24%%
25%% Description:
26%%    This file contains all decoding functions for the CDR
27%%    format.
28%%
29%%-----------------------------------------------------------------
30-module(cdr_decode).
31
32-include_lib("orber/src/orber_iiop.hrl").
33-include_lib("orber/include/ifr_types.hrl").
34-include_lib("orber/include/corba.hrl").
35
36-include_lib("orber/src/ifr_objects.hrl").
37
38%%-----------------------------------------------------------------
39%% External exports
40%%-----------------------------------------------------------------
41-export([dec_giop_message_header/1, dec_reply_header/4,
42	 dec_reply_body/6, dec_locate_reply_header/4,
43	 dec_locate_reply_body/5, dec_message_header/3, dec_request_body/6,
44	 dec_octet_sequence_bin/6, dec_message/2, peek_request_id/2]).
45
46%%-----------------------------------------------------------------
47%% Functions which only are exported for the testcases.
48%%-----------------------------------------------------------------
49-export([dec_type/5, dec_byte_order/1, dec_system_exception/4, dec_user_exception/4,
50	 dec_byte_order_list/1]).
51
52%%-----------------------------------------------------------------
53%% Internal exports
54%%-----------------------------------------------------------------
55
56%%-----------------------------------------------------------------
57%% Macros
58%%-----------------------------------------------------------------
59-define(DEBUG_LEVEL, 9).
60
61-define(ODD(N), (N rem 2) == 1).
62
63%%-----------------------------------------------------------------
64%% Func: dec_message/3
65%% Args:
66%%       TypeCodes - is the type_codes of the return value and out parameters
67%%                   when one decodes a reply.
68%%       Bytes - is the the message as a byte sequence.
69%% Returns:
70%%       A tupple which contains the decoded message,
71%%       {ok, Header, Parameters, TypeCodes}.
72%%-----------------------------------------------------------------
73dec_message(TypeCodes, Bytes) ->
74    Message = dec_giop_message_header(Bytes),
75    case Message#giop_message.message_type of
76        ?GIOP_MSG_REQUEST ->
77            {Version, ReqHdr, Rest, Len, ByteOrder} =
78		dec_request_header(Message#giop_message.giop_version,
79				   Message#giop_message.message, ?GIOP_HEADER_SIZE,
80				   Message#giop_message.byte_order, Bytes),
81	    dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Bytes);
82        ?GIOP_MSG_REPLY ->
83            dec_reply(Message#giop_message.giop_version,
84                      TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE,
85                      Message#giop_message.byte_order);
86        ?GIOP_MSG_CANCEL_REQUEST ->
87            dec_cancel_request(Message#giop_message.giop_version,
88                               Message#giop_message.message, ?GIOP_HEADER_SIZE,
89                               Message#giop_message.byte_order);
90        ?GIOP_MSG_LOCATE_REQUEST ->
91            dec_locate_request(Message#giop_message.giop_version,
92                               Message#giop_message.message, ?GIOP_HEADER_SIZE,
93                               Message#giop_message.byte_order);
94        ?GIOP_MSG_LOCATE_REPLY ->
95            dec_locate_reply(Message#giop_message.giop_version,
96                             Message#giop_message.message, ?GIOP_HEADER_SIZE,
97                             Message#giop_message.byte_order);
98        ?GIOP_MSG_CLOSE_CONNECTION ->
99            'close_connection';
100        ?GIOP_MSG_MESSAGE_ERROR ->
101            'message_error';
102        ?GIOP_MSG_FRAGMENT ->
103	    dec_fragment_header(Message#giop_message.giop_version,
104				Message#giop_message.message, ?GIOP_HEADER_SIZE,
105				Message#giop_message.byte_order, Bytes)
106    end.
107
108%%-----------------------------------------------------------------
109%% Func: dec_giop_message_header/1
110%% Args:
111%%       Bytes - is the the message as a byte sequence.
112%% Returns:
113%%       A giop_message record.
114%%-----------------------------------------------------------------
115%%                         Magic|Version|BO| Type | Size | Body
116dec_giop_message_header(<<"GIOP",1:8,0:8,1:8,MessType:8,
117			MessSize:32/little-unsigned-integer,Message/binary>>) ->
118    #giop_message{magic = "GIOP", giop_version = {1,0},
119		  byte_order = little, message_type = MessType,
120		  message_size = MessSize, message = Message};
121dec_giop_message_header(<<"GIOP",1:8,0:8,0:8,MessType:8,
122			MessSize:32/big-unsigned-integer,Message/binary>>) ->
123    #giop_message{magic = "GIOP", giop_version = {1,0},
124		  byte_order = big, message_type = MessType,
125		  message_size = MessSize, message = Message};
126dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8,
127			MessSize:32/little-unsigned-integer,Message/binary>>) when
128  ((Flags band 16#01) == 16#01) ->
129    #giop_message{magic = "GIOP", giop_version = {1,Minor},
130		  byte_order = little, fragments = ((Flags band 16#02) == 16#02),
131		  message_type = MessType, message_size = MessSize, message = Message};
132dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8,
133			MessSize:32/big-unsigned-integer,Message/binary>>) ->
134    #giop_message{magic = "GIOP", giop_version = {1,Minor},
135		  byte_order = big, fragments = ((Flags band 16#02) == 16#02),
136		  message_type = MessType, message_size = MessSize, message = Message};
137dec_giop_message_header(<<Hdr:?GIOP_HEADER_SIZE/binary, _Body/binary>>) ->
138    orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n"
139	      "Orber cannot decode the GIOP-header.", [?LINE, Hdr], ?DEBUG_LEVEL),
140    exit(message_error);
141dec_giop_message_header(Other) ->
142    orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n"
143	      "Orber cannot decode the GIOP-header.", [?LINE, Other], ?DEBUG_LEVEL),
144    exit(message_error).
145
146
147peek_request_id(big, <<ReqId:32/big-unsigned-integer,_/binary>>) ->
148    ReqId;
149peek_request_id(little, <<ReqId:32/little-unsigned-integer,_/binary>>) ->
150    ReqId.
151
152%%-----------------------------------------------------------------
153%% Func: dec_message_header/2
154%% Args:
155%%       Header - #giop_message{}
156%%       Bytes - is the the message body as a byte sequence.
157%% Returns:
158%%-----------------------------------------------------------------
159dec_message_header(TypeCodes, Message, Bytes) ->
160    case Message#giop_message.message_type of
161	?GIOP_MSG_REQUEST ->
162	    dec_request_header(Message#giop_message.giop_version,
163			       Message#giop_message.message, ?GIOP_HEADER_SIZE,
164			       Message#giop_message.byte_order, Bytes);
165	?GIOP_MSG_REPLY ->
166	    dec_reply(Message#giop_message.giop_version,
167		      TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE,
168		      Message#giop_message.byte_order);
169	?GIOP_MSG_CANCEL_REQUEST ->
170	    dec_cancel_request(Message#giop_message.giop_version,
171			       Message#giop_message.message, ?GIOP_HEADER_SIZE,
172			       Message#giop_message.byte_order);
173	?GIOP_MSG_LOCATE_REQUEST ->
174	    dec_locate_request(Message#giop_message.giop_version,
175			       Message#giop_message.message, ?GIOP_HEADER_SIZE,
176			       Message#giop_message.byte_order);
177	?GIOP_MSG_LOCATE_REPLY ->
178	    dec_locate_reply(Message#giop_message.giop_version,
179			     Message#giop_message.message, ?GIOP_HEADER_SIZE,
180			     Message#giop_message.byte_order);
181	?GIOP_MSG_CLOSE_CONNECTION ->
182	    'close_connection';
183	?GIOP_MSG_MESSAGE_ERROR ->
184	    'message_error';
185	?GIOP_MSG_FRAGMENT ->
186	    dec_fragment_header(Message#giop_message.giop_version,
187				Message#giop_message.message, ?GIOP_HEADER_SIZE,
188				Message#giop_message.byte_order, Bytes)
189    end.
190
191
192%%-----------------------------------------------------------------
193%% Func: dec_byte_order/1
194%% Args:
195%%       The message as a byte sequence.
196%% Returns:
197%%       A tuple {Endianness, Rest} where Endianness is big or little.
198%%       Rest is the remaining message byte sequence.
199%%-----------------------------------------------------------------
200dec_byte_order(<<0:8,T/binary>>) ->
201    {big, T};
202dec_byte_order(<<1:8,T/binary>>) ->
203    {little, T}.
204
205%%-----------------------------------------------------------------
206%% Func: dec_byte_order_list/1
207%% Args:
208%%       The message as a byte sequence.
209%% Returns:
210%%       A tuple {Endianness, Rest} where Endianness is big or little.
211%%       Rest is the remaining message byte sequence.
212%%-----------------------------------------------------------------
213dec_byte_order_list([0|T]) ->
214    {big, T};
215dec_byte_order_list([1|T]) ->
216    {little, T}.
217
218%%-----------------------------------------------------------------
219%% Func    : dec_response_flags
220%% Args    :
221%% Returns : boolean
222%%-----------------------------------------------------------------
223%% FIX ME!! Not correct flag handling.
224dec_response_flags(_Version, <<0:8, Rest/binary>>, Len) ->
225    {false, Rest, Len+1};
226dec_response_flags(_Version, <<1:8, Rest/binary>>, Len) ->
227    {true_oneway, Rest, Len+1};
228dec_response_flags(_Version, <<3:8, Rest/binary>>, Len) ->
229    {true, Rest, Len+1};
230dec_response_flags(_Version, <<X:8, Rest/binary>>, Len) ->
231    %% Not only the Response flag is set, test which.
232    if
233	%% Since the 6 most significant bits are unused we'll accept this for now.
234	((X band 16#03) == 16#03) ->
235	    {true, Rest, Len+1};
236	((X band 16#01) == 16#01) ->
237	    {true_oneway, Rest, Len+1};
238	true ->
239	    {false, Rest, Len+1}
240    end.
241
242%%-----------------------------------------------------------------
243%% Func    : dec_target_addr
244%% Args    : Octet
245%% Returns : boolean
246%%-----------------------------------------------------------------
247dec_target_addr(Version, Message, Len, ByteOrder, RequestId, Type) ->
248    case dec_type(?TARGETADDRESS, Version, Message, Len, ByteOrder, [], 0) of
249	{#'GIOP_TargetAddress'{label = ?GIOP_KeyAddr, value = KeyAddr}, Rest3, Len3, C} ->
250	    {dec_target_key(KeyAddr, RequestId, Version, Type), Rest3, Len3, C};
251	{#'GIOP_TargetAddress'{label = ?GIOP_ProfileAddr,
252			       value = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
253							    profile_data=PA}},
254	 Rest3, Len3, C} ->
255	    {dec_target_key(PA, RequestId, Version, Type), Rest3, Len3, C};
256	{#'GIOP_TargetAddress'{label = ?GIOP_ReferenceAddr,
257			       value = #'GIOP_IORAddressingInfo'{
258				 selected_profile_index = _PI,
259				 ior = IOR}}, Rest3, Len3, C} ->
260	    {dec_target_key(iop_ior:get_objkey(IOR), RequestId, Version, Type),
261	     Rest3, Len3, C};
262	Other ->
263	    orber:dbg("[~p] cdr_decode:dec_target_addr(~p);~n"
264		      "Unsupported TargetAddress.", [?LINE, Other], ?DEBUG_LEVEL),
265	    corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 12), completion_status=?COMPLETED_MAYBE})
266    end.
267
268%%-----------------------------------------------------------------
269%% Func    : dec_target_key
270%% Args    : Octet
271%% Returns : boolean
272%%-----------------------------------------------------------------
273dec_target_key(Key, RequestId, Version, Type) ->
274    %% The Type argument is used as an identifier of which operation it is.
275    %% We need it to be able to tell the difference if it's, for example,
276    %% a request or locate-request.
277    case corba:string_to_objkey_local(Key) of
278	{location_forward, Object} ->
279	    throw({Type, Object, RequestId, Version, Key});
280	ObjRef ->
281	    ObjRef
282    end.
283
284%%-----------------------------------------------------------------
285%% Func: dec_request_header/3
286%% Args:
287%%       Message - The message
288%%       Len0 - Number of bytes already read.
289%%       ByteOrder - little or big
290%% Returns:
291%%-----------------------------------------------------------------
292dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} ->
293    {Request_id, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0,
294					    ByteOrder, [], 0),
295    {ResponseFlags, Rest2, Len2} = dec_response_flags(Version, Rest1, Len1),
296    {_, Rest2b, Len2b, _} = dec_type({'tk_array', 'tk_octet', 3}, Version, Rest2, Len2, ByteOrder, [], 0),
297    {Object_key, Rest3, Len3, _} = dec_target_addr(Version, Rest2b, Len2b, ByteOrder, Request_id,
298						   'location_forward'),
299    {Operation, Rest4, Len4, _} = dec_type({'tk_string', 0},  Version, Rest3, Len3, ByteOrder, [], 0),
300    {Context, Rest5, Len5} = dec_service_context(Version, Rest4, Len4, ByteOrder),
301    {Version, #request_header{service_context=Context,
302			      request_id=Request_id,
303			      response_expected=ResponseFlags,
304			      object_key=Object_key,
305			      operation=list_to_atom(Operation),
306			      requesting_principal=""}, Rest5, Len5, ByteOrder};
307dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) ->
308    {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder),
309    {Request_id, Rest2, Len2, _} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder, [], 0),
310    {Response_expected, Rest3, Len3, _} = dec_type('tk_boolean',  Version, Rest2, Len2,
311						   ByteOrder, [], 0),
312    {ObjKey, Rest4, Len4, _} = dec_type({'tk_sequence', 'tk_octet', 0},  Version, Rest3,
313				   Len3, ByteOrder, [], 0),
314    Object_key = dec_target_key(ObjKey, Request_id, Version, 'location_forward'),
315    {Operation, Rest5, Len5, _} = dec_type({'tk_string', 0},  Version, Rest4, Len4, ByteOrder, [], 0),
316    {Principal, Rest, Len, _} = dec_type({'tk_string', 0},  Version, Rest5,Len5,  ByteOrder, [], 0),
317    {Version, #request_header{service_context=Context,
318			      request_id=Request_id,
319			      response_expected=Response_expected,
320			      object_key=Object_key,
321			      operation=list_to_atom(Operation),
322			      requesting_principal=Principal}, Rest, Len, ByteOrder}.
323
324
325%%-----------------------------------------------------------------
326%% Func: dec_service_context/4
327%% Args: Version - e.g. 1.2
328%%       Message - The message
329%%       Len - Number of bytes already read.
330%%       ByteOrder - little or big
331%% Returns:
332%%-----------------------------------------------------------------
333dec_service_context(Version, Message, Len, ByteOrder) ->
334    {Context, Rest, Len1} = dec_type(?IOP_SERVICECONTEXT, Version, Message,
335				     Len, ByteOrder),
336    {dec_used_contexts(Version, Context, []), Rest, Len1}.
337
338dec_used_contexts(_Version, [], Ctxs) ->
339    Ctxs;
340dec_used_contexts({1,0}, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets}|T], Ctxs) ->
341    %% Not supported by 1.0, drop it.
342    dec_used_contexts({1,0}, T, Ctxs);
343dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
344						  context_data = Bytes}|T], Ctxs) ->
345    {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
346    {CodeCtx, _, _} =  dec_type(?CONV_FRAME_CODESETCONTEXT, Version,
347				Rest, 1, ByteOrder),
348    dec_used_contexts(Version, T,
349		      [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
350					     context_data = CodeCtx}|Ctxs]);
351dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
352						  context_data = Bytes}|T], Ctxs) ->
353    {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
354    {BiDirCtx, _, _} =  dec_type(?IIOP_BIDIRIIOPSERVICECONTEXT, Version,
355				 Rest, 1, ByteOrder),
356    dec_used_contexts(Version, T,
357		      [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
358					     context_data = BiDirCtx}|Ctxs]);
359dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
360						  context_data = Bytes}|T], Ctxs) ->
361    {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
362    {Ctx, _, _} =  dec_type(?FT_FTRequestServiceContext, Version,
363			    Rest, 1, ByteOrder),
364    dec_used_contexts(Version, T,
365		      [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
366					     context_data = Ctx}|Ctxs]);
367dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
368						  context_data = Bytes}|T], Ctxs) ->
369    {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
370    {Ctx, _, _} =  dec_type(?FT_FTGroupVersionServiceContext, Version,
371			    Rest, 1, ByteOrder),
372    dec_used_contexts(Version, T,
373		      [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
374					     context_data = Ctx}|Ctxs]);
375dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
376						  context_data = Bytes}|T], Ctxs) ->
377    {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
378    {Ctx, _, _} =  dec_type(?CSI_SASContextBody, Version,
379			    Rest, 1, ByteOrder),
380    dec_used_contexts(Version, T,
381		      [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
382					     context_data = Ctx}|Ctxs]);
383dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
384						  context_data = Bytes}|T], Ctxs) ->
385    {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
386    {Ctx, _, _} =  dec_type(?ORBER_GENERIC_CTX, Version,
387			    Rest, 1, ByteOrder),
388    dec_used_contexts(Version, T,
389		      [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
390					     context_data = binary_to_term(list_to_binary(Ctx))}|Ctxs]);
391dec_used_contexts(Version, [H|T], Ctxs) ->
392    dec_used_contexts(Version, T, [H|Ctxs]).
393
394%%-----------------------------------------------------------------
395%% Func: dec_request_body
396%% Args: Version - e.g. 1.2
397%% Returns:
398%%-----------------------------------------------------------------
399dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Buffer) ->
400    {Parameters, TypeCodes, _} =
401	dec_request_body(Version, ReqHdr#request_header.object_key,
402			 ReqHdr#request_header.operation,
403			 Rest, Len, ByteOrder, Buffer, Len),
404    {Version, ReqHdr, Parameters, TypeCodes}.
405
406dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter)
407  when Version == {1,2} ->
408    case orber_typedefs:get_op_def(Object_key, Operation) of
409	{RetType, [], OutParameters} ->
410	    {[], {RetType, [], OutParameters}, Len};
411	{RetType, InParameters, OutParameters} ->
412	    {Rest, Len1, NewC} = dec_align(Body, Len, 8, Counter),
413	    {Parameters, Len2} = dec_parameters(Version, InParameters, Rest, Len1,
414						ByteOrder, Buffer, NewC),
415	    {Parameters, {RetType, InParameters, OutParameters}, Len2}
416    end;
417dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter) ->
418    {RetType, InParameters, OutParameters} =
419	orber_typedefs:get_op_def(Object_key, Operation),
420    {Parameters, Len1} = dec_parameters(Version, InParameters, Body, Len, ByteOrder, Buffer, Counter),
421    {Parameters, {RetType, InParameters, OutParameters}, Len1}.
422
423dec_parameters(_, [], _, Len, _, _, _) ->
424    {[], Len};
425dec_parameters(Version, [P1 |InParList], Body, Len, ByteOrder, Buffer, Counter) ->
426    {Object, Rest, Len1, NewCounter} = dec_type(P1, Version, Body, Len, ByteOrder, Buffer, Counter),
427    {List, Len2} = dec_parameters(Version, InParList, Rest, Len1, ByteOrder, Buffer, NewCounter),
428    {[Object | List], Len2}.
429
430%%-----------------------------------------------------------------
431%% Func: dec_reply/5
432%% Args:
433%%       Message - The message
434%%       Len0 - Number of bytes already read.
435%%       ByteOrder - little or big
436%% Returns:
437%%       A tuple {ReplyHeader, Result} where ReplyHeader is a
438%%       reply_header record and Result the decode result.
439%%-----------------------------------------------------------------
440dec_reply(Version, TypeCodes, Message, Len0, ByteOrder) ->
441    {ReplyHeader, Rest, Len} = dec_reply_header(Version, Message, Len0, ByteOrder),
442    {Result, Par} =
443	case ReplyHeader#reply_header.reply_status of
444	    'no_exception' ->
445		{R, P, _} = dec_reply_body(Version, TypeCodes, Rest, Len, ByteOrder, Message),
446		{R, P};
447	    'system_exception' ->
448		{R, _} = dec_system_exception(Version, Rest, Len, ByteOrder),
449		{R, []};
450	    'user_exception' ->
451		{R, _} = dec_user_exception(Version, Rest, Len, ByteOrder),
452		{R, []};
453	    'location_forward' ->
454		{R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
455					   Rest, Len, ByteOrder, Message),
456	    {R, []};
457	    %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for
458	    %% now.
459	    'location_forward_perm' ->
460		{R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
461					   Rest, Len, ByteOrder, Message),
462		{R, []};
463	    'needs_addressing_mode' ->
464		{R, _, _} = dec_reply_body(Version, {'tk_short', [],[]},
465					   Rest, Len, ByteOrder, Message),
466		{R, []}
467	     end,
468    {ReplyHeader, Result, Par}.
469
470
471%% ## NEW IIOP 1.2 ##
472dec_reply_header(Version, Message, Len0, ByteOrder) when Version == {1,2} ->
473    {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len0, ByteOrder),
474    {ReplyStatus, Rest2, Len2} = dec_reply_status(Version, Rest1, Len1, ByteOrder),
475    {Context, Rest, Len3} = dec_service_context(Version, Rest2, Len2, ByteOrder),
476    {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus},
477     Rest, Len3};
478
479dec_reply_header(Version, Message, Len0, ByteOrder) ->
480    {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder),
481    {Request_id, Rest2, Len2} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder),
482    {ReplyStatus, Rest, Len3} = dec_reply_status(Version, Rest2, Len2, ByteOrder),
483    {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus},
484     Rest, Len3}.
485
486dec_reply_status(Version, Status, Len, ByteOrder) ->
487    {L, Rest, Len1}= dec_type('tk_ulong', Version, Status, Len, ByteOrder),
488    {dec_giop_reply_status_type(L), Rest, Len1}.
489
490dec_reply_body(_, {'tk_void', _, []}, <<>>, Len, _, _) ->
491    %% This case is mainly to be able to avoid removing non-existent alignment for
492    %% IIOP-1.2 messages if the body should be empty, i.e., void return value and
493    %% no out parameters.
494    {ok, [], Len};
495dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len,
496	       ByteOrder, Bytes) when Version == {1,2} ->
497    {Rest, Len1, Counter} = dec_align(Body, Len, 8, Len),
498    {Result, Rest2, Len2, C} = dec_type(RetType, Version, Rest, Len1, ByteOrder, Bytes, Counter),
499    {Par, Len3} = dec_parameters(Version, OutParameters, Rest2, Len2, ByteOrder, Bytes, C),
500    {Result, Par, Len3};
501dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len, ByteOrder, Bytes) ->
502    {Result, Rest, Len1, C} = dec_type(RetType, Version, Body, Len, ByteOrder, Bytes, Len),
503    {Par, Len2} = dec_parameters(Version, OutParameters, Rest, Len1, ByteOrder, Bytes, C),
504    {Result, Par, Len2}.
505
506
507%%-----------------------------------------------------------------
508%% Func: dec_cancel_request/3
509%% Args:
510%%       Message - The message
511%%       Len - Number of bytes already read.
512%%       ByteOrder - little or big
513%% Returns:
514%%       A cancel_request_header record.
515%%-----------------------------------------------------------------
516dec_cancel_request(Version, Message, Len, ByteOrder) ->
517    {Request_id, _, _} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
518    #cancel_request_header{request_id=Request_id}.
519
520%%-----------------------------------------------------------------
521%% Func: dec_locate_request/3
522%% Args:
523%%       Message - The message
524%%       Len - Number of bytes already read.
525%%       ByteOrder - little or big
526%% Returns:
527%%       A locate_request_header record.
528%%-----------------------------------------------------------------
529%% ## NEW IIOP 1.2 ##
530dec_locate_request(Version, Message, Len, ByteOrder) when Version == {1,2} ->
531    {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
532    {Object_key, _, _, _} = dec_target_addr(Version, Rest, Len1, ByteOrder, Request_id,
533					    'object_forward'),
534    {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}};
535dec_locate_request(Version, Message, Len, ByteOrder) ->
536    {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
537    {ObjKey, _, _} = dec_type({'tk_sequence', 'tk_octet', 0}, Version, Rest,
538				   Len1, ByteOrder),
539    Object_key = dec_target_key(ObjKey, Request_id, Version, 'object_forward'),
540    {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}}.
541
542
543%%-----------------------------------------------------------------
544%% Func: dec_locate_reply/3
545%% Args:
546%%       Message - The message
547%%       Len - Number of bytes already read.
548%%       ByteOrder - little or big
549%% Returns:
550%%       A locate_reply_header record.
551%%-----------------------------------------------------------------
552dec_locate_reply(Version, Message, Len, ByteOrder) ->
553    {ReplyHeader, Rest1, Len1} = dec_locate_reply_header(Version, Message, Len, ByteOrder),
554    {ReplyHeader, dec_locate_reply_body(Version, ReplyHeader#locate_reply_header.locate_status, Rest1,
555					Len1, ByteOrder)}.
556
557dec_locate_reply_header(Version, Message, Len, ByteOrder) ->
558    {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
559    {Locate_status, Rest2, Len2} = dec_locate_status(Version, Rest1, Len1, ByteOrder),
560    {#locate_reply_header{request_id=Request_id, locate_status=Locate_status}, Rest2, Len2}.
561
562dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) when Version == {1,2} ->
563    %% In CORBA-2.3.1 the LocateReply body didn't align the body (8-octet
564    %% boundry) for IIOP-1.2. This have been changed in CORBA-2.4 and
565    %% changed back in CORBA-2.6. Hence, we should not change this.
566    case LocateStatus of
567	'object_forward' ->
568	    {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
569	    ObjRef;
570	'object_forward_perm' ->
571	    %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for
572	    %% now.
573	    {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
574	    ObjRef;
575	'loc_system_exception' ->
576	    %% This should be updated but since 'dec_system_exception' removes
577	    %% alignment, which the LocateReplyBody don't have, for 1.2 we
578	    %% pretend it's 1.1 for now.
579	    {SysExc, _} = dec_system_exception({1,1}, Rest, Len, ByteOrder),
580	    corba:raise(SysExc);
581	'loc_needs_addressing_mode' ->
582	    %% Not supported.
583	    [];
584	_ ->
585	    []
586    end;
587dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) ->
588    case LocateStatus of
589	'object_forward' ->
590	    {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
591	    ObjRef;
592	_ ->
593	    []
594    end.
595
596dec_locate_status(Version, Bytes, Len, ByteOrder) ->
597    {L, Rest, Len1} = dec_type('tk_ulong', Version, Bytes, Len, ByteOrder),
598    {dec_giop_locate_status_type(L), Rest, Len1}.
599
600
601%%-----------------------------------------------------------------
602%% Func: dec_fragment_header/5
603%% Args:
604%%       Message - The message
605%%       Len0 - Number of bytes already read.
606%%       ByteOrder - little or big
607%% Returns:
608%%-----------------------------------------------------------------
609dec_fragment_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} ->
610    {RequestId, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0,
611					    ByteOrder, [], 0),
612    {Version, #fragment_header{request_id=RequestId}, Rest1, Len1, ByteOrder};
613dec_fragment_header(Version, _Message, _Len0, _ByteOrder, _Buffer) ->
614    %% The FragmentHeader is IIOP-1.2 specific. Hence, do nothing here.
615    orber:dbg("[~p] cdr_decode:dec_fragment_header(~p)~n"
616	      "Orber only supports fragmented messages for IIOP-1.2.",
617	      [?LINE, Version], ?DEBUG_LEVEL),
618    exit(message_error).
619%    {Version, #fragment_header{}, Message, Len0, ByteOrder}.
620
621%%-----------------------------------------------------------------
622%% Func: dec_giop_reply_status_type
623%% Args:
624%%       An integer status code
625%% Returns:
626%%       An atom which is the reply status
627%%-----------------------------------------------------------------
628dec_giop_reply_status_type(0) ->
629    'no_exception';
630dec_giop_reply_status_type(1) ->
631    'user_exception';
632dec_giop_reply_status_type(2) ->
633    'system_exception';
634dec_giop_reply_status_type(3) ->
635    'location_forward';
636%% ## IIOP-1.2 ##
637dec_giop_reply_status_type(4) ->
638    'location_forward_perm';
639dec_giop_reply_status_type(5) ->
640    'needs_addressing_mode'.
641
642%%-----------------------------------------------------------------
643%% Func: dec_giop_locate_status_type
644%% Args:
645%%       An integer status code
646%% Returns:
647%%       An atom which is the reply status
648%%-----------------------------------------------------------------
649dec_giop_locate_status_type(0) ->
650    'unknown_object';
651dec_giop_locate_status_type(1) ->
652    'object_here';
653dec_giop_locate_status_type(2) ->
654    'object_forward';
655%% ## IIOP-1.2 ##
656dec_giop_locate_status_type(3) ->
657    'object_forward_perm';
658dec_giop_locate_status_type(4) ->
659    'loc_system_exception';
660dec_giop_locate_status_type(5) ->
661    'loc_needs_addressing_mode'.
662
663
664%%-----------------------------------------------------------------
665%% Func: dec_type/5
666%%-----------------------------------------------------------------
667dec_type(Type, Version, Bytes, Len, ByteOrder) ->
668    {Val, Rest, Len2, _} =
669	dec_type(Type, Version, Bytes, Len, ByteOrder, [], 0),
670    {Val, Rest, Len2}.
671
672dec_type('tk_null', _Version, Bytes, Len, _, _, C) ->
673    {'null', Bytes, Len, C};
674dec_type('tk_void', _Version, Bytes, Len, _, _, C) ->
675    {'ok', Bytes, Len, C};
676dec_type('tk_short', _Version, Bytes, Len, ByteOrder, _, C) ->
677    {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
678    {Short, Rest1} = cdrlib:dec_short(ByteOrder, Rest),
679    {Short, Rest1, Len1 + 2, NewC+2};
680dec_type('tk_long', _Version, Bytes, Len, ByteOrder, _, C) ->
681    {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
682    {Long, Rest1} = cdrlib:dec_long(ByteOrder, Rest),
683    {Long, Rest1, Len1 + 4, NewC+4};
684dec_type('tk_longlong', _Version, Bytes, Len, ByteOrder, _, C) ->
685    {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
686    {Long, Rest1} = cdrlib:dec_longlong(ByteOrder, Rest),
687    {Long, Rest1, Len1 + 8, NewC+8};
688dec_type('tk_ushort', _Version, Bytes, Len, ByteOrder, _, C) ->
689    {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
690    {Short, Rest1} = cdrlib:dec_unsigned_short(ByteOrder, Rest),
691    {Short, Rest1, Len1 + 2, NewC+2};
692dec_type('tk_ulong', _Version, Bytes, Len, ByteOrder, _, C) ->
693    {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
694    {Long, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
695    {Long, Rest1, Len1 + 4, NewC+4};
696dec_type('tk_ulonglong', _Version, Bytes, Len, ByteOrder, _, C) ->
697    {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
698    {Long, Rest1} = cdrlib:dec_unsigned_longlong(ByteOrder, Rest),
699    {Long, Rest1, Len1 + 8, NewC+8};
700dec_type('tk_float', _Version, Bytes, Len, ByteOrder, _, C) ->
701    {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
702    {Float, Rest1} = cdrlib:dec_float(ByteOrder, Rest),
703    {Float, Rest1, Len1 + 4, NewC+4};
704dec_type('tk_double', _Version, Bytes, Len, ByteOrder, _, C) ->
705    {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
706    {Double, Rest1} = cdrlib:dec_double(ByteOrder, Rest),
707    {Double, Rest1, Len1 + 8, NewC+8};
708dec_type('tk_boolean', _Version, Bytes, Len, _, _, C) ->
709    {Bool, Rest} = cdrlib:dec_bool(Bytes),
710    {Bool, Rest, Len + 1, C+1};
711dec_type('tk_char', _Version, Bytes, Len, _, _, C) ->
712    {Char, Rest} = cdrlib:dec_char(Bytes),
713    {Char, Rest, Len + 1, C+1};
714dec_type('tk_wchar', {1,2}, Bytes, Len, _ByteOrder, _, C) ->
715    %% For IIOP-1.2 a wchar is almost encoded the same way as an octet-sequence.
716    %% The only difference is that the length-value is an octet as well.
717    case cdrlib:dec_octet(Bytes) of
718	{2, Rest1} ->
719	    %% Currently we only allow 2-bytes wchar.
720	    {WChar, Rest2} = cdrlib:dec_unsigned_short(big, Rest1),
721	    {WChar, Rest2, Len+3, C+3};
722	{What, _} ->
723	    orber:dbg("[~p] cdr_decode:dec_type(~p); unsupported wchar",
724		      [?LINE, What], ?DEBUG_LEVEL),
725	    corba:raise(#'DATA_CONVERSION'{completion_status=?COMPLETED_NO})
726    end;
727%% For 1.1 the wchar is limited to the use of two-octet fixed-length encoding.
728dec_type('tk_wchar', _Version, Bytes, Len, ByteOrder, _, C) ->
729    {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
730    {WChar, Rest2} = cdrlib:dec_unsigned_short(ByteOrder, Rest),
731    {WChar, Rest2, Len1 + 2, NewC+2};
732dec_type('tk_octet', _Version, Bytes, Len, _, _, C) ->
733    {Octet, Rest} = cdrlib:dec_octet(Bytes),
734    {Octet, Rest, Len + 1, C+1};
735dec_type('tk_any', Version, Bytes, Len, ByteOrder, Buff, C) ->
736    {TypeCode, Rest1, Len1, NewC} = dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C),
737    {Value, Rest2, Len2, NewC2} = dec_type(TypeCode, Version, Rest1, Len1, ByteOrder, Buff, NewC),
738    {#any{typecode=TypeCode, value=Value}, Rest2, Len2, NewC2};
739dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C) ->
740    dec_type_code(Version, Bytes, Len, ByteOrder, Buff, C);
741dec_type('tk_Principal', Version, Bytes, Len, ByteOrder, Buff, C) ->
742    dec_sequence(Version, Bytes, 'tk_octet', Len, ByteOrder, Buff, C);
743dec_type({'tk_objref', _IFRId, _Name}, Version, Bytes, Len, ByteOrder, Buff, C) ->
744    dec_objref(Version, Bytes, Len, ByteOrder, Buff, C);
745dec_type({'tk_struct', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder, Buff, C) ->
746    dec_struct(Version, IFRId, Name, ElementList, Bytes, Len, ByteOrder, Buff, C);
747dec_type({'tk_union', IFRId, Name, DiscrTC, Default, ElementList},
748	 Version, Bytes, Len, ByteOrder, Buff, C) ->
749    dec_union(Version, IFRId, Name, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C);
750dec_type({'tk_enum', _IFRId, _Name, ElementList}, _Version, Bytes, Len, ByteOrder, _, C) ->
751    {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
752    {Enum, Rest1} = cdrlib:dec_enum(ByteOrder, ElementList, Rest),
753    {Enum, Rest1, Len1 + 4, NewC+4};
754dec_type({'tk_string', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
755    dec_string(Version, Bytes, Len, ByteOrder, Buff, C);
756dec_type({'tk_wstring', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
757    dec_wstring(Version, Bytes, Len, ByteOrder, Buff, C);
758dec_type({'tk_sequence', ElemTC, _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
759    dec_sequence(Version, Bytes, ElemTC, Len, ByteOrder, Buff, C);
760dec_type({'tk_array', ElemTC, Size}, Version, Bytes, Len, ByteOrder, Buff, C) ->
761    dec_array(Version, Bytes, Size, ElemTC, Len, ByteOrder, Buff, C);
762dec_type({'tk_alias', _IFRId, _Name, TC}, Version, Bytes, Len, ByteOrder, Buff, C) ->
763    dec_type(TC, Version, Bytes, Len, ByteOrder, Buff, C);
764%dec_type({'tk_except', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder) ->
765dec_type({'tk_fixed', Digits, Scale}, _Version, Bytes, Len, _ByteOrder, _Buff, C) ->
766    dec_fixed(Digits, Scale, Bytes, Len, C);
767dec_type(Type, _, _, _, _, _, _) ->
768    orber:dbg("[~p] cdr_decode:dec_type(~p)~n"
769	      "Incorrect TypeCode or unsupported type.",
770	      [?LINE, Type], ?DEBUG_LEVEL),
771    corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 13), completion_status=?COMPLETED_MAYBE}).
772
773stringify_enum({tk_enum,_,_,_}, Label) ->
774    atom_to_list(Label);
775stringify_enum(_, Label) ->
776    Label.
777
778%%-----------------------------------------------------------------
779%% Func: dec_fixed
780%%-----------------------------------------------------------------
781%% Digits eq. total number of digits.
782%% Scale  eq. position of the decimal point.
783%% E.g. fixed<5,2> - "123.45"
784%% E.g. fixed<4,2> - "12.34"
785%% These are encoded as:
786%% ## <5,2> ##  ## <4,2> ##
787%%     1,2          0,1     eq. 1 octet
788%%     3,4          2,3
789%%     5,0xC        4,0xC
790%%
791%% Each number is encoded as a half-octet. Note, for <4,2> a zero is
792%% added first to to be able to create "even" octets.
793dec_fixed(0, 0, Bytes, Len, C) ->
794    {#fixed{digits = 0, scale = 0, value = ""}, Bytes, Len, C};
795dec_fixed(Digits, Scale, Bytes, Len, C) ->
796    case ?ODD(Digits) of
797	true ->
798	    {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits, Scale, Bytes, Len, C),
799	    case Sign of
800		?FIXED_POSITIVE ->
801		    {#fixed{digits = Digits, scale = Scale,
802			    value = list_to_integer(Fixed)}, Bytes2, Len2, C2};
803		?FIXED_NEGATIVE ->
804		    {#fixed{digits = Digits, scale = Scale,
805			    value = -list_to_integer(Fixed)}, Bytes2, Len2, C2}
806	    end;
807	false ->
808	    %% If the length (of fixed) is even a zero is added first.
809	    %% Subtract that we've read 1 digit.
810	    <<0:4,D2:4,T/binary>> = Bytes,
811	    {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits-1, Scale, T, Len+1, C+1),
812	    case Sign of
813		?FIXED_POSITIVE ->
814		    {#fixed{digits = Digits, scale = Scale,
815			    value = list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2};
816		?FIXED_NEGATIVE ->
817		    {#fixed{digits = Digits, scale = Scale,
818			    value = -list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2}
819	    end
820    end.
821
822dec_fixed_2(1, _Scale, <<D1:4,?FIXED_POSITIVE:4,T/binary>>, Len, C) ->
823    {[D1+48], T, Len+1, C+1, ?FIXED_POSITIVE};
824dec_fixed_2(1, _Scale, <<D1:4,?FIXED_NEGATIVE:4,T/binary>>, Len, C) ->
825    {[D1+48], T, Len+1, C+1, ?FIXED_NEGATIVE};
826dec_fixed_2(Digits, Scale, _Bytes, _Len, _C) when Digits =< 0 ->
827    orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n"
828	      "Malformed fixed type.", [?LINE, Digits, Scale], ?DEBUG_LEVEL),
829    corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE});
830dec_fixed_2(Digits, Scale, <<>>, _Len, _C) ->
831    orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n"
832	      "The fixed type received was to short.",
833	      [?LINE, Digits, Scale], ?DEBUG_LEVEL),
834    corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE});
835dec_fixed_2(Digits, Scale, <<D1:4,D2:4,T/binary>>, Len, C) ->
836    {Seq, Rest2, Len2, NewC2, Sign} = dec_fixed_2(Digits-2, Scale, T, Len+1, C+1),
837    {[D1+48, D2+48 | Seq], Rest2, Len2, NewC2, Sign}.
838
839%%-----------------------------------------------------------------
840%% Func: dec_sequence/7 and dec_sequence/8
841%%-----------------------------------------------------------------
842dec_sequence(_Version, Message, 'tk_octet', Len, ByteOrder, _Buff, C) ->
843    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
844    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
845    <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
846    {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size};
847dec_sequence(_Version, Message, 'tk_char', Len, ByteOrder, _Buff, C) ->
848    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
849    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
850    <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
851    {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size};
852%% We test if it's a sequence of struct's or unions. By doing this we only
853%% have to look up the IFR-ID once instead of N times (N eq length of sequence).
854dec_sequence(Version, Message, {'tk_struct', IFRId, ShortName, ElementList},
855	     Len, ByteOrder, Buff, C) when IFRId /= "", ShortName /= "" ->
856    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
857    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
858    case IFRId of
859	?SYSTEM_TYPE ->
860	    dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4,
861				ByteOrder, Buff, NewC+4, ShortName);
862	_ ->
863	    Name = ifrid_to_name(IFRId, ?IFR_StructDef),
864	    dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4,
865				ByteOrder, Buff, NewC+4, Name)
866    end;
867dec_sequence(Version, Message,
868	     {'tk_union', ?SYSTEM_TYPE, TCName, DiscrTC, Default, ElementList},
869	     Len, ByteOrder, Buff, C) ->
870    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
871    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
872    dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4,
873		       ByteOrder, Buff, NewC+4, TCName);
874dec_sequence(Version, Message,
875	     {'tk_union', IFRId, _TCName, DiscrTC, Default, ElementList},
876	     Len, ByteOrder, Buff, C) ->
877    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
878    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
879    Name = ifrid_to_name(IFRId, ?IFR_UnionDef),
880    dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4,
881		       ByteOrder, Buff, NewC+4, Name);
882dec_sequence(Version, Message, TypeCode, Len, ByteOrder, Buff, C) ->
883    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
884    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
885    dec_sequence(Version, Rest1, Size, TypeCode, Len1 + 4, ByteOrder, Buff, NewC+4).
886
887
888dec_sequence(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C) ->
889    {[], Message, Len, C};
890dec_sequence(Version, Message, N, Type, Len, ByteOrder, Buff, C) ->
891    {Object, Rest1, Len1, NewC} = dec_type(Type, Version, Message, Len, ByteOrder, Buff, C),
892    {Seq, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, N - 1,  Type, Len1, ByteOrder, Buff, NewC),
893    {[Object | Seq], Rest2, Len2, NewC2}.
894
895dec_sequence_struct(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C, _Name) ->
896    {[], Message, Len, C};
897dec_sequence_struct(Version, Message, N, TypeCodeList, Len, ByteOrder, Buff, C, Name) ->
898    {Struct, Rest1, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
899    {Seq, Rest2, Len2, NewC2} = dec_sequence_struct(Version, Rest1, N - 1,  TypeCodeList, Len1, ByteOrder,
900						    Buff, NewC, Name),
901    {[list_to_tuple([Name |Struct]) | Seq], Rest2, Len2, NewC2}.
902
903
904dec_sequence_union(_, Message, 0, _DiscrTC, _Default, _ElementList,
905		   Len, _ByteOrder, _Buff, C, _Name) ->
906    {[], Message, Len, C};
907dec_sequence_union(Version, Message, N, DiscrTC, Default, ElementList,
908		   Len, ByteOrder, Buff, C, Name) when is_list(ElementList) ->
909
910    {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Message, Len, ByteOrder, Buff, C),
911    Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default,
912				     Rest1, Len1, ByteOrder, Buff, NewC),
913    {Value, Rest2, Len2, NewC3} = case Result of
914		{default, R, L, NewC2} ->
915		    dec_union(Version, default, ElementList, Default,
916				     R, L, ByteOrder, Buff, NewC2);
917		X ->
918		    X
919	    end,
920    {Seq, Rest3, Len3, NewC4} = dec_sequence_union(Version, Rest2, N - 1,
921						   DiscrTC, Default, ElementList,
922						   Len2, ByteOrder,
923						   Buff, NewC3, Name),
924    {[{Name, Label, Value} | Seq], Rest3, Len3, NewC4};
925dec_sequence_union(Version, Message, N, _DiscrTC, _Default, Module,
926		   Len, ByteOrder, Buff, C, Name) when is_atom(Module) ->
927    case catch Module:tc() of
928	{tk_union, _, _, DiscrTC, Default, ElementList} ->
929	    dec_sequence_union(Version, Message, N, DiscrTC, Default, ElementList,
930			       Len, ByteOrder, Buff, C, Name);
931	What ->
932	    orber:dbg("[~p] ~p:dec_sequence_union(~p). Union module doesn't exist or incorrect.",
933		      [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
934	    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
935    end.
936
937
938
939%% A special case; when something is encapsulated (i.e. sent as octet-sequence)
940%% we sometimes don not want the result to be converted to a list.
941dec_octet_sequence_bin(_Version, Message, Len, ByteOrder, _Buff, C) ->
942    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
943    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
944    <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
945    {OctetSeq, Rest2, Len1+4+Size, NewC+4+Size}.
946
947%%-----------------------------------------------------------------
948%% Func: dec_array/5
949%%-----------------------------------------------------------------
950dec_array(Version, Message, Size, TypeCode, Len, ByteOrder, Buff, C) ->
951    {Seq, Rest1, Len1, NewC} = dec_sequence(Version, Message, Size, TypeCode, Len,
952				     ByteOrder, Buff, C),
953    {list_to_tuple(Seq), Rest1, Len1, NewC}.
954
955
956%%-----------------------------------------------------------------
957%% Func: dec_string/4
958%%-----------------------------------------------------------------
959dec_string(_Version, Message, Len, ByteOrder, _Buff, C) ->
960    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
961    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
962    if
963	Size > 0 ->
964	    DataSize = Size-1,
965	    <<String:DataSize/binary, _Null:1/binary, Rest2/binary>> = Rest1,
966	    {binary_to_list(String), Rest2, Len1+4+Size, NewC+4+Size};
967	true ->
968	    {"", Rest1, Len1 + 4, NewC+4}
969    end.
970
971%%-----------------------------------------------------------------
972%% Func: dec_string/4
973%%-----------------------------------------------------------------
974dec_wstring({1,2}, Message, Len, ByteOrder, Buff, C) ->
975    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
976    {Octets, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
977    if
978	Octets == 0 ->
979	    {"", Rest1, Len1 + 4, NewC+4};
980	Octets > 0 ->
981	    Size = round(Octets/2),
982	    {String, Rest2, Len2, NewC2} =
983		dec_sequence({1,2}, Rest1, Size, 'tk_ushort',
984			     Len1 + 4, big, Buff, NewC+4),
985	    {String, Rest2, Len2, NewC2};
986	true ->
987	    orber:dbg("[~p] cdr_decode:dec_wstring(~p);",
988		      [?LINE, Rest1], ?DEBUG_LEVEL),
989	    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO})
990    end;
991dec_wstring(Version, Message, Len, ByteOrder, Buff, C) ->
992    {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
993    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
994    if
995	Size > 0 ->
996	    {String, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, Size - 1, 'tk_wchar',
997						 Len1 + 4, ByteOrder, Buff, NewC+4),
998	    %% Remove the NULL character.
999	    {_, Rest3} = cdrlib:dec_unsigned_short(ByteOrder, Rest2),
1000	    {String, Rest3, Len2 + 2, NewC2+2};
1001	Size == 0 ->
1002	    {"", Rest1, Len1 + 4, NewC+4};
1003	true ->
1004	    orber:dbg("[~p] cdr_decode:dec_wstring(~p);",
1005		      [?LINE, Rest1], ?DEBUG_LEVEL),
1006	    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO})
1007    end.
1008
1009
1010%%-----------------------------------------------------------------
1011%% Func: dec_union/9
1012%%-----------------------------------------------------------------
1013%% ## NEW IIOP 1.2 ##
1014dec_union(Version, ?SYSTEM_TYPE, Name, DiscrTC, Default, ElementList, Bytes,
1015	  Len, ByteOrder, Buff, C) ->
1016    {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C),
1017    {Value, Rest2, Len2, NewC3} = dec_union(Version, Label, ElementList, Default,
1018					    Rest1, Len1, ByteOrder, Buff, NewC),
1019    {{Name, Label, Value}, Rest2, Len2, NewC3};
1020
1021
1022dec_union(Version, IFRId, _, DiscrTC, Default, ElementList, Bytes, Len,
1023	  ByteOrder, Buff, C) when is_list(ElementList) ->
1024    {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C),
1025    Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default,
1026				     Rest1, Len1, ByteOrder, Buff, NewC),
1027    {Value, Rest2, Len2, NewC3} = case Result of
1028		{default, R, L, NewC2} ->
1029		    dec_union(Version, default, ElementList, Default,
1030				     R, L, ByteOrder, Buff, NewC2);
1031		X ->
1032		    X
1033	    end,
1034    Name = ifrid_to_name(IFRId, ?IFR_UnionDef),
1035    {{Name, Label, Value}, Rest2, Len2, NewC3};
1036dec_union(Version, IFRId, _, _DiscrTC, _Default, Module, Bytes, Len,
1037	  ByteOrder, Buff, C) when is_atom(Module) ->
1038    case catch Module:tc() of
1039	{tk_union, _, Name, DiscrTC, Default, ElementList} ->
1040	    dec_union(Version, IFRId, Name, DiscrTC, Default, ElementList, Bytes, Len,
1041		      ByteOrder, Buff, C);
1042	What ->
1043	    orber:dbg("[~p] ~p:dec_union(~p). Union module doesn't exist or incorrect.",
1044		      [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
1045	    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
1046    end.
1047
1048
1049
1050dec_union(_, _, [], Default,  Message, Len, _, _Buff, C) when Default < 0 ->
1051    {undefined, Message, Len, C};
1052dec_union(_, _, [], _Default, Message, Len, _, _Buff, C) ->
1053    {default, Message, Len, C};
1054dec_union(Version, Label, [{Label, _Name, Type}|_List], _Default, Message, Len, ByteOrder, Buff, C) ->
1055    dec_type(Type, Version, Message, Len, ByteOrder, Buff, C);
1056dec_union(Version, Label, [_H|List], Default, Message,  Len, ByteOrder, Buff, C) ->
1057    dec_union(Version, Label, List, Default, Message, Len, ByteOrder, Buff, C).
1058
1059%%-----------------------------------------------------------------
1060%% Func: dec_struct/7
1061%%-----------------------------------------------------------------
1062dec_struct(Version, "", "", TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
1063    {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
1064    {list_to_tuple(Struct), Rest, Len1, NewC};
1065dec_struct(Version, [], Name, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
1066    %% This case is used when communicating with ORB:s which don't supply the IFRId
1067    %% field in struct type codes (used in any)
1068    {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
1069    {list_to_tuple([list_to_atom(Name) |Struct]), Rest, Len1, NewC};
1070dec_struct(Version, ?SYSTEM_TYPE, ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
1071    {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
1072    {list_to_tuple([ShortName |Struct]), Rest, Len1, NewC};
1073dec_struct(Version, IFRId, _ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
1074    Name = ifrid_to_name(IFRId, ?IFR_StructDef),
1075    {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
1076    {list_to_tuple([Name |Struct]), Rest, Len1, NewC}.
1077
1078dec_struct1(_, [], Message, Len, _ByteOrder, _, C) ->
1079    {[], Message, Len, C};
1080dec_struct1(Version, [{_ElemName, ElemType} | TypeCodeList], Message, Len, ByteOrder, Buff, C) ->
1081    {Element, Rest, Len1, NewC} = dec_type(ElemType, Version, Message, Len, ByteOrder, Buff, C),
1082    {Struct, Rest1, Len2, NewC2} = dec_struct1(Version, TypeCodeList, Rest, Len1, ByteOrder, Buff, NewC),
1083    {[Element |Struct], Rest1, Len2, NewC2};
1084dec_struct1(Version, Module, Message, Len, ByteOrder, Buff, C) ->
1085    case catch Module:tc() of
1086	{tk_struct, _, _, TypeCodeList} ->
1087	    dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C);
1088	What ->
1089	    orber:dbg("[~p] ~p:dec_struct1(~p). Struct module doesn't exist or incorrect.",
1090		      [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
1091	    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
1092    end.
1093
1094ifrid_to_name([], Type) ->
1095    orber:dbg("[~p] ~p:ifrid_to_name([], ~p). No Id supplied.",
1096	      [?LINE, ?MODULE, Type], ?DEBUG_LEVEL),
1097    corba:raise(#'MARSHAL'{minor=(?CORBA_OMGVMCID bor 11),
1098			   completion_status=?COMPLETED_MAYBE});
1099ifrid_to_name(Id, Type) ->
1100    case orber:light_ifr() of
1101	true ->
1102	    orber_ifr:get_module(Id, Type);
1103	false ->
1104	    case catch ifrid_to_name_helper(Id, Type) of
1105		{'EXCEPTION', E} ->
1106		    corba:raise(E);
1107		{'EXIT',{aborted,{no_exists,_}}} ->
1108		    case orber:get_lightweight_nodes() of
1109			false ->
1110			    orber:dbg("[~p] cdr_decode:ifrid_to_name(~p, ~p). IFRid not found.",
1111				      [?LINE, Id, Type], ?DEBUG_LEVEL),
1112			    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
1113			Nodes ->
1114			    L = length(Nodes),
1115			    IFR = get_ifr_node(Nodes, rand:uniform(L), L),
1116			    list_to_atom('OrberApp_IFR':get_absolute_name(IFR, Id))
1117		    end;
1118		{'EXIT', Other} ->
1119		    orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). Unknown: ~p",
1120			      [?LINE, Id, Other], ?DEBUG_LEVEL),
1121		    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
1122		Name ->
1123		    list_to_atom(Name)
1124	    end
1125    end.
1126
1127ifrid_to_name_helper(Id, ?IFR_UnionDef) ->
1128    case mnesia:dirty_index_read(ir_UnionDef, Id, #ir_UnionDef.id) of
1129	[#ir_UnionDef{absolute_name = [$:,$:|N]}] ->
1130	    change_colons_to_underscore(N, []);
1131	Other ->
1132	    orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
1133		      [?LINE, Id, Other], ?DEBUG_LEVEL),
1134	    corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 9),
1135				   completion_status=?COMPLETED_MAYBE})
1136    end;
1137ifrid_to_name_helper(Id, ?IFR_StructDef) ->
1138    case mnesia:dirty_index_read(ir_StructDef, Id, #ir_StructDef.id) of
1139	[#ir_StructDef{absolute_name = [$:,$:|N]}] ->
1140	    change_colons_to_underscore(N, []);
1141	Other ->
1142	    orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
1143		      [?LINE, Id, Other], ?DEBUG_LEVEL),
1144	    corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 10),
1145				   completion_status=?COMPLETED_MAYBE})
1146    end;
1147ifrid_to_name_helper(Id, ?IFR_ExceptionDef) ->
1148    case mnesia:dirty_index_read(ir_ExceptionDef, Id, #ir_ExceptionDef.id) of
1149	[#ir_ExceptionDef{absolute_name = [$:,$:|N]}] ->
1150	    change_colons_to_underscore(N, []);
1151	Other ->
1152	    orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
1153		      [?LINE, Id, Other], ?DEBUG_LEVEL),
1154	    corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
1155				   completion_status=?COMPLETED_MAYBE})
1156    end.
1157
1158change_colons_to_underscore([$:, $: | T], Acc) ->
1159    change_colons_to_underscore(T, [$_ |Acc]);
1160change_colons_to_underscore([H |T], Acc) ->
1161    change_colons_to_underscore(T, [H |Acc]);
1162change_colons_to_underscore([], Acc) ->
1163    lists:reverse(Acc).
1164
1165get_ifr_node([], _, _) ->
1166    %% Were not able to contact any of the given nodes.
1167    orber:dbg("[~p] cdr_decode:get_ifr_node([]). No Node available.",
1168			    [?LINE], ?DEBUG_LEVEL),
1169    corba:raise(#'INTERNAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_MAYBE});
1170get_ifr_node(Nodes, N, L) ->
1171    Node = lists:nth(N, Nodes),
1172    case catch corba:resolve_initial_references_remote("OrberIFR", [Node]) of
1173	IFR when is_record(IFR, 'IOP_IOR') ->
1174	    IFR;
1175	_ ->
1176	    %% Not able to commincate with the node. Try next one.
1177	    NewL = L-1,
1178	    get_ifr_node(lists:delete(Node, Nodes), rand:uniform(NewL), NewL)
1179    end.
1180
1181
1182%%-----------------------------------------------------------------
1183%% Func: dec_objref/4
1184%%-----------------------------------------------------------------
1185dec_objref(Version, Message, Len, ByteOrder) ->
1186    dec_objref(Version, Message, Len, ByteOrder, [], 0).
1187dec_objref(Version, Message, Len, ByteOrder, _Buff, C) ->
1188    {IOR, Rest, Length} = iop_ior:decode(Version, Message, Len, ByteOrder),
1189    {IOR, Rest, Length, C+Length-Len}.
1190
1191%%-----------------------------------------------------------------
1192%% Func: dec_system_exception/4 and dec_user_exception/4
1193%%-----------------------------------------------------------------
1194dec_system_exception(Version, Message, Len, ByteOrder) when Version == {1,2} ->
1195    {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len),
1196    {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder),
1197    Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION),
1198    {Struct, _Rest2, Len2} =
1199	dec_exception_1(Version, [{"minor",'tk_ulong'},
1200				  {"completed",
1201				   {'tk_enum', "", "completion_status",
1202				    ["COMPLETED_YES", "COMPLETED_NO",
1203				     "COMPLETED_MAYBE"]}}],
1204			Rest1, Len1, ByteOrder),
1205    {list_to_tuple([Name, "" |Struct]), Len2};
1206dec_system_exception(Version, Message, Len, ByteOrder) ->
1207    {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder),
1208    Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION),
1209    {Struct, _Rest2, Len2} =
1210	dec_exception_1(Version, [{"minor",'tk_ulong'},
1211				  {"completed",
1212				   {'tk_enum', "", "completion_status",
1213				    ["COMPLETED_YES", "COMPLETED_NO",
1214				     "COMPLETED_MAYBE"]}}],
1215			Rest1, Len1, ByteOrder),
1216    {list_to_tuple([Name, "" |Struct]), Len2}.
1217
1218dec_user_exception(Version, Message, Len, ByteOrder) when Version == {1,2} ->
1219    {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len),
1220    {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder),
1221    Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef),
1222    {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId),
1223    {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1,
1224					     ByteOrder),
1225    {list_to_tuple([Name, TypeId |Struct]), Len2};
1226dec_user_exception(Version, Message, Len, ByteOrder) ->
1227    {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder),
1228    Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef),
1229    {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId),
1230    {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1,
1231					     ByteOrder),
1232    {list_to_tuple([Name, TypeId |Struct]), Len2}.
1233
1234dec_exception_1(_, [], Message, Len, _ByteOrder) ->
1235    {[], Message, Len};
1236dec_exception_1(Version, [{_ElemName, ElemType} | ElementList], Message,
1237		Len, ByteOrder) ->
1238    {Element, Rest, Len1} = dec_type(ElemType, Version, Message, Len, ByteOrder),
1239    {Struct, Rest1, Len2} = dec_exception_1(Version, ElementList, Rest, Len1,
1240						   ByteOrder),
1241    {[Element |Struct], Rest1, Len2}.
1242
1243
1244get_user_exception_type(TypeId) ->
1245    case orber:light_ifr() of
1246	true ->
1247	    orber_ifr:get_tc(TypeId, ?IFR_ExceptionDef);
1248	false ->
1249	    case orber:get_lightweight_nodes() of
1250		false ->
1251		    case mnesia:dirty_index_read(ir_ExceptionDef, TypeId,
1252						 #ir_ExceptionDef.id) of
1253			[ExcDef] when is_record(ExcDef, ir_ExceptionDef) ->
1254			    ExcDef#ir_ExceptionDef.type;
1255			Other ->
1256			    orber:dbg("[~p] cdr_decode:get_user_exception_type(~p). IFR Id not found: ~p",
1257				      [?LINE, TypeId, Other], ?DEBUG_LEVEL),
1258			    corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
1259						   completion_status=?COMPLETED_MAYBE})
1260		    end;
1261		Nodes ->
1262		    L = length(Nodes),
1263		    IFR = get_ifr_node(Nodes, rand:uniform(L), L),
1264		    'OrberApp_IFR':get_user_exception_type(IFR, TypeId)
1265	    end
1266    end.
1267
1268%%-----------------------------------------------------------------
1269%% Func: dec_type_code/4
1270%%-----------------------------------------------------------------
1271dec_type_code(Version, Message, Len, ByteOrder, Buff, C) ->
1272    {TypeNo, Message1, Len1, NewC} = dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
1273    TC = dec_type_code(TypeNo, Version, Message1, Len1, ByteOrder, Buff, NewC),
1274    erase(orber_indirection),
1275    TC.
1276
1277%%-----------------------------------------------------------------
1278%% Func: dec_type_code/5
1279%%-----------------------------------------------------------------
1280dec_type_code(0, _, Message, Len, _, _, C) ->
1281    {'tk_null', Message, Len, C};
1282dec_type_code(1, _, Message, Len, _, _, C) ->
1283    {'tk_void', Message, Len, C};
1284dec_type_code(2, _, Message, Len, _, _, C) ->
1285    {'tk_short', Message, Len, C};
1286dec_type_code(3, _, Message, Len, _, _, C) ->
1287    {'tk_long', Message, Len, C};
1288dec_type_code(23, _, Message, Len, _, _, C) ->
1289    {'tk_longlong', Message, Len, C};
1290dec_type_code(25, _, Message, Len, _, _, C) ->
1291    {'tk_longdouble', Message, Len, C};
1292dec_type_code(4, _, Message, Len, _, _, C) ->
1293    {'tk_ushort', Message, Len, C};
1294dec_type_code(5, _, Message, Len, _, _, C) ->
1295    {'tk_ulong', Message, Len, C};
1296dec_type_code(24, _, Message, Len, _, _, C) ->
1297    {'tk_ulonglong', Message, Len, C};
1298dec_type_code(6, _, Message, Len, _, _, C) ->
1299    {'tk_float', Message, Len, C};
1300dec_type_code(7, _, Message, Len, _, _, C) ->
1301    {'tk_double', Message, Len, C};
1302dec_type_code(8, _, Message, Len, _, _, C) ->
1303    {'tk_boolean', Message, Len, C};
1304dec_type_code(9, _, Message, Len, _, _, C) ->
1305    {'tk_char', Message, Len, C};
1306dec_type_code(26, _, Message, Len, _, _, C) ->
1307    {'tk_wchar', Message, Len, C};
1308dec_type_code(10, _, Message, Len, _, _, C) ->
1309    {'tk_octet', Message, Len, C};
1310dec_type_code(11, _, Message, Len, _, _, C) ->
1311    {'tk_any', Message, Len, C};
1312dec_type_code(12, _, Message, Len, _, _, C) ->
1313    {'tk_TypeCode', Message, Len, C};
1314dec_type_code(13, _, Message, Len, _, _, C) ->
1315    {'tk_Principal', Message, Len, C};
1316dec_type_code(14, Version, Message, Len, ByteOrder, Buff, C) ->
1317    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1318    %% Decode marshalled parameters, eg get the byteorder first
1319    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1320    {{RepId, Name}, <<>>, _Len2, NewC} =
1321	dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
1322					{"name", {'tk_string', 0}}]},
1323		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1324    {{'tk_objref', RepId, Name}, Message1, Len1, NewC};
1325dec_type_code(15, Version, Message, Len, ByteOrder, Buff, C) ->
1326    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1327    %% Decode marshalled parameters, eg get the byteorder first
1328    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1329    {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
1330	dec_type({'tk_struct', "", "",
1331		  [{"repository ID", {'tk_string', 0}},
1332		   {"name", {'tk_string', 0}},
1333		   {"element list",
1334		    {'tk_sequence', {'tk_struct', "","",
1335				     [{"member name", {'tk_string', 0}},
1336				      {"member type", 'tk_TypeCode'}]},
1337		     0}}]},
1338		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1339    {{'tk_struct', RepId, Name, ElementList}, Message1, Len1, NewC};
1340dec_type_code(16, Version, Message, Len, ByteOrder, Buff, C) ->
1341    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1342    %% Decode marshalled parameters, eg get the byteorder first
1343    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1344    {{RepId, Name, DiscrTC, Default}, Rest2, RestLen2, NewC} =
1345	dec_type({'tk_struct', "", "",
1346		  [{"repository ID", {'tk_string', 0}},
1347		   {"name", {'tk_string', 0}},
1348		   {"discriminant type", 'tk_TypeCode'},
1349		   {"default used", 'tk_long'}]},
1350		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1351    {ElementList, <<>>, _RestLen3, NewC2} =
1352	dec_type({'tk_sequence', {'tk_struct', "","",
1353				  [{"label value", DiscrTC},
1354				   {"member name", {'tk_string', 0}},
1355				   {"member type", 'tk_TypeCode'}]}, 0},
1356		 Version, Rest2, RestLen2, ByteOrder1, Buff, NewC),
1357    NewElementList =
1358	case check_enum(DiscrTC) of
1359	    true ->
1360		lists:map(fun({L,N,T}) -> {atom_to_list(L),N,T} end, ElementList);
1361	    false ->
1362		ElementList
1363	end,
1364    {{'tk_union', RepId, Name, DiscrTC, Default, NewElementList}, Message1, Len1, NewC2};
1365dec_type_code(17, Version, Message, Len, ByteOrder, Buff, C) ->
1366    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1367    %% Decode marshalled parameters, eg get the byteorder first
1368    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1369    {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
1370	dec_type({'tk_struct', "", "",
1371		  [{"repository ID", {'tk_string', 0}},
1372		   {"name", {'tk_string', 0}},
1373		   {"element list",
1374		    {'tk_sequence', {'tk_string', 0}, 0}}]},
1375		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1376    {{'tk_enum', RepId, Name, ElementList}, Message1, Len1, NewC};
1377dec_type_code(18, Version, Message, Len, ByteOrder, Buff, C) ->
1378    {MaxLength, Message1, Len1, NewC} =
1379	dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
1380    {{'tk_string', MaxLength}, Message1, Len1, NewC};
1381dec_type_code(19, Version, Message, Len, ByteOrder, Buff, C) ->
1382    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1383    %% Decode marshalled parameters, eg get the byteorder first
1384    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1385    {{ElemTC, MaxLength}, <<>>, _Len2, NewC} =
1386	dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
1387					{"max length", 'tk_ulong'}]},
1388		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1389    {{'tk_sequence', ElemTC, MaxLength}, Message1, Len1, NewC};
1390dec_type_code(20, Version, Message, Len, ByteOrder, Buff, C) ->
1391    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1392    %% Decode marshalled parameters, eg get the byteorder first
1393    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1394    {{ElemTC, Length}, <<>>, _Len2, NewC} =
1395	dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
1396					{"length", 'tk_ulong'}]},
1397		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1398    {{'tk_array', ElemTC, Length}, Message1, Len1, NewC};
1399dec_type_code(21, Version, Message, Len, ByteOrder, Buff, C) ->
1400    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1401    %% Decode marshalled parameters, eg ge a byteorder first
1402    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1403    {{RepId, Name, TC}, <<>>, _Len2, NewC} =
1404	dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
1405					{"name", {'tk_string', 0}},
1406					{"TypeCode", 'tk_TypeCode'}]},
1407		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1408    {{'tk_alias', RepId, Name, TC}, Message1, Len1, NewC};
1409dec_type_code(22, Version, Message, Len, ByteOrder, Buff, C) ->
1410    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1411    %% Decode marshalled parameters, eg get the byteorder first
1412    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1413    {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
1414	dec_type({'tk_struct', "", "",
1415		  [{"repository ID", {'tk_string', 0}},
1416		   {"name", {'tk_string', 0}},
1417		   {"element list",
1418		    {'tk_sequence', {'tk_struct', "","",
1419				     [{"member name", {'tk_string', 0}},
1420				      {"member type", 'tk_TypeCode'}]},
1421		     0}}]},
1422		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1423    {{'tk_except', RepId, Name, ElementList}, Message1, Len1, NewC};
1424dec_type_code(27, Version, Message, Len, ByteOrder, Buff, C) ->
1425    {MaxLength, Message1, Len1, NewC} =
1426	dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
1427    {{'tk_wstring', MaxLength}, Message1, Len1, NewC};
1428dec_type_code(28, Version, Message, Len, ByteOrder, Buff, C) ->
1429    {Digits, Message1, Len1, C1} =
1430	dec_type('tk_ushort', Version, Message, Len, ByteOrder, Buff, C),
1431    {Scale, Message2, Len2, C2} =
1432	dec_type('tk_short', Version, Message1, Len1, ByteOrder, Buff, C1),
1433    {{'tk_fixed', Digits, Scale}, Message2, Len2, C2};
1434dec_type_code(29, Version, Message, Len, ByteOrder, Buff, C) ->
1435    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1436    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1437    {{RepId, Name, ValueModifier, TC, ElementList}, <<>>, _Len2, NewC} =
1438	dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
1439					{"name", {'tk_string', 0}},
1440					{"ValueModifier", 'tk_short'},
1441					{"TypeCode", 'tk_TypeCode'},
1442					{"element list",
1443					 {'tk_sequence',
1444					  {'tk_struct', "","",
1445					   [{"member name", {'tk_string', 0}},
1446					    {"member type", 'tk_TypeCode'},
1447					    {"Visibility", 'tk_short'}]},
1448					  0}}]},
1449		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1450    {{'tk_value', RepId, Name, ValueModifier, TC, ElementList}, Message1, Len1, NewC};
1451dec_type_code(30, Version, Message, Len, ByteOrder, Buff, C) ->
1452    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1453    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1454    {{RepId, Name, TC}, <<>>, _Len2, NewC} =
1455	dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
1456					{"name", {'tk_string', 0}},
1457					{"TypeCode", 'tk_TypeCode'}]},
1458		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1459    {{'tk_value_box', RepId, Name, TC}, Message1, Len1, NewC};
1460dec_type_code(31, Version, Message, Len, ByteOrder, Buff, C) ->
1461    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1462    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1463    {{RepId, Name}, <<>>, _Len2, NewC} =
1464	dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
1465					{"name", {'tk_string', 0}}]},
1466		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1467    {{'tk_native', RepId, Name}, Message1, Len1, NewC};
1468dec_type_code(32, Version, Message, Len, ByteOrder, Buff, C) ->
1469    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1470    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1471    {{RepId, Name}, <<>>, _Len2, NewC} =
1472	dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}},
1473					{"name", {'tk_string', 0}}]},
1474		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1475    {{'tk_abstract_interface', RepId, Name}, Message1, Len1, NewC};
1476dec_type_code(33, Version, Message, Len, ByteOrder, Buff, C) ->
1477    {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
1478    {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
1479    {{RepId, Name}, <<>>, _Len2, NewC} =
1480	dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}},
1481					{"name", {'tk_string', 0}}]},
1482		 Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
1483    {{'tk_local_interface', RepId, Name}, Message1, Len1, NewC};
1484dec_type_code(16#ffffffff, Version, Message, Len, ByteOrder, Buff, C) ->
1485    {Indirection, Message1, Len1, NewC} =
1486	dec_type('tk_long', Version, Message, Len, ByteOrder, Buff, C),
1487    Position = C+Indirection,
1488    case put(orber_indirection, Position) of
1489	Position ->
1490%%	    {{'none', Indirection}, Message1, Len1, NewC};
1491            %% Recursive TypeCode. Break the loop.
1492 	    orber:dbg("[~p] cdr_decode:dec_type_code(~p); Recursive TC not supported.",
1493 		      [?LINE,Position], ?DEBUG_LEVEL),
1494 	    corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
1495	_ ->
1496	    <<_:Position/binary, SubBuff/binary>> = Buff,
1497	    {TC, _, _, _} = dec_type_code(Version, SubBuff, Position, ByteOrder, Buff, Position),
1498	    {TC, Message1, Len1, NewC}
1499    end;
1500dec_type_code(Type, _, _, _, _, _, _) ->
1501    orber:dbg("[~p] cdr_decode:dec_type_code(~p); No match.",
1502			    [?LINE, Type], ?DEBUG_LEVEL),
1503    corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 8), completion_status=?COMPLETED_MAYBE}).
1504
1505check_enum({'tk_enum', _, _, _}) ->
1506    true;
1507check_enum(_) ->
1508    false.
1509
1510
1511decode_complex_tc_parameters(_Version, Message, Len, ByteOrder) ->
1512    {Rest, Len1, NewC} = dec_align(Message, Len, 4, 0),
1513    {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
1514    <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
1515    {OctetSeq, Rest2, Len1+4+Size, NewC+4}.
1516
1517%%-----------------------------------------------------------------
1518%% Func: dec_align/3
1519%% Args:
1520%%       R - The byte sequence that shall be aligned.
1521%%       Len - The number of bytes read so far.
1522%%       Alignment - The alignment as an integer (for example: 2,4,8).
1523%% Returns:
1524%%       An aligned byte sequence.
1525%%-----------------------------------------------------------------
1526dec_align(R, Len, Alignment, C) ->
1527    Rem = Len rem Alignment,
1528    if Rem == 0 ->
1529	    {R, Len, C};
1530       true ->
1531	    Diff = Alignment - Rem,
1532	    <<_:Diff/binary,Rest/binary>> = R,
1533	    {Rest, Len + Diff, C + Diff}
1534    end.
1535
1536%%---------------- EOF MODULE ----------------------------------------
1537