61
61
-export([start_timer/1, timeout/1, timeout/2, stop_timer/1]).
64
-import(lists, [append/1, duplicate/2, member/2, filter/2,
65
map/2, foldl/3, foreach/2]).
64
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
67
66
%% Record Signature
68
67
-define(RS(Record),
69
{Record,record_info(size, Record)}).
68
{Record, record_info(size, Record)}).
70
69
%% Record Signature Check (guard)
71
70
-define(RSC(Record, RS),
72
71
element(1, Record) =:= element(1, RS),
73
size(Record) =:= element(2, RS)).
72
tuple_size(Record) =:= element(2, RS)).
75
74
%%% ---------------------------------
76
75
%%% Contract type definitions
78
-type(socket() :: port()).
79
-type(posix() :: atom()).
77
-type socket() :: port().
78
-type posix() :: atom().
81
-type(socket_setopt() ::
80
-type socket_setopt() ::
82
81
{'raw', non_neg_integer(), non_neg_integer(), binary()} |
84
83
{'reuseaddr', bool()} |
175
174
{'flags', ['up' | 'down' | 'broadcast' | 'no_broadcast' |
176
175
'pointtopoint' | 'no_pointtopoint' |
177
176
'running' | 'multicast']} |
178
{'hwaddr', ether_address()}).
177
{'hwaddr', ether_address()}.
181
180
'addr' | 'broadaddr' | 'dstaddr' |
182
'mtu' | 'netmask' | 'flags' |'hwaddr').
181
'mtu' | 'netmask' | 'flags' |'hwaddr'.
184
-type(family_option() :: 'inet' | 'inet6').
185
-type(protocol_option() :: 'tcp' | 'udp' | 'sctp').
186
-type(stat_option() ::
183
-type family_option() :: 'inet' | 'inet6'.
184
-type protocol_option() :: 'tcp' | 'udp' | 'sctp'.
185
-type stat_option() ::
187
186
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
188
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend').
187
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
189
189
%%% ---------------------------------
191
-spec(get_rc/0 :: () -> [{any(),any()}]).
191
-spec get_rc() -> [{any(),any()}].
194
194
inet_db:get_rc().
196
-spec(close/1 :: (Socket :: socket()) -> 'ok').
196
-spec close(Socket :: socket()) -> 'ok'.
199
199
prim_inet:close(Socket),
221
219
prim_inet:setpeername(Socket, undefined).
224
-spec(sockname/1 :: (Socket :: socket()) ->
225
{'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}).
222
-spec sockname(Socket :: socket()) ->
223
{'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}.
227
225
sockname(Socket) ->
228
226
prim_inet:sockname(Socket).
230
-spec(setsockname/2 :: (
232
Address :: {ip_address(), ip_port()}) ->
233
'ok' | {'error', any()}).
228
-spec setsockname(Socket :: socket(), Address :: {ip_address(), ip_port()}) ->
229
'ok' | {'error', any()}.
235
231
setsockname(Socket, {IP,Port}) ->
236
232
prim_inet:setsockname(Socket, {IP,Port});
237
233
setsockname(Socket, undefined) ->
238
234
prim_inet:setsockname(Socket, undefined).
240
-spec(port/1 :: (Socket :: socket()) ->
241
{'ok', ip_port()} | {'error', any()}).
236
-spec port(Socket :: socket()) -> {'ok', ip_port()} | {'error', any()}.
244
239
case prim_inet:sockname(Socket) of
251
Packet :: iolist()) -> % iolist()?
252
'ok' | {'error', posix()}).
244
-spec send(Socket :: socket(), Packet :: iolist()) -> % iolist()?
245
'ok' | {'error', posix()}.
254
247
send(Socket, Packet) ->
255
248
prim_inet:send(Socket, Packet).
259
Opts :: [socket_setopt()]) ->
260
'ok' | {'error', posix()}).
250
-spec setopts(Socket :: socket(), Opts :: [socket_setopt()]) ->
251
'ok' | {'error', posix()}.
262
253
setopts(Socket, Opts) ->
263
254
prim_inet:setopts(Socket, Opts).
267
Opts :: [socket_getopt()]) ->
268
{'ok', [socket_setopt()]} | {'error', posix()}).
256
-spec getopts(Socket :: socket(), Opts :: [socket_getopt()]) ->
257
{'ok', [socket_setopt()]} | {'error', posix()}.
270
259
getopts(Socket, Opts) ->
271
260
prim_inet:getopts(Socket, Opts).
273
-spec(getiflist/1 :: (Socket :: socket()) ->
274
{'ok', [string()]} | {'error', posix()}).
262
-spec getiflist(Socket :: socket()) ->
263
{'ok', [string()]} | {'error', posix()}.
276
265
getiflist(Socket) ->
277
266
prim_inet:getiflist(Socket).
279
-spec(getiflist/0 :: () ->
280
{'ok', [string()]} | {'error', posix()}).
268
-spec getiflist() -> {'ok', [string()]} | {'error', posix()}.
283
271
withsocket(fun(S) -> prim_inet:getiflist(S) end).
287
Name :: string() | atom(),
288
Opts :: [if_getopt()]) ->
289
{'ok', [if_setopt()]} |
273
-spec ifget(Socket :: socket(),
274
Name :: string() | atom(),
275
Opts :: [if_getopt()]) ->
276
{'ok', [if_setopt()]} | {'error', posix()}.
292
278
ifget(Socket, Name, Opts) ->
293
279
prim_inet:ifget(Socket, Name, Opts).
296
Name :: string() | atom(),
297
Opts :: [if_getopt()]) ->
298
{'ok', [if_setopt()]} |
281
-spec ifget(Name :: string() | atom(), Opts :: [if_getopt()]) ->
282
{'ok', [if_setopt()]} | {'error', posix()}.
302
285
withsocket(fun(S) -> prim_inet:ifget(S, Name, Opts) end).
306
Name :: string() | atom(),
307
Opts :: [if_setopt()]) ->
308
'ok' | {'error', posix()}).
287
-spec ifset(Socket :: socket(),
288
Name :: string() | atom(),
289
Opts :: [if_setopt()]) ->
290
'ok' | {'error', posix()}.
310
292
ifset(Socket, Name, Opts) ->
311
293
prim_inet:ifset(Socket, Name, Opts).
314
Name :: string() | atom(),
315
Opts :: [if_setopt()]) ->
316
'ok' | {'error', posix()}).
295
-spec ifset(Name :: string() | atom(), Opts :: [if_setopt()]) ->
296
'ok' | {'error', posix()}.
319
299
withsocket(fun(S) -> prim_inet:ifset(S, Name, Opts) end).
321
-spec(getif/0 :: () ->
322
302
{'ok', [{ip_address(), ip_address() | 'undefined', ip_address()}]} |
326
306
withsocket(fun(S) -> getif(S) end).
328
308
%% backwards compatible getif
329
-spec(getif/1 :: (Socket :: socket()) ->
309
-spec getif(Socket :: socket()) ->
330
310
{'ok', [{ip_address(), ip_address() | 'undefined', ip_address()}]} |
334
314
case prim_inet:getiflist(Socket) of
386
366
{ok, "nohost.nodomain"}
389
-spec(gethostname/1 :: (Socket :: socket()) ->
390
{'ok', string()} | {'error', posix()}).
369
-spec gethostname(Socket :: socket()) ->
370
{'ok', string()} | {'error', posix()}.
392
372
gethostname(Socket) ->
393
373
prim_inet:gethostname(Socket).
395
-spec(getstat/1 :: (Socket :: socket()) ->
396
{'ok', [{stat_option(), integer()}]} | {'error', posix()}).
375
-spec getstat(Socket :: socket()) ->
376
{'ok', [{stat_option(), integer()}]} | {'error', posix()}.
398
378
getstat(Socket) ->
399
379
prim_inet:getstat(Socket, stats()).
403
Statoptions :: [stat_option()]) ->
404
{'ok', [{stat_option(), integer()}]} | {'error', posix()}).
381
-spec getstat(Socket :: socket(), Statoptions :: [stat_option()]) ->
382
{'ok', [{stat_option(), integer()}]} | {'error', posix()}.
406
384
getstat(Socket,What) ->
407
385
prim_inet:getstat(Socket, What).
409
-spec(gethostbyname/1 :: (Name :: string() | atom()) ->
410
{'ok', #hostent{}} | {'error', posix()}).
387
-spec gethostbyname(Name :: string() | atom()) ->
388
{'ok', #hostent{}} | {'error', posix()}.
412
390
gethostbyname(Name) ->
413
391
gethostbyname_tm(Name, inet, false).
415
-spec(gethostbyname/2 :: (
416
Name :: string() | atom(),
417
Family :: family_option()) ->
418
{'ok', #hostent{}} | {'error', posix()}).
393
-spec gethostbyname(Name :: string() | atom(), Family :: family_option()) ->
394
{'ok', #hostent{}} | {'error', posix()}.
420
396
gethostbyname(Name,Family) ->
421
397
gethostbyname_tm(Name, Family, false).
423
-spec(gethostbyname/3 :: (
424
Name :: string() | atom(),
425
Family :: family_option(),
426
Timeout :: non_neg_integer() | 'infinity') ->
427
{'ok', #hostent{}} | {'error', posix()}).
399
-spec gethostbyname(Name :: string() | atom(),
400
Family :: family_option(),
401
Timeout :: non_neg_integer() | 'infinity') ->
402
{'ok', #hostent{}} | {'error', posix()}.
429
404
gethostbyname(Name,Family,Timeout) ->
430
405
Timer = start_timer(Timeout),
436
411
gethostbyname_tm(Name,Family,Timer,inet_db:res_option(lookup)).
439
-spec(gethostbyaddr/1 :: (Address :: string() | ip_address()) ->
440
{'ok', #hostent{}} | {'error', posix()}).
414
-spec gethostbyaddr(Address :: string() | ip_address()) ->
415
{'ok', #hostent{}} | {'error', posix()}.
442
417
gethostbyaddr(Address) ->
443
418
gethostbyaddr_tm(Address, false).
445
-spec(gethostbyaddr/2 :: (
446
Address :: string() | ip_address(),
447
Timeout :: non_neg_integer() | 'infinity') ->
448
{'ok', #hostent{}} | {'error', posix()}).
420
-spec gethostbyaddr(Address :: string() | ip_address(),
421
Timeout :: non_neg_integer() | 'infinity') ->
422
{'ok', #hostent{}} | {'error', posix()}.
450
424
gethostbyaddr(Address,Timeout) ->
451
425
Timer = start_timer(Timeout),
492
463
%% Lookup an ip address
496
Host :: ip_address() | string() | atom(),
497
Family :: family_option()) ->
498
{'ok', ip_address()} | {'error', posix()}).
466
-spec getaddr(Host :: ip_address() | string() | atom(),
467
Family :: family_option()) ->
468
{'ok', ip_address()} | {'error', posix()}.
500
470
getaddr(Address, Family) ->
501
471
getaddr(Address, Family, infinity).
504
Host :: ip_address() | string() | atom(),
505
Family :: family_option(),
506
Timeout :: non_neg_integer() | 'infinity') ->
507
{'ok', ip_address()} | {'error', posix()}).
473
-spec getaddr(Host :: ip_address() | string() | atom(),
474
Family :: family_option(),
475
Timeout :: non_neg_integer() | 'infinity') ->
476
{'ok', ip_address()} | {'error', posix()}.
509
478
getaddr(Address, Family, Timeout) ->
510
479
Timer = start_timer(Timeout),
511
480
Res = getaddr_tm(Address, Family, Timer),
512
481
stop_timer(Timer),
515
484
getaddr_tm(Address, Family, Timer) ->
516
485
case getaddrs_tm(Address, Family, Timer) of
517
486
{ok, [IP|_]} -> {ok, IP};
521
-spec(getaddrs/2 :: (
522
Host :: ip_address() | string() | atom(),
523
Family :: family_option()) ->
524
{'ok', [ip_address()]} | {'error', posix()}).
490
-spec getaddrs(Host :: ip_address() | string() | atom(),
491
Family :: family_option()) ->
492
{'ok', [ip_address()]} | {'error', posix()}.
526
494
getaddrs(Address, Family) ->
527
495
getaddrs(Address, Family, infinity).
529
-spec(getaddrs/3 :: (
530
Host :: ip_address() | string() | atom(),
531
Family :: family_option(),
532
Timeout :: non_neg_integer() | 'infinity') ->
533
{'ok', [ip_address()]} | {'error', posix()}).
497
-spec getaddrs(Host :: ip_address() | string() | atom(),
498
Family :: family_option(),
499
Timeout :: non_neg_integer() | 'infinity') ->
500
{'ok', [ip_address()]} | {'error', posix()}.
535
getaddrs(Address, Family,Timeout) ->
536
Timer = start_timer(Timeout),
502
getaddrs(Address, Family, Timeout) ->
503
Timer = start_timer(Timeout),
537
504
Res = getaddrs_tm(Address, Family, Timer),
538
505
stop_timer(Timer),
541
-spec(getservbyport/2 :: (
543
Protocol :: atom() | string()) ->
544
{'ok', string()} | {'error', posix()}).
508
-spec getservbyport(Port :: ip_port(), Protocol :: atom() | string()) ->
509
{'ok', string()} | {'error', posix()}.
546
511
getservbyport(Port, Proto) ->
547
512
case inet_udp:open(0, []) of
549
Res = prim_inet:getservbyport(U,Port, Proto),
514
Res = prim_inet:getservbyport(U, Port, Proto),
550
515
inet_udp:close(U),
555
-spec(getservbyname/2 :: (
556
Name :: atom() | string(),
557
Protocol :: atom() | string()) ->
558
{'ok', ip_port()} | {'error', posix()}).
520
-spec getservbyname(Name :: atom() | string(),
521
Protocol :: atom() | string()) ->
522
{'ok', ip_port()} | {'error', posix()}.
560
getservbyname(Name, Proto) when is_atom(Name) ->
524
getservbyname(Name, Protocol) when is_atom(Name) ->
561
525
case inet_udp:open(0, []) of
563
Res = prim_inet:getservbyname(U,Name, Proto),
527
Res = prim_inet:getservbyname(U, Name, Protocol),
564
528
inet_udp:close(U),
997
961
gethostbyaddr_tm(_Addr, _Timer, []) ->
998
962
{error, nxdomain}.
1002
Addr :: ip_address(),
1004
Opts :: [socket_setopt()],
1005
Protocol :: protocol_option(),
1006
Family :: 'inet' | 'inet6',
1007
Module :: atom()) ->
1008
{'ok', socket()} | {'error', posix()}).
964
-spec open(Fd :: integer(),
965
Addr :: ip_address(),
967
Opts :: [socket_setopt()],
968
Protocol :: protocol_option(),
969
Family :: 'inet' | 'inet6',
971
{'ok', socket()} | {'error', posix()}.
1010
973
open(Fd, Addr, Port, Opts, Protocol, Family, Module) when Fd < 0 ->
1011
974
case prim_inet:open(Protocol, Family) of
1038
1001
open(Fd, _Addr, _Port, Opts, Protocol, Family, Module) ->
1039
1002
fdopen(Fd, Opts, Protocol, Family, Module).
1042
Fd :: non_neg_integer(),
1043
Opts :: [socket_setopt()],
1044
Protocol :: protocol_option(),
1045
Family :: family_option(),
1046
Module :: atom()) ->
1047
{'ok', socket()} | {'error', posix()}).
1004
-spec fdopen(Fd :: non_neg_integer(),
1005
Opts :: [socket_setopt()],
1006
Protocol :: protocol_option(),
1007
Family :: family_option(),
1008
Module :: atom()) ->
1009
{'ok', socket()} | {'error', posix()}.
1049
1011
fdopen(Fd, Opts, Protocol, Family, Module) ->
1050
1012
case prim_inet:fdopen(Protocol, Fd, Family) of
1079
1041
fun(Line,Max0) -> smax(Max0,Line) end,
1080
1042
duplicate(length(Fs),0),LLs),
1081
Fmt = append(map(fun(N) -> "~-" ++ integer_to_list(N) ++ "s " end,
1084
fun(Line) -> io:format(Fmt, Line) end, LLs).
1043
Fmt = append(["~-" ++ integer_to_list(N) ++ "s " || N <- Maxs]) ++ "\n",
1044
lists:foreach(fun(Line) -> io:format(Fmt, Line) end, LLs).
1086
1046
smax([Max|Ms], [Str|Strs]) ->
1087
1047
N = length(Str),
1088
[ if N > Max -> N; true -> Max end | smax(Ms, Strs)];
1048
[if N > Max -> N; true -> Max end | smax(Ms, Strs)];
1089
1049
smax([], []) -> [].
1091
info_lines(Ss, Fs,Proto) -> map(fun(S) -> i_line(S, Fs,Proto) end, Ss).
1092
i_line(S, Fs, Proto) -> map(fun(F) -> info(S, F, Proto) end, Fs).
1051
info_lines(Ss, Fs, Proto) -> [i_line(S, Fs,Proto) || S <- Ss].
1052
i_line(S, Fs, Proto) -> [info(S, F, Proto) || F <- Fs].
1094
h_line(Fs) -> map(fun(F) -> h_field(atom_to_list(F)) end, Fs).
1054
h_line(Fs) -> [h_field(atom_to_list(F)) || F <- Fs].
1096
1056
h_field([C|Cs]) -> [upper(C) | hh_field(Cs)].
1287
1249
{connected, Pid} when Pid =/= self() ->
1288
1250
{error, not_owner};
1290
{ok,A0} = prim_inet:getopt(S, active),
1252
{ok, A0} = prim_inet:getopt(S, active),
1291
1253
prim_inet:setopt(S, active, false),
1292
case udp_sync_input(S, NewOwner, false) of
1294
case catch erlang:port_connect(S, NewOwner) of
1297
prim_inet:setopt(S, active, A0),
1254
udp_sync_input(S, NewOwner),
1255
try erlang:port_connect(S, NewOwner) of
1258
prim_inet:setopt(S, active, A0),
1307
udp_sync_input(S, Owner, Flag) ->
1266
udp_sync_input(S, Owner) ->
1309
{sctp, S, _, _, _}=Msg -> udp_sync_input(S, Owner, Flag, Msg);
1310
{udp, S, _, _, _}=Msg -> udp_sync_input(S, Owner, Flag, Msg);
1311
{udp_closed, S}=Msg -> udp_sync_input(S, Owner, Flag, Msg);
1312
{S, {data,_}}=Msg -> udp_sync_input(S, Owner, Flag, Msg);
1313
{inet_async, S, _, _}=Msg -> udp_sync_input(S, Owner, Flag, Msg);
1314
{inet_reply, S, _}=Msg -> udp_sync_input(S, Owner, Flag, Msg)
1268
{sctp, S, _, _, _}=Msg -> udp_sync_input(S, Owner, Msg);
1269
{udp, S, _, _, _}=Msg -> udp_sync_input(S, Owner, Msg);
1270
{udp_closed, S}=Msg -> udp_sync_input(S, Owner, Msg);
1271
{S, {data,_}}=Msg -> udp_sync_input(S, Owner, Msg);
1272
{inet_async, S, _, _}=Msg -> udp_sync_input(S, Owner, Msg);
1273
{inet_reply, S, _}=Msg -> udp_sync_input(S, Owner, Msg)
1319
udp_sync_input(S, Owner, Flag, Msg) ->
1278
udp_sync_input(S, Owner, Msg) ->
1321
udp_sync_input(S, Owner, Flag).
1280
udp_sync_input(S, Owner).
1323
1282
start_timer(infinity) -> false;
1324
start_timer(Timeout) ->
1283
start_timer(Timeout) ->
1325
1284
erlang:start_timer(Timeout, self(), inet).
1327
1286
timeout(false) -> infinity;