/
addr_util.erl
83 lines (67 loc) · 2.56 KB
/
addr_util.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
%% @author Northscale <info@northscale.com>
%% @copyright 2010 NorthScale, Inc.
%% All rights reserved.
-module(addr_util).
-include_lib("eunit/include/eunit.hrl").
-export([get_my_address/0, get_my_address/1]).
%% Find the best IP address we can find for the current host.
get_my_address() ->
get_my_address("255.255.255.255").
get_my_address(CurrentAddress) ->
determine_address(CurrentAddress, list_all_addresses()).
get_my_address_test() ->
%% Verify the result of this looks like an IP address.
4 = length(string:tokens(get_my_address(), ".")).
determine_address(CurrentAddress, AddrList) ->
case lists:member(CurrentAddress, AddrList) of
true -> CurrentAddress;
_ -> extract_addr(AddrList)
end.
determine_address_test() ->
"4.1.1.1" = determine_address("255.255.255.255", ["4.1.1.1", "1.2.3.4"]),
"1.2.3.4" = determine_address("1.2.3.4", ["4.1.1.1", "1.2.3.4"]),
"127.0.0.1" = determine_address("1.2.3.4", []).
list_all_addresses() ->
{ok, AddrInfo} = inet:getifaddrs(),
CandidateList = lists:map(fun(X) -> element(2, X) end,
lists:filter(fun(Y) -> element(1, Y) == addr end,
lists:flatten(lists:map(fun(Z) -> element(2, Z) end,
AddrInfo)))),
lists:sort(lists:map(fun(X) -> addr_to_s(X) end,
lists:filter(fun is_valid_ip/1,
CandidateList))
-- ["127.0.0.1"]).
list_all_addresses_test() ->
%% I can't test too much here since this isn't functional, but
%% I'll verify we go through the code and return something.
true = is_list(list_all_addresses()).
%% check for some common invalid addresses
is_valid_ip(Addr) ->
case Addr of
{0, 0, 0, 0} -> false;
{255, 255, 255, 255} -> false;
{169, 254, _, _ } -> false;
{224, _, _, _ } -> false;
{_, _, _, _} -> true;
_ -> false
end.
is_valid_ip_test() ->
true = is_valid_ip({192,168,1,1}),
false = is_valid_ip({169,254,1,1}).
%% [X,...] -> X
extract_addr([H|_Tl]) ->
H;
%% [] -> "127.0.0.1"
extract_addr([]) ->
"127.0.0.1".
extract_addr_test() ->
"4.1.1.1" = extract_addr(["4.1.1.1", "1.2.3.4"]),
"4.1.1.1" = extract_addr(["4.1.1.1"]),
"127.0.0.1" = extract_addr([]).
%% {1,2,3,4} -> "1.2.3.4"
addr_to_s(T) ->
string:join(lists:map(fun erlang:integer_to_list/1,
tuple_to_list(T)),
".").
addr_to_s_test() ->
"1.2.3.4" = addr_to_s({1,2,3,4}).