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

📄 eldap.erl

📁 ejabberd-0.7.5 分布式Jabber服务器
💻 ERL
📖 第 1 页 / 共 3 页
字号:
%%%%%% A substring filter seem to be based on a pattern:%%%%%%   InitValue*AnyValue*FinalValue%%%%%% where all three parts seem to be optional (at least when%%% talking with an OpenLDAP server). Thus, the arguments%%% to substrings/2 looks like this:%%%%%% Type   ::= string( <attribute> )%%% SubStr ::= listof( {initial,Value} | {any,Value}, {final,Value})%%%%%% Example: substrings("sn",[{initial,"To"},{any,"kv"},{final,"st"}])%%% will match entries containing:  'sn: Tornkvist'%%%substrings(Type, SubStr) when list(Type), list(SubStr) ->     Ss = {'SubstringFilter_substrings',v_substr(SubStr)},    {substrings,#'SubstringFilter'{type = Type,				   substrings = Ss}}.get_handle(Pid) when pid(Pid)    -> Pid;get_handle(Atom) when atom(Atom) -> Atom;get_handle(Name) when list(Name) -> list_to_atom("eldap_" ++ Name).%%%----------------------------------------------------------------------%%% Callback functions from gen_fsm%%%----------------------------------------------------------------------%%----------------------------------------------------------------------%% Func: init/1%% Returns: {ok, StateName, StateData}          |%%          {ok, StateName, StateData, Timeout} |%%          ignore                              |%%          {stop, StopReason}             %% I use the trick of setting a timeout of 0 to pass control into the%% process.      %%----------------------------------------------------------------------init([]) ->    case get_config() of	{ok, Hosts, Rootdn, Passwd, Log} ->	    init({Hosts, Rootdn, Passwd, Log});	{error, Reason} ->	    {stop, Reason}    end;init({Hosts, Port, Rootdn, Passwd, Log}) ->    {ok, connecting, #eldap{hosts = Hosts,			    port = Port,			    rootdn = Rootdn,			    passwd = Passwd,			    id = 0,			    log = Log,			    dict = dict:new(),			    debug_level = 0}, 0}.%%----------------------------------------------------------------------%% Func: StateName/2%% Called when gen_fsm:send_event/2,3 is invoked (async)%% Returns: {next_state, NextStateName, NextStateData}          |%%          {next_state, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                         %%----------------------------------------------------------------------connecting(timeout, S) ->    {ok, NextState, NewS} = connect_bind(S),    {next_state, NextState, NewS}.%%----------------------------------------------------------------------%% Func: StateName/3%% Called when gen_fsm:sync_send_event/2,3 is invoked.%% Returns: {next_state, NextStateName, NextStateData}            |%%          {next_state, NextStateName, NextStateData, Timeout}   |%%          {reply, Reply, NextStateName, NextStateData}          |%%          {reply, Reply, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                          |%%          {stop, Reason, Reply, NewStateData}                    %%----------------------------------------------------------------------connecting(Event, From, S) ->    Reply = {error, connecting},    {reply, Reply, connecting, S}.wait_bind_response(Event, From, S) ->    Reply = {error, wait_bind_response},    {reply, Reply, wait_bind_response, S}.active(Event, From, S) ->    case catch send_command(Event, From, S) of	{ok, NewS} ->	    {next_state, active, NewS};	{error, Reason} ->	    {reply, {error, Reason}, active, S};	{'EXIT', Reason} ->	    {reply, {error, Reason}, active, S}    end.%%----------------------------------------------------------------------%% Func: handle_event/3%% Called when gen_fsm:send_all_state_event/2 is invoked.%% Returns: {next_state, NextStateName, NextStateData}          |%%          {next_state, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                         %%----------------------------------------------------------------------handle_event(close, StateName, S) ->    gen_tcp:close(S#eldap.fd),    {stop, closed, S};handle_event(Event, StateName, S) ->    {next_state, StateName, S}.%%----------------------------------------------------------------------%% Func: handle_sync_event/4%% Called when gen_fsm:sync_send_all_state_event/2,3 is invoked%% Returns: {next_state, NextStateName, NextStateData}            |%%          {next_state, NextStateName, NextStateData, Timeout}   |%%          {reply, Reply, NextStateName, NextStateData}          |%%          {reply, Reply, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                          |%%          {stop, Reason, Reply, NewStateData}                    %%----------------------------------------------------------------------handle_sync_event({debug_level, N}, From, StateName, S) ->    {reply, ok, StateName, S#eldap{debug_level = N}};handle_sync_event(Event, From, StateName, S) ->    {reply, {StateName, S}, StateName, S};handle_sync_event(Event, From, StateName, S) ->    Reply = ok,    {reply, Reply, StateName, S}.%%----------------------------------------------------------------------%% Func: handle_info/3%% Returns: {next_state, NextStateName, NextStateData}          |%%          {next_state, NextStateName, NextStateData, Timeout} |%%          {stop, Reason, NewStateData}                         %%----------------------------------------------------------------------%%%% Packets arriving in various states%%handle_info({tcp, Socket, Data}, connecting, S) ->    log1("eldap. tcp packet received when disconnected!~n~p~n", [Data], S),    {next_state, connecting, S};handle_info({tcp, Socket, Data}, wait_bind_response, S) ->    cancel_timer(S#eldap.bind_timer),    case catch recvd_wait_bind_response(Data, S) of	bound                -> {next_state, active, S};	{fail_bind, Reason}  -> close_and_retry(S),				{next_state, connecting, S#eldap{fd = null}};	{'EXIT', Reason}     -> close_and_retry(S),				{next_state, connecting, S#eldap{fd = null}};	{error, Reason}      -> close_and_retry(S),				{next_state, connecting, S#eldap{fd = null}}    end;handle_info({tcp, Socket, Data}, active, S) ->    case catch recvd_packet(Data, S) of	{reply, Reply, To, NewS} -> gen_fsm:reply(To, Reply),				    {next_state, active, NewS};	{ok, NewS}               -> {next_state, active, NewS};	{'EXIT', Reason}         -> {next_state, active, S};	{error, Reason}          -> {next_state, active, S}    end;handle_info({tcp_closed, Socket}, All_fsm_states, S) ->    F = fun(Id, [{Timer, From, Name}|Res]) ->		gen_fsm:reply(From, {error, tcp_closed}),		cancel_timer(Timer)	end,    dict:map(F, S#eldap.dict),    retry_connect(),    {next_state, connecting, S#eldap{fd = null,				     dict = dict:new()}};handle_info({tcp_error, Socket, Reason}, Fsm_state, S) ->    log1("eldap received tcp_error: ~p~nIn State: ~p~n", [Reason, Fsm_state], S),    {next_state, Fsm_state, S};%%%% Timers%%handle_info({timeout, Timer, {cmd_timeout, Id}}, active, S) ->    case cmd_timeout(Timer, Id, S) of	{reply, To, Reason, NewS} -> gen_fsm:reply(To, Reason),				     {next_state, active, NewS};	{error, Reason}           -> {next_state, active, S}    end;handle_info({timeout, retry_connect}, connecting, S) ->    {ok, NextState, NewS} = connect_bind(S),     {next_state, NextState, NewS};handle_info({timeout, Timer, bind_timeout}, wait_bind_response, S) ->    close_and_retry(S),    {next_state, connecting, S#eldap{fd = null}};%%%% Make sure we don't fill the message queue with rubbish%%handle_info(Info, StateName, S) ->    log1("eldap. Unexpected Info: ~p~nIn state: ~p~n when StateData is: ~p~n",			[Info, StateName, S], S),    {next_state, StateName, S}.%%----------------------------------------------------------------------%% Func: terminate/3%% Purpose: Shutdown the fsm%% Returns: any%%----------------------------------------------------------------------terminate(Reason, StateName, StatData) ->    ok.%%----------------------------------------------------------------------%% Func: code_change/4%% Purpose: Convert process state when code is changed%% Returns: {ok, NewState, NewStateData}%%----------------------------------------------------------------------code_change(OldVsn, StateName, S, Extra) ->    {ok, StateName, S}.%%%----------------------------------------------------------------------%%% Internal functions%%%----------------------------------------------------------------------send_command(Command, From, S) ->    Id = bump_id(S),    {Name, Request} = gen_req(Command),    Message = #'LDAPMessage'{messageID  = Id,			     protocolOp = {Name, Request}},    log2("~p~n",[{Name, Request}], S),    {ok, Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message),    ok = gen_tcp:send(S#eldap.fd, Bytes),    Timer = erlang:start_timer(?CMD_TIMEOUT, self(), {cmd_timeout, Id}),    New_dict = dict:store(Id, [{Timer, From, Name}], S#eldap.dict),    {ok, S#eldap{id = Id,		 dict = New_dict}}.gen_req({search, A}) ->    {searchRequest,     #'SearchRequest'{baseObject   = A#eldap_search.base,		      scope        = v_scope(A#eldap_search.scope),		      derefAliases = neverDerefAliases,		      sizeLimit    = 0, % no size limit		      timeLimit    = v_timeout(A#eldap_search.timeout),		      typesOnly    = v_bool(A#eldap_search.types_only),		      filter       = v_filter(A#eldap_search.filter),		      attributes   = v_attributes(A#eldap_search.attributes)		     }};gen_req({add, Entry, Attrs}) ->    {addRequest,     #'AddRequest'{entry      = Entry,		   attributes = Attrs}};gen_req({delete, Entry}) ->    {delRequest, Entry};gen_req({modify, Obj, Mod}) ->    v_modifications(Mod),    {modifyRequest,      #'ModifyRequest'{object       = Obj,		      modification = Mod}};gen_req({modify_dn, Entry, NewRDN, DelOldRDN, NewSup}) ->    {modDNRequest,     #'ModifyDNRequest'{entry        = Entry,			newrdn       = NewRDN,			deleteoldrdn = DelOldRDN,			newSuperior  = NewSup}};gen_req({bind, RootDN, Passwd}) ->    {bindRequest,     #'BindRequest'{version        = ?LDAP_VERSION,		    name           = RootDN,  		    authentication = {simple, Passwd}}}.%%-----------------------------------------------------------------------%% recvd_packet%% Deals with incoming packets in the active state%% Will return one of:%%  {ok, NewS} - Don't reply to client yet as this is part of a search %%               result and we haven't got all the answers yet.%%  {reply, Result, From, NewS} - Reply with result to client From%%  {error, Reason}%%  {'EXIT', Reason} - Broke%%-----------------------------------------------------------------------recvd_packet(Pkt, S) ->    check_tag(Pkt),    case asn1rt:decode('ELDAPv3', 'LDAPMessage', Pkt) of	{ok,Msg} ->	    Op = Msg#'LDAPMessage'.protocolOp,	    log2("~p~n",[Op], S),	    Dict = S#eldap.dict,	    Id = Msg#'LDAPMessage'.messageID,	    {Timer, From, Name, Result_so_far} = get_op_rec(Id, Dict),	    case {Name, Op} of		{searchRequest, {searchResEntry, R}} when		      record(R,'SearchResultEntry') ->		    New_dict = dict:append(Id, R, Dict),		    {ok, S#eldap{dict = New_dict}};		{searchRequest, {searchResDone, Result}} ->		    case Result#'LDAPResult'.resultCode of			success ->			    {Res, Ref} = polish(Result_so_far),			    New_dict = dict:erase(Id, Dict),			    cancel_timer(Timer),			    {reply, #eldap_search_result{entries = Res,							 referrals = Ref}, From,			                              S#eldap{dict = New_dict}};			Reason ->			    New_dict = dict:erase(Id, Dict),			    cancel_timer(Timer),			    {reply, {error, Reason}, From, S#eldap{dict = New_dict}}			end;		{searchRequest, {searchResRef, R}} ->		    New_dict = dict:append(Id, R, Dict),		    {ok, S#eldap{dict = New_dict}};		{addRequest, {addResponse, Result}} ->		    New_dict = dict:erase(Id, Dict),		    cancel_timer(Timer),		    Reply = check_reply(Result, From),		    {reply, Reply, From, S#eldap{dict = New_dict}};		{delRequest, {delResponse, Result}} ->		    New_dict = dict:erase(Id, Dict),		    cancel_timer(Timer),		    Reply = check_reply(Result, From),		    {reply, Reply, From, S#eldap{dict = New_dict}};		{modifyRequest, {modifyResponse, Result}} ->		    New_dict = dict:erase(Id, Dict),		    cancel_timer(Timer),		    Reply = check_reply(Result, From),		    {reply, Reply, From, S#eldap{dict = New_dict}};		{modDNRequest, {modDNResponse, Result}} ->		    New_dict = dict:erase(Id, Dict),		    cancel_timer(Timer),		    Reply = check_reply(Result, From),		    {reply, Reply, From, S#eldap{dict = New_dict}};		{bindRequest, {bindResponse, Result}} ->		    New_dict = dict:erase(Id, Dict),

⌨️ 快捷键说明

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