inet_gethost_native.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 617 行 · 第 1/2 页

ERL
617
字号
	    NRid = get_rid(),	    Req = #request{rid = NRid, op = Op, proto = Proto, rdata = Data},	    ets:insert(State#state.requests, Req),	    ets:insert(State#state.req_index,{R,NRid}),	    put(num_requests,get(num_requests) + 1),	    Req    end.    pick_request(State, RID) ->    case ets:lookup(State#state.requests, RID) of	[] ->	    false;	[#request{rid = RID, op = Op, proto = Proto, rdata = Data}=R] ->	    ets:delete(State#state.requests,RID),	    ets:delete(State#state.req_index,{Op,Proto,Data}),	    put(num_requests,get(num_requests) - 1),	    R    end.pick_client(State,RID,Clid) ->    case ets:lookup(State#state.requests, RID) of	[] ->	    false;	[R] ->	    case R#request.clients of		[SoleClient] ->		    {last, SoleClient}; % Note, not removed, the caller 					% should cleanup request data		CList ->		    case lists:keysearch(Clid,1,CList) of			{value, Client} ->			    NCList = lists:keydelete(Clid,1,CList),			    ets:insert(State#state.requests, 				       R#request{clients = NCList}),			    {more, Client};			false ->			    false		    end	    end    end.get_rid () ->    New = (get(rid) + 1) rem 16#7FFFFFF,    put(rid,New),    New.foreach(Fun,Table) ->    foreach(Fun,Table,ets:first(Table)).foreach(_Fun,_Table,'$end_of_table') ->    ok;foreach(Fun,Table,Key) ->    [Object] = ets:lookup(Table,Key),    Fun(Object),    foreach(Fun,Table,ets:next(Table,Key)).restart_port(#state{port = Port, requests = Requests}) ->    (catch port_close(Port)),    NewPort = do_open_port(get_poolsize(), get_extra_args()),    foreach(fun(#request{rid = Rid, op = Op, proto = Proto, rdata = Rdata}) ->		    case Op of 			?OP_GETHOSTBYNAME ->			    port_command(NewPort,[<<Rid:32,?OP_GETHOSTBYNAME:8,						  Proto:8>>,						  Rdata,0]);			?OP_GETHOSTBYADDR ->			    port_command(NewPort,					 <<Rid:32,?OP_GETHOSTBYADDR:8, Proto:8,					 Rdata/binary>>)		    end	    end,	    Requests),    NewPort.			        do_open_port(Poolsize, ExtraArgs) ->    open_port({spawn, 	       ?PORT_PROGRAM++" "++integer_to_list(Poolsize)++" "++ExtraArgs},	      [{packet,4},eof,binary]).get_extra_args() ->    FirstPart = case application:get_env(kernel, gethost_prioritize) of		    {ok, false} ->			" -ng";		    _ ->			""		end,    case application:get_env(kernel, gethost_extra_args) of	{ok, L} when is_list(L) ->	    FirstPart++" "++L;	_ ->	    FirstPart++""    end.get_poolsize() ->    case application:get_env(kernel, gethost_poolsize) of	{ok,I} when is_integer(I) ->	    I;	_ ->	    ?DEFAULT_POOLSIZE    end.%%------------------------------------------------------------------%% System messages callbacks%%------------------------------------------------------------------system_continue(_Parent, _, State) ->    main_loop(State).system_terminate(Reason, _Parent, _, _State) ->    exit(Reason).system_code_change(State, _Module, _OldVsn, _Extra) ->    {ok, State}. %% Nothing to do in this version.%%-----------------------------------------------------------------------%% Client API%%-----------------------------------------------------------------------gethostbyname(Name) ->    gethostbyname(Name, inet).gethostbyname(Name, inet) when is_list(Name) ->    getit(?OP_GETHOSTBYNAME, ?PROTO_IPV4, Name);gethostbyname(Name, inet6) when is_list(Name) ->    getit(?OP_GETHOSTBYNAME, ?PROTO_IPV6, Name);gethostbyname(Name, Type) when is_atom(Name) ->    gethostbyname(atom_to_list(Name), Type);gethostbyname(_, _)  ->    {error, formerr}.gethostbyaddr({A,B,C,D}) when ?VALID_V4(A), ?VALID_V4(B), ?VALID_V4(C), ?VALID_V4(D) ->    getit(?OP_GETHOSTBYADDR, ?PROTO_IPV4, <<A,B,C,D>>);gethostbyaddr({A,B,C,D,E,F,G,H}) when ?VALID_V6(A), ?VALID_V6(B), ?VALID_V6(C), ?VALID_V6(D),				      ?VALID_V6(E), ?VALID_V6(F), ?VALID_V6(G), ?VALID_V6(H) ->    getit(?OP_GETHOSTBYADDR, ?PROTO_IPV6, <<A:16,B:16,C:16,D:16,E:16,F:16,G:16,H:16>>);gethostbyaddr(Addr) when is_list(Addr) ->    case inet_parse:address(Addr) of        {ok, IP} -> gethostbyaddr(IP);        _Error -> {error, formerr}    end;gethostbyaddr(Addr) when is_atom(Addr) ->    gethostbyaddr(atom_to_list(Addr));gethostbyaddr(_) -> {error, formerr}.control({debug_level, Level}) when is_integer(Level) ->    getit(?OP_CONTROL, ?SETOPT_DEBUG_LEVEL, <<Level:32>>);control(soft_restart) ->    getit(restart_port);control(_) -> {error, formerr}.getit(Op, Proto, Data) ->    getit({Op, Proto, Data}).getit(Req) ->    Pid = ensure_started(),    Ref = make_ref(),    Pid ! {{self(),Ref}, Req},    receive	{Ref, {ok,BinHostent}} ->	    parse_address(BinHostent);	{Ref, Error} -> 	    Error    after 5000 ->	    Ref2 = erlang:monitor(process,Pid),	    Res2 = receive		       {Ref, {ok,BinHostent}} ->			   parse_address(BinHostent);		       {Ref, Error} -> 			   Error;		       {'DOWN', Ref2, process, 			Pid, Reason} ->			   {error, Reason}		   end,	    catch erlang:demonitor(Ref2),	    receive {'DOWN',Ref2,_,_,_} -> ok after 0 -> ok end,	    Res2    end.do_start(Sup, C) ->    {Child,_,_,_,_,_} = C,    case supervisor:start_child(Sup,C) of	{ok,_} ->	    ok;	{error, {already_started, Pid}} when is_pid(Pid) ->	    ok;	{error, {{already_started, Pid}, _Child}} when is_pid(Pid) ->	    ok;	{error, already_present} ->	    supervisor:delete_child(Sup, Child),	    do_start(Sup, C)    end.ensure_started() ->    case whereis(?MODULE) of	undefined -> 	    C = {?PROCNAME_SUP, {?MODULE, start_link, []}, temporary, 		 1000, worker, [?MODULE]},	    case whereis(kernel_safe_sup) of		undefined ->		    case whereis(net_sup) of			undefined ->			    %% Icky fallback, run once without supervisor			    start_raw();			_ ->			    do_start(net_sup,C),			    case whereis(?MODULE) of				undefined ->				    exit({could_not_start_server, ?MODULE});				Pid0 ->				    Pid0			    end		    end;		_ ->		    do_start(kernel_safe_sup,C),		    case whereis(?MODULE) of			undefined ->			    exit({could_not_start_server, ?MODULE});			Pid1 ->			    Pid1		    end	    end;	Pid -> 	    Pid    end.parse_address(BinHostent) ->    case catch 	begin	    case BinHostent of		<<?UNIT_ERROR, Errstring/binary>> -> 		    {error, list_to_atom(listify(Errstring))};		<<?UNIT_IPV4, Naddr:32, T0/binary>> ->		    {T1,Addresses} = pick_addresses_v4(Naddr, T0),		    [Name | Names] = pick_names(T1),		    {ok, #hostent{h_addr_list = Addresses, h_addrtype = inet,				  h_aliases = Names, h_length = ?UNIT_IPV4, 				  h_name = Name}};		<<?UNIT_IPV6, Naddr:32, T0/binary>> ->		    {T1,Addresses} = pick_addresses_v6(Naddr, T0),		    [Name | Names] = pick_names(T1),		    {ok, #hostent{h_addr_list = Addresses, h_addrtype = inet6,				  h_aliases = Names, h_length = ?UNIT_IPV6, 				  h_name = Name}};		_Else ->		    {error, {internal_error, {malformed_response, BinHostent}}}	    end	end of	{'EXIT', Reason} ->	    Reason;	Normal ->	    Normal    end.	    listify(Bin) ->    N = size(Bin) - 1,    <<Bin2:N/binary, Ch>> = Bin,    case Ch of	0 ->	    listify(Bin2);	_ ->	    binary_to_list(Bin)    end.    pick_addresses_v4(0,Tail) ->    {Tail,[]};pick_addresses_v4(N,<<A,B,C,D,Tail/binary>>) ->    {NTail, OList} = pick_addresses_v4(N-1,Tail),    {NTail, [{A,B,C,D} | OList]}.pick_addresses_v6(0,Tail) ->    {Tail,[]};pick_addresses_v6(Num,<<A:16,B:16,C:16,D:16,E:16,F:16,G:16,H:16,		  Tail/binary>>) ->    {NTail, OList} = pick_addresses_v6(Num-1,Tail),    {NTail, [{A,B,C,D,E,F,G,H} | OList]}.ndx(Ch,Bin) ->    ndx(Ch,0,size(Bin),Bin).ndx(_,N,N,_) ->    undefined;ndx(Ch,I,N,Bin) ->    case Bin of	<<_:I/binary,Ch,_/binary>> ->	    I;	_ ->	    ndx(Ch,I+1,N,Bin)    end.pick_names(<<Length:32,Namelist/binary>>) ->    pick_names(Length,Namelist).pick_names(0,<<>>) ->    [];pick_names(0,_) ->    exit({error,format_error});pick_names(_N,<<>>) ->    exit({error,format_error});pick_names(N,Bin) ->    Ndx = ndx(0,Bin),    <<Str:Ndx/binary,0,Rest/binary>> = Bin,    [binary_to_list(Str)|pick_names(N-1,Rest)].

⌨️ 快捷键说明

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