⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eldap.erl

📁 ejabberd-0.7.5 分布式Jabber服务器
💻 ERL
📖 第 1 页 / 共 3 页
字号:
		    cancel_timer(Timer),		    Reply = check_bind_reply(Result, From),		    {reply, Reply, From, S#eldap{dict = New_dict}};		{OtherName, OtherResult} ->		    New_dict = dict:erase(Id, Dict),		    cancel_timer(Timer),		    {reply, {error, {invalid_result, OtherName, OtherResult}},		            From, S#eldap{dict = New_dict}}	    end;	Error -> Error    end.check_reply(#'LDAPResult'{resultCode = success}, From) ->    ok;check_reply(#'LDAPResult'{resultCode = Reason}, From) ->    {error, Reason};check_reply(Other, From) ->    {error, Other}.check_bind_reply(#'BindResponse'{resultCode = success}, From) ->    ok;check_bind_reply(#'BindResponse'{resultCode = Reason}, From) ->    {error, Reason};check_bind_reply(Other, From) ->    {error, Other}.get_op_rec(Id, Dict) ->    case dict:find(Id, Dict) of	{ok, [{Timer, From, Name}|Res]} ->	    {Timer, From, Name, Res};	error ->	    throw({error, unkown_id})    end.%%-----------------------------------------------------------------------%% recvd_wait_bind_response packet%% Deals with incoming packets in the wait_bind_response state%% Will return one of:%%  bound - Success - move to active state%%  {fail_bind, Reason} - Failed%%  {error, Reason}%%  {'EXIT', Reason} - Broken packet%%-----------------------------------------------------------------------recvd_wait_bind_response(Pkt, S) ->    check_tag(Pkt),    case asn1rt:decode('ELDAPv3', 'LDAPMessage', Pkt) of	{ok,Msg} ->	    log2("~p", [Msg], S),	    check_id(S#eldap.id, Msg#'LDAPMessage'.messageID),	    case Msg#'LDAPMessage'.protocolOp of		{bindResponse, Result} ->		    case Result#'LDAPResult'.resultCode of			success -> bound;			Error   -> {fail_bind, Error}		    end	    end;	Else ->	    {fail_bind, Else}    end.check_id(Id, Id) -> ok;check_id(_, _)   -> throw({error, wrong_bind_id}).%%-----------------------------------------------------------------------%% General Helpers%%-----------------------------------------------------------------------cancel_timer(Timer) ->    erlang:cancel_timer(Timer),    receive	{timeout, Timer, _} ->	    ok    after 0 ->	    ok    end.%%% Sanity check of received packetcheck_tag(Data) ->    case asn1rt_ber_bin:decode_tag(Data) of	{Tag, Data1, Rb} ->	    case asn1rt_ber_bin:decode_length(Data1) of		{{Len,Data2}, Rb2} -> ok;		_ -> throw({error,decoded_tag_length})	    end;	_ -> throw({error,decoded_tag})    end.close_and_retry(S) ->    gen_tcp:close(S#eldap.fd),    retry_connect().retry_connect() ->    erlang:send_after(?RETRY_TIMEOUT, self(),		      {timeout, retry_connect}).%%-----------------------------------------------------------------------%% Sort out timed out commands%%-----------------------------------------------------------------------cmd_timeout(Timer, Id, S) ->    Dict = S#eldap.dict,    case dict:find(Id, Dict) of	{ok, [{Timer, From, Name}|Res]} ->	    case Name of		searchRequest ->		    {Res1, Ref1} = polish(Res),		    New_dict = dict:erase(Id, Dict),		    {reply, From, {timeout,				   #eldap_search_result{entries = Res1,							referrals = Ref1}},		                   S#eldap{dict = New_dict}};		Others ->		    New_dict = dict:erase(Id, Dict),		    {reply, From, {error, timeout}, S#eldap{dict = New_dict}}	    end;	error ->	    {error, timed_out_cmd_not_in_dict}    end.%%-----------------------------------------------------------------------%% Common stuff for results%%-----------------------------------------------------------------------%%%%%% Polish the returned search result%%%polish(Entries) ->    polish(Entries, [], []).polish([H|T], Res, Ref) when record(H, 'SearchResultEntry') ->    ObjectName = H#'SearchResultEntry'.objectName,    F = fun({_,A,V}) -> {A,V} end,    Attrs = lists:map(F, H#'SearchResultEntry'.attributes),    polish(T, [#eldap_entry{object_name = ObjectName,			    attributes  = Attrs}|Res], Ref);polish([H|T], Res, Ref) ->     % No special treatment of referrals at the moment.    polish(T, Res, [H|Ref]);polish([], Res, Ref) ->    {Res, Ref}.%%-----------------------------------------------------------------------%% Connect to next server in list and attempt to bind to it.%%-----------------------------------------------------------------------connect_bind(S) ->    Host = next_host(S#eldap.host, S#eldap.hosts),    TcpOpts = [{packet, asn1}, {active, true}, binary],    case gen_tcp:connect(Host, S#eldap.port, TcpOpts) of	{ok, Socket} ->	    case bind_request(Socket, S) of		{ok, NewS} ->		    Timer = erlang:start_timer(?BIND_TIMEOUT, self(),					       {timeout, bind_timeout}),		    {ok, wait_bind_response, NewS#eldap{fd = Socket,							host = Host,							bind_timer = Timer}};		{error, Reason} ->		    gen_tcp:close(Socket),		    erlang:send_after(?RETRY_TIMEOUT, self(),				      {timeout, retry_connect}),		    {ok, connecting, S#eldap{host = Host}}	    end;	{error, Reason} ->	    erlang:send_after(?RETRY_TIMEOUT, self(), 			      {timeout, retry_connect}),	    {ok, connecting, S#eldap{host = Host}}    end.bind_request(Socket, S) ->    Id = bump_id(S),    Req = #'BindRequest'{version        = S#eldap.version,			 name           = S#eldap.rootdn,  			 authentication = {simple, S#eldap.passwd}},    Message = #'LDAPMessage'{messageID  = Id,			     protocolOp = {bindRequest, Req}},    log2("Message:~p~n",[Message], S),    {ok, Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message),    ok = gen_tcp:send(Socket, Bytes),    {ok, S#eldap{id = Id}}.%% Given last tried Server, find next one to trynext_host(null, [H|_]) -> H;			% First time, take firstnext_host(Host, Hosts) ->			% Find next in turn    next_host(Host, Hosts, Hosts).next_host(Host, [Host], Hosts) -> hd(Hosts);	% Wrap back to firstnext_host(Host, [Host|Tail], Hosts) -> hd(Tail);	% Take nextnext_host(Host, [], Hosts) -> hd(Hosts);	% Never connected before? (shouldn't happen)next_host(Host, [H|T], Hosts) -> next_host(Host, T, Hosts).%%% --------------------------------------------------------------------%%% Verify the input data%%% --------------------------------------------------------------------v_filter({'and',L})           -> {'and',L};v_filter({'or', L})           -> {'or',L};v_filter({'not',L})           -> {'not',L};v_filter({equalityMatch,AV})  -> {equalityMatch,AV};v_filter({greaterOrEqual,AV}) -> {greaterOrEqual,AV};v_filter({lessOrEqual,AV})    -> {lessOrEqual,AV};v_filter({approxMatch,AV})    -> {approxMatch,AV};v_filter({present,A})         -> {present,A};v_filter({substrings,S}) when record(S,'SubstringFilter') -> {substrings,S};v_filter(_Filter) -> throw({error,concat(["unknown filter: ",_Filter])}).v_modifications(Mods) ->    F = fun({_,Op,_}) ->		case lists:member(Op,[add,delete,replace]) of		    true -> true;		    _    -> throw({error,{mod_operation,Op}})		end	end,    lists:foreach(F, Mods).v_substr([{Key,Str}|T]) when list(Str),Key==initial;Key==any;Key==final ->    [{Key,Str}|v_substr(T)];v_substr([H|T]) ->    throw({error,{substring_arg,H}});v_substr([]) ->     [].v_scope(baseObject)   -> baseObject;v_scope(singleLevel)  -> singleLevel;v_scope(wholeSubtree) -> wholeSubtree;v_scope(_Scope)       -> throw({error,concat(["unknown scope: ",_Scope])}).v_bool(true)  -> true;v_bool(false) -> false;v_bool(_Bool) -> throw({error,concat(["not Boolean: ",_Bool])}).v_timeout(I) when integer(I), I>=0 -> I;v_timeout(_I) -> throw({error,concat(["timeout not positive integer: ",_I])}).v_attributes(Attrs) ->    F = fun(A) when list(A) -> A;	   (A) -> throw({error,concat(["attribute not String: ",A])})	end,    lists:map(F,Attrs).%%% --------------------------------------------------------------------%%% Get and Validate the initial configuration%%% --------------------------------------------------------------------get_config() ->    Priv_dir = code:priv_dir(eldap),    File = filename:join(Priv_dir, "eldap.conf"),    case file:consult(File) of	{ok, Entries} ->	    case catch parse(Entries) of		{ok, Hosts, Port, Rootdn, Passwd, Log} ->		    {ok, Hosts, Port, Rootdn, Passwd, Log};		{error, Reason} ->		    {error, Reason};		{'EXIT', Reason} ->		    {error, Reason}	    end;	{error, Reason} ->	    {error, Reason}    end.parse(Entries) ->    {ok,     get_hosts(host, Entries),     get_integer(port, Entries),     get_list(rootdn, Entries),     get_list(passwd, Entries),     get_log(log, Entries)}.get_integer(Key, List) ->    case lists:keysearch(Key, 1, List) of	{value, {Key, Value}} when integer(Value) ->	    Value;	{value, {Key, Value}} ->	    throw({error, "Bad Value in Config for " ++ atom_to_list(Key)});	false ->	    throw({error, "No Entry in Config for " ++ atom_to_list(Key)})    end.get_list(Key, List) ->    case lists:keysearch(Key, 1, List) of	{value, {Key, Value}} when list(Value) ->	    Value;	{value, {Key, Value}} ->	    throw({error, "Bad Value in Config for " ++ atom_to_list(Key)});	false ->	    throw({error, "No Entry in Config for " ++ atom_to_list(Key)})    end.get_log(Key, List) ->    case lists:keysearch(Key, 1, List) of	{value, {Key, Value}} when function(Value) ->	    Value;	{value, {Key, Else}} ->	    false;	false ->	    fun(Level, Format, Args) -> io:format("--- " ++ Format, Args) end    end.get_hosts(Key, List) ->    lists:map(fun({Key1, {A,B,C,D}}) when integer(A),					  integer(B),					  integer(C),					  integer(D),					  Key == Key1->		      {A,B,C,D};		 ({Key1, Value}) when list(Value),				      Key == Key1->		      Value;		 ({Else, Value}) ->		      throw({error, "Bad Hostname in config"}) 	      end, List).%%% --------------------------------------------------------------------%%% Other Stuff%%% --------------------------------------------------------------------bump_id(#eldap{id = Id}) when Id > ?MAX_TRANSACTION_ID ->     ?MIN_TRANSACTION_ID;bump_id(#eldap{id = Id}) ->    Id + 1.%%% --------------------------------------------------------------------%%% Log routines. Call a user provided log routine Fun.%%% --------------------------------------------------------------------log1(Str, Args, #eldap{log = Fun, debug_level = N}) -> log(Fun, Str, Args, 1, N).log2(Str, Args, #eldap{log = Fun, debug_level = N}) -> log(Fun, Str, Args, 2, N).log(Fun, Str, Args, This_level, Status) when function(Fun), This_level =< Status ->    catch Fun(This_level, Str, Args);log(_, _, _, _, _) ->     ok.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -