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 + -
显示快捷键?