%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
-module(convopts).
-export([?MODULE/0]).
-define(UINT32_MAX, ((1 bsl 32) - 1)).
?MODULE() ->
Type = 12345,
Inst = 1,
Zone = 0,
case convopts([{dest, {tipc_name, Type, Inst, Zone}}]) of
{ok, [{$B, <<Type:32, Inst:32, Zone:32>>}]} ->
ok;
Other ->
{error, Other}
end.
convopts(Opts) ->
catch
case getopts(Opts, [active, recvfrom, importance, distribution,
dest]) of
{[Active, Recvfrom, Importance, Distribution,
Dest], []} ->
{R, RR} =
case {Active, Recvfrom} of
{[], [recvfrom]} ->
throw({error, einval});
{_, [recvfrom]} ->
{$r, $R};
{_, _} ->
{$e, $E}
end,
{ok,
lists:flatten(
[case Active of
[{active, true}] ->
[{R, <<?UINT32_MAX:32>>}];
[{active, N}] when integer(N),
0 =< N, N < ?UINT32_MAX ->
[{R, <<N:32>>}];
[{active, N}] when integer(N),
-?UINT32_MAX < N, N < 0 ->
[{RR, <<-N:32>>}];
[{active, once}] ->
[{R, <<1:32>>}];
[{active, false}] ->
[{R, <<0:32>>}];
[] ->
[];
_ ->
throw({error, einval})
end,
case Importance of
[{importance, normal}] ->
[{$i, []}];
[{importance, high}] ->
[{$I, []}];
[] ->
[];
_ ->
throw({error, einval})
end,
case Distribution of
[distribution] ->
[{$d, []}];
[] ->
[];
_ ->
throw({error, einval})
end,
case Dest of
%% Port addressed message
[{dest, {tipc_port_id, Port, Proc}}]
when binary(Port),
integer(Proc), 0 =< Proc, Proc =< ?UINT32_MAX
;
list(Port),
integer(Proc), 0 =< Proc, Proc =< ?UINT32_MAX ->
[{$p, [Port | <<Proc:32>>]}];
%% Name addressed message
[{dest, {tipc_name, Type, Inst, Zone}}]
when integer(Type), 0 =< Type, Type =< ?UINT32_MAX,
integer(Inst), 0 =< Inst, Inst =< ?UINT32_MAX,
integer(Zone), 0 =< Zone, Zone =< ?UINT32_MAX ->
[{$B, <<Type:32, Inst:32, Zone:32>>}];
%%
%% This undocumented clause uses an undocumented
%% feature of the TIPC socket interface that takes
%% advantage of some gory internals of the protocol.
%% It is protocol implementation dependant and
%% breaks the whole idea of location transparency
%% for name addressed messages. Therefore it should
%% only be used when all other possibilities are
%% exhausted.
%%
[{dest, {tipc_name, Type, Inst,
{tipc_processor_id,
Zone, Subnetwork, Processor}}}]
when integer(Type), 0 =< Type, Type =< ?UINT32_MAX,
integer(Inst), 0 =< Inst, Inst =< ?UINT32_MAX,
integer(Zone),
0 =< Zone, Zone < 16#FF,
integer(Subnetwork),
0 =< Subnetwork, Subnetwork < 16#FFF,
integer(Processor),
0 =< Processor, Processor < 16#FFF ->
[{$B, <<Type:32,
Inst:32,
Zone:8, Subnetwork:12, Processor:12>>}];
[] ->
[];
_ ->
throw({error, einval})
end
])};
_ ->
throw({error, einval})
end.
getopts(List, Options) when list(List), list(Options) ->
getopts_1(Options, List, []).
getopts_1([], List, Result) ->
{lists:reverse(Result), List};
getopts_1([Option | Options], List, Result) ->
{Optvals, Remaining} = getopts_2(List, Option, [], []),
getopts_1(Options, Remaining, [Optvals | Result]).
getopts_2([], _Option, Result, Remaining) ->
{lists:reverse(Result), lists:reverse(Remaining)};
getopts_2([Option | Tail], Option, Result, Remaining) ->
getopts_2(Tail, Option, [Option | Result], Remaining);
getopts_2([Optval | Tail], Option, Result, Remaining)
when element(1, Optval) == Option ->
getopts_2(Tail, Option, [Optval | Result], Remaining);
getopts_2([Other | Tail], Option, Result, Remaining) ->
getopts_2(Tail, Option, Result, [Other | Remaining]).